Merge pull request #14140 from AndrewMeadows/dps-setPos-vs-grab

Make EntityScriptingInterface aware of distributed physics simulation (DPS) rules
This commit is contained in:
John Conklin II 2018-10-19 10:33:14 -07:00 committed by GitHub
commit 81fbb5a332
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 207 additions and 120 deletions

View file

@ -78,8 +78,10 @@ void addAvatarEntities(const QVariantList& avatarEntities) {
} }
entity->setLastBroadcast(usecTimestampNow()); entity->setLastBroadcast(usecTimestampNow());
// since we're creating this object we will immediately volunteer to own its simulation if (entityProperties.getDynamic()) {
entity->setScriptSimulationPriority(VOLUNTEER_SIMULATION_PRIORITY); // since we're creating a dynamic object we volunteer immediately to own its simulation
entity->upgradeScriptSimulationPriority(VOLUNTEER_SIMULATION_PRIORITY);
}
entityProperties.setLastEdited(entity->getLastEdited()); entityProperties.setLastEdited(entity->getLastEdited());
} else { } else {
qCDebug(entities) << "AvatarEntitiesBookmark failed to add new Entity to local Octree"; qCDebug(entities) << "AvatarEntitiesBookmark failed to add new Entity to local Octree";

View file

@ -673,7 +673,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
const QUuid& myNodeID = nodeList->getSessionUUID(); const QUuid& myNodeID = nodeList->getSessionUUID();
bool weOwnSimulation = _simulationOwner.matchesValidID(myNodeID); 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 // 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. // even when we would otherwise ignore the rest of the packet.
@ -1358,8 +1358,7 @@ EntityItemProperties EntityItem::getProperties(const EntityPropertyFlags& desire
return properties; return properties;
} }
void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) const { void EntityItem::getTransformAndVelocityProperties(EntityItemProperties& properties) const {
// a TerseUpdate includes the transform and its derivatives
if (!properties._positionChanged) { if (!properties._positionChanged) {
properties._position = getLocalPosition(); properties._position = getLocalPosition();
} }
@ -1383,8 +1382,11 @@ void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) c
properties._accelerationChanged = true; properties._accelerationChanged = true;
} }
void EntityItem::setScriptSimulationPriority(uint8_t priority) { void EntityItem::upgradeScriptSimulationPriority(uint8_t priority) {
uint8_t newPriority = stillHasGrabActions() ? glm::max(priority, SCRIPT_GRAB_SIMULATION_PRIORITY) : priority; uint8_t newPriority = glm::max(priority, _scriptSimulationPriority);
if (newPriority < SCRIPT_GRAB_SIMULATION_PRIORITY && stillHasGrabActions()) {
newPriority = SCRIPT_GRAB_SIMULATION_PRIORITY;
}
if (newPriority != _scriptSimulationPriority) { if (newPriority != _scriptSimulationPriority) {
// set the dirty flag to trigger a bid or ownership update // set the dirty flag to trigger a bid or ownership update
markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_PRIORITY); markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_PRIORITY);
@ -1419,7 +1421,7 @@ bool EntityItem::stillWaitingToTakeOwnership(uint64_t timestamp) const {
bool EntityItem::setProperties(const EntityItemProperties& properties) { bool EntityItem::setProperties(const EntityItemProperties& properties) {
bool somethingChanged = false; 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(simulationOwner, setSimulationOwner);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(position, setPosition); SET_ENTITY_PROPERTY_FROM_PROPERTIES(position, setPosition);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(rotation, setRotation); SET_ENTITY_PROPERTY_FROM_PROPERTIES(rotation, setRotation);
@ -3256,3 +3258,26 @@ void EntityItem::setScriptHasFinishedPreload(bool value) {
bool EntityItem::isScriptPreloadFinished() { bool EntityItem::isScriptPreloadFinished() {
return _scriptPreloadFinished; 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
}

View file

@ -325,7 +325,7 @@ public:
// TODO: move this "ScriptSimulationPriority" and "PendingOwnership" stuff into EntityMotionState // 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" // 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. // to allow libs that don't know about each other to communicate.
void setScriptSimulationPriority(uint8_t priority); void upgradeScriptSimulationPriority(uint8_t priority);
void clearScriptSimulationPriority(); void clearScriptSimulationPriority();
uint8_t getScriptSimulationPriority() const { return _scriptSimulationPriority; } uint8_t getScriptSimulationPriority() const { return _scriptSimulationPriority; }
void setPendingOwnershipPriority(uint8_t priority); void setPendingOwnershipPriority(uint8_t priority);
@ -420,7 +420,7 @@ public:
quint64 getLastEditedFromRemote() const { return _lastEditedFromRemote; } quint64 getLastEditedFromRemote() const { return _lastEditedFromRemote; }
void updateLastEditedFromRemote() { _lastEditedFromRemote = usecTimestampNow(); } void updateLastEditedFromRemote() { _lastEditedFromRemote = usecTimestampNow(); }
void getAllTerseUpdateProperties(EntityItemProperties& properties) const; void getTransformAndVelocityProperties(EntityItemProperties& properties) const;
void flagForMotionStateChange() { _flags |= Simulation::DIRTY_MOTION_TYPE; } void flagForMotionStateChange() { _flags |= Simulation::DIRTY_MOTION_TYPE; }
@ -535,6 +535,8 @@ public:
const GrabPropertyGroup& getGrabProperties() const { return _grabProperties; } const GrabPropertyGroup& getGrabProperties() const { return _grabProperties; }
void prepareForSimulationOwnershipBid(EntityItemProperties& properties, uint64_t now, uint8_t priority);
signals: signals:
void requestRenderUpdate(); void requestRenderUpdate();
void spaceUpdate(std::pair<int32_t, glm::vec4> data); void spaceUpdate(std::pair<int32_t, glm::vec4> data);

View file

@ -3244,9 +3244,12 @@ AABox EntityItemProperties::getAABox() const {
return AABox(rotatedExtentsRelativeToRegistrationPoint); return AABox(rotatedExtentsRelativeToRegistrationPoint);
} }
bool EntityItemProperties::hasTerseUpdateChanges() const { bool EntityItemProperties::hasTransformOrVelocityChanges() const {
// a TerseUpdate includes the transform and its derivatives return _positionChanged ||_localPositionChanged
return _positionChanged || _velocityChanged || _rotationChanged || _angularVelocityChanged || _accelerationChanged; || _rotationChanged || _localRotationChanged
|| _velocityChanged || _localVelocityChanged
|| _angularVelocityChanged || _localAngularVelocityChanged
|| _accelerationChanged;
} }
bool EntityItemProperties::hasMiscPhysicsChanges() const { bool EntityItemProperties::hasMiscPhysicsChanges() const {
@ -3255,6 +3258,56 @@ bool EntityItemProperties::hasMiscPhysicsChanges() const {
_compoundShapeURLChanged || _dynamicChanged || _collisionlessChanged || _collisionMaskChanged; _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() { void EntityItemProperties::clearSimulationOwner() {
_simulationOwner.clear(); _simulationOwner.clear();
_simulationOwnerChanged = true; _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> EntityItemProperties::listChangedProperties() {
QList<QString> out; QList<QString> out;
if (containsPositionChange()) { if (containsPositionChange()) {

View file

@ -349,13 +349,18 @@ public:
void setCreated(QDateTime& v); void setCreated(QDateTime& v);
bool hasTerseUpdateChanges() const; bool hasTransformOrVelocityChanges() const;
bool hasMiscPhysicsChanges() const; bool hasMiscPhysicsChanges() const;
bool hasSimulationRestrictedChanges() const;
void copySimulationRestrictedProperties(const EntityItemPointer& entity);
void clearSimulationRestrictedProperties();
void clearSimulationOwner(); void clearSimulationOwner();
void setSimulationOwner(const QUuid& id, uint8_t priority); void setSimulationOwner(const QUuid& id, uint8_t priority);
void setSimulationOwner(const QByteArray& data); void setSimulationOwner(const QByteArray& data);
void setSimulationPriority(uint8_t priority) { _simulationOwner.setPriority(priority); } void setSimulationPriority(uint8_t priority) { _simulationOwner.setPriority(priority); }
uint8_t computeSimulationBidPriority() const;
void setActionDataDirty() { _actionDataChanged = true; } void setActionDataDirty() { _actionDataChanged = true; }

View file

@ -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, EntityItemProperties convertPropertiesFromScriptSemantics(const EntityItemProperties& scriptSideProperties,
bool scalesWithParent) { bool scalesWithParent) {
// convert position and rotation properties from world-space to local, unless localPosition and localRotation // 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++; _activityTracking.addedEntityCount++;
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
auto sessionID = nodeList->getSessionUUID(); const auto sessionID = nodeList->getSessionUUID();
EntityItemProperties propertiesWithSimID = properties; EntityItemProperties propertiesWithSimID = properties;
if (clientOnly) { if (clientOnly) {
const QUuid myNodeID = sessionID;
propertiesWithSimID.setClientOnly(clientOnly); propertiesWithSimID.setClientOnly(clientOnly);
propertiesWithSimID.setOwningAvatarID(myNodeID); propertiesWithSimID.setOwningAvatarID(sessionID);
} }
propertiesWithSimID.setLastEditedBy(sessionID); propertiesWithSimID.setLastEditedBy(sessionID);
@ -290,7 +290,7 @@ bool EntityScriptingInterface::addLocalEntityCopy(EntityItemProperties& properti
entity->setLastBroadcast(usecTimestampNow()); entity->setLastBroadcast(usecTimestampNow());
// since we're creating this object we will immediately volunteer to own its simulation // 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()); properties.setLastEdited(entity->getLastEdited());
} else { } else {
qCDebug(entities) << "script failed to add new Entity to local Octree"; qCDebug(entities) << "script failed to add new Entity to local Octree";
@ -530,54 +530,86 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties&
_activityTracking.editedEntityCount++; _activityTracking.editedEntityCount++;
auto nodeList = DependencyManager::get<NodeList>(); const auto sessionID = DependencyManager::get<NodeList>()->getSessionUUID();
auto sessionID = nodeList->getSessionUUID();
EntityItemProperties properties = scriptSideProperties; EntityItemProperties properties = scriptSideProperties;
properties.setLastEditedBy(sessionID);
EntityItemID entityID(id); EntityItemID entityID(id);
if (!_entityTree) { if (!_entityTree) {
properties.setLastEditedBy(sessionID);
queueEntityMessage(PacketType::EntityEdit, entityID, properties); queueEntityMessage(PacketType::EntityEdit, entityID, properties);
return id; return id;
} }
// If we have a local entity tree set, then also update it.
bool updatedEntity = false; EntityItemPointer entity(nullptr);
_entityTree->withWriteLock([&] { SimulationOwner simulationOwner;
EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID); _entityTree->withReadLock([&] {
// make a copy of entity for local logic outside of tree lock
entity = _entityTree->findEntityByEntityItemID(entityID);
if (!entity) { if (!entity) {
return; return;
} }
if (entity->getClientOnly() && entity->getOwningAvatarID() != nodeList->getSessionUUID()) { if (entity->getClientOnly() && entity->getOwningAvatarID() != sessionID) {
// don't edit other avatar's avatarEntities // don't edit other avatar's avatarEntities
properties = EntityItemProperties();
return; return;
} }
// make a copy of simulationOwner for local logic outside of tree lock
simulationOwner = entity->getSimulationOwner();
});
if (scriptSideProperties.parentRelatedPropertyChanged()) { if (entity) {
// All of parentID, parentJointIndex, position, rotation are needed to make sense of any of them. if (properties.hasSimulationRestrictedChanges()) {
// If any of these changed, pull any missing properties from the entity. 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()) { uint8_t desiredPriority = entity->getScriptSimulationPriority();
properties.setParentID(entity->getParentID()); if (desiredPriority < simulationOwner.getPriority()) {
} // the priority at which we'd like to own it is not high enough
if (!scriptSideProperties.parentJointIndexChanged()) { // --> assume failure and clear all restricted property changes
properties.setParentJointIndex(entity->getParentJointIndex()); properties.clearSimulationRestrictedProperties();
} } else {
if (!scriptSideProperties.localPositionChanged() && !scriptSideProperties.positionChanged()) { // the priority at which we'd like to own it is high enough to win.
properties.setPosition(entity->getWorldPosition()); // --> assume success and copy ALL restricted properties
} properties.copySimulationRestrictedProperties(entity);
if (!scriptSideProperties.localRotationChanged() && !scriptSideProperties.rotationChanged()) { }
properties.setRotation(entity->getWorldOrientation()); }
} } else if (!simulationOwner.getID().isNull()) {
if (!scriptSideProperties.localDimensionsChanged() && !scriptSideProperties.dimensionsChanged()) { // someone owns this but not us
properties.setDimensions(entity->getScaledDimensions()); // 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.setClientOnly(entity->getClientOnly());
properties.setOwningAvatarID(entity->getOwningAvatarID()); 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); updatedEntity = _entityTree->updateEntity(entityID, properties);
}); });
@ -590,63 +622,37 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties&
// return QUuid(); // return QUuid();
// } // }
bool entityFound { false }; bool hasQueryAACubeRelatedChanges = properties.queryAACubeRelatedPropertyChanged();
// done writing, send update
_entityTree->withReadLock([&] { _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) { if (entity) {
entityFound = true; uint64_t now = usecTimestampNow();
// make sure the properties has a type, so that the encode can know which properties to include entity->setLastBroadcast(now);
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();
if (entity->getSimulatorID() == myNodeID) { if (hasQueryAACubeRelatedChanges) {
// 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()) {
properties.setQueryAACube(entity->getQueryAACube()); 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 we've moved an entity with children, check/update the queryAACube of all descendents and tell the server
// if they've changed. // if they've changed.
entity->forEachDescendant([&](SpatiallyNestablePointer descendant) { entity->forEachDescendant([&](SpatiallyNestablePointer descendant) {
if (descendant->getNestableType() == NestableType::Entity) { if (descendant->getNestableType() == NestableType::Entity) {
if (descendant->updateQueryAACube()) { if (descendant->updateQueryAACube()) {
EntityItemPointer entityDescendant = std::static_pointer_cast<EntityItem>(descendant); EntityItemPointer entityDescendant = std::static_pointer_cast<EntityItem>(descendant);
EntityItemProperties newQueryCubeProperties; EntityItemProperties newQueryCubeProperties;
newQueryCubeProperties.setQueryAACube(descendant->getQueryAACube()); newQueryCubeProperties.setQueryAACube(descendant->getQueryAACube());
newQueryCubeProperties.setLastEdited(properties.getLastEdited()); newQueryCubeProperties.setLastEdited(properties.getLastEdited());
queueEntityMessage(PacketType::EntityEdit, descendant->getID(), newQueryCubeProperties); queueEntityMessage(PacketType::EntityEdit, descendant->getID(), newQueryCubeProperties);
entityDescendant->setLastBroadcast(usecTimestampNow()); 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, // 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. // 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 // 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()); 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, // 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. // print a warning and don't send an edit packet to the entity-server.
QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>(); QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
@ -1449,7 +1453,7 @@ QUuid EntityScriptingInterface::addAction(const QString& actionTypeString,
} }
action->setIsMine(true); action->setIsMine(true);
success = entity->addAction(simulation, action); 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. return false; // Physics will cause a packet to be sent, so don't send from here.
}); });
if (success) { if (success) {
@ -1465,7 +1469,7 @@ bool EntityScriptingInterface::updateAction(const QUuid& entityID, const QUuid&
return actionWorker(entityID, [&](EntitySimulationPointer simulation, EntityItemPointer entity) { return actionWorker(entityID, [&](EntitySimulationPointer simulation, EntityItemPointer entity) {
bool success = entity->updateAction(simulation, actionID, arguments); bool success = entity->updateAction(simulation, actionID, arguments);
if (success) { if (success) {
entity->setScriptSimulationPriority(SCRIPT_GRAB_SIMULATION_PRIORITY); entity->upgradeScriptSimulationPriority(SCRIPT_GRAB_SIMULATION_PRIORITY);
} }
return success; return success;
}); });
@ -1479,7 +1483,7 @@ bool EntityScriptingInterface::deleteAction(const QUuid& entityID, const QUuid&
success = entity->removeAction(simulation, actionID); success = entity->removeAction(simulation, actionID);
if (success) { if (success) {
// reduce from grab to poke // 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. return false; // Physics will cause a packet to be sent, so don't send from here.
}); });

View file

@ -502,36 +502,18 @@ void EntityMotionState::sendBid(OctreeEditPacketSender* packetSender, uint32_t s
properties.setVelocity(linearVelocity); properties.setVelocity(linearVelocity);
properties.setAcceleration(_entity->getAcceleration()); properties.setAcceleration(_entity->getAcceleration());
properties.setAngularVelocity(angularVelocity); 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 // 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(); uint8_t finalBidPriority = computeFinalBidPriority();
_entity->clearScriptSimulationPriority(); _entity->prepareForSimulationOwnershipBid(properties, now, finalBidPriority);
properties.setSimulationOwner(Physics::getSessionUUID(), finalBidPriority);
_entity->setPendingOwnershipPriority(finalBidPriority);
EntityTreeElementPointer element = _entity->getElement(); EntityTreeElementPointer element = _entity->getElement();
EntityTreePointer tree = element ? element->getTree() : nullptr; EntityTreePointer tree = element ? element->getTree() : nullptr;
properties.setClientOnly(_entity->getClientOnly());
properties.setOwningAvatarID(_entity->getOwningAvatarID());
EntityItemID id(_entity->getID()); EntityItemID id(_entity->getID());
EntityEditPacketSender* entityPacketSender = static_cast<EntityEditPacketSender*>(packetSender); EntityEditPacketSender* entityPacketSender = static_cast<EntityEditPacketSender*>(packetSender);
entityPacketSender->queueEditEntityMessage(PacketType::EntityPhysics, tree, id, properties); 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 // 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. // then in sendUpdate() we'll walk descendents and send updates for their QueryAACubes if necessary.