Merge pull request #10079 from jherico/entity_thread_safety

Thread safety for property getter/setters on entities
This commit is contained in:
Brad Hefta-Gaub 2017-04-07 19:01:07 -07:00 committed by GitHub
commit 0d4649ded8
22 changed files with 1242 additions and 329 deletions

View file

@ -277,10 +277,11 @@ bool RenderableModelEntityItem::getAnimationFrame() {
return false;
}
if (_animation && _animation->isLoaded()) {
auto animation = getAnimation();
if (animation && animation->isLoaded()) {
const QVector<FBXAnimationFrame>& frames = _animation->getFramesReference(); // NOTE: getFrames() is too heavy
auto& fbxJoints = _animation->getGeometry().joints;
const QVector<FBXAnimationFrame>& frames = animation->getFramesReference(); // NOTE: getFrames() is too heavy
auto& fbxJoints = animation->getGeometry().joints;
int frameCount = frames.size();
if (frameCount > 0) {
@ -566,7 +567,7 @@ void RenderableModelEntityItem::update(const quint64& now) {
}
// make a copy of the animation properites
_renderAnimationProperties = _animationProperties;
_renderAnimationProperties = getAnimationProperties();
ModelEntityItem::update(now);
}
@ -608,11 +609,11 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori
void RenderableModelEntityItem::setShapeType(ShapeType type) {
ModelEntityItem::setShapeType(type);
if (_shapeType == SHAPE_TYPE_COMPOUND) {
if (!_compoundShapeResource && !_compoundShapeURL.isEmpty()) {
if (getShapeType() == SHAPE_TYPE_COMPOUND) {
if (!_compoundShapeResource && !getCompoundShapeURL().isEmpty()) {
_compoundShapeResource = DependencyManager::get<ModelCache>()->getGeometryResource(getCompoundShapeURL());
}
} else if (_compoundShapeResource && !_compoundShapeURL.isEmpty()) {
} else if (_compoundShapeResource && !getCompoundShapeURL().isEmpty()) {
// the compoundURL has been set but the shapeType does not agree
_compoundShapeResource.reset();
}
@ -627,7 +628,7 @@ void RenderableModelEntityItem::setCompoundShapeURL(const QString& url) {
if (tree) {
QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID()));
}
if (_shapeType == SHAPE_TYPE_COMPOUND) {
if (getShapeType() == SHAPE_TYPE_COMPOUND) {
_compoundShapeResource = DependencyManager::get<ModelCache>()->getGeometryResource(url);
}
}
@ -637,7 +638,7 @@ bool RenderableModelEntityItem::isReadyToComputeShape() {
ShapeType type = getShapeType();
if (type == SHAPE_TYPE_COMPOUND) {
if (!_model || _compoundShapeURL.isEmpty()) {
if (!_model || getCompoundShapeURL().isEmpty()) {
EntityTreePointer tree = getTree();
if (tree) {
QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID()));
@ -659,8 +660,8 @@ bool RenderableModelEntityItem::isReadyToComputeShape() {
doInitialModelSimulation();
}
return true;
} else if (!_compoundShapeURL.isEmpty()) {
_compoundShapeResource = DependencyManager::get<ModelCache>()->getGeometryResource(_compoundShapeURL);
} else if (!getCompoundShapeURL().isEmpty()) {
_compoundShapeResource = DependencyManager::get<ModelCache>()->getGeometryResource(getCompoundShapeURL());
}
}
@ -775,7 +776,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
pointCollection[i][j] = scaleToFit * (pointCollection[i][j] + _model->getOffset()) - registrationOffset;
}
}
shapeInfo.setParams(type, dimensions, _compoundShapeURL);
shapeInfo.setParams(type, dimensions, getCompoundShapeURL());
} else if (type >= SHAPE_TYPE_SIMPLE_HULL && type <= SHAPE_TYPE_STATIC_MESH) {
// should never fall in here when model not fully loaded
assert(_model && _model->isLoaded());
@ -1001,7 +1002,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
}
}
shapeInfo.setParams(type, 0.5f * dimensions, _modelURL);
shapeInfo.setParams(type, 0.5f * dimensions, getModelURL());
} else {
ModelEntityItem::computeShapeInfo(shapeInfo);
shapeInfo.setParams(type, 0.5f * dimensions);

View file

@ -660,22 +660,22 @@ void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) {
});
}
void RenderablePolyVoxEntityItem::setXTextureURL(QString xTextureURL) {
if (xTextureURL != _xTextureURL) {
void RenderablePolyVoxEntityItem::setXTextureURL(const QString& xTextureURL) {
if (xTextureURL != getXTextureURL()) {
_xTexture.clear();
PolyVoxEntityItem::setXTextureURL(xTextureURL);
}
}
void RenderablePolyVoxEntityItem::setYTextureURL(QString yTextureURL) {
if (yTextureURL != _yTextureURL) {
void RenderablePolyVoxEntityItem::setYTextureURL(const QString& yTextureURL) {
if (yTextureURL != getYTextureURL()) {
_yTexture.clear();
PolyVoxEntityItem::setYTextureURL(yTextureURL);
}
}
void RenderablePolyVoxEntityItem::setZTextureURL(QString zTextureURL) {
if (zTextureURL != _zTextureURL) {
void RenderablePolyVoxEntityItem::setZTextureURL(const QString& zTextureURL) {
if (zTextureURL != getZTextureURL()) {
_zTexture.clear();
PolyVoxEntityItem::setZTextureURL(zTextureURL);
}

View file

@ -101,9 +101,9 @@ public:
virtual bool setAll(uint8_t toValue) override;
virtual bool setCuboid(const glm::vec3& lowPosition, const glm::vec3& cuboidSize, int toValue) override;
virtual void setXTextureURL(QString xTextureURL) override;
virtual void setYTextureURL(QString yTextureURL) override;
virtual void setZTextureURL(QString zTextureURL) override;
virtual void setXTextureURL(const QString& xTextureURL) override;
virtual void setYTextureURL(const QString& yTextureURL) override;
virtual void setZTextureURL(const QString& zTextureURL) override;
virtual bool addToScene(EntityItemPointer self,
std::shared_ptr<render::Scene> scene,

View file

@ -77,14 +77,16 @@ void RenderableTextEntityItem::render(RenderArgs* args) {
geometryCache->bindSimpleProgram(batch, false, transparent, false, false, true);
geometryCache->renderQuad(batch, minCorner, maxCorner, backgroundColor, _geometryID);
float scale = _lineHeight / _textRenderer->getFontSize();
float lineheight = getLineHeight();
float scale = lineheight / _textRenderer->getFontSize();
transformToTopLeft.setScale(scale); // Scale to have the correct line height
batch.setModelTransform(transformToTopLeft);
float leftMargin = 0.1f * _lineHeight, topMargin = 0.1f * _lineHeight;
float leftMargin = 0.1f * lineheight, topMargin = 0.1f * lineheight;
glm::vec2 bounds = glm::vec2(dimensions.x - 2.0f * leftMargin,
dimensions.y - 2.0f * topMargin);
_textRenderer->draw(batch, leftMargin / scale, -topMargin / scale, _text, textColor, bounds / scale);
auto text = getText();
_textRenderer->draw(batch, leftMargin / scale, -topMargin / scale, text, textColor, bounds / scale);
}

View file

@ -683,7 +683,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
// However, for now, when the server uses a newer time than what we sent, listen to what we're told.
if (overwriteLocalData) weOwnSimulation = false;
} else if (_simulationOwner.set(newSimOwner)) {
_dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID;
markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
somethingChanged = true;
// recompute weOwnSimulation for later
weOwnSimulation = _simulationOwner.matchesValidID(myNodeID);
@ -695,19 +695,19 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
weOwnSimulation = true;
if (!_simulationOwner.isNull()) {
// someone else really did own it
_dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID;
markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
somethingChanged = true;
_simulationOwner.clearCurrentOwner();
}
} else if (newSimOwner.matchesValidID(myNodeID) && !_hasBidOnSimulation) {
// entity-server tells us that we have simulation ownership while we never requested this for this EntityItem,
// this could happen when the user reloads the cache and entity tree.
_dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID;
markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
somethingChanged = true;
_simulationOwner.clearCurrentOwner();
weOwnSimulation = false;
} else if (_simulationOwner.set(newSimOwner)) {
_dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID;
markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
somethingChanged = true;
// recompute weOwnSimulation for later
weOwnSimulation = _simulationOwner.matchesValidID(myNodeID);
@ -909,19 +909,23 @@ void EntityItem::adjustEditPacketForClockSkew(QByteArray& buffer, qint64 clockSk
float EntityItem::computeMass() const {
glm::vec3 dimensions = getDimensions();
return _density * _volumeMultiplier * dimensions.x * dimensions.y * dimensions.z;
return getDensity() * _volumeMultiplier * dimensions.x * dimensions.y * dimensions.z;
}
void EntityItem::setDensity(float density) {
_density = glm::max(glm::min(density, ENTITY_ITEM_MAX_DENSITY), ENTITY_ITEM_MIN_DENSITY);
withWriteLock([&] {
_density = glm::max(glm::min(density, ENTITY_ITEM_MAX_DENSITY), ENTITY_ITEM_MIN_DENSITY);
});
}
void EntityItem::updateDensity(float density) {
float clampedDensity = glm::max(glm::min(density, ENTITY_ITEM_MAX_DENSITY), ENTITY_ITEM_MIN_DENSITY);
if (_density != clampedDensity) {
_density = clampedDensity;
_dirtyFlags |= Simulation::DIRTY_MASS;
}
withWriteLock([&] {
if (_density != clampedDensity) {
_density = clampedDensity;
_dirtyFlags |= Simulation::DIRTY_MASS;
}
});
}
void EntityItem::setMass(float mass) {
@ -941,10 +945,12 @@ void EntityItem::setMass(float mass) {
} else {
newDensity = glm::max(glm::min(mass / volume, ENTITY_ITEM_MAX_DENSITY), ENTITY_ITEM_MIN_DENSITY);
}
if (_density != newDensity) {
_density = newDensity;
_dirtyFlags |= Simulation::DIRTY_MASS;
}
withWriteLock([&] {
if (_density != newDensity) {
_density = newDensity;
_dirtyFlags |= Simulation::DIRTY_MASS;
}
});
}
void EntityItem::setHref(QString value) {
@ -952,32 +958,47 @@ void EntityItem::setHref(QString value) {
if (! (value.toLower().startsWith("hifi://")) ) {
return;
}
_href = value;
withWriteLock([&] {
_href = value;
});
}
void EntityItem::setCollisionSoundURL(const QString& value) {
if (_collisionSoundURL != value) {
_collisionSoundURL = value;
bool modified = false;
withWriteLock([&] {
if (_collisionSoundURL != value) {
_collisionSoundURL = value;
modified = true;
}
});
if (modified) {
if (auto myTree = getTree()) {
myTree->notifyNewCollisionSoundURL(_collisionSoundURL, getEntityItemID());
myTree->notifyNewCollisionSoundURL(value, getEntityItemID());
}
}
}
SharedSoundPointer EntityItem::getCollisionSound() {
if (!_collisionSound) {
_collisionSound = DependencyManager::get<SoundCache>()->getSound(_collisionSoundURL);
SharedSoundPointer result;
withReadLock([&] {
result = _collisionSound;
});
if (!result) {
result = DependencyManager::get<SoundCache>()->getSound(_collisionSoundURL);
withWriteLock([&] {
_collisionSound = result;
});
}
return _collisionSound;
return result;
}
void EntityItem::simulate(const quint64& now) {
if (_lastSimulated == 0) {
_lastSimulated = now;
if (getLastSimulated() == 0) {
setLastSimulated(now);
}
float timeElapsed = (float)(now - _lastSimulated) / (float)(USECS_PER_SECOND);
float timeElapsed = (float)(now - getLastSimulated()) / (float)(USECS_PER_SECOND);
#ifdef WANT_DEBUG
qCDebug(entities) << "********** EntityItem::simulate()";
@ -1021,10 +1042,10 @@ void EntityItem::simulate(const quint64& now) {
if (!stepKinematicMotion(timeElapsed)) {
// this entity is no longer moving
// flag it to transition from KINEMATIC to STATIC
_dirtyFlags |= Simulation::DIRTY_MOTION_TYPE;
markDirtyFlags(Simulation::DIRTY_MOTION_TYPE);
setAcceleration(Vectors::ZERO);
}
_lastSimulated = now;
setLastSimulated(now);
}
bool EntityItem::stepKinematicMotion(float timeElapsed) {
@ -1056,9 +1077,10 @@ bool EntityItem::stepKinematicMotion(float timeElapsed) {
timeElapsed = glm::min(timeElapsed, MAX_TIME_ELAPSED);
if (isSpinning) {
float angularDamping = getAngularDamping();
// angular damping
if (_angularDamping > 0.0f) {
angularVelocity *= powf(1.0f - _angularDamping, timeElapsed);
if (angularDamping > 0.0f) {
angularVelocity *= powf(1.0f - angularDamping, timeElapsed);
}
const float MIN_KINEMATIC_ANGULAR_SPEED_SQUARED =
@ -1086,15 +1108,17 @@ bool EntityItem::stepKinematicMotion(float timeElapsed) {
glm::vec3 deltaVelocity = Vectors::ZERO;
// linear damping
if (_damping > 0.0f) {
deltaVelocity = (powf(1.0f - _damping, timeElapsed) - 1.0f) * linearVelocity;
float damping = getDamping();
if (damping > 0.0f) {
deltaVelocity = (powf(1.0f - damping, timeElapsed) - 1.0f) * linearVelocity;
}
const float MIN_KINEMATIC_LINEAR_ACCELERATION_SQUARED = 1.0e-4f; // 0.01 m/sec^2
if (glm::length2(_acceleration) > MIN_KINEMATIC_LINEAR_ACCELERATION_SQUARED) {
vec3 acceleration = getAcceleration();
if (glm::length2(acceleration) > MIN_KINEMATIC_LINEAR_ACCELERATION_SQUARED) {
// yes acceleration
// acceleration is in world-frame but we need it in local-frame
glm::vec3 linearAcceleration = _acceleration;
glm::vec3 linearAcceleration = acceleration;
bool success;
Transform parentTransform = getParentTransform(success);
if (success) {
@ -1180,7 +1204,7 @@ bool EntityItem::lifetimeHasExpired() const {
}
quint64 EntityItem::getExpiry() const {
return _created + (quint64)(_lifetime * (float)USECS_PER_SECOND);
return getCreated() + (quint64)(getLifetime() * (float)USECS_PER_SECOND);
}
EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
@ -1189,10 +1213,10 @@ EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProper
EntityItemProperties properties(propertyFlags);
properties._id = getID();
properties._idSet = true;
properties._created = _created;
properties._lastEdited = _lastEdited;
properties.setClientOnly(_clientOnly);
properties.setOwningAvatarID(_owningAvatarID);
properties._created = getCreated();
properties._lastEdited = getLastEdited();
properties.setClientOnly(getClientOnly());
properties.setOwningAvatarID(getOwningAvatarID());
properties._type = getType();
@ -1259,7 +1283,7 @@ void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) c
properties._angularVelocity = getLocalAngularVelocity();
}
if (!properties._accelerationChanged) {
properties._acceleration = _acceleration;
properties._acceleration = getAcceleration();
}
properties._positionChanged = true;
@ -1270,7 +1294,7 @@ void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) c
}
void EntityItem::pokeSimulationOwnership() {
_dirtyFlags |= Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_POKE;
markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_POKE);
auto nodeList = DependencyManager::get<NodeList>();
if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) {
// we already own it
@ -1282,7 +1306,7 @@ void EntityItem::pokeSimulationOwnership() {
}
void EntityItem::grabSimulationOwnership() {
_dirtyFlags |= Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB;
markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB);
auto nodeList = DependencyManager::get<NodeList>();
if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) {
// we already own it
@ -1575,18 +1599,18 @@ float EntityItem::getVolumeEstimate() const {
void EntityItem::updateRegistrationPoint(const glm::vec3& value) {
if (value != _registrationPoint) {
setRegistrationPoint(value);
_dirtyFlags |= Simulation::DIRTY_SHAPE;
markDirtyFlags(Simulation::DIRTY_SHAPE);
}
}
void EntityItem::updatePosition(const glm::vec3& value) {
if (getLocalPosition() != value) {
setLocalPosition(value);
_dirtyFlags |= Simulation::DIRTY_POSITION;
markDirtyFlags(Simulation::DIRTY_POSITION);
forEachDescendant([&](SpatiallyNestablePointer object) {
if (object->getNestableType() == NestableType::Entity) {
EntityItemPointer entity = std::static_pointer_cast<EntityItem>(object);
entity->_dirtyFlags |= Simulation::DIRTY_POSITION;
entity->markDirtyFlags(Simulation::DIRTY_POSITION);
}
});
}
@ -1595,8 +1619,9 @@ void EntityItem::updatePosition(const glm::vec3& value) {
void EntityItem::updateParentID(const QUuid& value) {
if (getParentID() != value) {
setParentID(value);
_dirtyFlags |= Simulation::DIRTY_MOTION_TYPE; // children are forced to be kinematic
_dirtyFlags |= Simulation::DIRTY_COLLISION_GROUP; // may need to not collide with own avatar
// children are forced to be kinematic
// may need to not collide with own avatar
markDirtyFlags(Simulation::DIRTY_MOTION_TYPE | Simulation::DIRTY_COLLISION_GROUP);
}
}
@ -1610,7 +1635,7 @@ void EntityItem::updatePositionFromNetwork(const glm::vec3& value) {
void EntityItem::updateDimensions(const glm::vec3& value) {
if (getDimensions() != value) {
setDimensions(value);
_dirtyFlags |= (Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS);
markDirtyFlags(Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS);
}
}
@ -1621,8 +1646,7 @@ void EntityItem::updateRotation(const glm::quat& rotation) {
forEachDescendant([&](SpatiallyNestablePointer object) {
if (object->getNestableType() == NestableType::Entity) {
EntityItemPointer entity = std::static_pointer_cast<EntityItem>(object);
entity->_dirtyFlags |= Simulation::DIRTY_ROTATION;
entity->_dirtyFlags |= Simulation::DIRTY_POSITION;
entity->markDirtyFlags(Simulation::DIRTY_ROTATION | Simulation::DIRTY_POSITION);
}
});
}
@ -1777,20 +1801,26 @@ void EntityItem::updateRestitution(float value) {
void EntityItem::updateFriction(float value) {
float clampedValue = glm::max(glm::min(ENTITY_ITEM_MAX_FRICTION, value), ENTITY_ITEM_MIN_FRICTION);
if (_friction != clampedValue) {
_friction = clampedValue;
_dirtyFlags |= Simulation::DIRTY_MATERIAL;
}
withWriteLock([&] {
if (_friction != clampedValue) {
_friction = clampedValue;
_dirtyFlags |= Simulation::DIRTY_MATERIAL;
}
});
}
void EntityItem::setRestitution(float value) {
float clampedValue = glm::max(glm::min(ENTITY_ITEM_MAX_RESTITUTION, value), ENTITY_ITEM_MIN_RESTITUTION);
_restitution = clampedValue;
withWriteLock([&] {
_restitution = clampedValue;
});
}
void EntityItem::setFriction(float value) {
float clampedValue = glm::max(glm::min(ENTITY_ITEM_MAX_FRICTION, value), ENTITY_ITEM_MIN_FRICTION);
_friction = clampedValue;
withWriteLock([&] {
_friction = clampedValue;
});
}
void EntityItem::updateLifetime(float value) {
@ -1883,7 +1913,7 @@ void EntityItem::updateSimulationOwner(const SimulationOwner& owner) {
}
if (_simulationOwner.set(owner)) {
_dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID;
markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
}
}
@ -1896,7 +1926,7 @@ void EntityItem::clearSimulationOwnership() {
// don't bother setting the DIRTY_SIMULATOR_ID flag because:
// (a) when entity-server calls clearSimulationOwnership() the dirty-flags are meaningless (only used by interface)
// (b) the interface only calls clearSimulationOwnership() in a context that already knows best about dirty flags
//_dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID;
//markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
}
@ -2103,7 +2133,7 @@ void EntityItem::deserializeActionsInternal() {
static QString repeatedMessage =
LogHandler::getInstance().addRepeatedMessageRegex(".*action creation failed for.*");
qCDebug(entities) << "EntityItem::deserializeActionsInternal -- action creation failed for"
<< getID() << getName();
<< getID() << _name; // getName();
removeActionInternal(actionID, nullptr);
}
}
@ -2327,3 +2357,443 @@ bool EntityItem::matchesJSONFilters(const QJsonObject& jsonFilters) const {
// the json filter syntax did not match what we expected, return a match
return true;
}
quint64 EntityItem::getLastSimulated() const {
quint64 result;
withReadLock([&] {
result = _lastSimulated;
});
return result;
}
void EntityItem::setLastSimulated(quint64 now) {
withWriteLock([&] {
_lastSimulated = now;
});
}
quint64 EntityItem::getLastEdited() const {
quint64 result;
withReadLock([&] {
result = _lastEdited;
});
return result;
}
void EntityItem::setLastEdited(quint64 lastEdited) {
withWriteLock([&] {
_lastEdited = _lastUpdated = lastEdited;
_changedOnServer = glm::max(lastEdited, _changedOnServer);
});
}
quint64 EntityItem::getLastBroadcast() const {
quint64 result;
withReadLock([&] {
result = _lastBroadcast;
});
return result;
}
void EntityItem::setLastBroadcast(quint64 lastBroadcast) {
withWriteLock([&] {
_lastBroadcast = lastBroadcast;
});
}
void EntityItem::markAsChangedOnServer() {
withWriteLock([&] {
_changedOnServer = usecTimestampNow();
});
}
quint64 EntityItem::getLastChangedOnServer() const {
quint64 result;
withReadLock([&] {
result = _changedOnServer;
});
return result;
}
void EntityItem::update(const quint64& now) {
withWriteLock([&] {
_lastUpdated = now;
});
}
quint64 EntityItem::getLastUpdated() const {
quint64 result;
withReadLock([&] {
result = _lastUpdated;
});
return result;
}
void EntityItem::requiresRecalcBoxes() {
withWriteLock([&] {
_recalcAABox = true;
_recalcMinAACube = true;
_recalcMaxAACube = true;
});
}
QString EntityItem::getHref() const {
QString result;
withReadLock([&] {
result = _href;
});
return result;
}
QString EntityItem::getDescription() const {
QString result;
withReadLock([&] {
result = _description;
});
return result;
}
void EntityItem::setDescription(const QString& value) {
withWriteLock([&] {
_description = value;
});
}
float EntityItem::getLocalRenderAlpha() const {
float result;
withReadLock([&] {
result = _localRenderAlpha;
});
return result;
}
void EntityItem::setLocalRenderAlpha(float localRenderAlpha) {
withWriteLock([&] {
_localRenderAlpha = localRenderAlpha;
});
}
glm::vec3 EntityItem::getGravity() const {
glm::vec3 result;
withReadLock([&] {
result = _gravity;
});
return result;
}
void EntityItem::setGravity(const glm::vec3& value) {
withWriteLock([&] {
_gravity = value;
});
}
glm::vec3 EntityItem::getAcceleration() const {
glm::vec3 result;
withReadLock([&] {
result = _acceleration;
});
return result;
}
void EntityItem::setAcceleration(const glm::vec3& value) {
withWriteLock([&] {
_acceleration = value;
});
}
float EntityItem::getDamping() const {
float result;
withReadLock([&] {
result = _damping;
});
return result;
}
void EntityItem::setDamping(float value) {
withWriteLock([&] {
_damping = value;
});
}
float EntityItem::getRestitution() const {
float result;
withReadLock([&] {
result = _restitution;
});
return result;
}
float EntityItem::getFriction() const {
float result;
withReadLock([&] {
result = _friction;
});
return result;
}
// lifetime related properties.
float EntityItem::getLifetime() const {
float result;
withReadLock([&] {
result = _lifetime;
});
return result;
}
void EntityItem::setLifetime(float value) {
withWriteLock([&] {
_lifetime = value;
});
}
quint64 EntityItem::getCreated() const {
quint64 result;
withReadLock([&] {
result = _created;
});
return result;
}
void EntityItem::setCreated(quint64 value) {
withWriteLock([&] {
_created = value;
});
}
QString EntityItem::getScript() const {
QString result;
withReadLock([&] {
result = _script;
});
return result;
}
void EntityItem::setScript(const QString& value) {
withWriteLock([&] {
_script = value;
});
}
quint64 EntityItem::getScriptTimestamp() const {
quint64 result;
withReadLock([&] {
result = _scriptTimestamp;
});
return result;
}
void EntityItem::setScriptTimestamp(const quint64 value) {
withWriteLock([&] {
_scriptTimestamp = value;
});
}
QString EntityItem::getServerScripts() const {
QString result;
withReadLock([&] {
result = _serverScripts;
});
return result;
}
void EntityItem::setServerScripts(const QString& serverScripts) {
withWriteLock([&] {
_serverScripts = serverScripts;
_serverScriptsChangedTimestamp = usecTimestampNow();
});
}
QString EntityItem::getCollisionSoundURL() const {
QString result;
withReadLock([&] {
result = _collisionSoundURL;
});
return result;
}
void EntityItem::setCollisionSound(SharedSoundPointer sound) {
withWriteLock([&] {
_collisionSound = sound;
});
}
glm::vec3 EntityItem::getRegistrationPoint() const {
glm::vec3 result;
withReadLock([&] {
result = _registrationPoint;
});
return result;
}
void EntityItem::setRegistrationPoint(const glm::vec3& value) {
withWriteLock([&] {
_registrationPoint = glm::clamp(value, 0.0f, 1.0f);
});
dimensionsChanged(); // Registration Point affects the bounding box
}
float EntityItem::getAngularDamping() const {
float result;
withReadLock([&] {
result = _angularDamping;
});
return result;
}
void EntityItem::setAngularDamping(float value) {
withWriteLock([&] {
_angularDamping = value;
});
}
QString EntityItem::getName() const {
QString result;
withReadLock([&] {
result = _name;
});
return result;
}
void EntityItem::setName(const QString& value) {
withWriteLock([&] {
_name = value;
});
}
QString EntityItem::getDebugName() {
QString result = getName();
if (result.isEmpty()) {
result = getID().toString();
}
return result;
}
bool EntityItem::getVisible() const {
bool result;
withReadLock([&] {
result = _visible;
});
return result;
}
void EntityItem::setVisible(bool value) {
withWriteLock([&] {
_visible = value;
});
}
bool EntityItem::getCollisionless() const {
bool result;
withReadLock([&] {
result = _collisionless;
});
return result;
}
void EntityItem::setCollisionless(bool value) {
withWriteLock([&] {
_collisionless = value;
});
}
uint8_t EntityItem::getCollisionMask() const {
uint8_t result;
withReadLock([&] {
result = _collisionMask;
});
return result;
}
void EntityItem::setCollisionMask(uint8_t value) {
withWriteLock([&] {
_collisionMask = value;
});
}
bool EntityItem::getDynamic() const {
if (SHAPE_TYPE_STATIC_MESH == getShapeType()) {
return false;
}
bool result;
withReadLock([&] {
result = _dynamic;
});
return result;
}
void EntityItem::setDynamic(bool value) {
withWriteLock([&] {
_dynamic = value;
});
}
bool EntityItem::getLocked() const {
bool result;
withReadLock([&] {
result = _locked;
});
return result;
}
void EntityItem::setLocked(bool value) {
withWriteLock([&] {
_locked = value;
});
}
QString EntityItem::getUserData() const {
QString result;
withReadLock([&] {
result = _userData;
});
return result;
}
void EntityItem::setUserData(const QString& value) {
withWriteLock([&] {
_userData = value;
});
}
QString EntityItem::getMarketplaceID() const {
QString result;
withReadLock([&] {
result = _marketplaceID;
});
return result;
}
void EntityItem::setMarketplaceID(const QString& value) {
withWriteLock([&] {
_marketplaceID = value;
});
}
uint32_t EntityItem::getDirtyFlags() const {
uint32_t result;
withReadLock([&] {
result = _dirtyFlags;
});
return result;
}
void EntityItem::markDirtyFlags(uint32_t mask) {
withWriteLock([&] {
_dirtyFlags |= mask;
});
}
void EntityItem::clearDirtyFlags(uint32_t mask) {
withWriteLock([&] {
_dirtyFlags &= ~mask;
});
}
float EntityItem::getDensity() const {
float result;
withReadLock([&] {
result = _density;
});
return result;
}

View file

@ -110,22 +110,21 @@ public:
virtual void somethingChangedNotification() { }
void recordCreationTime(); // set _created to 'now'
quint64 getLastSimulated() const { return _lastSimulated; } /// Last simulated time of this entity universal usecs
void setLastSimulated(quint64 now) { _lastSimulated = now; }
quint64 getLastSimulated() const; /// Last simulated time of this entity universal usecs
void setLastSimulated(quint64 now);
/// Last edited time of this entity universal usecs
quint64 getLastEdited() const { return _lastEdited; }
void setLastEdited(quint64 lastEdited)
{ _lastEdited = _lastUpdated = lastEdited; _changedOnServer = glm::max(lastEdited, _changedOnServer); }
quint64 getLastEdited() const;
void setLastEdited(quint64 lastEdited);
float getEditedAgo() const /// Elapsed seconds since this entity was last edited
{ return (float)(usecTimestampNow() - getLastEdited()) / (float)USECS_PER_SECOND; }
/// Last time we sent out an edit packet for this entity
quint64 getLastBroadcast() const { return _lastBroadcast; }
void setLastBroadcast(quint64 lastBroadcast) { _lastBroadcast = lastBroadcast; }
quint64 getLastBroadcast() const;
void setLastBroadcast(quint64 lastBroadcast);
void markAsChangedOnServer() { _changedOnServer = usecTimestampNow(); }
quint64 getLastChangedOnServer() const { return _changedOnServer; }
void markAsChangedOnServer();
quint64 getLastChangedOnServer() const;
// TODO: eventually only include properties changed since the params.lastQuerySent time
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const;
@ -163,8 +162,8 @@ public:
static void adjustEditPacketForClockSkew(QByteArray& buffer, qint64 clockSkew);
// perform update
virtual void update(const quint64& now) { _lastUpdated = now; }
quint64 getLastUpdated() const { return _lastUpdated; }
virtual void update(const quint64& now);
quint64 getLastUpdated() const;
// perform linear extrapolation for SimpleEntitySimulation
void simulate(const quint64& now);
@ -188,63 +187,63 @@ public:
const Transform getTransformToCenter(bool& success) const;
inline void requiresRecalcBoxes() { _recalcAABox = true; _recalcMinAACube = true; _recalcMaxAACube = true; }
inline void requiresRecalcBoxes();
// Hyperlink related getters and setters
QString getHref() const { return _href; }
QString getHref() const;
void setHref(QString value);
QString getDescription() const { return _description; }
void setDescription(QString value) { _description = value; }
QString getDescription() const;
void setDescription(const QString& value);
/// Dimensions in meters (0.0 - TREE_SCALE)
inline const glm::vec3 getDimensions() const { return getScale(); }
virtual void setDimensions(const glm::vec3& value);
float getLocalRenderAlpha() const { return _localRenderAlpha; }
void setLocalRenderAlpha(float localRenderAlpha) { _localRenderAlpha = localRenderAlpha; }
float getLocalRenderAlpha() const;
void setLocalRenderAlpha(float localRenderAlpha);
void setDensity(float density);
float computeMass() const;
void setMass(float mass);
float getDensity() const { return _density; }
float getDensity() const;
bool hasVelocity() const { return getVelocity() != ENTITY_ITEM_ZERO_VEC3; }
bool hasLocalVelocity() const { return getLocalVelocity() != ENTITY_ITEM_ZERO_VEC3; }
const glm::vec3& getGravity() const { return _gravity; } /// get gravity in meters
void setGravity(const glm::vec3& value) { _gravity = value; } /// gravity in meters
bool hasGravity() const { return _gravity != ENTITY_ITEM_ZERO_VEC3; }
glm::vec3 getGravity() const; /// get gravity in meters
void setGravity(const glm::vec3& value); /// gravity in meters
bool hasGravity() const { return getGravity() != ENTITY_ITEM_ZERO_VEC3; }
const glm::vec3& getAcceleration() const { return _acceleration; } /// get acceleration in meters/second/second
void setAcceleration(const glm::vec3& value) { _acceleration = value; } /// acceleration in meters/second/second
bool hasAcceleration() const { return _acceleration != ENTITY_ITEM_ZERO_VEC3; }
glm::vec3 getAcceleration() const; /// get acceleration in meters/second/second
void setAcceleration(const glm::vec3& value); /// acceleration in meters/second/second
bool hasAcceleration() const { return getAcceleration() != ENTITY_ITEM_ZERO_VEC3; }
float getDamping() const { return _damping; }
void setDamping(float value) { _damping = value; }
float getDamping() const;
void setDamping(float value);
float getRestitution() const { return _restitution; }
float getRestitution() const;
void setRestitution(float value);
float getFriction() const { return _friction; }
float getFriction() const;
void setFriction(float value);
// lifetime related properties.
float getLifetime() const { return _lifetime; } /// get the lifetime in seconds for the entity
void setLifetime(float value) { _lifetime = value; } /// set the lifetime in seconds for the entity
float getLifetime() const; /// get the lifetime in seconds for the entity
void setLifetime(float value); /// set the lifetime in seconds for the entity
quint64 getCreated() const { return _created; } /// get the created-time in useconds for the entity
void setCreated(quint64 value) { _created = value; } /// set the created-time in useconds for the entity
quint64 getCreated() const; /// get the created-time in useconds for the entity
void setCreated(quint64 value); /// set the created-time in useconds for the entity
/// is this entity immortal, in that it has no lifetime set, and will exist until manually deleted
bool isImmortal() const { return _lifetime == ENTITY_ITEM_IMMORTAL_LIFETIME; }
bool isImmortal() const { return getLifetime() == ENTITY_ITEM_IMMORTAL_LIFETIME; }
/// is this entity mortal, in that it has a lifetime set, and will automatically be deleted when that lifetime expires
bool isMortal() const { return _lifetime != ENTITY_ITEM_IMMORTAL_LIFETIME; }
bool isMortal() const { return getLifetime() != ENTITY_ITEM_IMMORTAL_LIFETIME; }
/// age of this entity in seconds
float getAge() const { return (float)(usecTimestampNow() - _created) / (float)USECS_PER_SECOND; }
float getAge() const { return (float)(usecTimestampNow() - getCreated()) / (float)USECS_PER_SECOND; }
bool lifetimeHasExpired() const;
quint64 getExpiry() const;
@ -256,63 +255,61 @@ public:
using SpatiallyNestable::getQueryAACube;
virtual AACube getQueryAACube(bool& success) const override;
QString getScript() const { return _script; }
void setScript(const QString& value) { _script = value; }
QString getScript() const;
void setScript(const QString& value);
quint64 getScriptTimestamp() const { return _scriptTimestamp; }
void setScriptTimestamp(const quint64 value) { _scriptTimestamp = value; }
quint64 getScriptTimestamp() const;
void setScriptTimestamp(const quint64 value);
QString getServerScripts() const { return _serverScripts; }
void setServerScripts(const QString& serverScripts)
{ _serverScripts = serverScripts; _serverScriptsChangedTimestamp = usecTimestampNow(); }
QString getServerScripts() const;
void setServerScripts(const QString& serverScripts);
const QString& getCollisionSoundURL() const { return _collisionSoundURL; }
QString getCollisionSoundURL() const;
void setCollisionSoundURL(const QString& value);
SharedSoundPointer getCollisionSound();
void setCollisionSound(SharedSoundPointer sound) { _collisionSound = sound; }
void setCollisionSound(SharedSoundPointer sound);
const glm::vec3& getRegistrationPoint() const { return _registrationPoint; } /// registration point as ratio of entity
glm::vec3 getRegistrationPoint() const; /// registration point as ratio of entity
/// registration point as ratio of entity
void setRegistrationPoint(const glm::vec3& value) {
_registrationPoint = glm::clamp(value, 0.0f, 1.0f); dimensionsChanged(); // Registration Point affects the bounding box
}
void setRegistrationPoint(const glm::vec3& value);
bool hasAngularVelocity() const { return getAngularVelocity() != ENTITY_ITEM_ZERO_VEC3; }
bool hasLocalAngularVelocity() const { return getLocalAngularVelocity() != ENTITY_ITEM_ZERO_VEC3; }
float getAngularDamping() const { return _angularDamping; }
void setAngularDamping(float value) { _angularDamping = value; }
float getAngularDamping() const;
void setAngularDamping(float value);
QString getName() const { return _name; }
void setName(const QString& value) { _name = value; }
QString getDebugName() { return _name != "" ? _name : getID().toString(); }
QString getName() const;
void setName(const QString& value);
QString getDebugName();
bool getVisible() const { return _visible; }
void setVisible(bool value) { _visible = value; }
bool isVisible() const { return _visible; }
bool isInvisible() const { return !_visible; }
bool getVisible() const;
void setVisible(bool value);
inline bool isVisible() const { return getVisible(); }
inline bool isInvisible() const { return !getVisible(); }
bool getCollisionless() const { return _collisionless; }
void setCollisionless(bool value) { _collisionless = value; }
bool getCollisionless() const;
void setCollisionless(bool value);
uint8_t getCollisionMask() const { return _collisionMask; }
void setCollisionMask(uint8_t value) { _collisionMask = value; }
uint8_t getCollisionMask() const;
void setCollisionMask(uint8_t value);
void computeCollisionGroupAndFinalMask(int16_t& group, int16_t& mask) const;
bool getDynamic() const { return SHAPE_TYPE_STATIC_MESH == getShapeType() ? false : _dynamic; }
void setDynamic(bool value) { _dynamic = value; }
bool getDynamic() const;
void setDynamic(bool value);
virtual bool shouldBePhysical() const { return false; }
bool getLocked() const { return _locked; }
void setLocked(bool value) { _locked = value; }
bool getLocked() const;
void setLocked(bool value);
const QString& getUserData() const { return _userData; }
virtual void setUserData(const QString& value) { _userData = value; }
QString getUserData() const;
virtual void setUserData(const QString& value);
// FIXME not thread safe?
const SimulationOwner& getSimulationOwner() const { return _simulationOwner; }
void setSimulationOwner(const QUuid& id, quint8 priority);
void setSimulationOwner(const SimulationOwner& owner);
@ -325,8 +322,8 @@ public:
void setPendingOwnershipPriority(quint8 priority, const quint64& timestamp);
void rememberHasSimulationOwnershipBid() const;
const QString& getMarketplaceID() const { return _marketplaceID; }
void setMarketplaceID(const QString& value) { _marketplaceID = value; }
QString getMarketplaceID() const;
void setMarketplaceID(const QString& value);
// TODO: get rid of users of getRadius()...
float getRadius() const;
@ -369,8 +366,9 @@ public:
void updateCreated(uint64_t value);
virtual void setShapeType(ShapeType type) { /* do nothing */ }
uint32_t getDirtyFlags() const { return _dirtyFlags; }
void clearDirtyFlags(uint32_t mask = 0xffffffff) { _dirtyFlags &= ~mask; }
uint32_t getDirtyFlags() const;
void markDirtyFlags(uint32_t mask);
void clearDirtyFlags(uint32_t mask = 0xffffffff);
bool isMoving() const;
bool isMovingRelativeToParent() const;

View file

@ -69,38 +69,59 @@ EntityItemProperties LightEntityItem::getProperties(EntityPropertyFlags desiredP
}
void LightEntityItem::setFalloffRadius(float value) {
_falloffRadius = glm::max(value, 0.0f);
_lightPropertiesChanged = true;
value = glm::max(value, 0.0f);
if (value == getFalloffRadius()) {
return;
}
withWriteLock([&] {
_falloffRadius = value;
_lightPropertiesChanged = true;
});
}
void LightEntityItem::setIsSpotlight(bool value) {
if (value != _isSpotlight) {
_isSpotlight = value;
glm::vec3 dimensions = getDimensions();
if (_isSpotlight) {
const float length = dimensions.z;
const float width = length * glm::sin(glm::radians(_cutoff));
setDimensions(glm::vec3(width, width, length));
} else {
float maxDimension = glm::compMax(dimensions);
setDimensions(glm::vec3(maxDimension, maxDimension, maxDimension));
}
_lightPropertiesChanged = true;
if (value == getIsSpotlight()) {
return;
}
glm::vec3 dimensions = getDimensions();
glm::vec3 newDimensions;
if (value) {
const float length = dimensions.z;
const float width = length * glm::sin(glm::radians(getCutoff()));
newDimensions = glm::vec3(width, width, length);
} else {
newDimensions = glm::vec3(glm::compMax(dimensions));
}
withWriteLock([&] {
_isSpotlight = value;
_lightPropertiesChanged = true;
});
setDimensions(newDimensions);
}
void LightEntityItem::setCutoff(float value) {
_cutoff = glm::clamp(value, 0.0f, 90.0f);
value = glm::clamp(value, 0.0f, 90.0f);
if (value == getCutoff()) {
return;
}
if (_isSpotlight) {
withWriteLock([&] {
_cutoff = value;
});
if (getIsSpotlight()) {
// If we are a spotlight, adjusting the cutoff will affect the area we encapsulate,
// so update the dimensions to reflect this.
const float length = getDimensions().z;
const float width = length * glm::sin(glm::radians(_cutoff));
setDimensions(glm::vec3(width, width, length));
}
_lightPropertiesChanged = true;
withWriteLock([&] {
_lightPropertiesChanged = true;
});
}
bool LightEntityItem::setProperties(const EntityItemProperties& properties) {
@ -205,5 +226,86 @@ void LightEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit
void LightEntityItem::somethingChangedNotification() {
EntityItem::somethingChangedNotification();
_lightPropertiesChanged = false;
withWriteLock([&] {
_lightPropertiesChanged = false;
});
}
const rgbColor& LightEntityItem::getColor() const {
return _color;
}
xColor LightEntityItem::getXColor() const {
xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color;
}
void LightEntityItem::setColor(const rgbColor& value) {
withWriteLock([&] {
memcpy(_color, value, sizeof(_color));
_lightPropertiesChanged = true;
});
}
void LightEntityItem::setColor(const xColor& value) {
withWriteLock([&] {
_color[RED_INDEX] = value.red;
_color[GREEN_INDEX] = value.green;
_color[BLUE_INDEX] = value.blue;
_lightPropertiesChanged = true;
});
}
bool LightEntityItem::getIsSpotlight() const {
bool result;
withReadLock([&] {
result = _isSpotlight;
});
return result;
}
float LightEntityItem::getIntensity() const {
float result;
withReadLock([&] {
result = _intensity;
});
return result;
}
void LightEntityItem::setIntensity(float value) {
withWriteLock([&] {
_intensity = value;
_lightPropertiesChanged = true;
});
}
float LightEntityItem::getFalloffRadius() const {
float result;
withReadLock([&] {
result = _falloffRadius;
});
return result;
}
float LightEntityItem::getExponent() const {
float result;
withReadLock([&] {
result = _exponent;
});
return result;
}
void LightEntityItem::setExponent(float value) {
withWriteLock([&] {
_exponent = value;
_lightPropertiesChanged = true;
});
}
float LightEntityItem::getCutoff() const {
float result;
withReadLock([&] {
result = _cutoff;
});
return result;
}

View file

@ -57,47 +57,33 @@ public:
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) override;
const rgbColor& getColor() const { return _color; }
xColor getXColor() const {
xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color;
}
const rgbColor& getColor() const;
xColor getXColor() const;
void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); }
void setColor(const xColor& value) {
_color[RED_INDEX] = value.red;
_color[GREEN_INDEX] = value.green;
_color[BLUE_INDEX] = value.blue;
_lightPropertiesChanged = true;
}
void setColor(const rgbColor& value);
void setColor(const xColor& value);
bool getIsSpotlight() const { return _isSpotlight; }
bool getIsSpotlight() const;
void setIsSpotlight(bool value);
void setIgnoredColor(const rgbColor& value) { }
void setIgnoredAttenuation(float value) { }
float getIntensity() const { return _intensity; }
void setIntensity(float value) {
_intensity = value;
_lightPropertiesChanged = true;
}
float getFalloffRadius() const { return _falloffRadius; }
float getIntensity() const;
void setIntensity(float value);
float getFalloffRadius() const;
void setFalloffRadius(float value);
float getExponent() const { return _exponent; }
void setExponent(float value) {
_exponent = value;
_lightPropertiesChanged = true;
}
float getExponent() const;
void setExponent(float value);
float getCutoff() const { return _cutoff; }
float getCutoff() const;
void setCutoff(float value);
static bool getLightsArePickable() { return _lightsArePickable; }
static void setLightsArePickable(bool value) { _lightsArePickable = value; }
protected:
private:
// properties of a light
@ -108,6 +94,7 @@ protected:
float _exponent { DEFAULT_EXPONENT };
float _cutoff { DEFAULT_CUTOFF };
protected:
// Dirty flag turn true when either light properties is changing values.
// This gets back to false in the somethingChangedNotification() call
// Which is called after a setProperties() or a readEntitySubClassFromBUfferCall on the entity.

View file

@ -34,8 +34,8 @@ EntityItemPointer LineEntityItem::factory(const EntityItemID& entityID, const En
LineEntityItem::LineEntityItem(const EntityItemID& entityItemID) :
EntityItem(entityItemID),
_lineWidth(DEFAULT_LINE_WIDTH),
_pointsChanged(true),
_points(QVector<glm::vec3>(0))
_points(QVector<glm::vec3>(0)),
_pointsChanged(true)
{
_type = EntityTypes::Line;
}
@ -88,8 +88,10 @@ bool LineEntityItem::appendPoint(const glm::vec3& point) {
qCDebug(entities) << "Point is outside entity's bounding box";
return false;
}
_points << point;
_pointsChanged = true;
withWriteLock([&] {
_points << point;
_pointsChanged = true;
});
return true;
}
@ -105,8 +107,11 @@ bool LineEntityItem::setLinePoints(const QVector<glm::vec3>& points) {
return false;
}
}
_points = points;
_pointsChanged = true;
withWriteLock([&] {
_points = points;
_pointsChanged = true;
});
return true;
}
@ -159,3 +164,51 @@ void LineEntityItem::debugDump() const {
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
}
const rgbColor& LineEntityItem::getColor() const {
return _color;
}
xColor LineEntityItem::getXColor() const {
xColor result;
withReadLock([&] {
result = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] };
});
return result;
}
void LineEntityItem::setColor(const rgbColor& value) {
withWriteLock([&] {
memcpy(_color, value, sizeof(_color));
});
}
void LineEntityItem::setColor(const xColor& value) {
withWriteLock([&] {
_color[RED_INDEX] = value.red;
_color[GREEN_INDEX] = value.green;
_color[BLUE_INDEX] = value.blue;
});
}
void LineEntityItem::setLineWidth(float lineWidth) {
withWriteLock([&] {
_lineWidth = lineWidth;
});
}
float LineEntityItem::getLineWidth() const {
float result;
withReadLock([&] {
result = _lineWidth;
});
return result;
}
QVector<glm::vec3> LineEntityItem::getLinePoints() const {
QVector<glm::vec3> result;
withReadLock([&] {
result = _points;
});
return result;
}

View file

@ -42,23 +42,19 @@ class LineEntityItem : public EntityItem {
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) override;
const rgbColor& getColor() const { return _color; }
xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; }
const rgbColor& getColor() const;
xColor getXColor() const;
void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); }
void setColor(const xColor& value) {
_color[RED_INDEX] = value.red;
_color[GREEN_INDEX] = value.green;
_color[BLUE_INDEX] = value.blue;
}
void setColor(const rgbColor& value);
void setColor(const xColor& value);
void setLineWidth(float lineWidth){ _lineWidth = lineWidth; }
float getLineWidth() const{ return _lineWidth; }
void setLineWidth(float lineWidth);
float getLineWidth() const;
bool setLinePoints(const QVector<glm::vec3>& points);
bool appendPoint(const glm::vec3& point);
const QVector<glm::vec3>& getLinePoints() const{ return _points; }
QVector<glm::vec3> getLinePoints() const;
virtual ShapeType getShapeType() const override { return SHAPE_TYPE_NONE; }
@ -74,11 +70,12 @@ class LineEntityItem : public EntityItem {
static const float DEFAULT_LINE_WIDTH;
static const int MAX_POINTS_PER_LINE;
protected:
private:
rgbColor _color;
float _lineWidth;
bool _pointsChanged;
QVector<glm::vec3> _points;
protected:
bool _pointsChanged;
};
#endif // hifi_LineEntityItem_h

View file

@ -733,3 +733,20 @@ void ParticleEffectEntityItem::setMaxParticles(quint32 maxParticles) {
_timeUntilNextEmit = 0.0f;
}
}
QString ParticleEffectEntityItem::getTextures() const {
QString result;
withReadLock([&] {
result = _textures;
});
return result;
}
void ParticleEffectEntityItem::setTextures(const QString& textures) {
withWriteLock([&] {
if (_textures != textures) {
_textures = textures;
_texturesChangedFlag = true;
}
});
}

View file

@ -205,13 +205,8 @@ public:
void computeAndUpdateDimensions();
static const QString DEFAULT_TEXTURES;
const QString& getTextures() const { return _textures; }
void setTextures(const QString& textures) {
if (_textures != textures) {
_textures = textures;
_texturesChangedFlag = true;
}
}
QString getTextures() const;
void setTextures(const QString& textures);
static const bool DEFAULT_EMITTER_SHOULD_TRAIL;
bool getEmitterShouldTrail() const { return _emitterShouldTrail; }

View file

@ -104,14 +104,18 @@ bool PolyLineEntityItem::appendPoint(const glm::vec3& point) {
bool PolyLineEntityItem::setStrokeWidths(const QVector<float>& strokeWidths) {
_strokeWidths = strokeWidths;
_strokeWidthsChanged = true;
withWriteLock([&] {
_strokeWidths = strokeWidths;
_strokeWidthsChanged = true;
});
return true;
}
bool PolyLineEntityItem::setNormals(const QVector<glm::vec3>& normals) {
_normals = normals;
_normalsChanged = true;
withWriteLock([&] {
_normals = normals;
_normalsChanged = true;
});
return true;
}
@ -119,35 +123,39 @@ bool PolyLineEntityItem::setLinePoints(const QVector<glm::vec3>& points) {
if (points.size() > MAX_POINTS_PER_LINE) {
return false;
}
if (points.size() != _points.size()) {
_pointsChanged = true;
}
//Check to see if points actually changed. If they haven't, return before doing anything else
else if (points.size() == _points.size()) {
//same number of points, so now compare every point
for (int i = 0; i < points.size(); i++) {
if (points.at(i) != _points.at(i)){
_pointsChanged = true;
break;
bool result = false;
withWriteLock([&] {
//Check to see if points actually changed. If they haven't, return before doing anything else
if (points.size() != _points.size()) {
_pointsChanged = true;
} else if (points.size() == _points.size()) {
//same number of points, so now compare every point
for (int i = 0; i < points.size(); i++) {
if (points.at(i) != _points.at(i)) {
_pointsChanged = true;
break;
}
}
}
}
if (!_pointsChanged) {
return false;
}
for (int i = 0; i < points.size(); i++) {
glm::vec3 point = points.at(i);
glm::vec3 halfBox = getDimensions() * 0.5f;
if ((point.x < -halfBox.x || point.x > halfBox.x) ||
(point.y < -halfBox.y || point.y > halfBox.y) ||
(point.z < -halfBox.z || point.z > halfBox.z)) {
qCDebug(entities) << "Point is outside entity's bounding box";
return false;
if (!_pointsChanged) {
return;
}
}
_points = points;
return true;
for (int i = 0; i < points.size(); i++) {
glm::vec3 point = points.at(i);
glm::vec3 halfBox = getDimensions() * 0.5f;
if ((point.x < -halfBox.x || point.x > halfBox.x) ||
(point.y < -halfBox.y || point.y > halfBox.y) ||
(point.z < -halfBox.z || point.z > halfBox.z)) {
qCDebug(entities) << "Point is outside entity's bounding box";
return;
}
}
_points = points;
result = true;
});
return result;
}
int PolyLineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
@ -210,3 +218,45 @@ void PolyLineEntityItem::debugDump() const {
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
}
QVector<glm::vec3> PolyLineEntityItem::getLinePoints() const {
QVector<glm::vec3> result;
withReadLock([&] {
result = _points;
});
return result;
}
QVector<glm::vec3> PolyLineEntityItem::getNormals() const {
QVector<glm::vec3> result;
withReadLock([&] {
result = _normals;
});
return result;
}
QVector<float> PolyLineEntityItem::getStrokeWidths() const {
QVector<float> result;
withReadLock([&] {
result = _strokeWidths;
});
return result;
}
QString PolyLineEntityItem::getTextures() const {
QString result;
withReadLock([&] {
result = _textures;
});
return result;
}
void PolyLineEntityItem::setTextures(const QString& textures) {
withWriteLock([&] {
if (_textures != textures) {
_textures = textures;
_texturesChangedFlag = true;
}
});
}

View file

@ -59,21 +59,16 @@ class PolyLineEntityItem : public EntityItem {
bool setLinePoints(const QVector<glm::vec3>& points);
bool appendPoint(const glm::vec3& point);
const QVector<glm::vec3>& getLinePoints() const{ return _points; }
QVector<glm::vec3> getLinePoints() const;
bool setNormals(const QVector<glm::vec3>& normals);
const QVector<glm::vec3>& getNormals() const{ return _normals; }
QVector<glm::vec3> getNormals() const;
bool setStrokeWidths(const QVector<float>& strokeWidths);
const QVector<float>& getStrokeWidths() const{ return _strokeWidths; }
QVector<float> getStrokeWidths() const;
const QString& getTextures() const { return _textures; }
void setTextures(const QString& textures) {
if (_textures != textures) {
_textures = textures;
_texturesChangedFlag = true;
}
}
QString getTextures() const;
void setTextures(const QString& textures);
virtual bool needsToCallUpdate() const override { return true; }

View file

@ -242,3 +242,129 @@ const QByteArray PolyVoxEntityItem::getVoxelData() const {
});
return voxelDataCopy;
}
void PolyVoxEntityItem::setXTextureURL(const QString& xTextureURL) {
withWriteLock([&] {
_xTextureURL = xTextureURL;
});
}
QString PolyVoxEntityItem::getXTextureURL() const {
QString result;
withReadLock([&] {
result = _xTextureURL;
});
return result;
}
void PolyVoxEntityItem::setYTextureURL(const QString& yTextureURL) {
withWriteLock([&] {
_yTextureURL = yTextureURL;
});
}
QString PolyVoxEntityItem::getYTextureURL() const {
QString result;
withReadLock([&] {
result = _yTextureURL;
});
return result;
}
void PolyVoxEntityItem::setZTextureURL(const QString& zTextureURL) {
withWriteLock([&] {
_zTextureURL = zTextureURL;
});
}
QString PolyVoxEntityItem::getZTextureURL() const {
QString result;
withReadLock([&] {
result = _zTextureURL;
});
return result;
}
void PolyVoxEntityItem::setXNNeighborID(const EntityItemID& xNNeighborID) {
withWriteLock([&] {
_xNNeighborID = xNNeighborID;
});
}
EntityItemID PolyVoxEntityItem::getXNNeighborID() const {
EntityItemID result;
withReadLock([&] {
result = _xNNeighborID;
});
return result;
}
void PolyVoxEntityItem::setYNNeighborID(const EntityItemID& yNNeighborID) {
withWriteLock([&] {
_yNNeighborID = yNNeighborID;
});
}
EntityItemID PolyVoxEntityItem::getYNNeighborID() const {
EntityItemID result;
withReadLock([&] {
result = _yNNeighborID;
});
return result;
}
void PolyVoxEntityItem::setZNNeighborID(const EntityItemID& zNNeighborID) {
withWriteLock([&] {
_zNNeighborID = zNNeighborID;
});
}
EntityItemID PolyVoxEntityItem::getZNNeighborID() const {
EntityItemID result;
withReadLock([&] {
result = _zNNeighborID;
});
return result;
}
void PolyVoxEntityItem::setXPNeighborID(const EntityItemID& xPNeighborID) {
withWriteLock([&] {
_xPNeighborID = xPNeighborID;
});
}
EntityItemID PolyVoxEntityItem::getXPNeighborID() const {
EntityItemID result;
withReadLock([&] {
result = _xPNeighborID;
});
return result;
}
void PolyVoxEntityItem::setYPNeighborID(const EntityItemID& yPNeighborID) {
withWriteLock([&] {
_yPNeighborID = yPNeighborID;
});
}
EntityItemID PolyVoxEntityItem::getYPNeighborID() const {
EntityItemID result;
withReadLock([&] {
result = _yPNeighborID;
});
return result;
}
void PolyVoxEntityItem::setZPNeighborID(const EntityItemID& zPNeighborID) {
withWriteLock([&] {
_zPNeighborID = zPNeighborID;
});
}
EntityItemID PolyVoxEntityItem::getZPNeighborID() const {
EntityItemID result;
withReadLock([&] {
result = _zPNeighborID;
});
return result;
}

View file

@ -99,36 +99,36 @@ class PolyVoxEntityItem : public EntityItem {
static QByteArray makeEmptyVoxelData(quint16 voxelXSize = 16, quint16 voxelYSize = 16, quint16 voxelZSize = 16);
static const QString DEFAULT_X_TEXTURE_URL;
virtual void setXTextureURL(QString xTextureURL) { _xTextureURL = xTextureURL; }
virtual const QString& getXTextureURL() const { return _xTextureURL; }
virtual void setXTextureURL(const QString& xTextureURL);
QString getXTextureURL() const;
static const QString DEFAULT_Y_TEXTURE_URL;
virtual void setYTextureURL(QString yTextureURL) { _yTextureURL = yTextureURL; }
virtual const QString& getYTextureURL() const { return _yTextureURL; }
virtual void setYTextureURL(const QString& yTextureURL);
QString getYTextureURL() const;
static const QString DEFAULT_Z_TEXTURE_URL;
virtual void setZTextureURL(QString zTextureURL) { _zTextureURL = zTextureURL; }
virtual const QString& getZTextureURL() const { return _zTextureURL; }
virtual void setZTextureURL(const QString& zTextureURL);
QString getZTextureURL() const;
virtual void setXNNeighborID(const EntityItemID& xNNeighborID) { _xNNeighborID = xNNeighborID; }
void setXNNeighborID(const QString& xNNeighborID) { setXNNeighborID(QUuid(xNNeighborID)); }
virtual const EntityItemID& getXNNeighborID() const { return _xNNeighborID; }
virtual void setYNNeighborID(const EntityItemID& yNNeighborID) { _yNNeighborID = yNNeighborID; }
void setYNNeighborID(const QString& yNNeighborID) { setYNNeighborID(QUuid(yNNeighborID)); }
virtual const EntityItemID& getYNNeighborID() const { return _yNNeighborID; }
virtual void setZNNeighborID(const EntityItemID& zNNeighborID) { _zNNeighborID = zNNeighborID; }
void setZNNeighborID(const QString& zNNeighborID) { setZNNeighborID(QUuid(zNNeighborID)); }
virtual const EntityItemID& getZNNeighborID() const { return _zNNeighborID; }
virtual void setXNNeighborID(const EntityItemID& xNNeighborID);
void setXNNeighborID(const QString& xNNeighborID);
virtual EntityItemID getXNNeighborID() const;
virtual void setYNNeighborID(const EntityItemID& yNNeighborID);
void setYNNeighborID(const QString& yNNeighborID);
virtual EntityItemID getYNNeighborID() const;
virtual void setZNNeighborID(const EntityItemID& zNNeighborID);
void setZNNeighborID(const QString& zNNeighborID);
virtual EntityItemID getZNNeighborID() const;
virtual void setXPNeighborID(const EntityItemID& xPNeighborID) { _xPNeighborID = xPNeighborID; }
void setXPNeighborID(const QString& xPNeighborID) { setXPNeighborID(QUuid(xPNeighborID)); }
virtual const EntityItemID& getXPNeighborID() const { return _xPNeighborID; }
virtual void setYPNeighborID(const EntityItemID& yPNeighborID) { _yPNeighborID = yPNeighborID; }
void setYPNeighborID(const QString& yPNeighborID) { setYPNeighborID(QUuid(yPNeighborID)); }
virtual const EntityItemID& getYPNeighborID() const { return _yPNeighborID; }
virtual void setZPNeighborID(const EntityItemID& zPNeighborID) { _zPNeighborID = zPNeighborID; }
void setZPNeighborID(const QString& zPNeighborID) { setZPNeighborID(QUuid(zPNeighborID)); }
virtual const EntityItemID& getZPNeighborID() const { return _zPNeighborID; }
virtual void setXPNeighborID(const EntityItemID& xPNeighborID);
void setXPNeighborID(const QString& xPNeighborID);
virtual EntityItemID getXPNeighborID() const;
virtual void setYPNeighborID(const EntityItemID& yPNeighborID);
void setYPNeighborID(const QString& yPNeighborID);
virtual EntityItemID getYPNeighborID() const;
virtual void setZPNeighborID(const EntityItemID& zPNeighborID);
void setZPNeighborID(const QString& zPNeighborID);
virtual EntityItemID getZPNeighborID() const;
virtual void rebakeMesh() {};

View file

@ -141,3 +141,98 @@ bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const
// FIXME - should set face and surfaceNormal
return findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance);
}
void TextEntityItem::setText(const QString& value) {
withWriteLock([&] {
_text = value;
});
}
QString TextEntityItem::getText() const {
QString result;
withReadLock([&] {
result = _text;
});
return result;
}
void TextEntityItem::setLineHeight(float value) {
withWriteLock([&] {
_lineHeight = value;
});
}
float TextEntityItem::getLineHeight() const {
float result;
withReadLock([&] {
result = _lineHeight;
});
return result;
}
const rgbColor& TextEntityItem::getTextColor() const {
return _textColor;
}
const rgbColor& TextEntityItem::getBackgroundColor() const {
return _backgroundColor;
}
xColor TextEntityItem::getTextColorX() const {
xColor result;
withReadLock([&] {
result = { _textColor[RED_INDEX], _textColor[GREEN_INDEX], _textColor[BLUE_INDEX] };
});
return result;
}
void TextEntityItem::setTextColor(const rgbColor& value) {
withWriteLock([&] {
memcpy(_textColor, value, sizeof(_textColor));
});
}
void TextEntityItem::setTextColor(const xColor& value) {
withWriteLock([&] {
_textColor[RED_INDEX] = value.red;
_textColor[GREEN_INDEX] = value.green;
_textColor[BLUE_INDEX] = value.blue;
});
}
xColor TextEntityItem::getBackgroundColorX() const {
xColor result;
withReadLock([&] {
result = { _backgroundColor[RED_INDEX], _backgroundColor[GREEN_INDEX], _backgroundColor[BLUE_INDEX] };
});
return result;
}
void TextEntityItem::setBackgroundColor(const rgbColor& value) {
withWriteLock([&] {
memcpy(_backgroundColor, value, sizeof(_backgroundColor));
});
}
void TextEntityItem::setBackgroundColor(const xColor& value) {
withWriteLock([&] {
_backgroundColor[RED_INDEX] = value.red;
_backgroundColor[GREEN_INDEX] = value.green;
_backgroundColor[BLUE_INDEX] = value.blue;
});
}
bool TextEntityItem::getFaceCamera() const {
bool result;
withReadLock([&] {
result = _faceCamera;
});
return result;
}
void TextEntityItem::setFaceCamera(bool value) {
withWriteLock([&] {
_faceCamera = value;
});
}

View file

@ -53,40 +53,34 @@ public:
void** intersectedObject, bool precisionPicking) const override;
static const QString DEFAULT_TEXT;
void setText(const QString& value) { _text = value; }
const QString& getText() const { return _text; }
void setText(const QString& value);
QString getText() const;
static const float DEFAULT_LINE_HEIGHT;
void setLineHeight(float value) { _lineHeight = value; }
float getLineHeight() const { return _lineHeight; }
void setLineHeight(float value);
float getLineHeight() const;
static const xColor DEFAULT_TEXT_COLOR;
const rgbColor& getTextColor() const { return _textColor; }
xColor getTextColorX() const { xColor color = { _textColor[RED_INDEX], _textColor[GREEN_INDEX], _textColor[BLUE_INDEX] }; return color; }
// FIXME should not return a reference because of thread safety, but can't return an array
const rgbColor& getTextColor() const;
xColor getTextColorX() const;
void setTextColor(const rgbColor& value) { memcpy(_textColor, value, sizeof(_textColor)); }
void setTextColor(const xColor& value) {
_textColor[RED_INDEX] = value.red;
_textColor[GREEN_INDEX] = value.green;
_textColor[BLUE_INDEX] = value.blue;
}
void setTextColor(const rgbColor& value);
void setTextColor(const xColor& value);
static const xColor DEFAULT_BACKGROUND_COLOR;
const rgbColor& getBackgroundColor() const { return _backgroundColor; }
xColor getBackgroundColorX() const { xColor color = { _backgroundColor[RED_INDEX], _backgroundColor[GREEN_INDEX], _backgroundColor[BLUE_INDEX] }; return color; }
// FIXME should not return a reference because of thread safety, but can't return an array
const rgbColor& getBackgroundColor() const;
xColor getBackgroundColorX() const;
void setBackgroundColor(const rgbColor& value) { memcpy(_backgroundColor, value, sizeof(_backgroundColor)); }
void setBackgroundColor(const xColor& value) {
_backgroundColor[RED_INDEX] = value.red;
_backgroundColor[GREEN_INDEX] = value.green;
_backgroundColor[BLUE_INDEX] = value.blue;
}
void setBackgroundColor(const rgbColor& value);
void setBackgroundColor(const xColor& value);
static const bool DEFAULT_FACE_CAMERA;
bool getFaceCamera() const { return _faceCamera; }
void setFaceCamera(bool value) { _faceCamera = value; }
bool getFaceCamera() const;
void setFaceCamera(bool value);
protected:
private:
QString _text;
float _lineHeight;
rgbColor _textColor;

View file

@ -124,18 +124,26 @@ bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const g
}
void WebEntityItem::setSourceUrl(const QString& value) {
if (_sourceUrl != value) {
auto newURL = QUrl::fromUserInput(value);
withWriteLock([&] {
if (_sourceUrl != value) {
auto newURL = QUrl::fromUserInput(value);
if (newURL.isValid()) {
_sourceUrl = newURL.toDisplayString();
} else {
qCDebug(entities) << "Clearing web entity source URL since" << value << "cannot be parsed to a valid URL.";
if (newURL.isValid()) {
_sourceUrl = newURL.toDisplayString();
} else {
qCDebug(entities) << "Clearing web entity source URL since" << value << "cannot be parsed to a valid URL.";
}
}
}
});
}
const QString& WebEntityItem::getSourceUrl() const { return _sourceUrl; }
QString WebEntityItem::getSourceUrl() const {
QString result;
withReadLock([&] {
result = _sourceUrl;
});
return result;
}
void WebEntityItem::setDPI(uint16_t value) {
_dpi = value;

View file

@ -52,7 +52,7 @@ public:
void** intersectedObject, bool precisionPicking) const override;
virtual void setSourceUrl(const QString& value);
const QString& getSourceUrl() const;
QString getSourceUrl() const;
virtual bool wantsHandControllerPointerEvents() const override { return true; }

View file

@ -208,10 +208,12 @@ ShapeType ZoneEntityItem::getShapeType() const {
}
void ZoneEntityItem::setCompoundShapeURL(const QString& url) {
_compoundShapeURL = url;
if (_compoundShapeURL.isEmpty() && _shapeType == SHAPE_TYPE_COMPOUND) {
_shapeType = DEFAULT_SHAPE_TYPE;
}
withWriteLock([&] {
_compoundShapeURL = url;
if (_compoundShapeURL.isEmpty() && _shapeType == SHAPE_TYPE_COMPOUND) {
_shapeType = DEFAULT_SHAPE_TYPE;
}
});
}
bool ZoneEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
@ -223,7 +225,9 @@ bool ZoneEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const
}
void ZoneEntityItem::setFilterURL(QString url) {
_filterURL = url;
withWriteLock([&] {
_filterURL = url;
});
if (DependencyManager::isSet<EntityEditFilters>()) {
auto entityEditFilters = DependencyManager::get<EntityEditFilters>();
qCDebug(entities) << "adding filter " << url << "for zone" << getEntityItemID();
@ -231,3 +235,22 @@ void ZoneEntityItem::setFilterURL(QString url) {
}
}
QString ZoneEntityItem::getFilterURL() const {
QString result;
withReadLock([&] {
result = _filterURL;
});
return result;
}
bool ZoneEntityItem::hasCompoundShapeURL() const {
return !getCompoundShapeURL().isEmpty();
}
QString ZoneEntityItem::getCompoundShapeURL() const {
QString result;
withReadLock([&] {
result = _compoundShapeURL;
});
return result;
}

View file

@ -58,8 +58,8 @@ public:
void setShapeType(ShapeType type) override { _shapeType = type; }
virtual ShapeType getShapeType() const override;
virtual bool hasCompoundShapeURL() const { return !_compoundShapeURL.isEmpty(); }
const QString getCompoundShapeURL() const { return _compoundShapeURL; }
virtual bool hasCompoundShapeURL() const;
QString getCompoundShapeURL() const;
virtual void setCompoundShapeURL(const QString& url);
const KeyLightPropertyGroup& getKeyLightProperties() const { return _keyLightProperties; }
@ -74,7 +74,7 @@ public:
void setFlyingAllowed(bool value) { _flyingAllowed = value; }
bool getGhostingAllowed() const { return _ghostingAllowed; }
void setGhostingAllowed(bool value) { _ghostingAllowed = value; }
QString getFilterURL() const { return _filterURL; }
QString getFilterURL() const;
void setFilterURL(const QString url);
virtual bool supportsDetailedRayIntersection() const override { return true; }