diff --git a/assignment-client/src/AssignmentAction.h b/assignment-client/src/AssignmentAction.h index 91c41c3d52..b49e8aa609 100644 --- a/assignment-client/src/AssignmentAction.h +++ b/assignment-client/src/AssignmentAction.h @@ -30,6 +30,7 @@ public: virtual const EntityItemWeakPointer getOwnerEntity() const { return _ownerEntity; } virtual void setOwnerEntity(const EntityItemPointer ownerEntity) { _ownerEntity = ownerEntity; } virtual bool updateArguments(QVariantMap arguments) { assert(false); return false; } + virtual QVariantMap getArguments() { assert(false); return QVariantMap(); } virtual QByteArray serialize(); virtual void deserialize(QByteArray serializedArguments); diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index f0c007b11c..c1e2080521 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "QVariantGLM.h" #include "avatar/MyAvatar.h" #include "avatar/AvatarManager.h" @@ -118,6 +119,21 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) { return true; } + +QVariantMap AvatarActionHold::getArguments() { + QVariantMap arguments; + lockForRead(); + if (_parametersSet) { + arguments["relativePosition"] = glmToQMap(_relativePosition); + arguments["relativeRotation"] = glmToQMap(_relativeRotation); + arguments["timeScale"] = _linearTimeScale; + arguments["hand"] = _hand; + } + unlock(); + return arguments; +} + + QByteArray AvatarActionHold::serialize() { QByteArray ba; QDataStream dataStream(&ba, QIODevice::WriteOnly); diff --git a/interface/src/avatar/AvatarActionHold.h b/interface/src/avatar/AvatarActionHold.h index 2e9fc3fce7..fd92944302 100644 --- a/interface/src/avatar/AvatarActionHold.h +++ b/interface/src/avatar/AvatarActionHold.h @@ -25,6 +25,8 @@ public: virtual EntityActionType getType() { return ACTION_TYPE_HOLD; } virtual bool updateArguments(QVariantMap arguments); + virtual QVariantMap getArguments(); + virtual void updateActionWorker(float deltaTimeStep); virtual QByteArray serialize(); diff --git a/libraries/entities/src/EntityActionInterface.h b/libraries/entities/src/EntityActionInterface.h index d71e070121..599ddc35c2 100644 --- a/libraries/entities/src/EntityActionInterface.h +++ b/libraries/entities/src/EntityActionInterface.h @@ -38,6 +38,7 @@ public: virtual const EntityItemWeakPointer getOwnerEntity() const = 0; virtual void setOwnerEntity(const EntityItemPointer ownerEntity) = 0; virtual bool updateArguments(QVariantMap arguments) = 0; + virtual QVariantMap getArguments() = 0; virtual QByteArray serialize() = 0; virtual void deserialize(QByteArray serializedArguments) = 0; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index dfb2d6c8ba..61d045769e 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1492,7 +1492,6 @@ void EntityItem::setActionData(QByteArray actionData) { } } - bool EntityItem::serializeActionData() { if (_objectActions.size() == 0) { _actionData = QByteArray(); @@ -1521,7 +1520,15 @@ bool EntityItem::serializeActionData() { return true; } - const QByteArray EntityItem::getActionData() const { return _actionData; } + +QVariantMap EntityItem::getActionArguments(const QUuid& actionID) { + QVariantMap result; + if (_objectActions.contains(actionID)) { + EntityActionPointer action = _objectActions[actionID]; + result = action->getArguments(); + } + return result; +} diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index b7f816ecf9..6859d4252d 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -386,6 +386,8 @@ public: void setActionData(QByteArray actionData); const QByteArray getActionData() const; bool hasActions() { return !_objectActions.empty(); } + QList getActionIDs() { return _objectActions.keys(); } + QVariantMap getActionArguments(const QUuid& actionID); protected: diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 4b2f37445d..bc89e74863 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -62,7 +62,7 @@ void EntityScriptingInterface::setEntityTree(EntityTree* modelTree) { } void bidForSimulationOwnership(EntityItemProperties& properties) { - // We make a bid for simulation ownership by declaring our sessionID as simulation owner + // We make a bid for simulation ownership by declaring our sessionID as simulation owner // in the outgoing properties. The EntityServer may accept the bid or might not. auto nodeList = DependencyManager::get(); const QUuid myNodeID = nodeList->getSessionUUID(); @@ -113,7 +113,7 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identit if (entity) { results = entity->getProperties(); - // TODO: improve sitting points and naturalDimensions in the future, + // TODO: improve sitting points and naturalDimensions in the future, // for now we've included the old sitting points model behavior for entity types that are models // we've also added this hack for setting natural dimensions of models if (entity->getType() == EntityTypes::Model) { @@ -149,15 +149,15 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, EntityItemProperties proper if (properties.hasTerseUpdateChanges()) { auto nodeList = DependencyManager::get(); const QUuid myNodeID = nodeList->getSessionUUID(); - + if (entity->getSimulatorID() == myNodeID) { // we think we already own the simulation, so make sure to send ALL TerseUpdate properties 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 + // 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 a 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 + // 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. } @@ -204,7 +204,7 @@ void EntityScriptingInterface::deleteEntity(QUuid id) { } QUuid EntityScriptingInterface::findClosestEntity(const glm::vec3& center, float radius) const { - EntityItemID result; + EntityItemID result; if (_entityTree) { _entityTree->lockForRead(); EntityItemPointer closestEntity = _entityTree->findClosestEntity(center, radius); @@ -264,8 +264,8 @@ RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionBlock return findRayIntersectionWorker(ray, Octree::Lock, precisionPicking); } -RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionWorker(const PickRay& ray, - Octree::lockType lockType, +RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionWorker(const PickRay& ray, + Octree::lockType lockType, bool precisionPicking) { @@ -273,8 +273,8 @@ RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionWorke if (_entityTree) { OctreeElement* element; EntityItemPointer intersectedEntity = NULL; - result.intersects = _entityTree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face, - (void**)&intersectedEntity, lockType, &result.accurate, + result.intersects = _entityTree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face, + (void**)&intersectedEntity, lockType, &result.accurate, precisionPicking); if (result.intersects && intersectedEntity) { result.entityID = intersectedEntity->getEntityItemID(); @@ -318,15 +318,15 @@ bool EntityScriptingInterface::getSendPhysicsUpdates() const { } -RayToEntityIntersectionResult::RayToEntityIntersectionResult() : - intersects(false), +RayToEntityIntersectionResult::RayToEntityIntersectionResult() : + intersects(false), accurate(true), // assume it's accurate entityID(), properties(), distance(0), face(), entity(NULL) -{ +{ } QScriptValue RayToEntityIntersectionResultToScriptValue(QScriptEngine* engine, const RayToEntityIntersectionResult& value) { @@ -341,7 +341,7 @@ QScriptValue RayToEntityIntersectionResultToScriptValue(QScriptEngine* engine, c obj.setProperty("distance", value.distance); - QString faceName = ""; + QString faceName = ""; // handle BoxFace switch (value.face) { case MIN_X_FACE: @@ -446,35 +446,35 @@ bool EntityScriptingInterface::setPoints(QUuid entityID, std::function(_entityTree->findEntityByEntityItemID(entityID)); if (!entity) { qCDebug(entities) << "EntityScriptingInterface::setPoints no entity with ID" << entityID; } - + EntityTypes::EntityType entityType = entity->getType(); - + if (entityType != EntityTypes::Line) { return false; } - + auto now = usecTimestampNow(); - + LineEntityItem* lineEntity = static_cast(entity.get()); _entityTree->lockForWrite(); bool success = actor(*lineEntity); entity->setLastEdited(now); entity->setLastBroadcast(now); _entityTree->unlock(); - + _entityTree->lockForRead(); EntityItemProperties properties = entity->getProperties(); _entityTree->unlock(); - + properties.setLinePointsDirty(); properties.setLastEdited(now); - - + + queueEntityMessage(PacketTypeEntityEdit, entityID, properties); return success; } @@ -509,7 +509,6 @@ bool EntityScriptingInterface::appendPoint(QUuid entityID, const glm::vec3& poin { return lineEntity.appendPoint(point); }); - } @@ -585,9 +584,27 @@ bool EntityScriptingInterface::updateAction(const QUuid& entityID, const QUuid& }); } - bool EntityScriptingInterface::deleteAction(const QUuid& entityID, const QUuid& actionID) { return actionWorker(entityID, [&](EntitySimulation* simulation, EntityItemPointer entity) { return entity->removeAction(simulation, actionID); }); } + +QVector EntityScriptingInterface::getActionIDs(const QUuid& entityID) { + QVector result; + actionWorker(entityID, [&](EntitySimulation* simulation, EntityItemPointer entity) { + QList actionIDs = entity->getActionIDs(); + result = QVector::fromList(actionIDs); + return true; + }); + return result; +} + +QVariantMap EntityScriptingInterface::getActionArguments(const QUuid& entityID, const QUuid& actionID) { + QVariantMap result; + actionWorker(entityID, [&](EntitySimulation* simulation, EntityItemPointer entity) { + result = entity->getActionArguments(actionID); + return true; + }); + return result; +} diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 12c8688816..5c1e4141a6 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -122,7 +122,7 @@ public slots: Q_INVOKABLE bool setVoxelSphere(QUuid entityID, const glm::vec3& center, float radius, int value); Q_INVOKABLE bool setVoxel(QUuid entityID, const glm::vec3& position, int value); Q_INVOKABLE bool setAllVoxels(QUuid entityID, int value); - + Q_INVOKABLE bool setAllPoints(QUuid entityID, const QVector& points); Q_INVOKABLE bool appendPoint(QUuid entityID, const glm::vec3& point); @@ -131,6 +131,8 @@ public slots: Q_INVOKABLE QUuid addAction(const QString& actionTypeString, const QUuid& entityID, const QVariantMap& arguments); Q_INVOKABLE bool updateAction(const QUuid& entityID, const QUuid& actionID, const QVariantMap& arguments); Q_INVOKABLE bool deleteAction(const QUuid& entityID, const QUuid& actionID); + Q_INVOKABLE QVector getActionIDs(const QUuid& entityID); + Q_INVOKABLE QVariantMap getActionArguments(const QUuid& entityID, const QUuid& actionID); signals: void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); @@ -165,7 +167,7 @@ private: void queueEntityMessage(PacketType packetType, EntityItemID entityID, const EntityItemProperties& properties); /// actually does the work of finding the ray intersection, can be called in locking mode or tryLock mode - RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType, + RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType, bool precisionPicking); EntityTree* _entityTree; diff --git a/libraries/physics/src/ObjectAction.h b/libraries/physics/src/ObjectAction.h index 320ae9e38f..8119657abe 100644 --- a/libraries/physics/src/ObjectAction.h +++ b/libraries/physics/src/ObjectAction.h @@ -34,7 +34,9 @@ public: virtual void removeFromSimulation(EntitySimulation* simulation) const; virtual const EntityItemWeakPointer getOwnerEntity() const { return _ownerEntity; } virtual void setOwnerEntity(const EntityItemPointer ownerEntity) { _ownerEntity = ownerEntity; } + virtual bool updateArguments(QVariantMap arguments) { return false; } + virtual QVariantMap getArguments() { return QVariantMap(); } // this is called from updateAction and should be overridden by subclasses virtual void updateActionWorker(float deltaTimeStep) {} @@ -62,6 +64,7 @@ protected: virtual glm::vec3 getAngularVelocity(); virtual void setAngularVelocity(glm::vec3 angularVelocity); + void lockForRead() { _lock.lockForRead(); } bool tryLockForRead() { return _lock.tryLockForRead(); } void lockForWrite() { _lock.lockForWrite(); } bool tryLockForWrite() { return _lock.tryLockForWrite(); } diff --git a/libraries/physics/src/ObjectActionOffset.cpp b/libraries/physics/src/ObjectActionOffset.cpp index 9ceecea42b..22c6b7e0d3 100644 --- a/libraries/physics/src/ObjectActionOffset.cpp +++ b/libraries/physics/src/ObjectActionOffset.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "QVariantGLM.h" + #include "ObjectActionOffset.h" const uint16_t ObjectActionOffset::offsetVersion = 1; @@ -115,6 +117,16 @@ bool ObjectActionOffset::updateArguments(QVariantMap arguments) { return true; } +QVariantMap ObjectActionOffset::getArguments() { + QVariantMap arguments; + lockForRead(); + arguments["pointToOffsetFrom"] = glmToQMap(_pointToOffsetFrom); + arguments["linearTimeScale"] = _linearTimeScale; + arguments["linearDistance"] = _linearDistance; + unlock(); + return arguments; +} + QByteArray ObjectActionOffset::serialize() { QByteArray ba; QDataStream dataStream(&ba, QIODevice::WriteOnly); diff --git a/libraries/physics/src/ObjectActionOffset.h b/libraries/physics/src/ObjectActionOffset.h index 2cba976660..28a08c2efe 100644 --- a/libraries/physics/src/ObjectActionOffset.h +++ b/libraries/physics/src/ObjectActionOffset.h @@ -25,6 +25,8 @@ public: virtual EntityActionType getType() { return ACTION_TYPE_OFFSET; } virtual bool updateArguments(QVariantMap arguments); + virtual QVariantMap getArguments(); + virtual void updateActionWorker(float deltaTimeStep); virtual QByteArray serialize(); diff --git a/libraries/physics/src/ObjectActionSpring.cpp b/libraries/physics/src/ObjectActionSpring.cpp index e85f5076b7..b3b8536b06 100644 --- a/libraries/physics/src/ObjectActionSpring.cpp +++ b/libraries/physics/src/ObjectActionSpring.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "QVariantGLM.h" + #include "ObjectActionSpring.h" const uint16_t ObjectActionSpring::springVersion = 1; @@ -150,6 +152,24 @@ bool ObjectActionSpring::updateArguments(QVariantMap arguments) { return true; } +QVariantMap ObjectActionSpring::getArguments() { + QVariantMap arguments; + lockForRead(); + + if (_positionalTargetSet) { + arguments["linearTimeScale"] = _linearTimeScale; + arguments["targetPosition"] = glmToQMap(_positionalTarget); + } + + if (_rotationalTargetSet) { + arguments["targetRotation"] = glmToQMap(_rotationalTarget); + arguments["angularTimeScale"] = _angularTimeScale; + } + + unlock(); + return arguments; +} + QByteArray ObjectActionSpring::serialize() { QByteArray ba; QDataStream dataStream(&ba, QIODevice::WriteOnly); diff --git a/libraries/physics/src/ObjectActionSpring.h b/libraries/physics/src/ObjectActionSpring.h index 82e30d245d..c887a046bb 100644 --- a/libraries/physics/src/ObjectActionSpring.h +++ b/libraries/physics/src/ObjectActionSpring.h @@ -25,6 +25,8 @@ public: virtual EntityActionType getType() { return ACTION_TYPE_SPRING; } virtual bool updateArguments(QVariantMap arguments); + virtual QVariantMap getArguments(); + virtual void updateActionWorker(float deltaTimeStep); virtual QByteArray serialize(); diff --git a/libraries/shared/src/QVariantGLM.cpp b/libraries/shared/src/QVariantGLM.cpp index aa8fa40593..bfa9a32393 100644 --- a/libraries/shared/src/QVariantGLM.cpp +++ b/libraries/shared/src/QVariantGLM.cpp @@ -24,6 +24,22 @@ QVariantList rgbColorToQList(rgbColor& v) { return QVariantList() << (int)(v[0]) << (int)(v[1]) << (int)(v[2]); } +QVariantMap glmToQMap(const glm::vec3& g) { + QVariantMap p; + p["x"] = g.x; + p["y"] = g.y; + p["z"] = g.z; + return p; +} + +QVariantMap glmToQMap(const glm::quat& g) { + QVariantMap q; + q["x"] = g.x; + q["y"] = g.y; + q["z"] = g.z; + q["w"] = g.w; + return q; +} glm::vec3 qListToGlmVec3(const QVariant q) { diff --git a/libraries/shared/src/QVariantGLM.h b/libraries/shared/src/QVariantGLM.h index 4cc1d038a1..cef625465f 100644 --- a/libraries/shared/src/QVariantGLM.h +++ b/libraries/shared/src/QVariantGLM.h @@ -21,6 +21,9 @@ QVariantList glmToQList(const glm::vec3& g); QVariantList glmToQList(const glm::quat& g); QVariantList rgbColorToQList(rgbColor& v); +QVariantMap glmToQMap(const glm::vec3& g); +QVariantMap glmToQMap(const glm::quat& g); + glm::vec3 qListToGlmVec3(const QVariant q); glm::quat qListToGlmQuat(const QVariant q); void qListtoRgbColor(const QVariant q, rgbColor returnValue);