mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
entity tags
This commit is contained in:
parent
78bc24cb22
commit
85f24f0951
17 changed files with 271 additions and 0 deletions
|
@ -104,6 +104,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param
|
|||
requestedProperties += PROP_IGNORE_PICK_INTERSECTION;
|
||||
requestedProperties += PROP_RENDER_WITH_ZONES;
|
||||
requestedProperties += PROP_BILLBOARD_MODE;
|
||||
requestedProperties += PROP_TAGS;
|
||||
requestedProperties += _grabProperties.getEntityProperties(params);
|
||||
|
||||
// Physics
|
||||
|
@ -301,6 +302,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
APPEND_ENTITY_PROPERTY(PROP_IGNORE_PICK_INTERSECTION, getIgnorePickIntersection());
|
||||
APPEND_ENTITY_PROPERTY(PROP_RENDER_WITH_ZONES, getRenderWithZones());
|
||||
APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)getBillboardMode());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TAGS, getTags());
|
||||
withReadLock([&] {
|
||||
_grabProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties,
|
||||
propertyFlags, propertiesDidntFit, propertyCount, appendState);
|
||||
|
@ -874,6 +876,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
READ_ENTITY_PROPERTY(PROP_IGNORE_PICK_INTERSECTION, bool, setIgnorePickIntersection);
|
||||
READ_ENTITY_PROPERTY(PROP_RENDER_WITH_ZONES, QVector<QUuid>, setRenderWithZones);
|
||||
READ_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode);
|
||||
READ_ENTITY_PROPERTY(PROP_TAGS, QSet<QString>, setTags);
|
||||
withWriteLock([&] {
|
||||
int bytesFromGrab = _grabProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
|
||||
propertyFlags, overwriteLocalData,
|
||||
|
@ -1358,6 +1361,7 @@ EntityItemProperties EntityItem::getProperties(const EntityPropertyFlags& desire
|
|||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(ignorePickIntersection, getIgnorePickIntersection);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(renderWithZones, getRenderWithZones);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(billboardMode, getBillboardMode);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(tags, getTags);
|
||||
withReadLock([&] {
|
||||
_grabProperties.getProperties(properties);
|
||||
});
|
||||
|
@ -1495,6 +1499,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(ignorePickIntersection, setIgnorePickIntersection);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(renderWithZones, setRenderWithZones);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(billboardMode, setBillboardMode);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(tags, setTags);
|
||||
withWriteLock([&] {
|
||||
bool grabPropertiesChanged = _grabProperties.setProperties(properties);
|
||||
somethingChanged |= grabPropertiesChanged;
|
||||
|
@ -3553,3 +3558,13 @@ void EntityItem::setBillboardMode(BillboardMode value) {
|
|||
_billboardMode = value;
|
||||
});
|
||||
}
|
||||
|
||||
void EntityItem::setTags(const QSet<QString>& tags) {
|
||||
withWriteLock([&] {
|
||||
_tags = tags;
|
||||
});
|
||||
}
|
||||
|
||||
QSet<QString> EntityItem::getTags() const {
|
||||
return resultWithReadLock<QSet<QString>>([&] { return _tags; });
|
||||
}
|
|
@ -559,6 +559,9 @@ public:
|
|||
BillboardMode getBillboardMode() const;
|
||||
virtual bool getRotateForPicking() const { return false; }
|
||||
|
||||
void setTags(const QSet<QString>& tags);
|
||||
QSet<QString> getTags() const;
|
||||
|
||||
signals:
|
||||
void spaceUpdate(std::pair<int32_t, glm::vec4> data);
|
||||
|
||||
|
@ -740,6 +743,8 @@ protected:
|
|||
|
||||
bool _cullWithParent { false };
|
||||
|
||||
QSet<QString> _tags;
|
||||
|
||||
mutable bool _needsRenderUpdate { false };
|
||||
};
|
||||
|
||||
|
|
|
@ -424,6 +424,21 @@ void EntityItemProperties::setEntityHostTypeFromString(const QString& entityHost
|
|||
}
|
||||
}
|
||||
|
||||
QVector<QString> EntityItemProperties::getTagsAsVector() const {
|
||||
QVector<QString> tags;
|
||||
for (const QString& tag : _tags) {
|
||||
tags.push_back(tag);
|
||||
}
|
||||
return tags;
|
||||
}
|
||||
|
||||
void EntityItemProperties::setTagsFromVector(const QVector<QString>& tags) {
|
||||
_tags.clear();
|
||||
for (const QString& tag : tags) {
|
||||
_tags.insert(tag);
|
||||
}
|
||||
}
|
||||
|
||||
EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
||||
EntityPropertyFlags changedProperties;
|
||||
|
||||
|
@ -454,6 +469,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
CHECK_PROPERTY_CHANGE(PROP_IGNORE_PICK_INTERSECTION, ignorePickIntersection);
|
||||
CHECK_PROPERTY_CHANGE(PROP_RENDER_WITH_ZONES, renderWithZones);
|
||||
CHECK_PROPERTY_CHANGE(PROP_BILLBOARD_MODE, billboardMode);
|
||||
CHECK_PROPERTY_CHANGE(PROP_TAGS, tags);
|
||||
changedProperties += _grab.getChangedProperties();
|
||||
|
||||
// Physics
|
||||
|
@ -822,6 +838,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
* one of the zones in this list.
|
||||
* @property {BillboardMode} billboardMode="none" - Whether the entity is billboarded to face the camera. Use the rotation
|
||||
* property to control which axis is facing you.
|
||||
* @property {string[]} tags=[] - A set of tags describing this entity.
|
||||
*
|
||||
* @property {Entities.Grab} grab - The entity's grab-related properties.
|
||||
*
|
||||
|
@ -1615,6 +1632,7 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IGNORE_PICK_INTERSECTION, ignorePickIntersection);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_RENDER_WITH_ZONES, renderWithZones);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BILLBOARD_MODE, billboardMode, getBillboardModeAsString());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_TAGS, tags, getTagsAsVector());
|
||||
_grab.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties);
|
||||
|
||||
// Physics
|
||||
|
@ -2031,6 +2049,7 @@ void EntityItemProperties::copyFromScriptValue(const ScriptValue& object, bool h
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE(ignorePickIntersection, bool, setIgnorePickIntersection);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(renderWithZones, qVectorQUuid, setRenderWithZones);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(billboardMode, BillboardMode);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(tags, qVectorQString, setTagsFromVector, getTagsAsVector);
|
||||
_grab.copyFromScriptValue(object, namesSet, _defaultSettings);
|
||||
|
||||
// Physics
|
||||
|
@ -2317,6 +2336,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) {
|
|||
COPY_PROPERTY_IF_CHANGED(ignorePickIntersection);
|
||||
COPY_PROPERTY_IF_CHANGED(renderWithZones);
|
||||
COPY_PROPERTY_IF_CHANGED(billboardMode);
|
||||
COPY_PROPERTY_IF_CHANGED(tags);
|
||||
_grab.merge(other._grab);
|
||||
|
||||
// Physics
|
||||
|
@ -2605,6 +2625,7 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr
|
|||
ADD_PROPERTY_TO_MAP(PROP_IGNORE_PICK_INTERSECTION, IgnorePickIntersection, ignorePickIntersection, bool);
|
||||
ADD_PROPERTY_TO_MAP(PROP_RENDER_WITH_ZONES, RenderWithZones, renderWithZones, QVector<QUuid>);
|
||||
ADD_PROPERTY_TO_MAP(PROP_BILLBOARD_MODE, BillboardMode, billboardMode, BillboardMode);
|
||||
ADD_PROPERTY_TO_MAP(PROP_TAGS, Tags, tags, QSet<QString>);
|
||||
{ // Grab
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_GRAB_GRABBABLE, Grab, grab, Grabbable, grabbable);
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_GRAB_KINEMATIC, Grab, grab, GrabKinematic, grabKinematic);
|
||||
|
@ -3087,6 +3108,7 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy
|
|||
APPEND_ENTITY_PROPERTY(PROP_IGNORE_PICK_INTERSECTION, properties.getIgnorePickIntersection());
|
||||
APPEND_ENTITY_PROPERTY(PROP_RENDER_WITH_ZONES, properties.getRenderWithZones());
|
||||
APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)properties.getBillboardMode());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TAGS, properties.getTags());
|
||||
_staticGrab.setProperties(properties);
|
||||
_staticGrab.appendToEditPacket(packetData, requestedProperties, propertyFlags,
|
||||
propertiesDidntFit, propertyCount, appendState);
|
||||
|
@ -3567,6 +3589,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IGNORE_PICK_INTERSECTION, bool, setIgnorePickIntersection);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RENDER_WITH_ZONES, QVector<QUuid>, setRenderWithZones);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TAGS, QSet<QString>, setTags);
|
||||
properties.getGrab().decodeFromEditPacket(propertyFlags, dataAt, processedBytes);
|
||||
|
||||
// Physics
|
||||
|
@ -3959,6 +3982,7 @@ void EntityItemProperties::markAllChanged() {
|
|||
_ignorePickIntersectionChanged = true;
|
||||
_renderWithZonesChanged = true;
|
||||
_billboardModeChanged = true;
|
||||
_tagsChanged = true;
|
||||
_grab.markAllChanged();
|
||||
|
||||
// Physics
|
||||
|
@ -4358,6 +4382,9 @@ QList<QString> EntityItemProperties::listChangedProperties() {
|
|||
if (billboardModeChanged()) {
|
||||
out += "billboardMode";
|
||||
}
|
||||
if (tagsChanged()) {
|
||||
out += "tags";
|
||||
}
|
||||
getGrab().listChangedProperties(out);
|
||||
|
||||
// Physics
|
||||
|
|
|
@ -203,6 +203,7 @@ public:
|
|||
DEFINE_PROPERTY(PROP_IGNORE_PICK_INTERSECTION, IgnorePickIntersection, ignorePickIntersection, bool, false);
|
||||
DEFINE_PROPERTY_REF(PROP_RENDER_WITH_ZONES, RenderWithZones, renderWithZones, QVector<QUuid>, QVector<QUuid>());
|
||||
DEFINE_PROPERTY_REF_ENUM(PROP_BILLBOARD_MODE, BillboardMode, billboardMode, BillboardMode, BillboardMode::NONE);
|
||||
DEFINE_PROPERTY_REF(PROP_TAGS, Tags, tags, QSet<QString>, QSet<QString>());
|
||||
DEFINE_PROPERTY_GROUP(Grab, grab, GrabPropertyGroup);
|
||||
|
||||
// Physics
|
||||
|
@ -498,6 +499,9 @@ protected:
|
|||
QString getCollisionMaskAsString() const;
|
||||
void setCollisionMaskFromString(const QString& maskString);
|
||||
|
||||
QVector<QString> getTagsAsVector() const;
|
||||
void setTagsFromVector(const QVector<QString>& tags);
|
||||
|
||||
private:
|
||||
QUuid _id;
|
||||
bool _idSet;
|
||||
|
|
|
@ -125,6 +125,7 @@ inline ScriptValue convertScriptValue(ScriptEngine* e, const QVector<glm::quat>&
|
|||
inline ScriptValue convertScriptValue(ScriptEngine* e, const QVector<bool>& v) {return qVectorBoolToScriptValue(e, v); }
|
||||
inline ScriptValue convertScriptValue(ScriptEngine* e, const QVector<float>& v) { return qVectorFloatToScriptValue(e, v); }
|
||||
inline ScriptValue convertScriptValue(ScriptEngine* e, const QVector<QUuid>& v) { return qVectorQUuidToScriptValue(e, v); }
|
||||
inline ScriptValue convertScriptValue(ScriptEngine* e, const QVector<QString>& v) { return qVectorQStringToScriptValue(e, v); }
|
||||
|
||||
inline ScriptValue convertScriptValue(ScriptEngine* e, const QRect& v) { return qRectToScriptValue(e, v); }
|
||||
|
||||
|
@ -223,6 +224,7 @@ typedef QVector<glm::quat> qVectorQuat;
|
|||
typedef QVector<bool> qVectorBool;
|
||||
typedef QVector<float> qVectorFloat;
|
||||
typedef QVector<QUuid> qVectorQUuid;
|
||||
typedef QVector<QString> qVectorQString;
|
||||
inline float float_convertFromScriptValue(const ScriptValue& v, bool& isValid) { return v.toVariant().toFloat(&isValid); }
|
||||
inline quint64 quint64_convertFromScriptValue(const ScriptValue& v, bool& isValid) { return v.toVariant().toULongLong(&isValid); }
|
||||
inline quint32 quint32_convertFromScriptValue(const ScriptValue& v, bool& isValid) {
|
||||
|
@ -305,6 +307,11 @@ inline qVectorQUuid qVectorQUuid_convertFromScriptValue(const ScriptValue& v, bo
|
|||
return qVectorQUuidFromScriptValue(v);
|
||||
}
|
||||
|
||||
inline qVectorQString qVectorQString_convertFromScriptValue(const ScriptValue& v, bool& isValid) {
|
||||
isValid = true;
|
||||
return qVectorQStringFromScriptValue(v);
|
||||
}
|
||||
|
||||
inline glm::quat quat_convertFromScriptValue(const ScriptValue& v, bool& isValid) {
|
||||
isValid = false; /// assume it can't be converted
|
||||
ScriptValue x = v.property("x");
|
||||
|
|
|
@ -46,6 +46,7 @@ enum EntityPropertyList {
|
|||
PROP_IGNORE_PICK_INTERSECTION,
|
||||
PROP_RENDER_WITH_ZONES,
|
||||
PROP_BILLBOARD_MODE,
|
||||
PROP_TAGS,
|
||||
// Grab
|
||||
PROP_GRAB_GRABBABLE,
|
||||
PROP_GRAB_KINEMATIC,
|
||||
|
|
|
@ -1457,6 +1457,17 @@ QVector<QUuid> EntityScriptingInterface::findEntitiesByName(const QString entity
|
|||
return result;
|
||||
}
|
||||
|
||||
QVector<QUuid> EntityScriptingInterface::findEntitiesByTags(const QVector<QString> entityTags, const glm::vec3& center, float radius, bool caseSensitiveSearch) const {
|
||||
QVector<QUuid> result;
|
||||
if (_entityTree) {
|
||||
_entityTree->withReadLock([&] {
|
||||
unsigned int searchFilter = PickFilter::getBitMask(PickFilter::FlagBit::DOMAIN_ENTITIES) | PickFilter::getBitMask(PickFilter::FlagBit::AVATAR_ENTITIES);
|
||||
_entityTree->evalEntitiesInSphereWithTags(center, radius, entityTags, caseSensitiveSearch, PickFilter(searchFilter), result);
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersection(const PickRay& ray, bool precisionPicking,
|
||||
const ScriptValue& entityIdsToInclude, const ScriptValue& entityIdsToDiscard, bool visibleOnly, bool collidableOnly) const {
|
||||
PROFILE_RANGE(script_entities, __FUNCTION__);
|
||||
|
|
|
@ -789,6 +789,25 @@ public slots:
|
|||
Q_INVOKABLE QVector<QUuid> findEntitiesByName(const QString entityName, const glm::vec3& center, float radius,
|
||||
bool caseSensitiveSearch = false) const;
|
||||
|
||||
/*@jsdoc
|
||||
* Finds all domain and avatar entities with particular tags that intersect a sphere.
|
||||
* <p><strong>Note:</strong> Server entity scripts only find entities that have a server entity script
|
||||
* running in them or a parent entity. You can apply a dummy script to entities that you want found in a search.</p>
|
||||
* @function Entities.findEntitiesByTags
|
||||
* @param {string[]} entityTags - The tags 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=false] - <code>true</code> if the search is case-sensitive, <code>false</code> if it is
|
||||
* case-insensitive.
|
||||
* @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 <caption>Report the number of entities with the tag, "Light-Target".</caption>
|
||||
* var entityIDs = Entities.findEntitiesByTags(["Light-Target"], MyAvatar.position, 10, false);
|
||||
* print("Number of entities with the tag Light-Target: " + entityIDs.length);
|
||||
*/
|
||||
Q_INVOKABLE QVector<QUuid> findEntitiesByTags(const QVector<QString> entityTags, const glm::vec3& center, float radius,
|
||||
bool caseSensitiveSearch = false) const;
|
||||
|
||||
/*@jsdoc
|
||||
* Finds the first avatar or domain entity intersected by a {@link PickRay}. <code>Light</code> and <code>Zone</code>
|
||||
* entities are not intersected unless they've been configured as pickable using
|
||||
|
|
|
@ -1110,6 +1110,42 @@ void EntityTree::evalEntitiesInSphereWithName(const glm::vec3& center, float rad
|
|||
foundEntities.swap(args.entities);
|
||||
}
|
||||
|
||||
class FindEntitiesInSphereWithTagsArgs {
|
||||
public:
|
||||
// Inputs
|
||||
glm::vec3 position;
|
||||
float targetRadius;
|
||||
QVector<QString> tags;
|
||||
bool caseSensitive;
|
||||
PickFilter searchFilter;
|
||||
|
||||
// Outputs
|
||||
QVector<QUuid> entities;
|
||||
};
|
||||
|
||||
bool evalInSphereWithTagsOperation(const OctreeElementPointer& element, void* extraData) {
|
||||
FindEntitiesInSphereWithTagsArgs* args = static_cast<FindEntitiesInSphereWithTagsArgs*>(extraData);
|
||||
glm::vec3 penetration;
|
||||
bool sphereIntersection = element->getAACube().findSpherePenetration(args->position, args->targetRadius, penetration);
|
||||
|
||||
// If this element contains the point, then search it...
|
||||
if (sphereIntersection) {
|
||||
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
|
||||
entityTreeElement->evalEntitiesInSphereWithTags(args->position, args->targetRadius, args->tags, args->caseSensitive, args->searchFilter, args->entities);
|
||||
return true; // keep searching in case children have closer entities
|
||||
}
|
||||
|
||||
// if this element doesn't contain the point, then none of it's children can contain the point, so stop searching
|
||||
return false;
|
||||
}
|
||||
|
||||
// NOTE: assumes caller has handled locking
|
||||
void EntityTree::evalEntitiesInSphereWithTags(const glm::vec3& center, float radius, const QVector<QString>& tags, bool caseSensitive, PickFilter searchFilter, QVector<QUuid>& foundEntities) {
|
||||
FindEntitiesInSphereWithTagsArgs args = { center, radius, tags, caseSensitive, searchFilter, QVector<QUuid>() };
|
||||
recurseTreeWithOperation(evalInSphereWithTagsOperation, &args);
|
||||
foundEntities.swap(args.entities);
|
||||
}
|
||||
|
||||
class FindEntitiesInCubeArgs {
|
||||
public:
|
||||
// Inputs
|
||||
|
|
|
@ -138,6 +138,7 @@ public:
|
|||
void evalEntitiesInSphere(const glm::vec3& center, float radius, PickFilter searchFilter, QVector<QUuid>& foundEntities);
|
||||
void evalEntitiesInSphereWithType(const glm::vec3& center, float radius, EntityTypes::EntityType type, PickFilter searchFilter, QVector<QUuid>& foundEntities);
|
||||
void evalEntitiesInSphereWithName(const glm::vec3& center, float radius, const QString& name, bool caseSensitive, PickFilter searchFilter, QVector<QUuid>& foundEntities);
|
||||
void evalEntitiesInSphereWithTags(const glm::vec3& center, float radius, const QVector<QString>& tags, bool caseSensitive, PickFilter searchFilter, QVector<QUuid>& foundEntities);
|
||||
void evalEntitiesInCube(const AACube& cube, PickFilter searchFilter, QVector<QUuid>& foundEntities);
|
||||
void evalEntitiesInBox(const AABox& box, PickFilter searchFilter, QVector<QUuid>& foundEntities);
|
||||
void evalEntitiesInFrustum(const ViewFrustum& frustum, PickFilter searchFilter, QVector<QUuid>& foundEntities);
|
||||
|
|
|
@ -602,6 +602,77 @@ void EntityTreeElement::evalEntitiesInSphereWithName(const glm::vec3& position,
|
|||
});
|
||||
}
|
||||
|
||||
void EntityTreeElement::evalEntitiesInSphereWithTags(const glm::vec3& position, float radius, const QVector<QString>& tags, bool caseSensitive, PickFilter searchFilter, QVector<QUuid>& foundEntities) const {
|
||||
forEachEntity([&](EntityItemPointer entity) {
|
||||
if (!checkFilterSettings(entity, searchFilter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
QSet<QString> entityTags = entity->getTags();
|
||||
for (const QString& tag : tags) {
|
||||
if (caseSensitive && !entityTags.contains(tag)) {
|
||||
return;
|
||||
} else {
|
||||
const QString lowerTag = tag.toLower();
|
||||
bool found = false;
|
||||
for (const QString& entityTag : entityTags) {
|
||||
if (lowerTag == entityTag.toLower()) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool success;
|
||||
AABox entityBox = entity->getAABox(success);
|
||||
|
||||
// if the sphere doesn't intersect with our world frame AABox, we don't need to consider the more complex case
|
||||
glm::vec3 penetration;
|
||||
if (success && entityBox.findSpherePenetration(position, radius, penetration)) {
|
||||
|
||||
glm::vec3 dimensions = entity->getScaledDimensions();
|
||||
|
||||
// FIXME - consider allowing the entity to determine penetration so that
|
||||
// entities could presumably do actual hull testing if they wanted to
|
||||
// FIXME - handle entity->getShapeType() == SHAPE_TYPE_SPHERE case better in particular
|
||||
// can we handle the ellipsoid case better? We only currently handle perfect spheres
|
||||
// with centered registration points
|
||||
if (entity->getShapeType() == SHAPE_TYPE_SPHERE && (dimensions.x == dimensions.y && dimensions.y == dimensions.z)) {
|
||||
|
||||
// NOTE: entity->getRadius() doesn't return the true radius, it returns the radius of the
|
||||
// maximum bounding sphere, which is actually larger than our actual radius
|
||||
float entityTrueRadius = dimensions.x / 2.0f;
|
||||
bool success;
|
||||
glm::vec3 center = entity->getCenterPosition(success);
|
||||
|
||||
if (success && findSphereSpherePenetration(position, radius, center, entityTrueRadius, penetration)) {
|
||||
foundEntities.push_back(entity->getID());
|
||||
}
|
||||
} else {
|
||||
// determine the worldToEntityMatrix that doesn't include scale because
|
||||
// we're going to use the registration aware aa box in the entity frame
|
||||
glm::mat4 translation = glm::translate(entity->getWorldPosition());
|
||||
glm::mat4 rotation = glm::mat4_cast(entity->getWorldOrientation());
|
||||
glm::mat4 entityToWorldMatrix = translation * rotation;
|
||||
glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix);
|
||||
|
||||
glm::vec3 registrationPoint = entity->getRegistrationPoint();
|
||||
glm::vec3 corner = -(dimensions * registrationPoint) + entity->getPivot();
|
||||
|
||||
AABox entityFrameBox(corner, dimensions);
|
||||
|
||||
glm::vec3 entityFrameSearchPosition = glm::vec3(worldToEntityMatrix * glm::vec4(position, 1.0f));
|
||||
if (entityFrameBox.findSpherePenetration(entityFrameSearchPosition, radius, penetration)) {
|
||||
foundEntities.push_back(entity->getID());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void EntityTreeElement::evalEntitiesInCube(const AACube& cube, PickFilter searchFilter, QVector<QUuid>& foundEntities) const {
|
||||
forEachEntity([&](EntityItemPointer entity) {
|
||||
if (!checkFilterSettings(entity, searchFilter)) {
|
||||
|
|
|
@ -177,6 +177,7 @@ public:
|
|||
void evalEntitiesInSphere(const glm::vec3& position, float radius, PickFilter searchFilter, QVector<QUuid>& foundEntities) const;
|
||||
void evalEntitiesInSphereWithType(const glm::vec3& position, float radius, EntityTypes::EntityType type, PickFilter searchFilter, QVector<QUuid>& foundEntities) const;
|
||||
void evalEntitiesInSphereWithName(const glm::vec3& position, float radius, const QString& name, bool caseSensitive, PickFilter searchFilter, QVector<QUuid>& foundEntities) const;
|
||||
void evalEntitiesInSphereWithTags(const glm::vec3& position, float radius, const QVector<QString>& tags, bool caseSensitive, PickFilter searchFilter, QVector<QUuid>& foundEntities) const;
|
||||
void evalEntitiesInCube(const AACube& cube, PickFilter searchFilter, QVector<QUuid>& foundEntities) const;
|
||||
void evalEntitiesInBox(const AABox& box, PickFilter searchFilter, QVector<QUuid>& foundEntities) const;
|
||||
void evalEntitiesInFrustum(const ViewFrustum& frustum, PickFilter searchFilter, QVector<QUuid>& foundEntities) const;
|
||||
|
|
|
@ -290,6 +290,7 @@ enum class EntityVersion : PacketVersion {
|
|||
UserAgent,
|
||||
AllBillboardMode,
|
||||
TextAlignment,
|
||||
EntityTags,
|
||||
|
||||
// Add new versions above here
|
||||
NUM_PACKET_TYPE,
|
||||
|
|
|
@ -496,6 +496,24 @@ bool OctreePacketData::appendValue(const QVector<QUuid>& value) {
|
|||
return success;
|
||||
}
|
||||
|
||||
bool OctreePacketData::appendValue(const QSet<QString>& value) {
|
||||
QVector<QString> valueVector;
|
||||
for (const QString& valueString : value) {
|
||||
valueVector.push_back(valueString);
|
||||
}
|
||||
|
||||
uint16_t qVecSize = value.size();
|
||||
bool success = appendValue(qVecSize);
|
||||
if (success) {
|
||||
success = append((const unsigned char*)valueVector.constData(), qVecSize * sizeof(QString));
|
||||
if (success) {
|
||||
_bytesOfValues += qVecSize * sizeof(QString);
|
||||
_totalBytesOfValues += qVecSize * sizeof(QString);
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool OctreePacketData::appendValue(const glm::quat& value) {
|
||||
const size_t VALUES_PER_QUAT = 4;
|
||||
const size_t PACKED_QUAT_SIZE = sizeof(uint16_t) * VALUES_PER_QUAT;
|
||||
|
@ -802,6 +820,23 @@ int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QVecto
|
|||
return sizeof(uint16_t) + length * sizeof(QUuid);
|
||||
}
|
||||
|
||||
int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QSet<QString>& result) {
|
||||
QVector<QString> resultVector;
|
||||
|
||||
uint16_t length;
|
||||
memcpy(&length, dataBytes, sizeof(uint16_t));
|
||||
dataBytes += sizeof(length);
|
||||
resultVector.resize(length);
|
||||
memcpy(resultVector.data(), dataBytes, length * sizeof(QString));
|
||||
|
||||
result.clear();
|
||||
for (const QString& resultString : resultVector) {
|
||||
result.insert(resultString);
|
||||
}
|
||||
|
||||
return sizeof(uint16_t) + length * sizeof(QString);
|
||||
}
|
||||
|
||||
int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QByteArray& result) {
|
||||
uint16_t length;
|
||||
memcpy(&length, dataBytes, sizeof(length));
|
||||
|
|
|
@ -190,6 +190,9 @@ public:
|
|||
/// appends a QVector of QUuids to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||
bool appendValue(const QVector<QUuid>& value);
|
||||
|
||||
/// appends a QSet of QStrings to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||
bool appendValue(const QSet<QString>& value);
|
||||
|
||||
/// appends a packed quat to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||
bool appendValue(const glm::quat& value);
|
||||
|
||||
|
@ -290,6 +293,7 @@ public:
|
|||
static int unpackDataFromBytes(const unsigned char* dataBytes, QVector<float>& result);
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, QVector<bool>& result);
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, QVector<QUuid>& result);
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, QSet<QString>& result);
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, QByteArray& result);
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, AACube& result);
|
||||
static int unpackDataFromBytes(const unsigned char* dataBytes, QRect& result);
|
||||
|
|
|
@ -862,6 +862,14 @@ bool quuidFromScriptValue(const ScriptValue& object, QUuid& uuid) {
|
|||
return true;
|
||||
}
|
||||
|
||||
ScriptValue qStringToScriptValue(ScriptEngine* engine, const QString& string) {
|
||||
if (string.isNull()) {
|
||||
return engine->nullValue();
|
||||
}
|
||||
ScriptValue obj(engine->newValue(string));
|
||||
return obj;
|
||||
}
|
||||
|
||||
/*@jsdoc
|
||||
* A 2D size value.
|
||||
* @typedef {object} Size
|
||||
|
@ -1029,3 +1037,25 @@ QVector<EntityItemID> qVectorEntityItemIDFromScriptValue(const ScriptValue& arra
|
|||
}
|
||||
return newVector;
|
||||
}
|
||||
|
||||
ScriptValue qVectorQStringToScriptValue(ScriptEngine* engine, const QVector<QString>& vector) {
|
||||
ScriptValue array = engine->newArray();
|
||||
for (int i = 0; i < vector.size(); i++) {
|
||||
array.setProperty(i, qStringToScriptValue(engine, vector.at(i)));
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
QVector<QString> qVectorQStringFromScriptValue(const ScriptValue& array) {
|
||||
if (!array.isArray()) {
|
||||
return QVector<QString>();
|
||||
}
|
||||
QVector<QString> newVector;
|
||||
int length = array.property("length").toInteger();
|
||||
newVector.reserve(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
QString string = array.property(i).toString();
|
||||
newVector << string;
|
||||
}
|
||||
return newVector;
|
||||
}
|
|
@ -224,6 +224,9 @@ ScriptValue qVectorQUuidToScriptValue(ScriptEngine* engine, const QVector<QUuid>
|
|||
bool qVectorQUuidFromScriptValue(const ScriptValue& array, QVector<QUuid>& vector);
|
||||
QVector<QUuid> qVectorQUuidFromScriptValue(const ScriptValue& array);
|
||||
|
||||
ScriptValue qVectorQStringToScriptValue(ScriptEngine* engine, const QVector<QString>& vector);
|
||||
QVector<QString> qVectorQStringFromScriptValue(const ScriptValue& array);
|
||||
|
||||
class AACube;
|
||||
ScriptValue aaCubeToScriptValue(ScriptEngine* engine, const AACube& aaCube);
|
||||
bool aaCubeFromScriptValue(const ScriptValue& object, AACube& aaCube);
|
||||
|
|
Loading…
Reference in a new issue