diff --git a/assignment-client/src/AssignmentAction.cpp b/assignment-client/src/AssignmentAction.cpp index 8b5650ee42..388f4123f6 100644 --- a/assignment-client/src/AssignmentAction.cpp +++ b/assignment-client/src/AssignmentAction.cpp @@ -24,15 +24,24 @@ AssignmentAction::~AssignmentAction() { } void AssignmentAction::removeFromSimulation(EntitySimulation* simulation) const { - simulation->removeAction(_id); + withReadLock([&]{ + simulation->removeAction(_id); + simulation->applyActionChanges(); + }); } QByteArray AssignmentAction::serialize() const { - return _data; + QByteArray result; + withReadLock([&]{ + result = _data; + }); + return result; } void AssignmentAction::deserialize(QByteArray serializedArguments) { - _data = serializedArguments; + withWriteLock([&]{ + _data = serializedArguments; + }); } bool AssignmentAction::updateArguments(QVariantMap arguments) { diff --git a/assignment-client/src/AssignmentAction.h b/assignment-client/src/AssignmentAction.h index 23720bd465..6b901c9766 100644 --- a/assignment-client/src/AssignmentAction.h +++ b/assignment-client/src/AssignmentAction.h @@ -19,7 +19,7 @@ #include "EntityActionInterface.h" -class AssignmentAction : public EntityActionInterface { +class AssignmentAction : public EntityActionInterface, public ReadWriteLockable { public: AssignmentAction(EntityActionType type, const QUuid& id, EntityItemPointer ownerEntity); virtual ~AssignmentAction(); diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index bdd5728246..f2a4c2664a 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -147,9 +147,13 @@ bool EntityServer::readAdditionalConfiguration(const QJsonObject& settingsSectio readOptionBool(QString("wantEditLogging"), settingsSectionObject, wantEditLogging); qDebug("wantEditLogging=%s", debug::valueOf(wantEditLogging)); + bool wantTerseEditLogging = false; + readOptionBool(QString("wantTerseEditLogging"), settingsSectionObject, wantTerseEditLogging); + qDebug("wantTerseEditLogging=%s", debug::valueOf(wantTerseEditLogging)); EntityTreePointer tree = std::static_pointer_cast(_tree); tree->setWantEditLogging(wantEditLogging); + tree->setWantTerseEditLogging(wantTerseEditLogging); return true; } diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index eb1c478489..e0038117f0 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -484,6 +484,14 @@ "default": false, "advanced": true }, + { + "name": "wantTerseEditLogging", + "type": "checkbox", + "label": "Edit Logging (Terse)", + "help": "Logging of all edits to entities", + "default": false, + "advanced": true + }, { "name": "verboseDebug", "type": "checkbox", diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index f4bc7496da..117ee8c453 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -66,7 +66,8 @@ var MSEC_PER_SEC = 1000.0; // these control how long an abandoned pointer line will hang around var startTime = Date.now(); var LIFETIME = 10; -var ACTION_LIFETIME = 10; // seconds +var ACTION_LIFETIME = 15; // seconds +var ACTION_LIFETIME_REFRESH = 5; var PICKS_PER_SECOND_PER_HAND = 5; var MSECS_PER_SEC = 1000.0; @@ -339,11 +340,12 @@ function MyController(hand, triggerAction) { var handRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm)); var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation", "gravity", "ignoreForCollisions"]); + var now = Date.now(); // add the action and initialize some variables this.currentObjectPosition = grabbedProperties.position; this.currentObjectRotation = grabbedProperties.rotation; - this.currentObjectTime = Date.now(); + this.currentObjectTime = now; this.handPreviousPosition = handControllerPosition; this.handPreviousRotation = handRotation; @@ -359,6 +361,7 @@ function MyController(hand, triggerAction) { if (this.actionID === NULL_ACTION_ID) { this.actionID = null; } + this.actionTimeout = now + (ACTION_LIFETIME * MSEC_PER_SEC); if (this.actionID !== null) { this.setState(STATE_CONTINUE_DISTANCE_HOLDING); @@ -441,7 +444,9 @@ function MyController(hand, triggerAction) { this.currentObjectTime = now; // this doubles hand rotation - var handChange = Quat.multiply(Quat.slerp(this.handPreviousRotation, handRotation, DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR), Quat.inverse(this.handPreviousRotation)); + var handChange = Quat.multiply(Quat.slerp(this.handPreviousRotation, handRotation, + DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR), + Quat.inverse(this.handPreviousRotation)); this.handPreviousRotation = handRotation; this.currentObjectRotation = Quat.multiply(handChange, this.currentObjectRotation); @@ -454,9 +459,11 @@ function MyController(hand, triggerAction) { angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, lifetime: ACTION_LIFETIME }); + this.actionTimeout = now + (ACTION_LIFETIME * MSEC_PER_SEC); }; this.nearGrabbing = function() { + var now = Date.now(); if (this.triggerSmoothedReleased()) { this.setState(STATE_RELEASE); @@ -465,7 +472,7 @@ function MyController(hand, triggerAction) { this.lineOff(); - var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, + var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation", "gravity", "ignoreForCollisions"]); this.activateEntity(this.grabbedEntity, grabbedProperties); @@ -473,23 +480,24 @@ function MyController(hand, triggerAction) { var handPosition = this.getHandPosition(); var objectRotation = grabbedProperties.rotation; - var offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation); + this.offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation); var currentObjectPosition = grabbedProperties.position; var offset = Vec3.subtract(currentObjectPosition, handPosition); - var offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, offsetRotation)), offset); + this.offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, this.offsetRotation)), offset); this.actionID = NULL_ACTION_ID; this.actionID = Entities.addAction("hold", this.grabbedEntity, { hand: this.hand === RIGHT_HAND ? "right" : "left", timeScale: NEAR_GRABBING_ACTION_TIMEFRAME, - relativePosition: offsetPosition, - relativeRotation: offsetRotation, + relativePosition: this.offsetPosition, + relativeRotation: this.offsetRotation, lifetime: ACTION_LIFETIME }); if (this.actionID === NULL_ACTION_ID) { this.actionID = null; } else { + this.actionTimeout = now + (ACTION_LIFETIME * MSEC_PER_SEC); this.setState(STATE_CONTINUE_NEAR_GRABBING); if (this.hand === RIGHT_HAND) { Entities.callEntityMethod(this.grabbedEntity, "setRightHand"); @@ -511,10 +519,10 @@ function MyController(hand, triggerAction) { return; } - // Keep track of the fingertip velocity to impart when we release the object - // Note that the idea of using a constant 'tip' velocity regardless of the + // Keep track of the fingertip velocity to impart when we release the object. + // Note that the idea of using a constant 'tip' velocity regardless of the // object's actual held offset is an idea intended to make it easier to throw things: - // Because we might catch something or transfer it between hands without a good idea + // Because we might catch something or transfer it between hands without a good idea // of it's actual offset, let's try imparting a velocity which is at a fixed radius // from the palm. @@ -529,9 +537,17 @@ function MyController(hand, triggerAction) { this.currentObjectTime = now; Entities.callEntityMethod(this.grabbedEntity, "continueNearGrab"); - Entities.updateAction(this.grabbedEntity, this.actionID, { - lifetime: ACTION_LIFETIME - }); + if (this.actionTimeout - now < ACTION_LIFETIME_REFRESH * MSEC_PER_SEC) { + // if less than a 5 seconds left, refresh the actions lifetime + Entities.updateAction(this.grabbedEntity, this.actionID, { + hand: this.hand === RIGHT_HAND ? "right" : "left", + timeScale: NEAR_GRABBING_ACTION_TIMEFRAME, + relativePosition: this.offsetPosition, + relativeRotation: this.offsetRotation, + lifetime: ACTION_LIFETIME + }); + this.actionTimeout = now + (ACTION_LIFETIME * MSEC_PER_SEC); + } }; this.nearGrabbingNonColliding = function() { diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index c0636314b5..7796e4d840 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -56,6 +56,7 @@ const float DISPLAYNAME_FADE_TIME = 0.5f; const float DISPLAYNAME_FADE_FACTOR = pow(0.01f, 1.0f / DISPLAYNAME_FADE_TIME); const float DISPLAYNAME_ALPHA = 1.0f; const float DISPLAYNAME_BACKGROUND_ALPHA = 0.4f; +const glm::vec3 HAND_TO_PALM_OFFSET(0.0f, 0.12f, 0.08f); namespace render { template <> const ItemKey payloadGetKey(const AvatarSharedPointer& avatar) { @@ -1167,3 +1168,64 @@ void Avatar::rebuildSkeletonBody() { DependencyManager::get()->updateAvatarPhysicsShape(getSessionUUID()); } +glm::vec3 Avatar::getLeftPalmPosition() { + glm::vec3 leftHandPosition; + getSkeletonModel().getLeftHandPosition(leftHandPosition); + glm::quat leftRotation; + getSkeletonModel().getJointRotationInWorldFrame(getSkeletonModel().getLeftHandJointIndex(), leftRotation); + leftHandPosition += HAND_TO_PALM_OFFSET * glm::inverse(leftRotation); + return leftHandPosition; +} + +glm::vec3 Avatar::getLeftPalmVelocity() { + const PalmData* palm = getHand()->getPalm(LEFT_HAND_INDEX); + if (palm != NULL) { + return palm->getVelocity(); + } + return glm::vec3(0.0f); +} + +glm::vec3 Avatar::getLeftPalmAngularVelocity() { + const PalmData* palm = getHand()->getPalm(LEFT_HAND_INDEX); + if (palm != NULL) { + return palm->getRawAngularVelocity(); + } + return glm::vec3(0.0f); +} + +glm::quat Avatar::getLeftPalmRotation() { + glm::quat leftRotation; + getSkeletonModel().getJointRotationInWorldFrame(getSkeletonModel().getLeftHandJointIndex(), leftRotation); + return leftRotation; +} + +glm::vec3 Avatar::getRightPalmPosition() { + glm::vec3 rightHandPosition; + getSkeletonModel().getRightHandPosition(rightHandPosition); + glm::quat rightRotation; + getSkeletonModel().getJointRotationInWorldFrame(getSkeletonModel().getRightHandJointIndex(), rightRotation); + rightHandPosition += HAND_TO_PALM_OFFSET * glm::inverse(rightRotation); + return rightHandPosition; +} + +glm::vec3 Avatar::getRightPalmVelocity() { + const PalmData* palm = getHand()->getPalm(RIGHT_HAND_INDEX); + if (palm != NULL) { + return palm->getVelocity(); + } + return glm::vec3(0.0f); +} + +glm::vec3 Avatar::getRightPalmAngularVelocity() { + const PalmData* palm = getHand()->getPalm(RIGHT_HAND_INDEX); + if (palm != NULL) { + return palm->getRawAngularVelocity(); + } + return glm::vec3(0.0f); +} + +glm::quat Avatar::getRightPalmRotation() { + glm::quat rightRotation; + getSkeletonModel().getJointRotationInWorldFrame(getSkeletonModel().getRightHandJointIndex(), rightRotation); + return rightRotation; +} diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 534aefd3cb..9a46a145c2 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -174,6 +174,16 @@ public: void setMotionState(AvatarMotionState* motionState) { _motionState = motionState; } AvatarMotionState* getMotionState() { return _motionState; } +public slots: + glm::vec3 getLeftPalmPosition(); + glm::vec3 getLeftPalmVelocity(); + glm::vec3 getLeftPalmAngularVelocity(); + glm::quat getLeftPalmRotation(); + glm::vec3 getRightPalmPosition(); + glm::vec3 getRightPalmVelocity(); + glm::vec3 getRightPalmAngularVelocity(); + glm::quat getRightPalmRotation(); + protected: SkeletonModel _skeletonModel; glm::vec3 _skeletonOffset; diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index 1fa50b79fd..3c57db084b 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -21,8 +21,7 @@ AvatarActionHold::AvatarActionHold(const QUuid& id, EntityItemPointer ownerEntit ObjectActionSpring(id, ownerEntity), _relativePosition(glm::vec3(0.0f)), _relativeRotation(glm::quat()), - _hand("right"), - _mine(false) + _hand("right") { _type = ACTION_TYPE_HOLD; #if WANT_DEBUG @@ -37,17 +36,12 @@ AvatarActionHold::~AvatarActionHold() { } void AvatarActionHold::updateActionWorker(float deltaTimeStep) { - if (!_mine) { - // if a local script isn't updating this, then we are just getting spring-action data over the wire. - // let the super-class handle it. - ObjectActionSpring::updateActionWorker(deltaTimeStep); - return; - } - + bool gotLock = false; glm::quat rotation; glm::vec3 position; glm::vec3 offset; - bool gotLock = withTryReadLock([&]{ + + gotLock = withTryReadLock([&]{ auto myAvatar = DependencyManager::get()->getMyAvatar(); glm::vec3 palmPosition; glm::quat palmRotation; @@ -66,17 +60,16 @@ void AvatarActionHold::updateActionWorker(float deltaTimeStep) { if (gotLock) { gotLock = withTryWriteLock([&]{ - if (_positionalTarget != position || _rotationalTarget != rotation) { - auto ownerEntity = _ownerEntity.lock(); - if (ownerEntity) { - ownerEntity->setActionDataDirty(true); - } - _positionalTarget = position; - _rotationalTarget = rotation; + _positionalTarget = position; + _rotationalTarget = rotation; + _positionalTargetSet = true; + _rotationalTargetSet = true; + auto ownerEntity = _ownerEntity.lock(); + if (ownerEntity) { + ownerEntity->setActionDataDirty(true); } }); } - if (gotLock) { ObjectActionSpring::updateActionWorker(deltaTimeStep); } @@ -84,66 +77,76 @@ void AvatarActionHold::updateActionWorker(float deltaTimeStep) { bool AvatarActionHold::updateArguments(QVariantMap arguments) { - if (!ObjectAction::updateArguments(arguments)) { - return false; - } - bool ok = true; - glm::vec3 relativePosition = - EntityActionInterface::extractVec3Argument("hold", arguments, "relativePosition", ok, false); - if (!ok) { - relativePosition = _relativePosition; - } + glm::vec3 relativePosition; + glm::quat relativeRotation; + float timeScale; + QString hand; + QUuid holderID; + bool needUpdate = false; - ok = true; - glm::quat relativeRotation = - EntityActionInterface::extractQuatArgument("hold", arguments, "relativeRotation", ok, false); - if (!ok) { - relativeRotation = _relativeRotation; - } - - ok = true; - float timeScale = - EntityActionInterface::extractFloatArgument("hold", arguments, "timeScale", ok, false); - if (!ok) { - timeScale = _linearTimeScale; - } + bool somethingChanged = ObjectAction::updateArguments(arguments); + withReadLock([&]{ + bool ok = true; + relativePosition = EntityActionInterface::extractVec3Argument("hold", arguments, "relativePosition", ok, false); + if (!ok) { + relativePosition = _relativePosition; + } - ok = true; - QString hand = - EntityActionInterface::extractStringArgument("hold", arguments, "hand", ok, false); - if (!ok || !(hand == "left" || hand == "right")) { - hand = _hand; - } + ok = true; + relativeRotation = EntityActionInterface::extractQuatArgument("hold", arguments, "relativeRotation", ok, false); + if (!ok) { + relativeRotation = _relativeRotation; + } - if (relativePosition != _relativePosition - || relativeRotation != _relativeRotation - || timeScale != _linearTimeScale - || hand != _hand) { + ok = true; + timeScale = EntityActionInterface::extractFloatArgument("hold", arguments, "timeScale", ok, false); + if (!ok) { + timeScale = _linearTimeScale; + } + + ok = true; + hand = EntityActionInterface::extractStringArgument("hold", arguments, "hand", ok, false); + if (!ok || !(hand == "left" || hand == "right")) { + hand = _hand; + } + + ok = true; + auto myAvatar = DependencyManager::get()->getMyAvatar(); + holderID = myAvatar->getSessionUUID(); + + if (somethingChanged || + relativePosition != _relativePosition || + relativeRotation != _relativeRotation || + timeScale != _linearTimeScale || + hand != _hand) { + needUpdate = true; + } + }); + + if (needUpdate) { withWriteLock([&] { _relativePosition = relativePosition; _relativeRotation = relativeRotation; const float MIN_TIMESCALE = 0.1f; - _linearTimeScale = glm::min(MIN_TIMESCALE, timeScale); + _linearTimeScale = glm::max(MIN_TIMESCALE, timeScale); _angularTimeScale = _linearTimeScale; _hand = hand; - - _mine = true; _active = true; - activateBody(); + + auto ownerEntity = _ownerEntity.lock(); + if (ownerEntity) { + ownerEntity->setActionDataDirty(true); + } }); + activateBody(); } + return true; } - QVariantMap AvatarActionHold::getArguments() { QVariantMap arguments = ObjectAction::getArguments(); withReadLock([&]{ - if (!_mine) { - arguments = ObjectActionSpring::getArguments(); - return; - } - arguments["relativePosition"] = glmToQMap(_relativePosition); arguments["relativeRotation"] = glmToQMap(_relativeRotation); arguments["timeScale"] = _linearTimeScale; @@ -152,9 +155,10 @@ QVariantMap AvatarActionHold::getArguments() { return arguments; } +QByteArray AvatarActionHold::serialize() const { + return ObjectActionSpring::serialize(); +} void AvatarActionHold::deserialize(QByteArray serializedArguments) { - if (!_mine) { - ObjectActionSpring::deserialize(serializedArguments); - } + assert(false); } diff --git a/interface/src/avatar/AvatarActionHold.h b/interface/src/avatar/AvatarActionHold.h index 3500b5dfa1..840ba41c28 100644 --- a/interface/src/avatar/AvatarActionHold.h +++ b/interface/src/avatar/AvatarActionHold.h @@ -27,15 +27,17 @@ public: virtual void updateActionWorker(float deltaTimeStep); + QByteArray serialize() const; virtual void deserialize(QByteArray serializedArguments); + virtual bool shouldSuppressLocationEdits() { return false; } + private: static const uint16_t holdVersion; glm::vec3 _relativePosition; glm::quat _relativeRotation; QString _hand; - bool _mine = false; }; #endif // hifi_AvatarActionHold_h diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 69d76db7de..6e52fa1f85 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -343,3 +343,11 @@ void AvatarManager::updateAvatarRenderStatus(bool shouldRenderAvatars) { } } } + + +AvatarSharedPointer AvatarManager::getAvatarBySessionID(const QUuid& sessionID) { + if (sessionID == _myAvatar->getSessionUUID()) { + return std::static_pointer_cast(_myAvatar); + } + return getAvatarHash()[sessionID]; +} diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 277e931419..35c18dff0b 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -35,7 +35,8 @@ public: void init(); MyAvatar* getMyAvatar() { return _myAvatar.get(); } - + AvatarSharedPointer getAvatarBySessionID(const QUuid& sessionID); + void updateMyAvatar(float deltaTime); void updateOtherAvatars(float deltaTime); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 7c8a787f12..5920543dca 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -540,70 +540,6 @@ void MyAvatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { } } -const glm::vec3 HAND_TO_PALM_OFFSET(0.0f, 0.12f, 0.08f); - -glm::vec3 MyAvatar::getLeftPalmPosition() { - glm::vec3 leftHandPosition; - getSkeletonModel().getLeftHandPosition(leftHandPosition); - glm::quat leftRotation; - getSkeletonModel().getJointRotationInWorldFrame(getSkeletonModel().getLeftHandJointIndex(), leftRotation); - leftHandPosition += HAND_TO_PALM_OFFSET * glm::inverse(leftRotation); - return leftHandPosition; -} - -glm::vec3 MyAvatar::getLeftPalmVelocity() { - const PalmData* palm = getHand()->getPalm(LEFT_HAND_INDEX); - if (palm != NULL) { - return palm->getVelocity(); - } - return glm::vec3(0.0f); -} - -glm::vec3 MyAvatar::getLeftPalmAngularVelocity() { - const PalmData* palm = getHand()->getPalm(LEFT_HAND_INDEX); - if (palm != NULL) { - return palm->getRawAngularVelocity(); - } - return glm::vec3(0.0f); -} - -glm::quat MyAvatar::getLeftPalmRotation() { - glm::quat leftRotation; - getSkeletonModel().getJointRotationInWorldFrame(getSkeletonModel().getLeftHandJointIndex(), leftRotation); - return leftRotation; -} - -glm::vec3 MyAvatar::getRightPalmPosition() { - glm::vec3 rightHandPosition; - getSkeletonModel().getRightHandPosition(rightHandPosition); - glm::quat rightRotation; - getSkeletonModel().getJointRotationInWorldFrame(getSkeletonModel().getRightHandJointIndex(), rightRotation); - rightHandPosition += HAND_TO_PALM_OFFSET * glm::inverse(rightRotation); - return rightHandPosition; -} - -glm::vec3 MyAvatar::getRightPalmVelocity() { - const PalmData* palm = getHand()->getPalm(RIGHT_HAND_INDEX); - if (palm != NULL) { - return palm->getVelocity(); - } - return glm::vec3(0.0f); -} - -glm::vec3 MyAvatar::getRightPalmAngularVelocity() { - const PalmData* palm = getHand()->getPalm(RIGHT_HAND_INDEX); - if (palm != NULL) { - return palm->getRawAngularVelocity(); - } - return glm::vec3(0.0f); -} - -glm::quat MyAvatar::getRightPalmRotation() { - glm::quat rightRotation; - getSkeletonModel().getJointRotationInWorldFrame(getSkeletonModel().getRightHandJointIndex(), rightRotation); - return rightRotation; -} - void MyAvatar::clearReferential() { changeReferential(NULL); } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index e3d13a5e80..7347419fee 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -199,15 +199,6 @@ public slots: Q_INVOKABLE void updateMotionBehaviorFromMenu(); - glm::vec3 getLeftPalmPosition(); - glm::vec3 getLeftPalmVelocity(); - glm::vec3 getLeftPalmAngularVelocity(); - glm::quat getLeftPalmRotation(); - glm::vec3 getRightPalmPosition(); - glm::vec3 getRightPalmVelocity(); - glm::vec3 getRightPalmAngularVelocity(); - glm::quat getRightPalmRotation(); - void clearReferential(); bool setModelReferential(const QUuid& id); bool setJointReferential(const QUuid& id, int jointIndex); diff --git a/libraries/entities/src/AnimationPropertyGroup.cpp b/libraries/entities/src/AnimationPropertyGroup.cpp index d1da465079..f9d8c07443 100644 --- a/libraries/entities/src/AnimationPropertyGroup.cpp +++ b/libraries/entities/src/AnimationPropertyGroup.cpp @@ -163,6 +163,19 @@ void AnimationPropertyGroup::debugDump() const { qDebug() << "currentFrame:" << getCurrentFrame() << " has changed:" << currentFrameChanged(); } +void AnimationPropertyGroup::listChangedProperties(QList& out) { + if (urlChanged()) { + out << "animation-url"; + } + if (fpsChanged()) { + out << "animation-fps"; + } + if (currentFrameChanged()) { + out << "animation-currentFrame"; + } +} + + bool AnimationPropertyGroup::appendToEditPacket(OctreePacketData* packetData, EntityPropertyFlags& requestedProperties, EntityPropertyFlags& propertyFlags, diff --git a/libraries/entities/src/AnimationPropertyGroup.h b/libraries/entities/src/AnimationPropertyGroup.h index d0d218f4b3..8c40b0c036 100644 --- a/libraries/entities/src/AnimationPropertyGroup.h +++ b/libraries/entities/src/AnimationPropertyGroup.h @@ -37,6 +37,7 @@ public: virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const; virtual void copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings); virtual void debugDump() const; + virtual void listChangedProperties(QList& out); virtual bool appendToEditPacket(OctreePacketData* packetData, EntityPropertyFlags& requestedProperties, diff --git a/libraries/entities/src/AtmospherePropertyGroup.cpp b/libraries/entities/src/AtmospherePropertyGroup.cpp index 090fdb6c6f..8e7a5a5262 100644 --- a/libraries/entities/src/AtmospherePropertyGroup.cpp +++ b/libraries/entities/src/AtmospherePropertyGroup.cpp @@ -54,6 +54,30 @@ void AtmospherePropertyGroup::debugDump() const { qDebug() << " Has Stars:" << getHasStars() << " has changed:" << hasStarsChanged(); } +void AtmospherePropertyGroup::listChangedProperties(QList& out) { + if (centerChanged()) { + out << "center"; + } + if (innerRadiusChanged()) { + out << "innerRadius"; + } + if (outerRadiusChanged()) { + out << "outerRadius"; + } + if (mieScatteringChanged()) { + out << "mieScattering"; + } + if (rayleighScatteringChanged()) { + out << "rayleighScattering"; + } + if (scatteringWavelengthsChanged()) { + out << "scatteringWavelengths"; + } + if (hasStarsChanged()) { + out << "hasStars"; + } +} + bool AtmospherePropertyGroup::appendToEditPacket(OctreePacketData* packetData, EntityPropertyFlags& requestedProperties, EntityPropertyFlags& propertyFlags, diff --git a/libraries/entities/src/AtmospherePropertyGroup.h b/libraries/entities/src/AtmospherePropertyGroup.h index 661d91087b..1d43c848b8 100644 --- a/libraries/entities/src/AtmospherePropertyGroup.h +++ b/libraries/entities/src/AtmospherePropertyGroup.h @@ -53,6 +53,7 @@ public: virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const; virtual void copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings); virtual void debugDump() const; + virtual void listChangedProperties(QList& out); virtual bool appendToEditPacket(OctreePacketData* packetData, EntityPropertyFlags& requestedProperties, @@ -87,7 +88,7 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged); - + static const glm::vec3 DEFAULT_CENTER; static const float DEFAULT_INNER_RADIUS; static const float DEFAULT_OUTER_RADIUS; diff --git a/libraries/entities/src/EntityActionInterface.h b/libraries/entities/src/EntityActionInterface.h index 57f605c3e3..49739e7da9 100644 --- a/libraries/entities/src/EntityActionInterface.h +++ b/libraries/entities/src/EntityActionInterface.h @@ -51,15 +51,7 @@ public: bool locallyAddedButNotYetReceived = false; -protected: - virtual glm::vec3 getPosition() = 0; - virtual void setPosition(glm::vec3 position) = 0; - virtual glm::quat getRotation() = 0; - virtual void setRotation(glm::quat rotation) = 0; - virtual glm::vec3 getLinearVelocity() = 0; - virtual void setLinearVelocity(glm::vec3 linearVelocity) = 0; - virtual glm::vec3 getAngularVelocity() = 0; - virtual void setAngularVelocity(glm::vec3 angularVelocity) = 0; + virtual bool shouldSuppressLocationEdits() { return false; } // these look in the arguments map for a named argument. if it's not found or isn't well formed, // ok will be set to false (note that it's never set to true -- set it to true before calling these). @@ -75,6 +67,16 @@ protected: static QString extractStringArgument(QString objectName, QVariantMap arguments, QString argumentName, bool& ok, bool required = true); +protected: + virtual glm::vec3 getPosition() = 0; + virtual void setPosition(glm::vec3 position) = 0; + virtual glm::quat getRotation() = 0; + virtual void setRotation(glm::quat rotation) = 0; + virtual glm::vec3 getLinearVelocity() = 0; + virtual void setLinearVelocity(glm::vec3 linearVelocity) = 0; + virtual glm::vec3 getAngularVelocity() = 0; + virtual void setAngularVelocity(glm::vec3 angularVelocity) = 0; + QUuid _id; EntityActionType _type; }; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index a8f3adc12e..1ae0c481ac 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1579,6 +1579,7 @@ bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulation* s } EntityActionPointer action = _objectActions[actionID]; + action->setOwnerEntity(nullptr); _objectActions.remove(actionID); @@ -1630,8 +1631,6 @@ void EntityItem::deserializeActionsInternal() { return; } - // Keep track of which actions got added or updated by the new actionData - EntityTreePointer entityTree = _element ? _element->getTree() : nullptr; assert(entityTree); EntitySimulation* simulation = entityTree ? entityTree->getSimulation() : nullptr; @@ -1643,6 +1642,7 @@ void EntityItem::deserializeActionsInternal() { serializedActionsStream >> serializedActions; } + // Keep track of which actions got added or updated by the new actionData QSet updated; foreach(QByteArray serializedAction, serializedActions) { @@ -1720,9 +1720,11 @@ void EntityItem::setActionData(QByteArray actionData) { void EntityItem::setActionDataInternal(QByteArray actionData) { assertWriteLocked(); + if (_allActionsDataCache != actionData) { + _allActionsDataCache = actionData; + deserializeActionsInternal(); + } checkWaitingToRemove(); - _allActionsDataCache = actionData; - deserializeActionsInternal(); } void EntityItem::serializeActions(bool& success, QByteArray& result) const { @@ -1788,3 +1790,15 @@ QVariantMap EntityItem::getActionArguments(const QUuid& actionID) const { return result; } + +bool EntityItem::shouldSuppressLocationEdits() const { + QHash::const_iterator i = _objectActions.begin(); + while (i != _objectActions.end()) { + if (i.value()->shouldSuppressLocationEdits()) { + return true; + } + i++; + } + + return false; +} diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index cddd9df312..cc8fa6c00d 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -424,6 +424,7 @@ public: QVariantMap getActionArguments(const QUuid& actionID) const; void deserializeActions(); void setActionDataDirty(bool value) const { _actionDataDirty = value; } + bool shouldSuppressLocationEdits() const; protected: diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 4cbf7a043c..19c8f779b4 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1519,3 +1519,254 @@ void EntityItemProperties::setSimulationOwner(const QByteArray& data) { _simulationOwnerChanged = true; } } + +QList EntityItemProperties::listChangedProperties() { + QList out; + if (containsPositionChange()) { + out += "posistion"; + } + if (dimensionsChanged()) { + out += "dimensions"; + } + if (velocityChanged()) { + out += "velocity"; + } + if (nameChanged()) { + out += "name"; + } + if (visibleChanged()) { + out += "visible"; + } + if (rotationChanged()) { + out += "rotation"; + } + if (densityChanged()) { + out += "density"; + } + if (gravityChanged()) { + out += "gravity"; + } + if (accelerationChanged()) { + out += "acceleration"; + } + if (dampingChanged()) { + out += "damping"; + } + if (restitutionChanged()) { + out += "restitution"; + } + if (frictionChanged()) { + out += "friction"; + } + if (lifetimeChanged()) { + out += "lifetime"; + } + if (scriptChanged()) { + out += "script"; + } + if (scriptTimestampChanged()) { + out += "scriptTimestamp"; + } + if (collisionSoundURLChanged()) { + out += "collisionSoundURL"; + } + if (colorChanged()) { + out += "color"; + } + if (colorSpreadChanged()) { + out += "colorSpread"; + } + if (colorStartChanged()) { + out += "colorStart"; + } + if (colorFinishChanged()) { + out += "colorFinish"; + } + if (alphaChanged()) { + out += "alpha"; + } + if (alphaSpreadChanged()) { + out += "alphaSpread"; + } + if (alphaStartChanged()) { + out += "alphaStart"; + } + if (alphaFinishChanged()) { + out += "alphaFinish"; + } + if (modelURLChanged()) { + out += "modelURL"; + } + if (compoundShapeURLChanged()) { + out += "compoundShapeURL"; + } + if (registrationPointChanged()) { + out += "registrationPoint"; + } + if (angularVelocityChanged()) { + out += "angularVelocity"; + } + if (angularDampingChanged()) { + out += "angularDamping"; + } + if (ignoreForCollisionsChanged()) { + out += "ignoreForCollisions"; + } + if (collisionsWillMoveChanged()) { + out += "collisionsWillMove"; + } + if (isSpotlightChanged()) { + out += "isSpotlight"; + } + if (intensityChanged()) { + out += "intensity"; + } + if (exponentChanged()) { + out += "exponent"; + } + if (cutoffChanged()) { + out += "cutoff"; + } + if (lockedChanged()) { + out += "locked"; + } + if (texturesChanged()) { + out += "textures"; + } + if (userDataChanged()) { + out += "userData"; + } + if (simulationOwnerChanged()) { + out += "simulationOwner"; + } + if (textChanged()) { + out += "text"; + } + if (lineHeightChanged()) { + out += "lineHeight"; + } + if (textColorChanged()) { + out += "textColor"; + } + if (backgroundColorChanged()) { + out += "backgroundColor"; + } + if (shapeTypeChanged()) { + out += "shapeType"; + } + if (maxParticlesChanged()) { + out += "maxParticles"; + } + if (lifespanChanged()) { + out += "lifespan"; + } + if (isEmittingChanged()) { + out += "isEmitting"; + } + if (emitRateChanged()) { + out += "emitRate"; + } + if (emitSpeedChanged()) { + out += "emitSpeed"; + } + if (speedSpreadChanged()) { + out += "speedSpread"; + } + if (emitOrientationChanged()) { + out += "emitOrientation"; + } + if (emitDimensionsChanged()) { + out += "emitDimensions"; + } + if (emitRadiusStartChanged()) { + out += "emitRadiusStart"; + } + if (polarStartChanged()) { + out += "polarStart"; + } + if (polarFinishChanged()) { + out += "polarFinish"; + } + if (azimuthStartChanged()) { + out += "azimuthStart"; + } + if (azimuthFinishChanged()) { + out += "azimuthFinish"; + } + if (emitAccelerationChanged()) { + out += "emitAcceleration"; + } + if (accelerationSpreadChanged()) { + out += "accelerationSpread"; + } + if (particleRadiusChanged()) { + out += "particleRadius"; + } + if (radiusSpreadChanged()) { + out += "radiusSpread"; + } + if (radiusStartChanged()) { + out += "radiusStart"; + } + if (radiusFinishChanged()) { + out += "radiusFinish"; + } + if (marketplaceIDChanged()) { + out += "marketplaceID"; + } + if (backgroundModeChanged()) { + out += "backgroundMode"; + } + if (voxelVolumeSizeChanged()) { + out += "voxelVolumeSize"; + } + if (voxelDataChanged()) { + out += "voxelData"; + } + if (voxelSurfaceStyleChanged()) { + out += "voxelSurfaceStyle"; + } + if (hrefChanged()) { + out += "href"; + } + if (descriptionChanged()) { + out += "description"; + } + if (actionDataChanged()) { + out += "actionData"; + } + if (xTextureURLChanged()) { + out += "xTextureURL"; + } + if (yTextureURLChanged()) { + out += "yTextureURL"; + } + if (zTextureURLChanged()) { + out += "zTextureURL"; + } + if (xNNeighborIDChanged()) { + out += "xNNeighborID"; + } + if (yNNeighborIDChanged()) { + out += "yNNeighborID"; + } + if (zNNeighborIDChanged()) { + out += "zNNeighborID"; + } + if (xPNeighborIDChanged()) { + out += "xPNeighborID"; + } + if (yPNeighborIDChanged()) { + out += "yPNeighborID"; + } + if (zPNeighborIDChanged()) { + out += "zPNeighborID"; + } + + getAnimation().listChangedProperties(out); + getAtmosphere().listChangedProperties(out); + getSkybox().listChangedProperties(out); + getStage().listChangedProperties(out); + + return out; +} diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 22a4a298ef..4ed7454c17 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -253,6 +253,8 @@ public: void setActionDataDirty() { _actionDataChanged = true; } + QList listChangedProperties(); + private: QUuid _id; bool _idSet; @@ -370,7 +372,9 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, VoxelSurfaceStyle, voxelSurfaceStyle, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, Href, href, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, Description, description, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, ActionData, actionData, ""); + if (properties.actionDataChanged()) { + debug << " " << "actionData" << ":" << properties.getActionData().toHex() << "" << "\n"; + } DEBUG_PROPERTY_IF_CHANGED(debug, properties, XTextureURL, xTextureURL, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, YTextureURL, yTextureURL, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, ZTextureURL, zTextureURL, ""); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index c4c02d364f..fa2153f059 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -613,6 +613,9 @@ int EntityTree::processEditPacketData(NLPacket& packet, const unsigned char* edi qCDebug(entities) << "User [" << senderNode->getUUID() << "] editing entity. ID:" << entityItemID; qCDebug(entities) << " properties:" << properties; } + if (wantTerseEditLogging()) { + qCDebug(entities) << "edit" << entityItemID.toString() << properties.listChangedProperties(); + } endLogging = usecTimestampNow(); startUpdate = usecTimestampNow(); @@ -638,6 +641,9 @@ int EntityTree::processEditPacketData(NLPacket& packet, const unsigned char* edi << newEntity->getEntityItemID(); qCDebug(entities) << " properties:" << properties; } + if (wantTerseEditLogging()) { + qCDebug(entities) << "add" << entityItemID.toString() << properties.listChangedProperties(); + } endLogging = usecTimestampNow(); } @@ -869,7 +875,7 @@ int EntityTree::processEraseMessage(NLPacket& packet, const SharedNodePointer& s EntityItemID entityItemID(entityID); entityItemIDsToDelete << entityItemID; - if (wantEditLogging()) { + if (wantEditLogging() || wantTerseEditLogging()) { qCDebug(entities) << "User [" << sourceNode->getUUID() << "] deleting entity. ID:" << entityItemID; } @@ -913,7 +919,7 @@ int EntityTree::processEraseMessageDetails(const QByteArray& dataByteArray, cons EntityItemID entityItemID(entityID); entityItemIDsToDelete << entityItemID; - if (wantEditLogging()) { + if (wantEditLogging() || wantTerseEditLogging()) { qCDebug(entities) << "User [" << sourceNode->getUUID() << "] deleting entity. ID:" << entityItemID; } diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index dd1ee01969..ff84a79088 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -175,6 +175,9 @@ public: bool wantEditLogging() const { return _wantEditLogging; } void setWantEditLogging(bool value) { _wantEditLogging = value; } + bool wantTerseEditLogging() const { return _wantTerseEditLogging; } + void setWantTerseEditLogging(bool value) { _wantTerseEditLogging = value; } + bool writeToMap(QVariantMap& entityDescription, OctreeElementPointer element, bool skipDefaultValues); bool readFromMap(QVariantMap& entityDescription); @@ -240,6 +243,7 @@ private: EntitySimulation* _simulation; bool _wantEditLogging = false; + bool _wantTerseEditLogging = false; void maybeNotifyNewCollisionSoundURL(const QString& oldCollisionSoundURL, const QString& newCollisionSoundURL); diff --git a/libraries/entities/src/PropertyGroup.h b/libraries/entities/src/PropertyGroup.h index 27d35fa714..138ee020c1 100644 --- a/libraries/entities/src/PropertyGroup.h +++ b/libraries/entities/src/PropertyGroup.h @@ -57,6 +57,7 @@ public: virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const = 0; virtual void copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) = 0; virtual void debugDump() const { } + virtual void listChangedProperties(QList& out) { } virtual bool appendToEditPacket(OctreePacketData* packetData, EntityPropertyFlags& requestedProperties, diff --git a/libraries/entities/src/SkyboxPropertyGroup.cpp b/libraries/entities/src/SkyboxPropertyGroup.cpp index d291627d1e..0fd00bfe6e 100644 --- a/libraries/entities/src/SkyboxPropertyGroup.cpp +++ b/libraries/entities/src/SkyboxPropertyGroup.cpp @@ -33,6 +33,15 @@ void SkyboxPropertyGroup::debugDump() const { qDebug() << " URL:" << getURL() << " has changed:" << urlChanged(); } +void SkyboxPropertyGroup::listChangedProperties(QList& out) { + if (colorChanged()) { + out << "skybox-color"; + } + if (urlChanged()) { + out << "skybox-url"; + } +} + bool SkyboxPropertyGroup::appendToEditPacket(OctreePacketData* packetData, EntityPropertyFlags& requestedProperties, EntityPropertyFlags& propertyFlags, diff --git a/libraries/entities/src/SkyboxPropertyGroup.h b/libraries/entities/src/SkyboxPropertyGroup.h index 2ebfcfda14..745f762821 100644 --- a/libraries/entities/src/SkyboxPropertyGroup.h +++ b/libraries/entities/src/SkyboxPropertyGroup.h @@ -33,6 +33,7 @@ public: virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const; virtual void copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings); virtual void debugDump() const; + virtual void listChangedProperties(QList& out); virtual bool appendToEditPacket(OctreePacketData* packetData, EntityPropertyFlags& requestedProperties, diff --git a/libraries/entities/src/StagePropertyGroup.cpp b/libraries/entities/src/StagePropertyGroup.cpp index 629f65b72f..0c10795d6f 100644 --- a/libraries/entities/src/StagePropertyGroup.cpp +++ b/libraries/entities/src/StagePropertyGroup.cpp @@ -66,6 +66,27 @@ void StagePropertyGroup::debugDump() const { qDebug() << " _automaticHourDay:" << _automaticHourDay; } +void StagePropertyGroup::listChangedProperties(QList& out) { + if (sunModelEnabledChanged()) { + out << "stage-sunModelEnabled"; + } + if (latitudeChanged()) { + out << "stage-latitude"; + } + if (altitudeChanged()) { + out << "stage-altitude"; + } + if (dayChanged()) { + out << "stage-day"; + } + if (hourChanged()) { + out << "stage-hour"; + } + if (automaticHourDayChanged()) { + out << "stage-automaticHourDay"; + } +} + bool StagePropertyGroup::appendToEditPacket(OctreePacketData* packetData, EntityPropertyFlags& requestedProperties, EntityPropertyFlags& propertyFlags, diff --git a/libraries/entities/src/StagePropertyGroup.h b/libraries/entities/src/StagePropertyGroup.h index 95964f8264..c25a1e629e 100644 --- a/libraries/entities/src/StagePropertyGroup.h +++ b/libraries/entities/src/StagePropertyGroup.h @@ -33,6 +33,7 @@ public: virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const; virtual void copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings); virtual void debugDump() const; + virtual void listChangedProperties(QList& out); virtual bool appendToEditPacket(OctreePacketData* packetData, EntityPropertyFlags& requestedProperties, diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 42bf9bd438..2621347373 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -291,6 +291,10 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) { return true; } + if (_entity->shouldSuppressLocationEdits()) { + return false; + } + // Else we measure the error between current and extrapolated transform (according to expected behavior // of remote EntitySimulation) and return true if the error is significant. diff --git a/libraries/physics/src/ObjectAction.cpp b/libraries/physics/src/ObjectAction.cpp index 82395c21cf..2f0de6d0ab 100644 --- a/libraries/physics/src/ObjectAction.cpp +++ b/libraries/physics/src/ObjectAction.cpp @@ -24,20 +24,33 @@ ObjectAction::~ObjectAction() { } void ObjectAction::updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep) { - if (_ownerEntity.expired()) { + bool ownerEntityExpired = false; + quint64 expiresWhen = 0; + + withReadLock([&]{ + ownerEntityExpired = _ownerEntity.expired(); + expiresWhen = _expires; + }); + + if (ownerEntityExpired) { qDebug() << "warning -- action with no entity removing self from btCollisionWorld."; btDynamicsWorld* dynamicsWorld = static_cast(collisionWorld); dynamicsWorld->removeAction(this); return; } - if (_expires > 0) { + if (expiresWhen > 0) { quint64 now = usecTimestampNow(); - if (now > _expires) { - EntityItemPointer ownerEntity = _ownerEntity.lock(); - _active = false; + if (now > expiresWhen) { + EntityItemPointer ownerEntity = nullptr; + QUuid myID; + withWriteLock([&]{ + ownerEntity = _ownerEntity.lock(); + _active = false; + myID = getID(); + }); if (ownerEntity) { - ownerEntity->removeAction(nullptr, getID()); + ownerEntity->removeAction(nullptr, myID); } } } @@ -50,35 +63,48 @@ void ObjectAction::updateAction(btCollisionWorld* collisionWorld, btScalar delta } bool ObjectAction::updateArguments(QVariantMap arguments) { - bool lifetimeSet = true; - float lifetime = EntityActionInterface::extractFloatArgument("action", arguments, "lifetime", lifetimeSet, false); - if (lifetimeSet) { - quint64 now = usecTimestampNow(); - _expires = now + (quint64)(lifetime * USECS_PER_SECOND); - } else { - _expires = 0; - } + bool somethingChanged = false; - bool tagSet = true; - QString tag = EntityActionInterface::extractStringArgument("action", arguments, "tag", tagSet, false); - if (tagSet) { - _tag = tag; - } else { - tag = ""; - } + withWriteLock([&]{ + quint64 previousExpires = _expires; + QString previousTag = _tag; - return true; + bool lifetimeSet = true; + float lifetime = EntityActionInterface::extractFloatArgument("action", arguments, "lifetime", lifetimeSet, false); + if (lifetimeSet) { + quint64 now = usecTimestampNow(); + _expires = now + (quint64)(lifetime * USECS_PER_SECOND); + } else { + _expires = 0; + } + + bool tagSet = true; + QString tag = EntityActionInterface::extractStringArgument("action", arguments, "tag", tagSet, false); + if (tagSet) { + _tag = tag; + } else { + tag = ""; + } + + if (previousExpires != _expires || previousTag != _tag) { + somethingChanged = true; + } + }); + + return somethingChanged; } QVariantMap ObjectAction::getArguments() { QVariantMap arguments; - if (_expires == 0) { - arguments["lifetime"] = 0.0f; - } else { - quint64 now = usecTimestampNow(); - arguments["lifetime"] = (float)(_expires - now) / (float)USECS_PER_SECOND; - } - arguments["tag"] = _tag; + withReadLock([&]{ + if (_expires == 0) { + arguments["lifetime"] = 0.0f; + } else { + quint64 now = usecTimestampNow(); + arguments["lifetime"] = (float)(_expires - now) / (float)USECS_PER_SECOND; + } + arguments["tag"] = _tag; + }); return arguments; } @@ -87,20 +113,30 @@ void ObjectAction::debugDraw(btIDebugDraw* debugDrawer) { } void ObjectAction::removeFromSimulation(EntitySimulation* simulation) const { - simulation->removeAction(_id); + QUuid myID; + withReadLock([&]{ + myID = _id; + }); + simulation->removeAction(myID); } btRigidBody* ObjectAction::getRigidBody() { - auto ownerEntity = _ownerEntity.lock(); - if (!ownerEntity) { - return nullptr; + ObjectMotionState* motionState = nullptr; + withReadLock([&]{ + auto ownerEntity = _ownerEntity.lock(); + if (!ownerEntity) { + return; + } + void* physicsInfo = ownerEntity->getPhysicsInfo(); + if (!physicsInfo) { + return; + } + motionState = static_cast(physicsInfo); + }); + if (motionState) { + return motionState->getRigidBody(); } - void* physicsInfo = ownerEntity->getPhysicsInfo(); - if (!physicsInfo) { - return nullptr; - } - ObjectMotionState* motionState = static_cast(physicsInfo); - return motionState->getRigidBody(); + return nullptr; } glm::vec3 ObjectAction::getPosition() { diff --git a/libraries/physics/src/ObjectActionOffset.cpp b/libraries/physics/src/ObjectActionOffset.cpp index 448ec34689..d01178dcc3 100644 --- a/libraries/physics/src/ObjectActionOffset.cpp +++ b/libraries/physics/src/ObjectActionOffset.cpp @@ -80,44 +80,61 @@ void ObjectActionOffset::updateActionWorker(btScalar deltaTimeStep) { bool ObjectActionOffset::updateArguments(QVariantMap arguments) { - if (!ObjectAction::updateArguments(arguments)) { - return false; - } - bool ok = true; - glm::vec3 pointToOffsetFrom = - EntityActionInterface::extractVec3Argument("offset action", arguments, "pointToOffsetFrom", ok, true); - if (!ok) { - pointToOffsetFrom = _pointToOffsetFrom; - } + glm::vec3 pointToOffsetFrom; + float linearTimeScale; + float linearDistance; - ok = true; - float linearTimeScale = - EntityActionInterface::extractFloatArgument("offset action", arguments, "linearTimeScale", ok, false); - if (!ok) { - linearTimeScale = _linearTimeScale; - } + bool needUpdate = false; + bool somethingChanged = ObjectAction::updateArguments(arguments); - ok = true; - float linearDistance = - EntityActionInterface::extractFloatArgument("offset action", arguments, "linearDistance", ok, false); - if (!ok) { - linearDistance = _linearDistance; - } + withReadLock([&]{ + bool ok = true; + pointToOffsetFrom = + EntityActionInterface::extractVec3Argument("offset action", arguments, "pointToOffsetFrom", ok, true); + if (!ok) { + pointToOffsetFrom = _pointToOffsetFrom; + } - // only change stuff if something actually changed - if (_pointToOffsetFrom != pointToOffsetFrom - || _linearTimeScale != linearTimeScale - || _linearDistance != linearDistance) { + ok = true; + linearTimeScale = + EntityActionInterface::extractFloatArgument("offset action", arguments, "linearTimeScale", ok, false); + if (!ok) { + linearTimeScale = _linearTimeScale; + } + ok = true; + linearDistance = + EntityActionInterface::extractFloatArgument("offset action", arguments, "linearDistance", ok, false); + if (!ok) { + linearDistance = _linearDistance; + } + + // only change stuff if something actually changed + if (somethingChanged || + _pointToOffsetFrom != pointToOffsetFrom || + _linearTimeScale != linearTimeScale || + _linearDistance != linearDistance) { + needUpdate = true; + } + }); + + + if (needUpdate) { withWriteLock([&] { _pointToOffsetFrom = pointToOffsetFrom; _linearTimeScale = linearTimeScale; _linearDistance = linearDistance; _positionalTargetSet = true; _active = true; - activateBody(); + + auto ownerEntity = _ownerEntity.lock(); + if (ownerEntity) { + ownerEntity->setActionDataDirty(true); + } }); + activateBody(); } + return true; } @@ -134,17 +151,18 @@ QVariantMap ObjectActionOffset::getArguments() { QByteArray ObjectActionOffset::serialize() const { QByteArray ba; QDataStream dataStream(&ba, QIODevice::WriteOnly); - dataStream << getType(); + dataStream << ACTION_TYPE_OFFSET; dataStream << getID(); dataStream << ObjectActionOffset::offsetVersion; - dataStream << _pointToOffsetFrom; - dataStream << _linearDistance; - dataStream << _linearTimeScale; - dataStream << _positionalTargetSet; - - dataStream << _expires; - dataStream << _tag; + withReadLock([&] { + dataStream << _pointToOffsetFrom; + dataStream << _linearDistance; + dataStream << _linearTimeScale; + dataStream << _positionalTargetSet; + dataStream << _expires; + dataStream << _tag; + }); return ba; } @@ -166,13 +184,13 @@ void ObjectActionOffset::deserialize(QByteArray serializedArguments) { return; } - dataStream >> _pointToOffsetFrom; - dataStream >> _linearDistance; - dataStream >> _linearTimeScale; - dataStream >> _positionalTargetSet; - - dataStream >> _expires; - dataStream >> _tag; - - _active = true; + withWriteLock([&] { + dataStream >> _pointToOffsetFrom; + dataStream >> _linearDistance; + dataStream >> _linearTimeScale; + dataStream >> _positionalTargetSet; + dataStream >> _expires; + dataStream >> _tag; + _active = true; + }); } diff --git a/libraries/physics/src/ObjectActionSpring.cpp b/libraries/physics/src/ObjectActionSpring.cpp index 7d0bab5143..a99cfdd747 100644 --- a/libraries/physics/src/ObjectActionSpring.cpp +++ b/libraries/physics/src/ObjectActionSpring.cpp @@ -38,6 +38,7 @@ ObjectActionSpring::~ObjectActionSpring() { } void ObjectActionSpring::updateActionWorker(btScalar deltaTimeStep) { + // don't risk hanging the thread running the physics simulation auto lockResult = withTryReadLock([&]{ auto ownerEntity = _ownerEntity.lock(); if (!ownerEntity) { @@ -100,60 +101,73 @@ void ObjectActionSpring::updateActionWorker(btScalar deltaTimeStep) { } }); if (!lockResult) { - // don't risk hanging the thread running the physics simulation qDebug() << "ObjectActionSpring::updateActionWorker lock failed"; - return; } } const float MIN_TIMESCALE = 0.1f; + bool ObjectActionSpring::updateArguments(QVariantMap arguments) { - if (!ObjectAction::updateArguments(arguments)) { - return false; - } - // targets are required, spring-constants are optional - bool ok = true; - glm::vec3 positionalTarget = - EntityActionInterface::extractVec3Argument("spring action", arguments, "targetPosition", ok, false); - if (!ok) { - positionalTarget = _positionalTarget; - } - ok = true; - float linearTimeScale = - EntityActionInterface::extractFloatArgument("spring action", arguments, "linearTimeScale", ok, false); - if (!ok || linearTimeScale <= 0.0f) { - linearTimeScale = _linearTimeScale; - } + glm::vec3 positionalTarget; + float linearTimeScale; + glm::quat rotationalTarget; + float angularTimeScale; - ok = true; - glm::quat rotationalTarget = - EntityActionInterface::extractQuatArgument("spring action", arguments, "targetRotation", ok, false); - if (!ok) { - rotationalTarget = _rotationalTarget; - } + bool needUpdate = false; + bool somethingChanged = ObjectAction::updateArguments(arguments); + withReadLock([&]{ + // targets are required, spring-constants are optional + bool ok = true; + positionalTarget = EntityActionInterface::extractVec3Argument("spring action", arguments, "targetPosition", ok, false); + if (!ok) { + positionalTarget = _positionalTarget; + } + ok = true; + linearTimeScale = EntityActionInterface::extractFloatArgument("spring action", arguments, "linearTimeScale", ok, false); + if (!ok || linearTimeScale <= 0.0f) { + linearTimeScale = _linearTimeScale; + } - ok = true; - float angularTimeScale = - EntityActionInterface::extractFloatArgument("spring action", arguments, "angularTimeScale", ok, false); - if (!ok) { - angularTimeScale = _angularTimeScale; - } + ok = true; + rotationalTarget = EntityActionInterface::extractQuatArgument("spring action", arguments, "targetRotation", ok, false); + if (!ok) { + rotationalTarget = _rotationalTarget; + } - if (positionalTarget != _positionalTarget - || linearTimeScale != _linearTimeScale - || rotationalTarget != _rotationalTarget - || angularTimeScale != _angularTimeScale) { - // something changed + ok = true; + angularTimeScale = + EntityActionInterface::extractFloatArgument("spring action", arguments, "angularTimeScale", ok, false); + if (!ok) { + angularTimeScale = _angularTimeScale; + } + + if (somethingChanged || + positionalTarget != _positionalTarget || + linearTimeScale != _linearTimeScale || + rotationalTarget != _rotationalTarget || + angularTimeScale != _angularTimeScale) { + // something changed + needUpdate = true; + } + }); + + if (needUpdate) { withWriteLock([&] { _positionalTarget = positionalTarget; _linearTimeScale = glm::max(MIN_TIMESCALE, glm::abs(linearTimeScale)); _rotationalTarget = rotationalTarget; _angularTimeScale = glm::max(MIN_TIMESCALE, glm::abs(angularTimeScale)); _active = true; - activateBody(); + + auto ownerEntity = _ownerEntity.lock(); + if (ownerEntity) { + ownerEntity->setActionDataDirty(true); + } }); + activateBody(); } + return true; } @@ -177,16 +191,16 @@ QByteArray ObjectActionSpring::serialize() const { dataStream << getID(); dataStream << ObjectActionSpring::springVersion; - dataStream << _positionalTarget; - dataStream << _linearTimeScale; - dataStream << _positionalTargetSet; - - dataStream << _rotationalTarget; - dataStream << _angularTimeScale; - dataStream << _rotationalTargetSet; - - dataStream << _expires; - dataStream << _tag; + withReadLock([&] { + dataStream << _positionalTarget; + dataStream << _linearTimeScale; + dataStream << _positionalTargetSet; + dataStream << _rotationalTarget; + dataStream << _angularTimeScale; + dataStream << _rotationalTargetSet; + dataStream << _expires; + dataStream << _tag; + }); return serializedActionArguments; } @@ -205,19 +219,22 @@ void ObjectActionSpring::deserialize(QByteArray serializedArguments) { uint16_t serializationVersion; dataStream >> serializationVersion; if (serializationVersion != ObjectActionSpring::springVersion) { + assert(false); return; } - dataStream >> _positionalTarget; - dataStream >> _linearTimeScale; - dataStream >> _positionalTargetSet; + withWriteLock([&] { + dataStream >> _positionalTarget; + dataStream >> _linearTimeScale; + dataStream >> _positionalTargetSet; - dataStream >> _rotationalTarget; - dataStream >> _angularTimeScale; - dataStream >> _rotationalTargetSet; + dataStream >> _rotationalTarget; + dataStream >> _angularTimeScale; + dataStream >> _rotationalTargetSet; - dataStream >> _expires; - dataStream >> _tag; + dataStream >> _expires; + dataStream >> _tag; - _active = true; + _active = true; + }); }