mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 02:52:57 +02:00
Merge pull request #2820 from ey6es/master
Scripting interface for avatar attachments.
This commit is contained in:
commit
52d3c49fa7
7 changed files with 201 additions and 9 deletions
|
@ -39,6 +39,8 @@ var impactSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-pub
|
||||||
var targetHitSound = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Space%20Invaders/hit.raw");
|
var targetHitSound = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Space%20Invaders/hit.raw");
|
||||||
var targetLaunchSound = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Space%20Invaders/shoot.raw");
|
var targetLaunchSound = new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Space%20Invaders/shoot.raw");
|
||||||
|
|
||||||
|
var gunModel = "http://highfidelity-public.s3-us-west-1.amazonaws.com/models/attachments/Raygun2.fst";
|
||||||
|
|
||||||
var audioOptions = new AudioInjectionOptions();
|
var audioOptions = new AudioInjectionOptions();
|
||||||
audioOptions.volume = 0.9;
|
audioOptions.volume = 0.9;
|
||||||
|
|
||||||
|
@ -190,6 +192,8 @@ function keyPressEvent(event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MyAvatar.attach(gunModel, "RightHand", {x: -0.10, y: 0.0, z: 0.0}, Quat.fromPitchYawRollDegrees(-90, 180, 0), 0.14);
|
||||||
|
|
||||||
function update(deltaTime) {
|
function update(deltaTime) {
|
||||||
// Check for mouseLook movement, update rotation
|
// Check for mouseLook movement, update rotation
|
||||||
// rotate body yaw for yaw received from mouse
|
// rotate body yaw for yaw received from mouse
|
||||||
|
@ -303,7 +307,8 @@ function mouseMoveEvent(event) {
|
||||||
|
|
||||||
function scriptEnding() {
|
function scriptEnding() {
|
||||||
Overlays.deleteOverlay(reticle);
|
Overlays.deleteOverlay(reticle);
|
||||||
Overlays.deleteOverlay(text);
|
Overlays.deleteOverlay(text);
|
||||||
|
MyAvatar.detachOne(gunModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
Particles.particleCollisionWithVoxel.connect(particleCollisionWithVoxel);
|
Particles.particleCollisionWithVoxel.connect(particleCollisionWithVoxel);
|
||||||
|
|
|
@ -709,7 +709,9 @@ void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
||||||
|
|
||||||
void Avatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
void Avatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
||||||
AvatarData::setAttachmentData(attachmentData);
|
AvatarData::setAttachmentData(attachmentData);
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// make sure we have as many models as attachments
|
// make sure we have as many models as attachments
|
||||||
while (_attachmentModels.size() < attachmentData.size()) {
|
while (_attachmentModels.size() < attachmentData.size()) {
|
||||||
Model* model = new Model(this);
|
Model* model = new Model(this);
|
||||||
|
|
|
@ -584,6 +584,14 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
||||||
_billboardValid = false;
|
_billboardValid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyAvatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
||||||
|
Avatar::setAttachmentData(attachmentData);
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_billboardValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
void MyAvatar::renderBody(RenderMode renderMode, float glowLevel) {
|
void MyAvatar::renderBody(RenderMode renderMode, float glowLevel) {
|
||||||
if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
|
if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
|
||||||
return; // wait until both models are loaded
|
return; // wait until both models are loaded
|
||||||
|
@ -1247,6 +1255,11 @@ void MyAvatar::maybeUpdateBillboard() {
|
||||||
if (_billboardValid || !(_skeletonModel.isLoadedWithTextures() && getHead()->getFaceModel().isLoadedWithTextures())) {
|
if (_billboardValid || !(_skeletonModel.isLoadedWithTextures() && getHead()->getFaceModel().isLoadedWithTextures())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
foreach (Model* model, _attachmentModels) {
|
||||||
|
if (!model->isLoadedWithTextures()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
QImage image = Application::getInstance()->renderAvatarBillboard();
|
QImage image = Application::getInstance()->renderAvatarBillboard();
|
||||||
_billboard.clear();
|
_billboard.clear();
|
||||||
QBuffer buffer(&_billboard);
|
QBuffer buffer(&_billboard);
|
||||||
|
|
|
@ -86,7 +86,8 @@ public:
|
||||||
virtual void clearJointData(int index);
|
virtual void clearJointData(int index);
|
||||||
virtual void setFaceModelURL(const QUrl& faceModelURL);
|
virtual void setFaceModelURL(const QUrl& faceModelURL);
|
||||||
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
|
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
|
||||||
|
virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData);
|
||||||
|
|
||||||
virtual void setCollisionGroups(quint32 collisionGroups);
|
virtual void setCollisionGroups(quint32 collisionGroups);
|
||||||
|
|
||||||
void setMotionBehaviorsByScript(quint32 flags);
|
void setMotionBehaviorsByScript(quint32 flags);
|
||||||
|
|
|
@ -661,16 +661,87 @@ void AvatarData::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
||||||
updateJointMappings();
|
updateJointMappings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarData::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
|
||||||
_attachmentData = attachmentData;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AvatarData::setDisplayName(const QString& displayName) {
|
void AvatarData::setDisplayName(const QString& displayName) {
|
||||||
_displayName = displayName;
|
_displayName = displayName;
|
||||||
|
|
||||||
qDebug() << "Changing display name for avatar to" << displayName;
|
qDebug() << "Changing display name for avatar to" << displayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVector<AttachmentData> AvatarData::getAttachmentData() const {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
QVector<AttachmentData> result;
|
||||||
|
QMetaObject::invokeMethod(const_cast<AvatarData*>(this), "getAttachmentData", Qt::BlockingQueuedConnection,
|
||||||
|
Q_RETURN_ARG(QVector<AttachmentData>, result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return _attachmentData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AvatarData::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
QMetaObject::invokeMethod(this, "setAttachmentData", Q_ARG(const QVector<AttachmentData>&, attachmentData));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_attachmentData = attachmentData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AvatarData::attach(const QString& modelURL, const QString& jointName, const glm::vec3& translation,
|
||||||
|
const glm::quat& rotation, float scale, bool allowDuplicates) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
QMetaObject::invokeMethod(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, allowDuplicates));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QVector<AttachmentData> attachmentData = getAttachmentData();
|
||||||
|
if (!allowDuplicates) {
|
||||||
|
foreach (const AttachmentData& data, attachmentData) {
|
||||||
|
if (data.modelURL == modelURL && (jointName.isEmpty() || data.jointName == jointName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
QMetaObject::invokeMethod(this, "detachOne", Q_ARG(const QString&, modelURL), Q_ARG(const QString&, jointName));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QVector<AttachmentData> attachmentData = getAttachmentData();
|
||||||
|
for (QVector<AttachmentData>::iterator it = attachmentData.begin(); it != attachmentData.end(); it++) {
|
||||||
|
if (it->modelURL == modelURL && (jointName.isEmpty() || it->jointName == jointName)) {
|
||||||
|
attachmentData.erase(it);
|
||||||
|
setAttachmentData(attachmentData);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AvatarData::detachAll(const QString& modelURL, const QString& jointName) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
QMetaObject::invokeMethod(this, "detachAll", Q_ARG(const QString&, modelURL), Q_ARG(const QString&, jointName));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QVector<AttachmentData> attachmentData = getAttachmentData();
|
||||||
|
for (QVector<AttachmentData>::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) {
|
void AvatarData::setBillboard(const QByteArray& billboard) {
|
||||||
_billboard = billboard;
|
_billboard = billboard;
|
||||||
|
|
||||||
|
@ -793,3 +864,59 @@ QDataStream& operator>>(QDataStream& in, AttachmentData& attachment) {
|
||||||
attachment.translation >> attachment.rotation >> attachment.scale;
|
attachment.translation >> attachment.rotation >> attachment.scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AttachmentDataObject::setModelURL(const QString& modelURL) const {
|
||||||
|
AttachmentData data = qscriptvalue_cast<AttachmentData>(thisObject());
|
||||||
|
data.modelURL = modelURL;
|
||||||
|
thisObject() = engine()->toScriptValue(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString AttachmentDataObject::getModelURL() const {
|
||||||
|
return qscriptvalue_cast<AttachmentData>(thisObject()).modelURL.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AttachmentDataObject::setJointName(const QString& jointName) const {
|
||||||
|
AttachmentData data = qscriptvalue_cast<AttachmentData>(thisObject());
|
||||||
|
data.jointName = jointName;
|
||||||
|
thisObject() = engine()->toScriptValue(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString AttachmentDataObject::getJointName() const {
|
||||||
|
return qscriptvalue_cast<AttachmentData>(thisObject()).jointName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AttachmentDataObject::setTranslation(const glm::vec3& translation) const {
|
||||||
|
AttachmentData data = qscriptvalue_cast<AttachmentData>(thisObject());
|
||||||
|
data.translation = translation;
|
||||||
|
thisObject() = engine()->toScriptValue(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 AttachmentDataObject::getTranslation() const {
|
||||||
|
return qscriptvalue_cast<AttachmentData>(thisObject()).translation;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AttachmentDataObject::setRotation(const glm::quat& rotation) const {
|
||||||
|
AttachmentData data = qscriptvalue_cast<AttachmentData>(thisObject());
|
||||||
|
data.rotation = rotation;
|
||||||
|
thisObject() = engine()->toScriptValue(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::quat AttachmentDataObject::getRotation() const {
|
||||||
|
return qscriptvalue_cast<AttachmentData>(thisObject()).rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AttachmentDataObject::setScale(float scale) const {
|
||||||
|
AttachmentData data = qscriptvalue_cast<AttachmentData>(thisObject());
|
||||||
|
data.scale = scale;
|
||||||
|
thisObject() = engine()->toScriptValue(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
float AttachmentDataObject::getScale() const {
|
||||||
|
return qscriptvalue_cast<AttachmentData>(thisObject()).scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerAvatarTypes(QScriptEngine* engine) {
|
||||||
|
qScriptRegisterSequenceMetaType<QVector<AttachmentData> >(engine);
|
||||||
|
engine->setDefaultPrototype(qMetaTypeId<AttachmentData>(), engine->newQObject(
|
||||||
|
new AttachmentDataObject(), QScriptEngine::ScriptOwnership));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ typedef unsigned long long quint64;
|
||||||
#include <QtCore/QVector>
|
#include <QtCore/QVector>
|
||||||
#include <QtCore/QVariantMap>
|
#include <QtCore/QVariantMap>
|
||||||
#include <QRect>
|
#include <QRect>
|
||||||
|
#include <QScriptable>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
|
||||||
#include <CollisionInfo.h>
|
#include <CollisionInfo.h>
|
||||||
|
@ -123,6 +124,7 @@ class AvatarData : public QObject {
|
||||||
Q_PROPERTY(QString displayName READ getDisplayName WRITE setDisplayName)
|
Q_PROPERTY(QString displayName READ getDisplayName WRITE setDisplayName)
|
||||||
Q_PROPERTY(QString faceModelURL READ getFaceModelURLFromScript WRITE setFaceModelURLFromScript)
|
Q_PROPERTY(QString faceModelURL READ getFaceModelURLFromScript WRITE setFaceModelURLFromScript)
|
||||||
Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript WRITE setSkeletonModelURLFromScript)
|
Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript WRITE setSkeletonModelURLFromScript)
|
||||||
|
Q_PROPERTY(QVector<AttachmentData> attachmentData READ getAttachmentData WRITE setAttachmentData)
|
||||||
Q_PROPERTY(QString billboardURL READ getBillboardURL WRITE setBillboardFromURL)
|
Q_PROPERTY(QString billboardURL READ getBillboardURL WRITE setBillboardFromURL)
|
||||||
|
|
||||||
Q_PROPERTY(QStringList jointNames READ getJointNames)
|
Q_PROPERTY(QStringList jointNames READ getJointNames)
|
||||||
|
@ -229,13 +231,22 @@ public:
|
||||||
const QUrl& getFaceModelURL() const { return _faceModelURL; }
|
const QUrl& getFaceModelURL() const { return _faceModelURL; }
|
||||||
QString getFaceModelURLString() const { return _faceModelURL.toString(); }
|
QString getFaceModelURLString() const { return _faceModelURL.toString(); }
|
||||||
const QUrl& getSkeletonModelURL() const { return _skeletonModelURL; }
|
const QUrl& getSkeletonModelURL() const { return _skeletonModelURL; }
|
||||||
const QVector<AttachmentData>& getAttachmentData() const { return _attachmentData; }
|
|
||||||
const QString& getDisplayName() const { return _displayName; }
|
const QString& getDisplayName() const { return _displayName; }
|
||||||
virtual void setFaceModelURL(const QUrl& faceModelURL);
|
virtual void setFaceModelURL(const QUrl& faceModelURL);
|
||||||
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
|
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
|
||||||
virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData);
|
|
||||||
virtual void setDisplayName(const QString& displayName);
|
virtual void setDisplayName(const QString& displayName);
|
||||||
|
|
||||||
|
Q_INVOKABLE QVector<AttachmentData> getAttachmentData() const;
|
||||||
|
Q_INVOKABLE virtual void setAttachmentData(const QVector<AttachmentData>& 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,
|
||||||
|
bool allowDuplicates = false);
|
||||||
|
|
||||||
|
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);
|
virtual void setBillboard(const QByteArray& billboard);
|
||||||
const QByteArray& getBillboard() const { return _billboard; }
|
const QByteArray& getBillboard() const { return _billboard; }
|
||||||
|
|
||||||
|
@ -347,4 +358,36 @@ public:
|
||||||
QDataStream& operator<<(QDataStream& out, const AttachmentData& attachment);
|
QDataStream& operator<<(QDataStream& out, const AttachmentData& attachment);
|
||||||
QDataStream& operator>>(QDataStream& in, AttachmentData& attachment);
|
QDataStream& operator>>(QDataStream& in, AttachmentData& attachment);
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(AttachmentData)
|
||||||
|
Q_DECLARE_METATYPE(QVector<AttachmentData>)
|
||||||
|
|
||||||
|
/// 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
|
#endif // hifi_AvatarData_h
|
||||||
|
|
|
@ -210,6 +210,7 @@ void ScriptEngine::init() {
|
||||||
registerEventTypes(&_engine);
|
registerEventTypes(&_engine);
|
||||||
registerMenuItemProperties(&_engine);
|
registerMenuItemProperties(&_engine);
|
||||||
registerAnimationTypes(&_engine);
|
registerAnimationTypes(&_engine);
|
||||||
|
registerAvatarTypes(&_engine);
|
||||||
|
|
||||||
qScriptRegisterMetaType(&_engine, ParticlePropertiesToScriptValue, ParticlePropertiesFromScriptValue);
|
qScriptRegisterMetaType(&_engine, ParticlePropertiesToScriptValue, ParticlePropertiesFromScriptValue);
|
||||||
qScriptRegisterMetaType(&_engine, ParticleIDtoScriptValue, ParticleIDfromScriptValue);
|
qScriptRegisterMetaType(&_engine, ParticleIDtoScriptValue, ParticleIDfromScriptValue);
|
||||||
|
|
Loading…
Reference in a new issue