diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 92d9270d20..3f32f96795 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -5300,6 +5300,21 @@ void MyAvatar::releaseGrab(const QUuid& grabID) { bool tellHandler { false }; _avatarGrabsLock.withWriteLock([&] { + + std::map::iterator itr; + itr = _avatarGrabs.find(grabID); + if (itr != _avatarGrabs.end()) { + GrabPointer grab = itr->second; + if (grab) { + grab->setReleased(true); + bool success; + SpatiallyNestablePointer target = SpatiallyNestable::findByID(grab->getTargetID(), success); + if (target && success) { + target->disableGrab(grab); + } + } + } + if (_avatarGrabData.remove(grabID)) { _grabsToDelete.push_back(grabID); tellHandler = true; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 07c1ca9a32..b8626c813e 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -412,6 +412,9 @@ void Avatar::accumulateGrabPositions(std::map& g if (!grab || !grab->getActionID().isNull()) { continue; // the accumulated value isn't used, in this case. } + if (grab->getReleased()) { + continue; + } glm::vec3 jointTranslation = getAbsoluteJointTranslationInObjectFrame(grab->getParentJointIndex()); glm::quat jointRotation = getAbsoluteJointRotationInObjectFrame(grab->getParentJointIndex()); diff --git a/libraries/entities/src/EntityDynamicInterface.h b/libraries/entities/src/EntityDynamicInterface.h index 836dae2057..c911eda471 100644 --- a/libraries/entities/src/EntityDynamicInterface.h +++ b/libraries/entities/src/EntityDynamicInterface.h @@ -59,6 +59,7 @@ public: virtual bool isReadyForAdd() const { return true; } bool isActive() { return _active; } + void deactivate() { _active = false; } virtual void removeFromSimulation(EntitySimulationPointer simulation) const = 0; virtual EntityItemWeakPointer getOwnerEntity() const = 0; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 41e4f43a5d..1640e97ff4 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -3506,3 +3506,13 @@ void EntityItem::removeGrab(GrabPointer grab) { } disableNoBootstrap(); } + +void EntityItem::disableGrab(GrabPointer grab) { + QUuid actionID = grab->getActionID(); + if (!actionID.isNull()) { + EntityDynamicPointer action = _grabActions.value(actionID); + if (action) { + action->deactivate(); + } + } +} diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index ec7ad78313..27b207b6f3 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -561,6 +561,7 @@ public: virtual void addGrab(GrabPointer grab) override; virtual void removeGrab(GrabPointer grab) override; + virtual void disableGrab(GrabPointer grab) override; signals: void requestRenderUpdate(); diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index a82931064a..ce9cb20c21 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -115,17 +115,30 @@ void EntityMotionState::updateServerPhysicsVariables() { } void EntityMotionState::handleDeactivation() { - // copy _server data to entity - Transform localTransform = _entity->getLocalTransform(); - localTransform.setTranslation(_serverPosition); - localTransform.setRotation(_serverRotation); - _entity->setLocalTransformAndVelocities(localTransform, ENTITY_ITEM_ZERO_VEC3, ENTITY_ITEM_ZERO_VEC3); - // and also to RigidBody - btTransform worldTrans; - worldTrans.setOrigin(glmToBullet(_entity->getWorldPosition())); - worldTrans.setRotation(glmToBullet(_entity->getWorldOrientation())); - _body->setWorldTransform(worldTrans); - // no need to update velocities... should already be zero + if (_entity->getDirtyFlags() & (Simulation::DIRTY_TRANSFORM | Simulation::DIRTY_VELOCITIES)) { + // Some non-physical event (script-call or network-packet) has modified the entity's transform and/or velocities + // at the last minute before deactivation --> the values stored in _server* and _body are stale. + // We assume the EntityMotionState is the last to know, so we copy from EntityItem and let things sort themselves out. + Transform localTransform; + _entity->getLocalTransformAndVelocities(localTransform, _serverVelocity, _serverAngularVelocity); + _serverPosition = localTransform.getTranslation(); + _serverRotation = localTransform.getRotation(); + _serverAcceleration = _entity->getAcceleration(); + _serverActionData = _entity->getDynamicData(); + _lastStep = ObjectMotionState::getWorldSimulationStep(); + } else { + // copy _server data to entity + Transform localTransform = _entity->getLocalTransform(); + localTransform.setTranslation(_serverPosition); + localTransform.setRotation(_serverRotation); + _entity->setLocalTransformAndVelocities(localTransform, ENTITY_ITEM_ZERO_VEC3, ENTITY_ITEM_ZERO_VEC3); + // and also to RigidBody + btTransform worldTrans; + worldTrans.setOrigin(glmToBullet(_entity->getWorldPosition())); + worldTrans.setRotation(glmToBullet(_entity->getWorldOrientation())); + _body->setWorldTransform(worldTrans); + // no need to update velocities... should already be zero + } } // virtual diff --git a/libraries/shared/src/Grab.h b/libraries/shared/src/Grab.h index 5765d6fd0e..f16a80befa 100644 --- a/libraries/shared/src/Grab.h +++ b/libraries/shared/src/Grab.h @@ -26,16 +26,16 @@ public: void accumulate(glm::vec3 position, glm::quat orientation) { _position += position; _orientation = orientation; // XXX - count++; + _count++; } - glm::vec3 finalizePosition() { return count > 0 ? _position * (1.0f / count) : glm::vec3(0.0f); } + glm::vec3 finalizePosition() { return _count > 0 ? _position * (1.0f / _count) : glm::vec3(0.0f); } glm::quat finalizeOrientation() { return _orientation; } // XXX protected: glm::vec3 _position; glm::quat _orientation; - int count { 0 }; + int _count { 0 }; }; class Grab { @@ -48,7 +48,8 @@ public: _parentJointIndex(newParentJointIndex), _hand(newHand), _positionalOffset(newPositionalOffset), - _rotationalOffset(newRotationalOffset) {} + _rotationalOffset(newRotationalOffset), + _released(false) {} QByteArray toByteArray(); bool fromByteArray(const QByteArray& grabData); @@ -61,6 +62,7 @@ public: _positionalOffset = other->_positionalOffset; _rotationalOffset = other->_rotationalOffset; _actionID = other->_actionID; + _released = other->_released; return *this; } @@ -85,6 +87,9 @@ public: glm::quat getRotationalOffset() const { return _rotationalOffset; } void setRotationalOffset(glm::quat rotationalOffset) { _rotationalOffset = rotationalOffset; } + bool getReleased() const { return _released; } + void setReleased(bool value) { _released = value; } + protected: QUuid _actionID; // if an action is created in bullet for this grab, this is the ID QUuid _ownerID; // avatar ID of grabber @@ -93,6 +98,7 @@ protected: QString _hand; // "left" or "right" glm::vec3 _positionalOffset; // relative to joint glm::quat _rotationalOffset; // relative to joint + bool _released { false }; // released and scheduled for deletion }; diff --git a/libraries/shared/src/SpatiallyNestable.cpp b/libraries/shared/src/SpatiallyNestable.cpp index c524e3183b..d3ed79faf4 100644 --- a/libraries/shared/src/SpatiallyNestable.cpp +++ b/libraries/shared/src/SpatiallyNestable.cpp @@ -1390,7 +1390,12 @@ void SpatiallyNestable::removeGrab(GrabPointer grab) { bool SpatiallyNestable::hasGrabs() { bool result { false }; _grabsLock.withReadLock([&] { - result = !_grabs.isEmpty(); + foreach (const GrabPointer &grab, _grabs) { + if (grab && !grab->getReleased()) { + result = true; + break; + } + } }); return result; } diff --git a/libraries/shared/src/SpatiallyNestable.h b/libraries/shared/src/SpatiallyNestable.h index 319f07236b..e7a449f73f 100644 --- a/libraries/shared/src/SpatiallyNestable.h +++ b/libraries/shared/src/SpatiallyNestable.h @@ -218,6 +218,7 @@ public: virtual void addGrab(GrabPointer grab); virtual void removeGrab(GrabPointer grab); + virtual void disableGrab(GrabPointer grab) {}; bool hasGrabs(); virtual QUuid getEditSenderID(); @@ -241,7 +242,7 @@ protected: quint64 _rotationChanged { 0 }; mutable ReadWriteLockable _grabsLock; - QSet _grabs; + QSet _grabs; // upon this thing private: SpatiallyNestable() = delete;