From f866828db2a2f4f3dd43ae742a7fb443e103f222 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 8 May 2014 15:20:14 -0700 Subject: [PATCH] Avatar attachment scripting bits. --- libraries/avatars/src/AvatarData.cpp | 114 ++++++++++++++++++- libraries/avatars/src/AvatarData.h | 46 +++++++- libraries/script-engine/src/ScriptEngine.cpp | 1 + 3 files changed, 155 insertions(+), 6 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index ead5967c78..b226da8b5c 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -661,16 +661,66 @@ void AvatarData::setSkeletonModelURL(const QUrl& skeletonModelURL) { updateJointMappings(); } -void AvatarData::setAttachmentData(const QVector& attachmentData) { - _attachmentData = attachmentData; -} - void AvatarData::setDisplayName(const QString& displayName) { _displayName = displayName; qDebug() << "Changing display name for avatar to" << displayName; } +QVector AvatarData::getAttachmentData() const { + if (QThread::currentThread() != thread()) { + QVector result; + QMetaObject::invokeMethod(const_cast(this), "getAttachmentData", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(QVector, result)); + return result; + } + return _attachmentData; +} + +void AvatarData::setAttachmentData(const QVector& attachmentData) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setAttachmentData", Q_ARG(const QVector&, attachmentData)); + return; + } + _attachmentData = attachmentData; +} + +void AvatarData::attach(const QString& modelURL, const QString& jointName, + const glm::vec3& translation, const glm::quat& rotation, float scale) { + QVector attachmentData = getAttachmentData(); + AttachmentData data; + data.modelURL = modelURL; + data.jointName = jointName; + data.translation = translation; + data.rotation = rotation; + data.scale = scale; + attachmentData.append(data); + setAttachmentData(attachmentData); +} + +void AvatarData::detachOne(const QString& modelURL, const QString& jointName) { + QVector attachmentData = getAttachmentData(); + for (QVector::iterator it = attachmentData.begin(); it != attachmentData.end(); it++) { + if (it->modelURL == modelURL && (jointName.isEmpty() || it->jointName == jointName)) { + attachmentData.erase(it); + return; + } + } + setAttachmentData(attachmentData); +} + +void AvatarData::detachAll(const QString& modelURL, const QString& jointName) { + QVector attachmentData = getAttachmentData(); + for (QVector::iterator it = attachmentData.begin(); it != attachmentData.end(); ) { + if (it->modelURL == modelURL && (jointName.isEmpty() || it->jointName == jointName)) { + it = attachmentData.erase(it); + } else { + it++; + } + } + setAttachmentData(attachmentData); +} + void AvatarData::setBillboard(const QByteArray& billboard) { _billboard = billboard; @@ -793,3 +843,59 @@ QDataStream& operator>>(QDataStream& in, AttachmentData& attachment) { attachment.translation >> attachment.rotation >> attachment.scale; } +void AttachmentDataObject::setModelURL(const QString& modelURL) const { + AttachmentData data = qscriptvalue_cast(thisObject()); + data.modelURL = modelURL; + thisObject() = engine()->toScriptValue(data); +} + +QString AttachmentDataObject::getModelURL() const { + return qscriptvalue_cast(thisObject()).modelURL.toString(); +} + +void AttachmentDataObject::setJointName(const QString& jointName) const { + AttachmentData data = qscriptvalue_cast(thisObject()); + data.jointName = jointName; + thisObject() = engine()->toScriptValue(data); +} + +QString AttachmentDataObject::getJointName() const { + return qscriptvalue_cast(thisObject()).jointName; +} + +void AttachmentDataObject::setTranslation(const glm::vec3& translation) const { + AttachmentData data = qscriptvalue_cast(thisObject()); + data.translation = translation; + thisObject() = engine()->toScriptValue(data); +} + +glm::vec3 AttachmentDataObject::getTranslation() const { + return qscriptvalue_cast(thisObject()).translation; +} + +void AttachmentDataObject::setRotation(const glm::quat& rotation) const { + AttachmentData data = qscriptvalue_cast(thisObject()); + data.rotation = rotation; + thisObject() = engine()->toScriptValue(data); +} + +glm::quat AttachmentDataObject::getRotation() const { + return qscriptvalue_cast(thisObject()).rotation; +} + +void AttachmentDataObject::setScale(float scale) const { + AttachmentData data = qscriptvalue_cast(thisObject()); + data.scale = scale; + thisObject() = engine()->toScriptValue(data); +} + +float AttachmentDataObject::getScale() const { + return qscriptvalue_cast(thisObject()).scale; +} + +void registerAvatarTypes(QScriptEngine* engine) { + qScriptRegisterSequenceMetaType >(engine); + engine->setDefaultPrototype(qMetaTypeId(), engine->newQObject( + new AttachmentDataObject(), QScriptEngine::ScriptOwnership)); +} + diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 50c1608be8..1fd8f6c425 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -41,6 +41,7 @@ typedef unsigned long long quint64; #include #include #include +#include #include #include @@ -123,6 +124,7 @@ class AvatarData : public QObject { Q_PROPERTY(QString displayName READ getDisplayName WRITE setDisplayName) Q_PROPERTY(QString faceModelURL READ getFaceModelURLFromScript WRITE setFaceModelURLFromScript) Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript WRITE setSkeletonModelURLFromScript) + Q_PROPERTY(QVector attachmentData READ getAttachmentData WRITE setAttachmentData) Q_PROPERTY(QString billboardURL READ getBillboardURL WRITE setBillboardFromURL) Q_PROPERTY(QStringList jointNames READ getJointNames) @@ -229,13 +231,21 @@ public: const QUrl& getFaceModelURL() const { return _faceModelURL; } QString getFaceModelURLString() const { return _faceModelURL.toString(); } const QUrl& getSkeletonModelURL() const { return _skeletonModelURL; } - const QVector& getAttachmentData() const { return _attachmentData; } const QString& getDisplayName() const { return _displayName; } virtual void setFaceModelURL(const QUrl& faceModelURL); virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); - virtual void setAttachmentData(const QVector& attachmentData); + virtual void setDisplayName(const QString& displayName); + Q_INVOKABLE QVector getAttachmentData() const; + Q_INVOKABLE virtual void setAttachmentData(const QVector& attachmentData); + + Q_INVOKABLE virtual void attach(const QString& modelURL, const QString& jointName = QString(), + const glm::vec3& translation = glm::vec3(), const glm::quat& rotation = glm::quat(), float scale = 1.0f); + + Q_INVOKABLE void detachOne(const QString& modelURL, const QString& jointName = QString()); + Q_INVOKABLE void detachAll(const QString& modelURL, const QString& jointName = QString()); + virtual void setBillboard(const QByteArray& billboard); const QByteArray& getBillboard() const { return _billboard; } @@ -347,4 +357,36 @@ public: QDataStream& operator<<(QDataStream& out, const AttachmentData& attachment); QDataStream& operator>>(QDataStream& in, AttachmentData& attachment); +Q_DECLARE_METATYPE(AttachmentData) +Q_DECLARE_METATYPE(QVector) + +/// Scriptable wrapper for attachments. +class AttachmentDataObject : public QObject, protected QScriptable { + Q_OBJECT + Q_PROPERTY(QString modelURL READ getModelURL WRITE setModelURL) + Q_PROPERTY(QString jointName READ getJointName WRITE setJointName) + Q_PROPERTY(glm::vec3 translation READ getTranslation WRITE setTranslation) + Q_PROPERTY(glm::quat rotation READ getRotation WRITE setRotation) + Q_PROPERTY(float scale READ getScale WRITE setScale) + +public: + + Q_INVOKABLE void setModelURL(const QString& modelURL) const; + Q_INVOKABLE QString getModelURL() const; + + Q_INVOKABLE void setJointName(const QString& jointName) const; + Q_INVOKABLE QString getJointName() const; + + Q_INVOKABLE void setTranslation(const glm::vec3& translation) const; + Q_INVOKABLE glm::vec3 getTranslation() const; + + Q_INVOKABLE void setRotation(const glm::quat& rotation) const; + Q_INVOKABLE glm::quat getRotation() const; + + Q_INVOKABLE void setScale(float scale) const; + Q_INVOKABLE float getScale() const; +}; + +void registerAvatarTypes(QScriptEngine* engine); + #endif // hifi_AvatarData_h diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 9be2cb5252..be97b37b46 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -210,6 +210,7 @@ void ScriptEngine::init() { registerEventTypes(&_engine); registerMenuItemProperties(&_engine); registerAnimationTypes(&_engine); + registerAvatarTypes(&_engine); qScriptRegisterMetaType(&_engine, ParticlePropertiesToScriptValue, ParticlePropertiesFromScriptValue); qScriptRegisterMetaType(&_engine, ParticleIDtoScriptValue, ParticleIDfromScriptValue);