mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 18:44:00 +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 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();
|
||||
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) {
|
||||
// Check for mouseLook movement, update rotation
|
||||
// rotate body yaw for yaw received from mouse
|
||||
|
@ -303,7 +307,8 @@ function mouseMoveEvent(event) {
|
|||
|
||||
function scriptEnding() {
|
||||
Overlays.deleteOverlay(reticle);
|
||||
Overlays.deleteOverlay(text);
|
||||
Overlays.deleteOverlay(text);
|
||||
MyAvatar.detachOne(gunModel);
|
||||
}
|
||||
|
||||
Particles.particleCollisionWithVoxel.connect(particleCollisionWithVoxel);
|
||||
|
|
|
@ -709,7 +709,9 @@ void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
|||
|
||||
void Avatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
||||
AvatarData::setAttachmentData(attachmentData);
|
||||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
return;
|
||||
}
|
||||
// make sure we have as many models as attachments
|
||||
while (_attachmentModels.size() < attachmentData.size()) {
|
||||
Model* model = new Model(this);
|
||||
|
|
|
@ -584,6 +584,14 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
|||
_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) {
|
||||
if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
|
||||
return; // wait until both models are loaded
|
||||
|
@ -1247,6 +1255,11 @@ void MyAvatar::maybeUpdateBillboard() {
|
|||
if (_billboardValid || !(_skeletonModel.isLoadedWithTextures() && getHead()->getFaceModel().isLoadedWithTextures())) {
|
||||
return;
|
||||
}
|
||||
foreach (Model* model, _attachmentModels) {
|
||||
if (!model->isLoadedWithTextures()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
QImage image = Application::getInstance()->renderAvatarBillboard();
|
||||
_billboard.clear();
|
||||
QBuffer buffer(&_billboard);
|
||||
|
|
|
@ -86,7 +86,8 @@ public:
|
|||
virtual void clearJointData(int index);
|
||||
virtual void setFaceModelURL(const QUrl& faceModelURL);
|
||||
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
|
||||
|
||||
virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData);
|
||||
|
||||
virtual void setCollisionGroups(quint32 collisionGroups);
|
||||
|
||||
void setMotionBehaviorsByScript(quint32 flags);
|
||||
|
|
|
@ -661,16 +661,87 @@ void AvatarData::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
|||
updateJointMappings();
|
||||
}
|
||||
|
||||
void AvatarData::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
||||
_attachmentData = attachmentData;
|
||||
}
|
||||
|
||||
void AvatarData::setDisplayName(const QString& displayName) {
|
||||
_displayName = 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) {
|
||||
_billboard = billboard;
|
||||
|
||||
|
@ -793,3 +864,59 @@ QDataStream& operator>>(QDataStream& in, AttachmentData& attachment) {
|
|||
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/QVariantMap>
|
||||
#include <QRect>
|
||||
#include <QScriptable>
|
||||
#include <QUuid>
|
||||
|
||||
#include <CollisionInfo.h>
|
||||
|
@ -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> attachmentData READ getAttachmentData WRITE setAttachmentData)
|
||||
Q_PROPERTY(QString billboardURL READ getBillboardURL WRITE setBillboardFromURL)
|
||||
|
||||
Q_PROPERTY(QStringList jointNames READ getJointNames)
|
||||
|
@ -229,13 +231,22 @@ public:
|
|||
const QUrl& getFaceModelURL() const { return _faceModelURL; }
|
||||
QString getFaceModelURLString() const { return _faceModelURL.toString(); }
|
||||
const QUrl& getSkeletonModelURL() const { return _skeletonModelURL; }
|
||||
const QVector<AttachmentData>& 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>& attachmentData);
|
||||
|
||||
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);
|
||||
const QByteArray& getBillboard() const { return _billboard; }
|
||||
|
||||
|
@ -347,4 +358,36 @@ public:
|
|||
QDataStream& operator<<(QDataStream& out, const 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
|
||||
|
|
|
@ -210,6 +210,7 @@ void ScriptEngine::init() {
|
|||
registerEventTypes(&_engine);
|
||||
registerMenuItemProperties(&_engine);
|
||||
registerAnimationTypes(&_engine);
|
||||
registerAvatarTypes(&_engine);
|
||||
|
||||
qScriptRegisterMetaType(&_engine, ParticlePropertiesToScriptValue, ParticlePropertiesFromScriptValue);
|
||||
qScriptRegisterMetaType(&_engine, ParticleIDtoScriptValue, ParticleIDfromScriptValue);
|
||||
|
|
Loading…
Reference in a new issue