diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 432ac2ad49..e1ac743a80 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -1062,11 +1062,12 @@ void EntityScriptingInterface::handleEntityScriptCallMethodPacket(QSharedPointer -QUuid EntityScriptingInterface::evalClosestEntity(const glm::vec3& center, float radius, unsigned int searchFilter) const { +QUuid EntityScriptingInterface::findClosestEntity(const glm::vec3& center, float radius) const { PROFILE_RANGE(script_entities, __FUNCTION__); EntityItemID result; if (_entityTree) { + unsigned int searchFilter = PickFilter::getBitMask(PickFilter::FlagBit::DOMAIN_ENTITIES) | PickFilter::getBitMask(PickFilter::FlagBit::AVATAR_ENTITIES); _entityTree->withReadLock([&] { result = _entityTree->evalClosestEntity(center, radius, PickFilter(searchFilter)); }); @@ -1083,11 +1084,12 @@ void EntityScriptingInterface::dumpTree() const { } } -QVector EntityScriptingInterface::evalEntitiesInSphere(const glm::vec3& center, float radius, unsigned int searchFilter) const { +QVector EntityScriptingInterface::findEntities(const glm::vec3& center, float radius) const { PROFILE_RANGE(script_entities, __FUNCTION__); QVector result; if (_entityTree) { + unsigned int searchFilter = PickFilter::getBitMask(PickFilter::FlagBit::DOMAIN_ENTITIES) | PickFilter::getBitMask(PickFilter::FlagBit::AVATAR_ENTITIES); _entityTree->withReadLock([&] { _entityTree->evalEntitiesInSphere(center, radius, PickFilter(searchFilter), result); }); @@ -1095,11 +1097,12 @@ QVector EntityScriptingInterface::evalEntitiesInSphere(const glm::vec3& c return result; } -QVector EntityScriptingInterface::evalEntitiesInBox(const glm::vec3& corner, const glm::vec3& dimensions, unsigned int searchFilter) const { +QVector EntityScriptingInterface::findEntitiesInBox(const glm::vec3& corner, const glm::vec3& dimensions) const { PROFILE_RANGE(script_entities, __FUNCTION__); QVector result; if (_entityTree) { + unsigned int searchFilter = PickFilter::getBitMask(PickFilter::FlagBit::DOMAIN_ENTITIES) | PickFilter::getBitMask(PickFilter::FlagBit::AVATAR_ENTITIES); _entityTree->withReadLock([&] { AABox box(corner, dimensions); _entityTree->evalEntitiesInBox(box, PickFilter(searchFilter), result); @@ -1108,7 +1111,7 @@ QVector EntityScriptingInterface::evalEntitiesInBox(const glm::vec3& corn return result; } -QVector EntityScriptingInterface::evalEntitiesInFrustum(QVariantMap frustum, unsigned int searchFilter) const { +QVector EntityScriptingInterface::findEntitiesInFrustum(QVariantMap frustum) const { PROFILE_RANGE(script_entities, __FUNCTION__); QVector result; @@ -1138,6 +1141,7 @@ QVector EntityScriptingInterface::evalEntitiesInFrustum(QVariantMap frust viewFrustum.calculate(); if (_entityTree) { + unsigned int searchFilter = PickFilter::getBitMask(PickFilter::FlagBit::DOMAIN_ENTITIES) | PickFilter::getBitMask(PickFilter::FlagBit::AVATAR_ENTITIES); _entityTree->withReadLock([&] { _entityTree->evalEntitiesInFrustum(viewFrustum, PickFilter(searchFilter), result); }); @@ -1147,11 +1151,12 @@ QVector EntityScriptingInterface::evalEntitiesInFrustum(QVariantMap frust return result; } -QVector EntityScriptingInterface::evalEntitiesInSphereWithType(const QString entityType, const glm::vec3& center, float radius, unsigned int searchFilter) const { +QVector EntityScriptingInterface::findEntitiesByType(const QString entityType, const glm::vec3& center, float radius) const { EntityTypes::EntityType type = EntityTypes::getEntityTypeFromName(entityType); QVector result; if (_entityTree) { + unsigned int searchFilter = PickFilter::getBitMask(PickFilter::FlagBit::DOMAIN_ENTITIES) | PickFilter::getBitMask(PickFilter::FlagBit::AVATAR_ENTITIES); _entityTree->withReadLock([&] { _entityTree->evalEntitiesInSphereWithType(center, radius, type, PickFilter(searchFilter), result); }); @@ -1159,22 +1164,37 @@ QVector EntityScriptingInterface::evalEntitiesInSphereWithType(const QStr return result; } -QVector EntityScriptingInterface::evalEntitiesInSphereWithName(const QString entityName, const glm::vec3& center, float radius, bool caseSensitiveSearch, unsigned int searchFilter) const { +QVector EntityScriptingInterface::findEntitiesByName(const QString entityName, const glm::vec3& center, float radius, bool caseSensitiveSearch) const { QVector result; if (_entityTree) { _entityTree->withReadLock([&] { + unsigned int searchFilter = PickFilter::getBitMask(PickFilter::FlagBit::DOMAIN_ENTITIES) | PickFilter::getBitMask(PickFilter::FlagBit::AVATAR_ENTITIES); _entityTree->evalEntitiesInSphereWithName(center, radius, entityName, caseSensitiveSearch, PickFilter(searchFilter), result); }); } return result; } -RayToEntityIntersectionResult EntityScriptingInterface::evalRayIntersection(const PickRay& ray, unsigned int searchFilter, - const QScriptValue& entityIdsToInclude, const QScriptValue& entityIdsToDiscard) { +RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersection(const PickRay& ray, bool precisionPicking, + const QScriptValue& entityIdsToInclude, const QScriptValue& entityIdsToDiscard, bool visibleOnly, bool collidableOnly) const { PROFILE_RANGE(script_entities, __FUNCTION__); QVector entitiesToInclude = qVectorEntityItemIDFromScriptValue(entityIdsToInclude); QVector entitiesToDiscard = qVectorEntityItemIDFromScriptValue(entityIdsToDiscard); + unsigned int searchFilter = PickFilter::getBitMask(PickFilter::FlagBit::DOMAIN_ENTITIES) | PickFilter::getBitMask(PickFilter::FlagBit::AVATAR_ENTITIES); + + if (!precisionPicking) { + searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::COARSE); + } + + if (visibleOnly) { + searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::VISIBLE); + } + + if (collidableOnly) { + searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::COLLIDABLE); + } + return evalRayIntersectionWorker(ray, Octree::Lock, PickFilter(searchFilter), entitiesToInclude, entitiesToDiscard); } @@ -1187,7 +1207,7 @@ RayToEntityIntersectionResult EntityScriptingInterface::evalRayIntersectionVecto RayToEntityIntersectionResult EntityScriptingInterface::evalRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType, PickFilter searchFilter, const QVector& entityIdsToInclude, - const QVector& entityIdsToDiscard) { + const QVector& entityIdsToDiscard) const { RayToEntityIntersectionResult result; if (_entityTree) { @@ -1213,7 +1233,7 @@ ParabolaToEntityIntersectionResult EntityScriptingInterface::evalParabolaInterse ParabolaToEntityIntersectionResult EntityScriptingInterface::evalParabolaIntersectionWorker(const PickParabola& parabola, Octree::lockType lockType, PickFilter searchFilter, const QVector& entityIdsToInclude, - const QVector& entityIdsToDiscard) { + const QVector& entityIdsToDiscard) const { ParabolaToEntityIntersectionResult result; if (_entityTree) { diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 9b1dbfe330..e0447bd6b6 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -57,7 +57,7 @@ private: }; /**jsdoc - * The result of a {@link PickRay} search using {@link Entities.evalRayIntersection|evalRayIntersection}. + * The result of a {@link PickRay} search using {@link Entities.findRayIntersection|findRayIntersection}. * @typedef {object} Entities.RayToEntityIntersectionResult * @property {boolean} intersects - true if the {@link PickRay} intersected an entity, otherwise * false. @@ -393,21 +393,6 @@ public slots: Q_INVOKABLE void callEntityClientMethod(QUuid clientSessionID, QUuid entityID, const QString& method, const QStringList& params = QStringList()); - /**jsdoc - * Find the entity with a position closest to a specified point and within a specified radius that matches the search filter. - * @function Entities.evalClosestEntity - * @param {Vec3} center - The point about which to search. - * @param {number} radius - The radius within which to search. - * @param {number} searchFilter - The search filter, constructed using filter flags combined using bitwise OR. - * @returns {Uuid} The ID of the entity that is closest to the center and within the radius if - * there is one, otherwise null. - * @example Find the closest visible avatar entity within 10m of your avatar. - * var entityID = Entities.evalClosestEntity(MyAvatar.position, 10, Picks.PICK_AVATAR_ENTITIES | Picks.PICK_INCLUDE_VISIBLE); - * print("Closest visible avatar entity: " + entityID); - */ - /// this function will not find any models in script engine contexts which don't have access to models - Q_INVOKABLE QUuid evalClosestEntity(const glm::vec3& center, float radius, unsigned int searchFilter) const; - /**jsdoc * Find the non-local entity with a position closest to a specified point and within a specified radius. * @function Entities.findClosestEntity @@ -420,24 +405,7 @@ public slots: * print("Closest entity: " + entityID); */ /// this function will not find any models in script engine contexts which don't have access to models - Q_INVOKABLE QUuid findClosestEntity(const glm::vec3& center, float radius) const { - return evalClosestEntity(center, radius, PickFilter::getBitMask(PickFilter::FlagBit::DOMAIN_ENTITIES) | PickFilter::getBitMask(PickFilter::FlagBit::AVATAR_ENTITIES)); - } - - /**jsdoc - * Find all entities that intersect a sphere defined by a center point and radius that match the search filter. - * @function Entities.evalEntitiesInRadius - * @param {Vec3} center - The point about which to search. - * @param {number} radius - The radius within which to search. - * @param {number} searchFilter - The search filter, constructed using filter flags combined using bitwise OR. - * @returns {Uuid[]} An array of entity IDs that were found that intersect the search sphere. The array is empty if no - * entities could be found. - * @example Report how many visible domain entities are within 10m of your avatar. - * var entityIDs = Entities.evalEntitiesInRadius(MyAvatar.position, 10, Picks.PICK_DOMAIN_ENTITIES | Picks.PICK_INCLUDE_VISIBLE); - * print("Number of visible domain entities within 10m: " + entityIDs.length); - */ - /// this function will not find any models in script engine contexts which don't have access to models - Q_INVOKABLE QVector evalEntitiesInSphere(const glm::vec3& center, float radius, unsigned int searchFilter) const; + Q_INVOKABLE QUuid findClosestEntity(const glm::vec3& center, float radius) const; /**jsdoc * Find all non-local entities that intersect a sphere defined by a center point and radius. @@ -451,22 +419,7 @@ public slots: * print("Number of entities within 10m: " + entityIDs.length); */ /// this function will not find any models in script engine contexts which don't have access to models - Q_INVOKABLE QVector findEntities(const glm::vec3& center, float radius) const { - return evalEntitiesInSphere(center, radius, PickFilter::getBitMask(PickFilter::FlagBit::DOMAIN_ENTITIES) | PickFilter::getBitMask(PickFilter::FlagBit::AVATAR_ENTITIES)); - } - - /**jsdoc - * Find all entities whose axis-aligned boxes intersect a search axis-aligned box defined by its minimum coordinates corner - * and dimensions that match the search filter. - * @function Entities.evalEntitiesInBox - * @param {Vec3} corner - The corner of the search AA box with minimum co-ordinate values. - * @param {Vec3} dimensions - The dimensions of the search AA box. - * @param {number} searchFilter - The search filter, constructed using filter flags combined using bitwise OR. - * @returns {Uuid[]} An array of entity IDs whose AA boxes intersect the search AA box. The array is empty if no entities - * could be found. - */ - /// this function will not find any models in script engine contexts which don't have access to models - Q_INVOKABLE QVector evalEntitiesInBox(const glm::vec3& corner, const glm::vec3& dimensions, unsigned int searchFilter) const; + Q_INVOKABLE QVector findEntities(const glm::vec3& center, float radius) const; /**jsdoc * Find all non-local entities whose axis-aligned boxes intersect a search axis-aligned box defined by its minimum coordinates corner @@ -478,24 +431,7 @@ public slots: * could be found. */ /// this function will not find any models in script engine contexts which don't have access to models - Q_INVOKABLE QVector findEntitiesInBox(const glm::vec3& corner, const glm::vec3& dimensions) const { - return evalEntitiesInBox(corner, dimensions, PickFilter::getBitMask(PickFilter::FlagBit::DOMAIN_ENTITIES) | PickFilter::getBitMask(PickFilter::FlagBit::AVATAR_ENTITIES)); - } - - /**jsdoc - * Find all entities whose axis-aligned boxes intersect a search frustum that match the search filter. - * @function Entities.evalEntitiesInFrustum - * @param {ViewFrustum} frustum - The frustum to search in. The position, orientation, - * projection, and centerRadius properties must be specified. - * @param {number} searchFilter - The search filter, constructed using filter flags combined using bitwise OR. - * @returns {Uuid[]} An array of entity IDs axis-aligned boxes intersect the frustum. The array is empty if no entities - * could be found. - * @example Report the number of visible, collidable entities in view. - * var entityIDs = Entities.evalEntitiesInFrustum(Camera.frustum, Picks.PICK_INCLUDE_COLLIDABLE | Picks.PICK_INCLUDE_VISIBLE); - * print("Number of visible, collidable entities in view: " + entityIDs.length); - */ - /// this function will not find any models in script engine contexts which don't have access to entities - Q_INVOKABLE QVector evalEntitiesInFrustum(QVariantMap frustum, unsigned int searchFilter) const; + Q_INVOKABLE QVector findEntitiesInBox(const glm::vec3& corner, const glm::vec3& dimensions) const; /**jsdoc * Find all non-local entities whose axis-aligned boxes intersect a search frustum. @@ -509,25 +445,7 @@ public slots: * print("Number of entities in view: " + entityIDs.length); */ /// this function will not find any models in script engine contexts which don't have access to entities - Q_INVOKABLE QVector findEntitiesInFrustum(QVariantMap frustum) const { - return evalEntitiesInFrustum(frustum, PickFilter::getBitMask(PickFilter::FlagBit::DOMAIN_ENTITIES) | PickFilter::getBitMask(PickFilter::FlagBit::AVATAR_ENTITIES)); - } - - /**jsdoc - * Find all entities of a particular type that intersect a sphere defined by a center point and radius that match the search filter. - * @function Entities.evalEntitiesInRadiusWithType - * @param {Entities.EntityType} entityType - The type of entity to search for. - * @param {Vec3} center - The point about which to search. - * @param {number} radius - The radius within which to search. - * @param {number} searchFilter - The search filter, constructed using filter flags combined using bitwise OR. - * @returns {Uuid[]} An array of entity IDs of the specified type that intersect the search sphere. The array is empty if - * no entities could be found. - * @example Report the number of visible Model entities within 10m of your avatar. - * var entityIDs = Entities.evalEntitiesInRadiusWithType("Model", MyAvatar.position, 10, Picks.PICK_INCLUDE_VISIBLE); - * print("Number of visible Model entities within 10m: " + entityIDs.length); - */ - /// this function will not find any entities in script engine contexts which don't have access to entities - Q_INVOKABLE QVector evalEntitiesInSphereWithType(const QString entityType, const glm::vec3& center, float radius, unsigned int searchFilter) const; + Q_INVOKABLE QVector findEntitiesInFrustum(QVariantMap frustum) const; /**jsdoc * Find all non-local entities of a particular type that intersect a sphere defined by a center point and radius. @@ -542,26 +460,7 @@ public slots: * print("Number of Model entities within 10m: " + entityIDs.length); */ /// this function will not find any entities in script engine contexts which don't have access to entities - Q_INVOKABLE QVector findEntitiesByType(const QString entityType, const glm::vec3& center, float radius) const { - return evalEntitiesInSphereWithType(entityType, center, radius, PickFilter::getBitMask(PickFilter::FlagBit::DOMAIN_ENTITIES) | PickFilter::getBitMask(PickFilter::FlagBit::AVATAR_ENTITIES)); - } - - /**jsdoc - * Find all entities with a particular name that intersect a sphere defined by a center point and radius and match the search filter. - * @function Entities.findEntitiesByName - * @param {string} entityName - The name of the entity to search for. - * @param {Vec3} center - The point about which to search. - * @param {number} radius - The radius within which to search. - * @param {boolean} caseSensitive - If true then the search is case-sensitive. - * @param {number} searchFilter - The search filter, constructed using filter flags combined using bitwise OR. - * @returns {Uuid[]} An array of entity IDs that have the specified name and intersect the search sphere. The array is empty - * if no entities could be found. - * @example Report the number of collidable entities with the name, "Light-Target". - * var entityIDs = Entities.evalEntitiesInRadiusByName("Light-Target", MyAvatar.position, 10, false, Picks.PICK_INCLUDE_COLLIDABLE); - * print("Number of collidable entities with the name Light-Target: " + entityIDs.length); - */ - Q_INVOKABLE QVector evalEntitiesInSphereWithName(const QString entityName, const glm::vec3& center, float radius, - bool caseSensitiveSearch, unsigned int searchFilter) const; + Q_INVOKABLE QVector findEntitiesByType(const QString entityType, const glm::vec3& center, float radius) const; /**jsdoc * Find all non-local entities with a particular name that intersect a sphere defined by a center point and radius. @@ -577,38 +476,7 @@ public slots: * print("Number of entities with the name Light-Target: " + entityIDs.length); */ Q_INVOKABLE QVector findEntitiesByName(const QString entityName, const glm::vec3& center, float radius, - bool caseSensitiveSearch = false) const { - return evalEntitiesInSphereWithName(entityName, center, radius, caseSensitiveSearch, PickFilter::getBitMask(PickFilter::FlagBit::DOMAIN_ENTITIES) | PickFilter::getBitMask(PickFilter::FlagBit::AVATAR_ENTITIES)); - } - - /**jsdoc - * Find the first entity intersected by a {@link PickRay} that matches the search filter. Light and Zone entities are not - * intersected unless they've been configured as pickable using {@link Entities.setLightsArePickable|setLightsArePickable} - * and {@link Entities.setZonesArePickable|setZonesArePickable}, respectively.
- * @function Entities.evalRayIntersection - * @param {PickRay} pickRay - The PickRay to use for finding entities. - * @param {number} searchFilter - The search filter, constructed using filter flags combined using bitwise OR. - * @param {Uuid[]} [entitiesToInclude=[]] - If not empty then the search is restricted to these entities. - * @param {Uuid[]} [entitiesToDiscard=[]] - Entities to ignore during the search. - * @returns {Entities.RayToEntityIntersectionResult} The result of the search for the first intersected entity. - * @example Find the entity directly in front of your avatar. - * var pickRay = { - * origin: MyAvatar.position, - * direction: Quat.getFront(MyAvatar.orientation) - * }; - * - * var intersection = Entities.evalRayIntersection(pickRay, Picks.PICK_PRECISE); - * if (intersection.intersects) { - * print("Entity in front of avatar: " + intersection.entityID); - * } else { - * print("No entity in front of avatar."); - * } - */ - /// If the scripting context has visible entities, this will determine a ray intersection, the results - /// may be inaccurate if the engine is unable to access the visible entities, in which case result.accurate - /// will be false. - Q_INVOKABLE RayToEntityIntersectionResult evalRayIntersection(const PickRay& ray, unsigned int searchFilter, - const QScriptValue& entityIdsToInclude = QScriptValue(), const QScriptValue& entityIdsToDiscard = QScriptValue()); + bool caseSensitiveSearch = false) const; /**jsdoc * Find the first non-local entity intersected by a {@link PickRay}. Light and Zone entities are not @@ -643,23 +511,7 @@ public slots: /// will be false. Q_INVOKABLE RayToEntityIntersectionResult findRayIntersection(const PickRay& ray, bool precisionPicking = false, const QScriptValue& entityIdsToInclude = QScriptValue(), const QScriptValue& entityIdsToDiscard = QScriptValue(), - bool visibleOnly = false, bool collidableOnly = false) { - unsigned int searchFilter = PickFilter::getBitMask(PickFilter::FlagBit::DOMAIN_ENTITIES) | PickFilter::getBitMask(PickFilter::FlagBit::AVATAR_ENTITIES); - - if (!precisionPicking) { - searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::COARSE); - } - - if (visibleOnly) { - searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::VISIBLE); - } - - if (collidableOnly) { - searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::COLLIDABLE); - } - - return evalRayIntersection(ray, searchFilter, entityIdsToInclude, entityIdsToDiscard); - } + bool visibleOnly = false, bool collidableOnly = false) const; /**jsdoc * Reloads an entity's server entity script such that the latest version re-downloaded. @@ -724,7 +576,7 @@ public slots: /**jsdoc * Set whether or not ray picks intersect the bounding box of {@link Entities.EntityType|Light} entities. By default, Light * entities are not intersected. The setting lasts for the Interface session. Ray picks are done using - * {@link Entities.evalRayIntersection|evalRayIntersection}, or the {@link Picks} API. + * {@link Entities.findRayIntersection|findRayIntersection}, or the {@link Picks} API. * @function Entities.setLightsArePickable * @param {boolean} value - Set true to make ray picks intersect the bounding box of * {@link Entities.EntityType|Light} entities, otherwise false. @@ -734,7 +586,7 @@ public slots: /**jsdoc * Get whether or not ray picks intersect the bounding box of {@link Entities.EntityType|Light} entities. Ray picks are - * done using {@link Entities.evalRayIntersection|evalRayIntersection}, or the {@link Picks} API. + * done using {@link Entities.findRayIntersection|findRayIntersection}, or the {@link Picks} API. * @function Entities.getLightsArePickable * @returns {boolean} true if ray picks intersect the bounding box of {@link Entities.EntityType|Light} * entities, otherwise false. @@ -745,7 +597,7 @@ public slots: /**jsdoc * Set whether or not ray picks intersect the bounding box of {@link Entities.EntityType|Zone} entities. By default, Light * entities are not intersected. The setting lasts for the Interface session. Ray picks are done using - * {@link Entities.evalRayIntersection|evalRayIntersection}, or the {@link Picks} API. + * {@link Entities.findRayIntersection|findRayIntersection}, or the {@link Picks} API. * @function Entities.setZonesArePickable * @param {boolean} value - Set true to make ray picks intersect the bounding box of * {@link Entities.EntityType|Zone} entities, otherwise false. @@ -755,7 +607,7 @@ public slots: /**jsdoc * Get whether or not ray picks intersect the bounding box of {@link Entities.EntityType|Zone} entities. Ray picks are - * done using {@link Entities.evalRayIntersection|evalRayIntersection}, or the {@link Picks} API. + * done using {@link Entities.findRayIntersection|findRayIntersection}, or the {@link Picks} API. * @function Entities.getZonesArePickable * @returns {boolean} true if ray picks intersect the bounding box of {@link Entities.EntityType|Zone} * entities, otherwise false. @@ -2065,11 +1917,11 @@ private: /// actually does the work of finding the ray intersection, can be called in locking mode or tryLock mode RayToEntityIntersectionResult evalRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType, - PickFilter searchFilter, const QVector& entityIdsToInclude, const QVector& entityIdsToDiscard); + PickFilter searchFilter, const QVector& entityIdsToInclude, const QVector& entityIdsToDiscard) const; /// actually does the work of finding the parabola intersection, can be called in locking mode or tryLock mode ParabolaToEntityIntersectionResult evalParabolaIntersectionWorker(const PickParabola& parabola, Octree::lockType lockType, - PickFilter searchFilter, const QVector& entityIdsToInclude, const QVector& entityIdsToDiscard); + PickFilter searchFilter, const QVector& entityIdsToInclude, const QVector& entityIdsToDiscard) const; EntityTreePointer _entityTree;