diff --git a/assignment-client/src/avatars/ScriptableAvatar.cpp b/assignment-client/src/avatars/ScriptableAvatar.cpp index a2e13a03be..25cf702b22 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.cpp +++ b/assignment-client/src/avatars/ScriptableAvatar.cpp @@ -21,6 +21,8 @@ #include #include #include +#include +#include ScriptableAvatar::ScriptableAvatar() { @@ -249,3 +251,52 @@ void ScriptableAvatar::setHasProceduralEyeFaceMovement(bool hasProceduralEyeFace void ScriptableAvatar::setHasAudioEnabledFaceMovement(bool hasAudioEnabledFaceMovement) { _headData->setHasAudioEnabledFaceMovement(hasAudioEnabledFaceMovement); } + +void ScriptableAvatar::updateAvatarEntity(const QUuid& id, const QScriptValue& data) { + if (data.isNull()) { + // interpret this as a DELETE + std::map::iterator itr = _entities.find(id); + if (itr != _entities.end()) { + _entities.erase(itr); + clearAvatarEntity(id); + } + } else { + EntityItemPointer entity; + EntityItemProperties properties; + bool honorReadOnly = true; + properties.copyFromScriptValue(data, honorReadOnly); + + std::map::iterator itr = _entities.find(id); + if (itr == _entities.end()) { + // this is an ADD + entity = EntityTypes::constructEntityItem(id, properties); + if (entity) { + OctreePacketData packetData(false, AvatarTraits::MAXIMUM_TRAIT_SIZE); + EncodeBitstreamParams params; + EntityTreeElementExtraEncodeDataPointer extra { nullptr }; + OctreeElement::AppendState appendState = entity->appendEntityData(&packetData, params, extra); + + if (appendState == OctreeElement::COMPLETED) { + _entities[id] = entity; + QByteArray tempArray((const char*)packetData.getUncompressedData(), packetData.getUncompressedSize()); + storeAvatarEntityDataPayload(id, tempArray); + } + } + } else { + // this is an UPDATE + entity = itr->second; + bool somethingChanged = entity->setProperties(properties); + if (somethingChanged) { + OctreePacketData packetData(false, AvatarTraits::MAXIMUM_TRAIT_SIZE); + EncodeBitstreamParams params; + EntityTreeElementExtraEncodeDataPointer extra { nullptr }; + OctreeElement::AppendState appendState = entity->appendEntityData(&packetData, params, extra); + + if (appendState == OctreeElement::COMPLETED) { + QByteArray tempArray((const char*)packetData.getUncompressedData(), packetData.getUncompressedSize()); + storeAvatarEntityDataPayload(id, tempArray); + } + } + } + } +} diff --git a/assignment-client/src/avatars/ScriptableAvatar.h b/assignment-client/src/avatars/ScriptableAvatar.h index 66b0b5ae3f..f56d7c66b0 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.h +++ b/assignment-client/src/avatars/ScriptableAvatar.h @@ -16,6 +16,7 @@ #include #include #include +#include /**jsdoc * The Avatar API is used to manipulate scriptable avatars on the domain. This API is a subset of the @@ -184,6 +185,7 @@ public: bool getHasProceduralEyeFaceMovement() const override { return _headData->getHasProceduralEyeFaceMovement(); } void setHasAudioEnabledFaceMovement(bool hasAudioEnabledFaceMovement); bool getHasAudioEnabledFaceMovement() const override { return _headData->getHasAudioEnabledFaceMovement(); } + void updateAvatarEntity(const QUuid& id, const QScriptValue& data) override; public slots: void update(float deltatime); @@ -202,6 +204,7 @@ private: QHash _fstJointIndices; ///< 1-based, since zero is returned for missing keys QStringList _fstJointNames; ///< in order of depth-first traversal QUrl _skeletonFBXURL; + std::map _entities; /// Loads the joint indices, names from the FST file (if any) void updateJointMappings(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index f808928709..4bf446f6b9 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2061,6 +2061,10 @@ void MyAvatar::clearJointsData() { _skeletonModel->getRig().clearJointStates(); } +void MyAvatar::updateAvatarEntity(const QUuid& id, const QScriptValue& data) { + // TODO: implement this +} + void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { _skeletonModelChangeCount++; int skeletonModelChangeCount = _skeletonModelChangeCount; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 4306db8242..98c93f9ccc 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -851,6 +851,8 @@ public: virtual void clearJointData(const QString& name) override; virtual void clearJointsData() override; + void updateAvatarEntity(const QUuid& id, const QScriptValue& data) override; + /**jsdoc * @function MyAvatar.pinJoint * @param {number} index diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 9a57e46f1a..2b356675be 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -235,13 +235,13 @@ public: void updateDisplayNameAlpha(bool showDisplayName); virtual void setSessionDisplayName(const QString& sessionDisplayName) override { }; // no-op + virtual void updateAvatarEntity(const QUuid& entityID, const QScriptValue& entityData) override { }; // no-op + virtual int parseDataFromBuffer(const QByteArray& buffer) override; static void renderJointConnectingCone(gpu::Batch& batch, glm::vec3 position1, glm::vec3 position2, float radius1, float radius2, const glm::vec4& color); - virtual void applyCollision(const glm::vec3& contactPoint, const glm::vec3& penetration) { } - /**jsdoc * Set the offset applied to the current avatar. The offset adjusts the position that the avatar is rendered. For example, * with an offset of { x: 0, y: 0.1, z: 0 }, your avatar will appear to be raised off the ground slightly. diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 9380699504..f08e66af82 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -2776,8 +2776,8 @@ void AvatarData::storeAvatarEntityDataPayload(const QUuid& entityID, const QByte } } -void AvatarData::updateAvatarEntity(const QUuid& entityID, const QString& entityPropertiesString) { - // TODO: implement this to expose AvatarEntity to JS +void AvatarData::updateAvatarEntity(const QUuid& id, const QScriptValue& data) { + // no op } void AvatarData::clearAvatarEntity(const QUuid& entityID, bool requiresRemovalFromTree) { diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 65ea873502..3d6dd78e05 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -957,9 +957,9 @@ public: /**jsdoc * @function MyAvatar.updateAvatarEntity * @param {Uuid} entityID - * @param {string} entityData + * @param {object} entityData */ - Q_INVOKABLE virtual void updateAvatarEntity(const QUuid& entityID, const QString& entityPropertiesString); + Q_INVOKABLE virtual void updateAvatarEntity(const QUuid& id, const QScriptValue& data); /**jsdoc * @function MyAvatar.clearAvatarEntity @@ -1140,10 +1140,11 @@ public: Q_INVOKABLE AvatarEntityMap getAvatarEntityData() const; /**jsdoc + * Temporarily disabled. Use updateAvatarEntity(id, properties) in the meantime. * @function MyAvatar.setAvatarEntityData * @param {object} avatarEntityData */ - Q_INVOKABLE void setAvatarEntityData(const AvatarEntityMap& avatarEntityData); + void setAvatarEntityData(const AvatarEntityMap& avatarEntityData); virtual void setAvatarEntityDataChanged(bool value) { _avatarEntityDataChanged = value; } void insertDetachedEntityID(const QUuid entityID); diff --git a/libraries/entities/src/EntityTypes.cpp b/libraries/entities/src/EntityTypes.cpp index 6f05237b1e..584af55d5d 100644 --- a/libraries/entities/src/EntityTypes.cpp +++ b/libraries/entities/src/EntityTypes.cpp @@ -151,3 +151,7 @@ EntityItemPointer EntityTypes::constructEntityItem(const unsigned char* data, in } return nullptr; } + +EntityItemPointer EntityTypes::constructEntityItem(const QUuid& id, const EntityItemProperties& properties) { + return constructEntityItem(properties.getType(), id, properties); +} diff --git a/libraries/entities/src/EntityTypes.h b/libraries/entities/src/EntityTypes.h index 9f4ba36df1..2e8914c8a7 100644 --- a/libraries/entities/src/EntityTypes.h +++ b/libraries/entities/src/EntityTypes.h @@ -116,6 +116,7 @@ public: static void extractEntityTypeAndID(const unsigned char* data, int dataLength, EntityTypes::EntityType& typeOut, QUuid& idOut); static EntityItemPointer constructEntityItem(EntityType entityType, const EntityItemID& entityID, const EntityItemProperties& properties); static EntityItemPointer constructEntityItem(const unsigned char* data, int bytesToRead); + static EntityItemPointer constructEntityItem(const QUuid& id, const EntityItemProperties& properties); private: static QMap _typeToNameMap;