mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-04-10 08:12:08 +02:00
correctly load AvatarEntities from settings
This commit is contained in:
parent
263d6cb7ad
commit
026c6301a6
6 changed files with 76 additions and 21 deletions
|
@ -50,6 +50,7 @@
|
|||
#include <RecordingScriptingInterface.h>
|
||||
#include <trackers/FaceTracker.h>
|
||||
#include <RenderableModelEntityItem.h>
|
||||
#include <VariantMapToScriptValue.h>
|
||||
|
||||
#include "MyHead.h"
|
||||
#include "MySkeletonModel.h"
|
||||
|
@ -1437,6 +1438,38 @@ void MyAvatar::setEnableInverseKinematics(bool isEnabled) {
|
|||
_skeletonModel->getRig().setEnableInverseKinematics(isEnabled);
|
||||
}
|
||||
|
||||
void MyAvatar::updateAvatarEntity(const QUuid& entityID, const EntityItemProperties& properties) {
|
||||
auto entityTreeRenderer = qApp->getEntities();
|
||||
EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr;
|
||||
EntityItemPointer entity;
|
||||
if (entityTree) {
|
||||
entity = entityTree->findEntityByID(entityID);
|
||||
if (!entity) {
|
||||
entity = entityTree->addEntity(entityID, properties);
|
||||
if (!entity) {
|
||||
// unable to create entity
|
||||
// TODO? handle this case?
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// TODO: propagate changes to 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) {
|
||||
// this entity's data is too big
|
||||
return;
|
||||
}
|
||||
|
||||
packetData.shrinkByteArrays();
|
||||
storeAvatarEntityDataPayload(entity->getID(), packetData.getUncompressedByteArray());
|
||||
}
|
||||
|
||||
void MyAvatar::loadData() {
|
||||
getHead()->setBasePitch(_headPitchSetting.get());
|
||||
|
||||
|
@ -1450,13 +1483,29 @@ void MyAvatar::loadData() {
|
|||
useFullAvatarURL(_fullAvatarURLFromPreferences, _fullAvatarModelName);
|
||||
|
||||
int numEntities = _avatarEntityCountSetting.get(0);
|
||||
auto entityTree = DependencyManager::get<EntityTreeRenderer>()->getTree();
|
||||
|
||||
for (int i = 0; i < numEntities; i++) {
|
||||
resizeAvatarEntitySettingHandles(i);
|
||||
QUuid entityID = QUuid::createUuid(); // generate a new ID
|
||||
QString propertiesString = _avatarEntityDataSettings[i].get();
|
||||
// TODO: convert propertiesString to EntityItemProperties
|
||||
//updateAvatarEntity(entityID, properties);
|
||||
if (numEntities > 0) {
|
||||
QScriptEngine scriptEngine;
|
||||
for (int i = 0; i < numEntities; i++) {
|
||||
resizeAvatarEntitySettingHandles(i);
|
||||
QUuid entityID = QUuid::createUuid(); // generate a new ID
|
||||
|
||||
// NOTE: this path from EntityItemProperties JSON string to EntityItemProperties is NOT efficient
|
||||
QString propertiesString = _avatarEntityDataSettings[i].get();
|
||||
QJsonDocument propertiesDoc = QJsonDocument::fromJson(propertiesString.toUtf8());
|
||||
QJsonObject propertiesObj = propertiesDoc.object();
|
||||
QVariant propertiesVariant(propertiesObj);
|
||||
QVariantMap propertiesMap = propertiesVariant.toMap();
|
||||
QScriptValue propertiesScriptValue = variantMapToScriptValue(propertiesMap, scriptEngine);
|
||||
EntityItemProperties properties;
|
||||
EntityItemPropertiesFromScriptValueIgnoreReadOnly(propertiesScriptValue, properties);
|
||||
|
||||
// the ClientOnly property can get stripped out elsewhere so we need to always set it true here
|
||||
properties.setClientOnly(true);
|
||||
|
||||
updateAvatarEntity(entityID, properties);
|
||||
}
|
||||
}
|
||||
|
||||
// Flying preferences must be loaded before calling setFlyingEnabled()
|
||||
|
|
|
@ -1402,6 +1402,9 @@ public slots:
|
|||
*/
|
||||
bool getEnableMeshVisible() const override;
|
||||
|
||||
// TODO: make this invokable, probably also move down to AvatarData
|
||||
void updateAvatarEntity(const QUuid& entityID, const EntityItemProperties& properties);
|
||||
|
||||
/**jsdoc
|
||||
* Set whether or not your avatar mesh is visible.
|
||||
* @function MyAvatar.setEnableMeshVisible
|
||||
|
|
|
@ -2019,7 +2019,7 @@ void AvatarData::processTrait(AvatarTraits::TraitType traitType, QByteArray trai
|
|||
void AvatarData::processTraitInstance(AvatarTraits::TraitType traitType,
|
||||
AvatarTraits::TraitInstanceID instanceID, QByteArray traitBinaryData) {
|
||||
if (traitType == AvatarTraits::AvatarEntity) {
|
||||
updateAvatarEntity(instanceID, traitBinaryData);
|
||||
storeAvatarEntityDataPayload(instanceID, traitBinaryData);
|
||||
} else if (traitType == AvatarTraits::Grab) {
|
||||
updateAvatarGrabData(instanceID, traitBinaryData);
|
||||
}
|
||||
|
@ -2569,8 +2569,9 @@ void AvatarData::fromJson(const QJsonObject& json, bool useFrameSkeleton) {
|
|||
if (attachmentJson.isObject()) {
|
||||
QVariantMap entityData = attachmentJson.toObject().toVariantMap();
|
||||
QUuid entityID = entityData.value("id").toUuid();
|
||||
// ADEBUG TODO: fix this broken path
|
||||
QByteArray properties = QByteArray::fromBase64(entityData.value("properties").toByteArray());
|
||||
updateAvatarEntity(entityID, properties);
|
||||
storeAvatarEntityDataPayload(entityID, properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2754,15 +2755,15 @@ void AvatarData::setAttachmentsVariant(const QVariantList& variant) {
|
|||
|
||||
const int MAX_NUM_AVATAR_ENTITIES = 42;
|
||||
|
||||
void AvatarData::updateAvatarEntity(const QUuid& entityID, const QByteArray& entityData) {
|
||||
void AvatarData::storeAvatarEntityDataPayload(const QUuid& entityID, const QByteArray& data) {
|
||||
_avatarEntitiesLock.withWriteLock([&] {
|
||||
AvatarEntityMap::iterator itr = _avatarEntityData.find(entityID);
|
||||
if (itr == _avatarEntityData.end()) {
|
||||
if (_avatarEntityData.size() < MAX_NUM_AVATAR_ENTITIES) {
|
||||
_avatarEntityData.insert(entityID, entityData);
|
||||
_avatarEntityData.insert(entityID, data);
|
||||
}
|
||||
} else {
|
||||
itr.value() = entityData;
|
||||
itr.value() = data;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -2775,6 +2776,10 @@ void AvatarData::updateAvatarEntity(const QUuid& entityID, const QByteArray& ent
|
|||
}
|
||||
}
|
||||
|
||||
void AvatarData::updateAvatarEntity(const QUuid& entityID, const QString& entityPropertiesString) {
|
||||
// TODO: implement this as API exposed to JS
|
||||
}
|
||||
|
||||
void AvatarData::clearAvatarEntity(const QUuid& entityID, bool requiresRemovalFromTree) {
|
||||
|
||||
bool removedEntity = false;
|
||||
|
|
|
@ -952,13 +952,14 @@ public:
|
|||
// FIXME: Can this name be improved? Can it be deprecated?
|
||||
Q_INVOKABLE virtual void setAttachmentsVariant(const QVariantList& variant);
|
||||
|
||||
void storeAvatarEntityDataPayload(const QUuid& entityID, const QByteArray& payload);
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.updateAvatarEntity
|
||||
* @param {Uuid} entityID
|
||||
* @param {string} entityData
|
||||
*/
|
||||
Q_INVOKABLE void updateAvatarEntity(const QUuid& entityID, const QByteArray& entityData);
|
||||
Q_INVOKABLE void updateAvatarEntity(const QUuid& entityID, const QString& entityPropertiesString);
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.clearAvatarEntity
|
||||
|
|
|
@ -39,8 +39,7 @@ void EntityEditPacketSender::adjustEditPacketForClockSkew(PacketType type, QByte
|
|||
}
|
||||
}
|
||||
|
||||
void EntityEditPacketSender::queueEditAvatarEntityMessage(PacketType type,
|
||||
EntityTreePointer entityTree,
|
||||
void EntityEditPacketSender::queueEditAvatarEntityMessage(EntityTreePointer entityTree,
|
||||
EntityItemID entityItemID,
|
||||
const EntityItemProperties& properties) {
|
||||
assert(_myAvatar);
|
||||
|
@ -53,6 +52,7 @@ void EntityEditPacketSender::queueEditAvatarEntityMessage(PacketType type,
|
|||
qCDebug(entities) << "EntityEditPacketSender::queueEditAvatarEntityMessage can't find entity: " << entityItemID;
|
||||
return;
|
||||
}
|
||||
entity->setLastBroadcast(usecTimestampNow());
|
||||
|
||||
// serialize ALL properties in an "AvatarEntity" packet
|
||||
// rather than just the ones being edited.
|
||||
|
@ -65,17 +65,14 @@ void EntityEditPacketSender::queueEditAvatarEntityMessage(PacketType type,
|
|||
OctreeElement::AppendState appendState = entity->appendEntityData(&packetData, params, extra);
|
||||
|
||||
if (appendState != OctreeElement::COMPLETED) {
|
||||
// this entity is too big
|
||||
// this entity's payload is too big
|
||||
return;
|
||||
}
|
||||
|
||||
packetData.shrinkByteArrays();
|
||||
_myAvatar->updateAvatarEntity(entityItemID, packetData.getUncompressedByteArray());
|
||||
|
||||
entity->setLastBroadcast(usecTimestampNow());
|
||||
_myAvatar->storeAvatarEntityDataPayload(entity->getID(), packetData.getUncompressedByteArray());
|
||||
}
|
||||
|
||||
|
||||
void EntityEditPacketSender::queueEditEntityMessage(PacketType type,
|
||||
EntityTreePointer entityTree,
|
||||
EntityItemID entityItemID,
|
||||
|
@ -85,7 +82,7 @@ void EntityEditPacketSender::queueEditEntityMessage(PacketType type,
|
|||
qCWarning(entities) << "Suppressing entity edit message: cannot send avatar entity edit with no myAvatar";
|
||||
} else if (properties.getOwningAvatarID() == _myAvatar->getID()) {
|
||||
// this is an avatar-based entity --> update our avatar-data rather than sending to the entity-server
|
||||
queueEditAvatarEntityMessage(type, entityTree, entityItemID, properties);
|
||||
queueEditAvatarEntityMessage(entityTree, entityItemID, properties);
|
||||
} else {
|
||||
qCWarning(entities) << "Suppressing entity edit message: cannot send avatar entity edit for another avatar";
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ public slots:
|
|||
void processEntityEditNackPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
|
||||
|
||||
private:
|
||||
void queueEditAvatarEntityMessage(PacketType type, EntityTreePointer entityTree,
|
||||
void queueEditAvatarEntityMessage(EntityTreePointer entityTree,
|
||||
EntityItemID entityItemID, const EntityItemProperties& properties);
|
||||
|
||||
private:
|
||||
|
|
Loading…
Reference in a new issue