mirror of
https://github.com/lubosz/overte.git
synced 2025-04-08 00:02:05 +02:00
Merge pull request #14140 from AndrewMeadows/dps-setPos-vs-grab
Make EntityScriptingInterface aware of distributed physics simulation (DPS) rules
This commit is contained in:
commit
81fbb5a332
7 changed files with 207 additions and 120 deletions
|
@ -78,8 +78,10 @@ void addAvatarEntities(const QVariantList& avatarEntities) {
|
|||
}
|
||||
|
||||
entity->setLastBroadcast(usecTimestampNow());
|
||||
// since we're creating this object we will immediately volunteer to own its simulation
|
||||
entity->setScriptSimulationPriority(VOLUNTEER_SIMULATION_PRIORITY);
|
||||
if (entityProperties.getDynamic()) {
|
||||
// since we're creating a dynamic object we volunteer immediately to own its simulation
|
||||
entity->upgradeScriptSimulationPriority(VOLUNTEER_SIMULATION_PRIORITY);
|
||||
}
|
||||
entityProperties.setLastEdited(entity->getLastEdited());
|
||||
} else {
|
||||
qCDebug(entities) << "AvatarEntitiesBookmark failed to add new Entity to local Octree";
|
||||
|
|
|
@ -673,7 +673,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
const QUuid& myNodeID = nodeList->getSessionUUID();
|
||||
bool weOwnSimulation = _simulationOwner.matchesValidID(myNodeID);
|
||||
|
||||
// pack SimulationOwner and terse update properties near each other
|
||||
// pack SimulationOwner, transform, and velocity properties near each other
|
||||
// NOTE: the server is authoritative for changes to simOwnerID so we always unpack ownership data
|
||||
// even when we would otherwise ignore the rest of the packet.
|
||||
|
||||
|
@ -1358,8 +1358,7 @@ EntityItemProperties EntityItem::getProperties(const EntityPropertyFlags& desire
|
|||
return properties;
|
||||
}
|
||||
|
||||
void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) const {
|
||||
// a TerseUpdate includes the transform and its derivatives
|
||||
void EntityItem::getTransformAndVelocityProperties(EntityItemProperties& properties) const {
|
||||
if (!properties._positionChanged) {
|
||||
properties._position = getLocalPosition();
|
||||
}
|
||||
|
@ -1383,8 +1382,11 @@ void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) c
|
|||
properties._accelerationChanged = true;
|
||||
}
|
||||
|
||||
void EntityItem::setScriptSimulationPriority(uint8_t priority) {
|
||||
uint8_t newPriority = stillHasGrabActions() ? glm::max(priority, SCRIPT_GRAB_SIMULATION_PRIORITY) : priority;
|
||||
void EntityItem::upgradeScriptSimulationPriority(uint8_t priority) {
|
||||
uint8_t newPriority = glm::max(priority, _scriptSimulationPriority);
|
||||
if (newPriority < SCRIPT_GRAB_SIMULATION_PRIORITY && stillHasGrabActions()) {
|
||||
newPriority = SCRIPT_GRAB_SIMULATION_PRIORITY;
|
||||
}
|
||||
if (newPriority != _scriptSimulationPriority) {
|
||||
// set the dirty flag to trigger a bid or ownership update
|
||||
markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_PRIORITY);
|
||||
|
@ -1419,7 +1421,7 @@ bool EntityItem::stillWaitingToTakeOwnership(uint64_t timestamp) const {
|
|||
bool EntityItem::setProperties(const EntityItemProperties& properties) {
|
||||
bool somethingChanged = false;
|
||||
|
||||
// these affect TerseUpdate properties
|
||||
// these affect transform and velocity properties
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(simulationOwner, setSimulationOwner);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(position, setPosition);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(rotation, setRotation);
|
||||
|
@ -3256,3 +3258,26 @@ void EntityItem::setScriptHasFinishedPreload(bool value) {
|
|||
bool EntityItem::isScriptPreloadFinished() {
|
||||
return _scriptPreloadFinished;
|
||||
}
|
||||
|
||||
void EntityItem::prepareForSimulationOwnershipBid(EntityItemProperties& properties, uint64_t now, uint8_t priority) {
|
||||
if (dynamicDataNeedsTransmit()) {
|
||||
setDynamicDataNeedsTransmit(false);
|
||||
properties.setActionData(getDynamicData());
|
||||
}
|
||||
|
||||
if (updateQueryAACube()) {
|
||||
// due to parenting, the server may not know where something is in world-space, so include the bounding cube.
|
||||
properties.setQueryAACube(getQueryAACube());
|
||||
}
|
||||
|
||||
// set the LastEdited of the properties but NOT the entity itself
|
||||
properties.setLastEdited(now);
|
||||
|
||||
clearScriptSimulationPriority();
|
||||
properties.setSimulationOwner(Physics::getSessionUUID(), priority);
|
||||
setPendingOwnershipPriority(priority);
|
||||
|
||||
properties.setClientOnly(getClientOnly());
|
||||
properties.setOwningAvatarID(getOwningAvatarID());
|
||||
setLastBroadcast(now); // for debug/physics status icons
|
||||
}
|
||||
|
|
|
@ -325,7 +325,7 @@ public:
|
|||
// TODO: move this "ScriptSimulationPriority" and "PendingOwnership" stuff into EntityMotionState
|
||||
// but first would need to do some other cleanup. In the meantime these live here as "scratch space"
|
||||
// to allow libs that don't know about each other to communicate.
|
||||
void setScriptSimulationPriority(uint8_t priority);
|
||||
void upgradeScriptSimulationPriority(uint8_t priority);
|
||||
void clearScriptSimulationPriority();
|
||||
uint8_t getScriptSimulationPriority() const { return _scriptSimulationPriority; }
|
||||
void setPendingOwnershipPriority(uint8_t priority);
|
||||
|
@ -420,7 +420,7 @@ public:
|
|||
quint64 getLastEditedFromRemote() const { return _lastEditedFromRemote; }
|
||||
void updateLastEditedFromRemote() { _lastEditedFromRemote = usecTimestampNow(); }
|
||||
|
||||
void getAllTerseUpdateProperties(EntityItemProperties& properties) const;
|
||||
void getTransformAndVelocityProperties(EntityItemProperties& properties) const;
|
||||
|
||||
void flagForMotionStateChange() { _flags |= Simulation::DIRTY_MOTION_TYPE; }
|
||||
|
||||
|
@ -535,6 +535,8 @@ public:
|
|||
|
||||
const GrabPropertyGroup& getGrabProperties() const { return _grabProperties; }
|
||||
|
||||
void prepareForSimulationOwnershipBid(EntityItemProperties& properties, uint64_t now, uint8_t priority);
|
||||
|
||||
signals:
|
||||
void requestRenderUpdate();
|
||||
void spaceUpdate(std::pair<int32_t, glm::vec4> data);
|
||||
|
|
|
@ -3244,9 +3244,12 @@ AABox EntityItemProperties::getAABox() const {
|
|||
return AABox(rotatedExtentsRelativeToRegistrationPoint);
|
||||
}
|
||||
|
||||
bool EntityItemProperties::hasTerseUpdateChanges() const {
|
||||
// a TerseUpdate includes the transform and its derivatives
|
||||
return _positionChanged || _velocityChanged || _rotationChanged || _angularVelocityChanged || _accelerationChanged;
|
||||
bool EntityItemProperties::hasTransformOrVelocityChanges() const {
|
||||
return _positionChanged ||_localPositionChanged
|
||||
|| _rotationChanged || _localRotationChanged
|
||||
|| _velocityChanged || _localVelocityChanged
|
||||
|| _angularVelocityChanged || _localAngularVelocityChanged
|
||||
|| _accelerationChanged;
|
||||
}
|
||||
|
||||
bool EntityItemProperties::hasMiscPhysicsChanges() const {
|
||||
|
@ -3255,6 +3258,56 @@ bool EntityItemProperties::hasMiscPhysicsChanges() const {
|
|||
_compoundShapeURLChanged || _dynamicChanged || _collisionlessChanged || _collisionMaskChanged;
|
||||
}
|
||||
|
||||
bool EntityItemProperties::hasSimulationRestrictedChanges() const {
|
||||
return _positionChanged || _localPositionChanged
|
||||
|| _rotationChanged || _localRotationChanged
|
||||
|| _velocityChanged || _localVelocityChanged
|
||||
|| _angularVelocityChanged || _localAngularVelocityChanged
|
||||
|| _accelerationChanged
|
||||
|| _parentIDChanged || _parentJointIndexChanged;
|
||||
}
|
||||
|
||||
void EntityItemProperties::copySimulationRestrictedProperties(const EntityItemPointer& entity) {
|
||||
if (!_parentIDChanged) {
|
||||
setParentID(entity->getParentID());
|
||||
}
|
||||
if (!_parentJointIndexChanged) {
|
||||
setParentJointIndex(entity->getParentJointIndex());
|
||||
}
|
||||
if (!_localPositionChanged && !_positionChanged) {
|
||||
setPosition(entity->getWorldPosition());
|
||||
}
|
||||
if (!_localRotationChanged && !_rotationChanged) {
|
||||
setRotation(entity->getWorldOrientation());
|
||||
}
|
||||
if (!_localVelocityChanged && !_velocityChanged) {
|
||||
setVelocity(entity->getWorldVelocity());
|
||||
}
|
||||
if (!_localAngularVelocityChanged && !_angularVelocityChanged) {
|
||||
setAngularVelocity(entity->getWorldAngularVelocity());
|
||||
}
|
||||
if (!_accelerationChanged) {
|
||||
setAcceleration(entity->getAcceleration());
|
||||
}
|
||||
if (!_localDimensionsChanged && !_dimensionsChanged) {
|
||||
setDimensions(entity->getScaledDimensions());
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItemProperties::clearSimulationRestrictedProperties() {
|
||||
_positionChanged = false;
|
||||
_localPositionChanged = false;
|
||||
_rotationChanged = false;
|
||||
_localRotationChanged = false;
|
||||
_velocityChanged = false;
|
||||
_localVelocityChanged = false;
|
||||
_angularVelocityChanged = false;
|
||||
_localAngularVelocityChanged = false;
|
||||
_accelerationChanged = false;
|
||||
_parentIDChanged = false;
|
||||
_parentJointIndexChanged = false;
|
||||
}
|
||||
|
||||
void EntityItemProperties::clearSimulationOwner() {
|
||||
_simulationOwner.clear();
|
||||
_simulationOwnerChanged = true;
|
||||
|
@ -3273,6 +3326,20 @@ void EntityItemProperties::setSimulationOwner(const QByteArray& data) {
|
|||
}
|
||||
}
|
||||
|
||||
uint8_t EntityItemProperties::computeSimulationBidPriority() const {
|
||||
uint8_t priority = 0;
|
||||
if (_parentIDChanged || _parentJointIndexChanged) {
|
||||
// we need higher simulation ownership priority to chang parenting info
|
||||
priority = SCRIPT_GRAB_SIMULATION_PRIORITY;
|
||||
} else if ( _positionChanged || _localPositionChanged
|
||||
|| _rotationChanged || _localRotationChanged
|
||||
|| _velocityChanged || _localVelocityChanged
|
||||
|| _angularVelocityChanged || _localAngularVelocityChanged) {
|
||||
priority = SCRIPT_POKE_SIMULATION_PRIORITY;
|
||||
}
|
||||
return priority;
|
||||
}
|
||||
|
||||
QList<QString> EntityItemProperties::listChangedProperties() {
|
||||
QList<QString> out;
|
||||
if (containsPositionChange()) {
|
||||
|
|
|
@ -349,13 +349,18 @@ public:
|
|||
|
||||
void setCreated(QDateTime& v);
|
||||
|
||||
bool hasTerseUpdateChanges() const;
|
||||
bool hasTransformOrVelocityChanges() const;
|
||||
bool hasMiscPhysicsChanges() const;
|
||||
|
||||
bool hasSimulationRestrictedChanges() const;
|
||||
void copySimulationRestrictedProperties(const EntityItemPointer& entity);
|
||||
void clearSimulationRestrictedProperties();
|
||||
|
||||
void clearSimulationOwner();
|
||||
void setSimulationOwner(const QUuid& id, uint8_t priority);
|
||||
void setSimulationOwner(const QByteArray& data);
|
||||
void setSimulationPriority(uint8_t priority) { _simulationOwner.setPriority(priority); }
|
||||
uint8_t computeSimulationBidPriority() const;
|
||||
|
||||
void setActionDataDirty() { _actionDataChanged = true; }
|
||||
|
||||
|
|
|
@ -174,6 +174,7 @@ EntityItemProperties convertPropertiesToScriptSemantics(const EntityItemProperti
|
|||
}
|
||||
|
||||
|
||||
// TODO: this method looks expensive and should take properties by reference, update it, and return void
|
||||
EntityItemProperties convertPropertiesFromScriptSemantics(const EntityItemProperties& scriptSideProperties,
|
||||
bool scalesWithParent) {
|
||||
// convert position and rotation properties from world-space to local, unless localPosition and localRotation
|
||||
|
@ -242,13 +243,12 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties
|
|||
_activityTracking.addedEntityCount++;
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
auto sessionID = nodeList->getSessionUUID();
|
||||
const auto sessionID = nodeList->getSessionUUID();
|
||||
|
||||
EntityItemProperties propertiesWithSimID = properties;
|
||||
if (clientOnly) {
|
||||
const QUuid myNodeID = sessionID;
|
||||
propertiesWithSimID.setClientOnly(clientOnly);
|
||||
propertiesWithSimID.setOwningAvatarID(myNodeID);
|
||||
propertiesWithSimID.setOwningAvatarID(sessionID);
|
||||
}
|
||||
|
||||
propertiesWithSimID.setLastEditedBy(sessionID);
|
||||
|
@ -290,7 +290,7 @@ bool EntityScriptingInterface::addLocalEntityCopy(EntityItemProperties& properti
|
|||
|
||||
entity->setLastBroadcast(usecTimestampNow());
|
||||
// since we're creating this object we will immediately volunteer to own its simulation
|
||||
entity->setScriptSimulationPriority(VOLUNTEER_SIMULATION_PRIORITY);
|
||||
entity->upgradeScriptSimulationPriority(VOLUNTEER_SIMULATION_PRIORITY);
|
||||
properties.setLastEdited(entity->getLastEdited());
|
||||
} else {
|
||||
qCDebug(entities) << "script failed to add new Entity to local Octree";
|
||||
|
@ -530,54 +530,86 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties&
|
|||
|
||||
_activityTracking.editedEntityCount++;
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
auto sessionID = nodeList->getSessionUUID();
|
||||
const auto sessionID = DependencyManager::get<NodeList>()->getSessionUUID();
|
||||
|
||||
EntityItemProperties properties = scriptSideProperties;
|
||||
properties.setLastEditedBy(sessionID);
|
||||
|
||||
EntityItemID entityID(id);
|
||||
if (!_entityTree) {
|
||||
properties.setLastEditedBy(sessionID);
|
||||
queueEntityMessage(PacketType::EntityEdit, entityID, properties);
|
||||
return id;
|
||||
}
|
||||
// If we have a local entity tree set, then also update it.
|
||||
|
||||
bool updatedEntity = false;
|
||||
_entityTree->withWriteLock([&] {
|
||||
EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID);
|
||||
EntityItemPointer entity(nullptr);
|
||||
SimulationOwner simulationOwner;
|
||||
_entityTree->withReadLock([&] {
|
||||
// make a copy of entity for local logic outside of tree lock
|
||||
entity = _entityTree->findEntityByEntityItemID(entityID);
|
||||
if (!entity) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (entity->getClientOnly() && entity->getOwningAvatarID() != nodeList->getSessionUUID()) {
|
||||
if (entity->getClientOnly() && entity->getOwningAvatarID() != sessionID) {
|
||||
// don't edit other avatar's avatarEntities
|
||||
properties = EntityItemProperties();
|
||||
return;
|
||||
}
|
||||
// make a copy of simulationOwner for local logic outside of tree lock
|
||||
simulationOwner = entity->getSimulationOwner();
|
||||
});
|
||||
|
||||
if (scriptSideProperties.parentRelatedPropertyChanged()) {
|
||||
// All of parentID, parentJointIndex, position, rotation are needed to make sense of any of them.
|
||||
// If any of these changed, pull any missing properties from the entity.
|
||||
if (entity) {
|
||||
if (properties.hasSimulationRestrictedChanges()) {
|
||||
if (_bidOnSimulationOwnership) {
|
||||
// flag for simulation ownership, or upgrade existing ownership priority
|
||||
// (actual bids for simulation ownership are sent by the PhysicalEntitySimulation)
|
||||
entity->upgradeScriptSimulationPriority(properties.computeSimulationBidPriority());
|
||||
if (simulationOwner.getID() == sessionID) {
|
||||
// we own the simulation --> copy ALL restricted properties
|
||||
properties.copySimulationRestrictedProperties(entity);
|
||||
} else {
|
||||
// we don't own the simulation but think we would like to
|
||||
|
||||
if (!scriptSideProperties.parentIDChanged()) {
|
||||
properties.setParentID(entity->getParentID());
|
||||
}
|
||||
if (!scriptSideProperties.parentJointIndexChanged()) {
|
||||
properties.setParentJointIndex(entity->getParentJointIndex());
|
||||
}
|
||||
if (!scriptSideProperties.localPositionChanged() && !scriptSideProperties.positionChanged()) {
|
||||
properties.setPosition(entity->getWorldPosition());
|
||||
}
|
||||
if (!scriptSideProperties.localRotationChanged() && !scriptSideProperties.rotationChanged()) {
|
||||
properties.setRotation(entity->getWorldOrientation());
|
||||
}
|
||||
if (!scriptSideProperties.localDimensionsChanged() && !scriptSideProperties.dimensionsChanged()) {
|
||||
properties.setDimensions(entity->getScaledDimensions());
|
||||
uint8_t desiredPriority = entity->getScriptSimulationPriority();
|
||||
if (desiredPriority < simulationOwner.getPriority()) {
|
||||
// the priority at which we'd like to own it is not high enough
|
||||
// --> assume failure and clear all restricted property changes
|
||||
properties.clearSimulationRestrictedProperties();
|
||||
} else {
|
||||
// the priority at which we'd like to own it is high enough to win.
|
||||
// --> assume success and copy ALL restricted properties
|
||||
properties.copySimulationRestrictedProperties(entity);
|
||||
}
|
||||
}
|
||||
} else if (!simulationOwner.getID().isNull()) {
|
||||
// someone owns this but not us
|
||||
// clear restricted properties
|
||||
properties.clearSimulationRestrictedProperties();
|
||||
}
|
||||
// clear the cached simulationPriority level
|
||||
entity->upgradeScriptSimulationPriority(0);
|
||||
}
|
||||
|
||||
// set these to make EntityItemProperties::getScalesWithParent() work correctly
|
||||
properties.setClientOnly(entity->getClientOnly());
|
||||
properties.setOwningAvatarID(entity->getOwningAvatarID());
|
||||
properties = convertPropertiesFromScriptSemantics(properties, properties.getScalesWithParent());
|
||||
|
||||
// make sure the properties has a type, so that the encode can know which properties to include
|
||||
properties.setType(entity->getType());
|
||||
} else if (_bidOnSimulationOwnership) {
|
||||
// bail when simulation participants don't know about entity
|
||||
return QUuid();
|
||||
}
|
||||
// TODO: it is possible there is no remaining useful changes in properties and we should bail early.
|
||||
// How to check for this cheaply?
|
||||
|
||||
properties = convertPropertiesFromScriptSemantics(properties, properties.getScalesWithParent());
|
||||
properties.setLastEditedBy(sessionID);
|
||||
|
||||
// done reading and modifying properties --> start write
|
||||
bool updatedEntity = false;
|
||||
_entityTree->withWriteLock([&] {
|
||||
updatedEntity = _entityTree->updateEntity(entityID, properties);
|
||||
});
|
||||
|
||||
|
@ -590,63 +622,37 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties&
|
|||
// return QUuid();
|
||||
// }
|
||||
|
||||
bool entityFound { false };
|
||||
bool hasQueryAACubeRelatedChanges = properties.queryAACubeRelatedPropertyChanged();
|
||||
// done writing, send update
|
||||
_entityTree->withReadLock([&] {
|
||||
EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID);
|
||||
// find the entity again: maybe it was removed since we last found it
|
||||
entity = _entityTree->findEntityByEntityItemID(entityID);
|
||||
if (entity) {
|
||||
entityFound = true;
|
||||
// make sure the properties has a type, so that the encode can know which properties to include
|
||||
properties.setType(entity->getType());
|
||||
bool hasTerseUpdateChanges = properties.hasTerseUpdateChanges();
|
||||
bool hasPhysicsChanges = properties.hasMiscPhysicsChanges() || hasTerseUpdateChanges;
|
||||
if (_bidOnSimulationOwnership && hasPhysicsChanges) {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
const QUuid myNodeID = nodeList->getSessionUUID();
|
||||
uint64_t now = usecTimestampNow();
|
||||
entity->setLastBroadcast(now);
|
||||
|
||||
if (entity->getSimulatorID() == myNodeID) {
|
||||
// we think we already own the simulation, so make sure to send ALL TerseUpdate properties
|
||||
if (hasTerseUpdateChanges) {
|
||||
entity->getAllTerseUpdateProperties(properties);
|
||||
}
|
||||
// TODO: if we knew that ONLY TerseUpdate properties have changed in properties AND the object
|
||||
// is dynamic AND it is active in the physics simulation then we could chose to NOT queue an update
|
||||
// and instead let the physics simulation decide when to send a terse update. This would remove
|
||||
// the "slide-no-rotate" glitch (and typical double-update) that we see during the "poke rolling
|
||||
// balls" test. However, even if we solve this problem we still need to provide a "slerp the visible
|
||||
// proxy toward the true physical position" feature to hide the final glitches in the remote watcher's
|
||||
// simulation.
|
||||
|
||||
if (entity->getSimulationPriority() < SCRIPT_POKE_SIMULATION_PRIORITY) {
|
||||
// we re-assert our simulation ownership at a higher priority
|
||||
properties.setSimulationOwner(myNodeID, SCRIPT_POKE_SIMULATION_PRIORITY);
|
||||
}
|
||||
} else {
|
||||
// we make a bid for simulation ownership
|
||||
properties.setSimulationOwner(myNodeID, SCRIPT_POKE_SIMULATION_PRIORITY);
|
||||
entity->setScriptSimulationPriority(SCRIPT_POKE_SIMULATION_PRIORITY);
|
||||
}
|
||||
}
|
||||
if (properties.queryAACubeRelatedPropertyChanged()) {
|
||||
if (hasQueryAACubeRelatedChanges) {
|
||||
properties.setQueryAACube(entity->getQueryAACube());
|
||||
}
|
||||
entity->setLastBroadcast(usecTimestampNow());
|
||||
properties.setLastEdited(entity->getLastEdited());
|
||||
|
||||
// if we've moved an entity with children, check/update the queryAACube of all descendents and tell the server
|
||||
// if they've changed.
|
||||
entity->forEachDescendant([&](SpatiallyNestablePointer descendant) {
|
||||
if (descendant->getNestableType() == NestableType::Entity) {
|
||||
if (descendant->updateQueryAACube()) {
|
||||
EntityItemPointer entityDescendant = std::static_pointer_cast<EntityItem>(descendant);
|
||||
EntityItemProperties newQueryCubeProperties;
|
||||
newQueryCubeProperties.setQueryAACube(descendant->getQueryAACube());
|
||||
newQueryCubeProperties.setLastEdited(properties.getLastEdited());
|
||||
queueEntityMessage(PacketType::EntityEdit, descendant->getID(), newQueryCubeProperties);
|
||||
entityDescendant->setLastBroadcast(usecTimestampNow());
|
||||
// if we've moved an entity with children, check/update the queryAACube of all descendents and tell the server
|
||||
// if they've changed.
|
||||
entity->forEachDescendant([&](SpatiallyNestablePointer descendant) {
|
||||
if (descendant->getNestableType() == NestableType::Entity) {
|
||||
if (descendant->updateQueryAACube()) {
|
||||
EntityItemPointer entityDescendant = std::static_pointer_cast<EntityItem>(descendant);
|
||||
EntityItemProperties newQueryCubeProperties;
|
||||
newQueryCubeProperties.setQueryAACube(descendant->getQueryAACube());
|
||||
newQueryCubeProperties.setLastEdited(properties.getLastEdited());
|
||||
queueEntityMessage(PacketType::EntityEdit, descendant->getID(), newQueryCubeProperties);
|
||||
entityDescendant->setLastBroadcast(now);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!entity) {
|
||||
if (hasQueryAACubeRelatedChanges) {
|
||||
// Sometimes ESS don't have the entity they are trying to edit in their local tree. In this case,
|
||||
// convertPropertiesFromScriptSemantics doesn't get called and local* edits will get dropped.
|
||||
// This is because, on the script side, "position" is in world frame, but in the network
|
||||
|
@ -668,8 +674,6 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties&
|
|||
properties.setDimensions(properties.getLocalDimensions());
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!entityFound) {
|
||||
// we've made an edit to an entity we don't know about, or to a non-entity. If it's a known non-entity,
|
||||
// print a warning and don't send an edit packet to the entity-server.
|
||||
QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
|
||||
|
@ -1449,7 +1453,7 @@ QUuid EntityScriptingInterface::addAction(const QString& actionTypeString,
|
|||
}
|
||||
action->setIsMine(true);
|
||||
success = entity->addAction(simulation, action);
|
||||
entity->setScriptSimulationPriority(SCRIPT_GRAB_SIMULATION_PRIORITY);
|
||||
entity->upgradeScriptSimulationPriority(SCRIPT_GRAB_SIMULATION_PRIORITY);
|
||||
return false; // Physics will cause a packet to be sent, so don't send from here.
|
||||
});
|
||||
if (success) {
|
||||
|
@ -1465,7 +1469,7 @@ bool EntityScriptingInterface::updateAction(const QUuid& entityID, const QUuid&
|
|||
return actionWorker(entityID, [&](EntitySimulationPointer simulation, EntityItemPointer entity) {
|
||||
bool success = entity->updateAction(simulation, actionID, arguments);
|
||||
if (success) {
|
||||
entity->setScriptSimulationPriority(SCRIPT_GRAB_SIMULATION_PRIORITY);
|
||||
entity->upgradeScriptSimulationPriority(SCRIPT_GRAB_SIMULATION_PRIORITY);
|
||||
}
|
||||
return success;
|
||||
});
|
||||
|
@ -1479,7 +1483,7 @@ bool EntityScriptingInterface::deleteAction(const QUuid& entityID, const QUuid&
|
|||
success = entity->removeAction(simulation, actionID);
|
||||
if (success) {
|
||||
// reduce from grab to poke
|
||||
entity->setScriptSimulationPriority(SCRIPT_POKE_SIMULATION_PRIORITY);
|
||||
entity->upgradeScriptSimulationPriority(SCRIPT_POKE_SIMULATION_PRIORITY);
|
||||
}
|
||||
return false; // Physics will cause a packet to be sent, so don't send from here.
|
||||
});
|
||||
|
|
|
@ -502,36 +502,18 @@ void EntityMotionState::sendBid(OctreeEditPacketSender* packetSender, uint32_t s
|
|||
properties.setVelocity(linearVelocity);
|
||||
properties.setAcceleration(_entity->getAcceleration());
|
||||
properties.setAngularVelocity(angularVelocity);
|
||||
if (_entity->dynamicDataNeedsTransmit()) {
|
||||
_entity->setDynamicDataNeedsTransmit(false);
|
||||
properties.setActionData(_entity->getDynamicData());
|
||||
}
|
||||
|
||||
if (_entity->updateQueryAACube()) {
|
||||
// due to parenting, the server may not know where something is in world-space, so include the bounding cube.
|
||||
properties.setQueryAACube(_entity->getQueryAACube());
|
||||
}
|
||||
|
||||
// set the LastEdited of the properties but NOT the entity itself
|
||||
quint64 now = usecTimestampNow();
|
||||
properties.setLastEdited(now);
|
||||
|
||||
// we don't own the simulation for this entity yet, but we're sending a bid for it
|
||||
quint64 now = usecTimestampNow();
|
||||
uint8_t finalBidPriority = computeFinalBidPriority();
|
||||
_entity->clearScriptSimulationPriority();
|
||||
properties.setSimulationOwner(Physics::getSessionUUID(), finalBidPriority);
|
||||
_entity->setPendingOwnershipPriority(finalBidPriority);
|
||||
_entity->prepareForSimulationOwnershipBid(properties, now, finalBidPriority);
|
||||
|
||||
EntityTreeElementPointer element = _entity->getElement();
|
||||
EntityTreePointer tree = element ? element->getTree() : nullptr;
|
||||
|
||||
properties.setClientOnly(_entity->getClientOnly());
|
||||
properties.setOwningAvatarID(_entity->getOwningAvatarID());
|
||||
|
||||
EntityItemID id(_entity->getID());
|
||||
EntityEditPacketSender* entityPacketSender = static_cast<EntityEditPacketSender*>(packetSender);
|
||||
entityPacketSender->queueEditEntityMessage(PacketType::EntityPhysics, tree, id, properties);
|
||||
_entity->setLastBroadcast(now); // for debug/physics status icons
|
||||
|
||||
// NOTE: we don't descend to children for ownership bid. Instead, if we win ownership of the parent
|
||||
// then in sendUpdate() we'll walk descendents and send updates for their QueryAACubes if necessary.
|
||||
|
|
Loading…
Reference in a new issue