mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 21:26:25 +02:00
Turn attachments into avatar entities
This commit is contained in:
parent
079b276c2b
commit
8c121a531d
3 changed files with 176 additions and 27 deletions
|
@ -1688,16 +1688,6 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelN
|
||||||
markIdentityDataChanged();
|
markIdentityDataChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
|
||||||
if (QThread::currentThread() != thread()) {
|
|
||||||
BLOCKING_INVOKE_METHOD(this, "setAttachmentData",
|
|
||||||
Q_ARG(const QVector<AttachmentData>, attachmentData));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Avatar::setAttachmentData(attachmentData);
|
|
||||||
emit attachmentsChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 MyAvatar::getSkeletonPosition() const {
|
glm::vec3 MyAvatar::getSkeletonPosition() const {
|
||||||
CameraMode mode = qApp->getCamera().getMode();
|
CameraMode mode = qApp->getCamera().getMode();
|
||||||
if (mode == CAMERA_MODE_THIRD_PERSON || mode == CAMERA_MODE_INDEPENDENT) {
|
if (mode == CAMERA_MODE_THIRD_PERSON || mode == CAMERA_MODE_INDEPENDENT) {
|
||||||
|
@ -1968,20 +1958,165 @@ void MyAvatar::attach(const QString& modelURL, const QString& jointName,
|
||||||
float scale, bool isSoft,
|
float scale, bool isSoft,
|
||||||
bool allowDuplicates, bool useSaved) {
|
bool allowDuplicates, bool useSaved) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
Avatar::attach(modelURL, jointName, translation, rotation, scale, isSoft, allowDuplicates, useSaved);
|
BLOCKING_INVOKE_METHOD(this, "attach",
|
||||||
|
Q_ARG(const QString&, modelURL),
|
||||||
|
Q_ARG(const QString&, jointName),
|
||||||
|
Q_ARG(const glm::vec3&, translation),
|
||||||
|
Q_ARG(const glm::quat&, rotation),
|
||||||
|
Q_ARG(float, scale),
|
||||||
|
Q_ARG(bool, isSoft),
|
||||||
|
Q_ARG(bool, allowDuplicates),
|
||||||
|
Q_ARG(bool, useSaved)
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (useSaved) {
|
AttachmentData data;
|
||||||
AttachmentData attachment = loadAttachmentData(modelURL, jointName);
|
data.modelURL = modelURL;
|
||||||
if (attachment.isValid()) {
|
data.jointName = jointName;
|
||||||
Avatar::attach(modelURL, attachment.jointName,
|
data.translation = translation;
|
||||||
attachment.translation, attachment.rotation,
|
data.rotation = rotation;
|
||||||
attachment.scale, attachment.isSoft,
|
data.scale = scale;
|
||||||
allowDuplicates, useSaved);
|
data.isSoft = isSoft;
|
||||||
return;
|
EntityItemProperties properties;
|
||||||
|
attachmentDataToEntityProperties(data, properties);
|
||||||
|
DependencyManager::get<EntityScriptingInterface>()->addEntity(properties, true);
|
||||||
|
emit attachmentsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyAvatar::detachOne(const QString& modelURL, const QString& jointName) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
BLOCKING_INVOKE_METHOD(this, "detachOne",
|
||||||
|
Q_ARG(const QString&, modelURL),
|
||||||
|
Q_ARG(const QString&, jointName)
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QUuid entityID;
|
||||||
|
if (findAvatarEntity(modelURL, jointName, entityID)) {
|
||||||
|
DependencyManager::get<EntityScriptingInterface>()->deleteEntity(entityID);
|
||||||
|
}
|
||||||
|
emit attachmentsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyAvatar::detachAll(const QString& modelURL, const QString& jointName) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
BLOCKING_INVOKE_METHOD(this, "detachAll",
|
||||||
|
Q_ARG(const QString&, modelURL),
|
||||||
|
Q_ARG(const QString&, jointName)
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QUuid entityID;
|
||||||
|
while (findAvatarEntity(modelURL, jointName, entityID)) {
|
||||||
|
DependencyManager::get<EntityScriptingInterface>()->deleteEntity(entityID);
|
||||||
|
}
|
||||||
|
emit attachmentsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyAvatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
BLOCKING_INVOKE_METHOD(this, "setAttachmentData",
|
||||||
|
Q_ARG(const QVector<AttachmentData>&, attachmentData));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::vector<EntityItemProperties> newEntitiesProperties;
|
||||||
|
for (auto& data : attachmentData) {
|
||||||
|
QUuid entityID;
|
||||||
|
EntityItemProperties properties;
|
||||||
|
if (findAvatarEntity(data.modelURL.toString(), data.jointName, entityID)) {
|
||||||
|
properties = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(entityID);
|
||||||
|
}
|
||||||
|
attachmentDataToEntityProperties(data, properties);
|
||||||
|
newEntitiesProperties.push_back(properties);
|
||||||
|
}
|
||||||
|
removeAvatarEntities();
|
||||||
|
for (auto& properties : newEntitiesProperties) {
|
||||||
|
DependencyManager::get<EntityScriptingInterface>()->addEntity(properties, true);
|
||||||
|
}
|
||||||
|
emit attachmentsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<AttachmentData> MyAvatar::getAttachmentData() const {
|
||||||
|
QVector<AttachmentData> avatarData;
|
||||||
|
auto avatarEntities = getAvatarEntityData();
|
||||||
|
AvatarEntityMap::const_iterator dataItr = avatarEntities.begin();
|
||||||
|
while (dataItr != avatarEntities.end()) {
|
||||||
|
QUuid entityID = dataItr.key();
|
||||||
|
auto properties = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(entityID);
|
||||||
|
AttachmentData data = entityPropertiesToAttachmentData(properties);
|
||||||
|
avatarData.append(data);
|
||||||
|
dataItr++;
|
||||||
|
}
|
||||||
|
return avatarData;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantList MyAvatar::getAttachmentsVariant() const {
|
||||||
|
QVariantList result;
|
||||||
|
for (const auto& attachment : getAttachmentData()) {
|
||||||
|
result.append(attachment.toVariant());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyAvatar::setAttachmentsVariant(const QVariantList& variant) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
BLOCKING_INVOKE_METHOD(this, "setAttachmentsVariant",
|
||||||
|
Q_ARG(const QVariantList&, variant));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QVector<AttachmentData> newAttachments;
|
||||||
|
newAttachments.reserve(variant.size());
|
||||||
|
for (const auto& attachmentVar : variant) {
|
||||||
|
AttachmentData attachment;
|
||||||
|
if (attachment.fromVariant(attachmentVar)) {
|
||||||
|
newAttachments.append(attachment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Avatar::attach(modelURL, jointName, translation, rotation, scale, isSoft, allowDuplicates, useSaved);
|
setAttachmentData(newAttachments);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MyAvatar::findAvatarEntity(const QString& modelURL, const QString& jointName, QUuid& entityID) {
|
||||||
|
auto avatarEntities = getAvatarEntityData();
|
||||||
|
AvatarEntityMap::const_iterator dataItr = avatarEntities.begin();
|
||||||
|
while (dataItr != avatarEntities.end()) {
|
||||||
|
entityID = dataItr.key();
|
||||||
|
auto props = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(entityID);
|
||||||
|
if (props.getModelURL() == modelURL &&
|
||||||
|
(jointName.isEmpty() || props.getParentJointIndex() == getJointIndex(jointName))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
dataItr++;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AttachmentData MyAvatar::entityPropertiesToAttachmentData(const EntityItemProperties& properties) const {
|
||||||
|
AttachmentData data;
|
||||||
|
data.modelURL = properties.getModelURL();
|
||||||
|
data.translation = properties.getLocalPosition();
|
||||||
|
data.rotation = properties.getLocalRotation();
|
||||||
|
data.isSoft = properties.getRelayParentJoints();
|
||||||
|
quint16 jointIndex = properties.getParentJointIndex();
|
||||||
|
if (jointIndex > -1 && jointIndex < getJointNames().size()) {
|
||||||
|
data.jointName = getJointNames()[jointIndex];
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyAvatar::attachmentDataToEntityProperties(const AttachmentData& data, EntityItemProperties& properties) {
|
||||||
|
QString url = data.modelURL.toString();
|
||||||
|
properties.setName(QFileInfo(url).baseName());
|
||||||
|
properties.setType(EntityTypes::Model);
|
||||||
|
properties.setParentID(getID());
|
||||||
|
properties.setOwningAvatarID(getID());
|
||||||
|
properties.setLocalPosition(data.translation);
|
||||||
|
properties.setLocalRotation(data.rotation);
|
||||||
|
if (!data.isSoft) {
|
||||||
|
properties.setParentJointIndex(getJointIndex(data.jointName));
|
||||||
|
} else {
|
||||||
|
properties.setRelayParentJoints(true);
|
||||||
|
}
|
||||||
|
properties.setModelURL(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::initHeadBones() {
|
void MyAvatar::initHeadBones() {
|
||||||
|
|
|
@ -865,8 +865,6 @@ public:
|
||||||
|
|
||||||
void resetFullAvatarURL();
|
void resetFullAvatarURL();
|
||||||
|
|
||||||
virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData) override;
|
|
||||||
|
|
||||||
MyCharacterController* getCharacterController() { return &_characterController; }
|
MyCharacterController* getCharacterController() { return &_characterController; }
|
||||||
const MyCharacterController* getCharacterController() const { return &_characterController; }
|
const MyCharacterController* getCharacterController() const { return &_characterController; }
|
||||||
|
|
||||||
|
@ -1082,6 +1080,12 @@ public:
|
||||||
float computeStandingHeightMode(const controller::Pose& head);
|
float computeStandingHeightMode(const controller::Pose& head);
|
||||||
glm::quat computeAverageHeadRotation(const controller::Pose& head);
|
glm::quat computeAverageHeadRotation(const controller::Pose& head);
|
||||||
|
|
||||||
|
virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData) override;
|
||||||
|
virtual QVector<AttachmentData> getAttachmentData() const override;
|
||||||
|
|
||||||
|
virtual QVariantList getAttachmentsVariant() const override;
|
||||||
|
virtual void setAttachmentsVariant(const QVariantList& variant) override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
|
@ -1506,11 +1510,21 @@ private:
|
||||||
void setScriptedMotorTimescale(float timescale);
|
void setScriptedMotorTimescale(float timescale);
|
||||||
void setScriptedMotorFrame(QString frame);
|
void setScriptedMotorFrame(QString frame);
|
||||||
void setScriptedMotorMode(QString mode);
|
void setScriptedMotorMode(QString mode);
|
||||||
|
|
||||||
|
// Attachments
|
||||||
virtual void attach(const QString& modelURL, const QString& jointName = QString(),
|
virtual void attach(const QString& modelURL, const QString& jointName = QString(),
|
||||||
const glm::vec3& translation = glm::vec3(), const glm::quat& rotation = glm::quat(),
|
const glm::vec3& translation = glm::vec3(), const glm::quat& rotation = glm::quat(),
|
||||||
float scale = 1.0f, bool isSoft = false,
|
float scale = 1.0f, bool isSoft = false,
|
||||||
bool allowDuplicates = false, bool useSaved = true) override;
|
bool allowDuplicates = false, bool useSaved = true) override;
|
||||||
|
|
||||||
|
virtual void detachOne(const QString& modelURL, const QString& jointName = QString()) override;
|
||||||
|
virtual void detachAll(const QString& modelURL, const QString& jointName = QString()) override;
|
||||||
|
|
||||||
|
// Attachments/Avatar Entity
|
||||||
|
void attachmentDataToEntityProperties(const AttachmentData& data, EntityItemProperties& properties);
|
||||||
|
AttachmentData entityPropertiesToAttachmentData(const EntityItemProperties& properties) const;
|
||||||
|
bool findAvatarEntity(const QString& modelURL, const QString& jointName, QUuid& entityID);
|
||||||
|
|
||||||
bool cameraInsideHead(const glm::vec3& cameraPosition) const;
|
bool cameraInsideHead(const glm::vec3& cameraPosition) const;
|
||||||
|
|
||||||
void updateEyeContactTarget(float deltaTime);
|
void updateEyeContactTarget(float deltaTime);
|
||||||
|
|
|
@ -895,14 +895,14 @@ public:
|
||||||
* @returns {object}
|
* @returns {object}
|
||||||
*/
|
*/
|
||||||
// FIXME: Can this name be improved? Can it be deprecated?
|
// FIXME: Can this name be improved? Can it be deprecated?
|
||||||
Q_INVOKABLE QVariantList getAttachmentsVariant() const;
|
Q_INVOKABLE virtual QVariantList getAttachmentsVariant() const;
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* @function MyAvatar.setAttachmentsVariant
|
* @function MyAvatar.setAttachmentsVariant
|
||||||
* @param {object} variant
|
* @param {object} variant
|
||||||
*/
|
*/
|
||||||
// FIXME: Can this name be improved? Can it be deprecated?
|
// FIXME: Can this name be improved? Can it be deprecated?
|
||||||
Q_INVOKABLE void setAttachmentsVariant(const QVariantList& variant);
|
Q_INVOKABLE virtual void setAttachmentsVariant(const QVariantList& variant);
|
||||||
|
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
|
@ -969,7 +969,7 @@ public:
|
||||||
* print (attachments[i].modelURL);
|
* print (attachments[i].modelURL);
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE QVector<AttachmentData> getAttachmentData() const;
|
Q_INVOKABLE virtual QVector<AttachmentData> getAttachmentData() const;
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Set all models currently attached to your avatar. For example, if you retrieve attachment data using
|
* Set all models currently attached to your avatar. For example, if you retrieve attachment data using
|
||||||
|
@ -1040,7 +1040,7 @@ public:
|
||||||
* @param {string} [jointName=""] - The name of the joint to detach the model from. If <code>""</code>, then the most
|
* @param {string} [jointName=""] - The name of the joint to detach the model from. If <code>""</code>, then the most
|
||||||
* recently attached model is removed from which ever joint it was attached to.
|
* recently attached model is removed from which ever joint it was attached to.
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE void detachOne(const QString& modelURL, const QString& jointName = QString());
|
Q_INVOKABLE virtual void detachOne(const QString& modelURL, const QString& jointName = QString());
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Detach all instances of a particular model from either a specific joint or all joints.
|
* Detach all instances of a particular model from either a specific joint or all joints.
|
||||||
|
@ -1049,7 +1049,7 @@ public:
|
||||||
* @param {string} [jointName=""] - The name of the joint to detach the model from. If <code>""</code>, then the model is
|
* @param {string} [jointName=""] - The name of the joint to detach the model from. If <code>""</code>, then the model is
|
||||||
* detached from all joints.
|
* detached from all joints.
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE void detachAll(const QString& modelURL, const QString& jointName = QString());
|
Q_INVOKABLE virtual void detachAll(const QString& modelURL, const QString& jointName = QString());
|
||||||
|
|
||||||
QString getSkeletonModelURLFromScript() const { return _skeletonModelURL.toString(); }
|
QString getSkeletonModelURLFromScript() const { return _skeletonModelURL.toString(); }
|
||||||
void setSkeletonModelURLFromScript(const QString& skeletonModelString) { setSkeletonModelURL(QUrl(skeletonModelString)); }
|
void setSkeletonModelURLFromScript(const QString& skeletonModelString) { setSkeletonModelURL(QUrl(skeletonModelString)); }
|
||||||
|
|
Loading…
Reference in a new issue