From 7c6846c260b89f52ecc34aba67b52d0703152a9a Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 30 Sep 2015 13:09:41 -0700 Subject: [PATCH] add lifetime and tag arguments to actions --- examples/controllers/handControllerGrab.js | 7 ++- examples/grab.js | 6 +- interface/src/InterfaceActionFactory.cpp | 7 +++ interface/src/avatar/AvatarActionHold.cpp | 5 +- .../entities/src/EntityActionInterface.h | 2 + libraries/physics/src/ObjectAction.cpp | 57 +++++++++++++++++++ libraries/physics/src/ObjectAction.h | 12 ++-- libraries/physics/src/ObjectActionOffset.cpp | 13 ++++- libraries/physics/src/ObjectActionSpring.cpp | 11 +++- 9 files changed, 106 insertions(+), 14 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 388c042285..144500e4de 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -324,7 +324,9 @@ function MyController(hand, triggerAction) { targetPosition: this.currentObjectPosition, linearTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, targetRotation: this.currentObjectRotation, - angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME + angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, + tag: "grab", + lifetime: 5 }); if (this.actionID === NULL_ACTION_ID) { this.actionID = null; @@ -424,7 +426,8 @@ function MyController(hand, triggerAction) { targetPosition: this.currentObjectPosition, linearTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, targetRotation: this.currentObjectRotation, - angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME + angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, + lifetime: 5 }); }; diff --git a/examples/grab.js b/examples/grab.js index 05bcf128e2..15bab17f20 100644 --- a/examples/grab.js +++ b/examples/grab.js @@ -288,7 +288,7 @@ Grabber.prototype.moveEvent = function(event) { } this.currentPosition = entityProperties.position; - var actionArgs = {}; + var actionArgs = {tag: "grab", lifetime: 5}; if (this.mode === "rotate") { var drag = mouse.getDrag(); @@ -303,7 +303,7 @@ Grabber.prototype.moveEvent = function(event) { // var qZero = entityProperties.rotation; //var qZero = this.lastRotation; this.lastRotation = Quat.multiply(deltaQ, this.lastRotation); - actionArgs = {targetRotation: this.lastRotation, angularTimeScale: 0.1}; + actionArgs = {targetRotation: this.lastRotation, angularTimeScale: 0.1, tag: "grab", lifetime: 5}; } else { var newPointOnPlane; if (this.mode === "verticalCylinder") { @@ -327,7 +327,7 @@ Grabber.prototype.moveEvent = function(event) { } } this.targetPosition = Vec3.subtract(newPointOnPlane, this.offset); - actionArgs = {targetPosition: this.targetPosition, linearTimeScale: 0.1}; + actionArgs = {targetPosition: this.targetPosition, linearTimeScale: 0.1, tag: "grab", lifetime: 5}; beacon.updatePosition(this.targetPosition); } diff --git a/interface/src/InterfaceActionFactory.cpp b/interface/src/InterfaceActionFactory.cpp index dca1015ecc..2879c19eaa 100644 --- a/interface/src/InterfaceActionFactory.cpp +++ b/interface/src/InterfaceActionFactory.cpp @@ -43,6 +43,9 @@ EntityActionPointer InterfaceActionFactory::factory(EntityActionType type, if (action) { bool ok = action->updateArguments(arguments); if (ok) { + if (action->lifetimeIsOver()) { + return nullptr; + } return action; } } @@ -63,5 +66,9 @@ EntityActionPointer InterfaceActionFactory::factoryBA(EntityItemPointer ownerEnt if (action) { action->deserialize(data); } + if (action->lifetimeIsOver()) { + return nullptr; + } + return action; } diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index 4ecdb692ac..1fa50b79fd 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -84,6 +84,9 @@ 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); @@ -134,7 +137,7 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) { QVariantMap AvatarActionHold::getArguments() { - QVariantMap arguments; + QVariantMap arguments = ObjectAction::getArguments(); withReadLock([&]{ if (!_mine) { arguments = ObjectActionSpring::getArguments(); diff --git a/libraries/entities/src/EntityActionInterface.h b/libraries/entities/src/EntityActionInterface.h index a4f1c8ea15..e61019c98c 100644 --- a/libraries/entities/src/EntityActionInterface.h +++ b/libraries/entities/src/EntityActionInterface.h @@ -46,6 +46,8 @@ public: static EntityActionType actionTypeFromString(QString actionTypeString); static QString actionTypeToString(EntityActionType actionType); + virtual bool lifetimeIsOver() { return false; } + protected: virtual glm::vec3 getPosition() = 0; virtual void setPosition(glm::vec3 position) = 0; diff --git a/libraries/physics/src/ObjectAction.cpp b/libraries/physics/src/ObjectAction.cpp index 5205e08c62..8c382f8dad 100644 --- a/libraries/physics/src/ObjectAction.cpp +++ b/libraries/physics/src/ObjectAction.cpp @@ -30,6 +30,18 @@ void ObjectAction::updateAction(btCollisionWorld* collisionWorld, btScalar delta dynamicsWorld->removeAction(this); return; } + + if (_expires > 0.0f) { + float now = (float)usecTimestampNow() / USECS_PER_SECOND; + if (now > _expires) { + EntityItemPointer ownerEntity = _ownerEntity.lock(); + _active = false; + if (ownerEntity) { + ownerEntity->removeAction(nullptr, getID()); + } + } + } + if (!_active) { return; } @@ -37,6 +49,40 @@ void ObjectAction::updateAction(btCollisionWorld* collisionWorld, btScalar delta updateActionWorker(deltaTimeStep); } +bool ObjectAction::updateArguments(QVariantMap arguments) { + bool lifetimeSet = true; + float lifetime = EntityActionInterface::extractFloatArgument("action", arguments, "lifetime", lifetimeSet, false); + if (lifetimeSet) { + float now = (float)usecTimestampNow() / USECS_PER_SECOND; + _expires = now + lifetime; + } else { + _expires = 0.0f; + } + + bool tagSet = true; + QString tag = EntityActionInterface::extractStringArgument("action", arguments, "tag", tagSet, false); + if (tagSet) { + _tag = tag; + } else { + tag = ""; + } + + return true; +} + +QVariantMap ObjectAction::getArguments() { + QVariantMap arguments; + float now = (float)usecTimestampNow() / USECS_PER_SECOND; + if (_expires == 0.0f) { + arguments["lifetime"] = 0.0f; + } else { + arguments["lifetime"] = _expires - now; + } + arguments["tag"] = _tag; + return arguments; +} + + void ObjectAction::debugDraw(btIDebugDraw* debugDrawer) { } @@ -136,3 +182,14 @@ void ObjectAction::activateBody() { } } +bool ObjectAction::lifetimeIsOver() { + if (_expires == 0.0f) { + return false; + } + + float now = (float)usecTimestampNow() / USECS_PER_SECOND; + if (now >= _expires) { + return true; + } + return false; +} diff --git a/libraries/physics/src/ObjectAction.h b/libraries/physics/src/ObjectAction.h index 4d91d0dbb1..380263577a 100644 --- a/libraries/physics/src/ObjectAction.h +++ b/libraries/physics/src/ObjectAction.h @@ -33,8 +33,8 @@ public: virtual EntityItemWeakPointer getOwnerEntity() const { return _ownerEntity; } virtual void setOwnerEntity(const EntityItemPointer ownerEntity) { _ownerEntity = ownerEntity; } - virtual bool updateArguments(QVariantMap arguments) = 0; - virtual QVariantMap getArguments() = 0; + virtual bool updateArguments(QVariantMap arguments); + virtual QVariantMap getArguments(); // this is called from updateAction and should be overridden by subclasses virtual void updateActionWorker(float deltaTimeStep) = 0; @@ -46,6 +46,8 @@ public: virtual QByteArray serialize() const = 0; virtual void deserialize(QByteArray serializedArguments) = 0; + virtual bool lifetimeIsOver(); + protected: virtual btRigidBody* getRigidBody(); @@ -59,11 +61,11 @@ protected: virtual void setAngularVelocity(glm::vec3 angularVelocity); virtual void activateBody(); -private: - -protected: bool _active; EntityItemWeakPointer _ownerEntity; + + float _expires; // in seconds since epoch + QString _tag; }; #endif // hifi_ObjectAction_h diff --git a/libraries/physics/src/ObjectActionOffset.cpp b/libraries/physics/src/ObjectActionOffset.cpp index 2c1b391ba5..448ec34689 100644 --- a/libraries/physics/src/ObjectActionOffset.cpp +++ b/libraries/physics/src/ObjectActionOffset.cpp @@ -80,6 +80,9 @@ 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); @@ -90,7 +93,7 @@ bool ObjectActionOffset::updateArguments(QVariantMap arguments) { ok = true; float linearTimeScale = EntityActionInterface::extractFloatArgument("offset action", arguments, "linearTimeScale", ok, false); - if (!ok) { + if (!ok) { linearTimeScale = _linearTimeScale; } @@ -119,7 +122,7 @@ bool ObjectActionOffset::updateArguments(QVariantMap arguments) { } QVariantMap ObjectActionOffset::getArguments() { - QVariantMap arguments; + QVariantMap arguments = ObjectAction::getArguments(); withReadLock([&] { arguments["pointToOffsetFrom"] = glmToQMap(_pointToOffsetFrom); arguments["linearTimeScale"] = _linearTimeScale; @@ -140,6 +143,9 @@ QByteArray ObjectActionOffset::serialize() const { dataStream << _linearTimeScale; dataStream << _positionalTargetSet; + dataStream << _expires; + dataStream << _tag; + return ba; } @@ -165,5 +171,8 @@ void ObjectActionOffset::deserialize(QByteArray serializedArguments) { 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 d163933299..7d0bab5143 100644 --- a/libraries/physics/src/ObjectActionSpring.cpp +++ b/libraries/physics/src/ObjectActionSpring.cpp @@ -109,6 +109,9 @@ void ObjectActionSpring::updateActionWorker(btScalar deltaTimeStep) { 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 = @@ -155,7 +158,7 @@ bool ObjectActionSpring::updateArguments(QVariantMap arguments) { } QVariantMap ObjectActionSpring::getArguments() { - QVariantMap arguments; + QVariantMap arguments = ObjectAction::getArguments(); withReadLock([&] { arguments["linearTimeScale"] = _linearTimeScale; arguments["targetPosition"] = glmToQMap(_positionalTarget); @@ -182,6 +185,9 @@ QByteArray ObjectActionSpring::serialize() const { dataStream << _angularTimeScale; dataStream << _rotationalTargetSet; + dataStream << _expires; + dataStream << _tag; + return serializedActionArguments; } @@ -210,5 +216,8 @@ void ObjectActionSpring::deserialize(QByteArray serializedArguments) { dataStream >> _angularTimeScale; dataStream >> _rotationalTargetSet; + dataStream >> _expires; + dataStream >> _tag; + _active = true; }