diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index e28c04379f..07214176bd 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -29,8 +29,8 @@ #include #include #include -#include #include +#include #include #include diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3803607a44..99af5b1578 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -129,6 +129,7 @@ #include "AudioClient.h" #include "audio/AudioScope.h" #include "avatar/AvatarManager.h" +#include "avatar/ScriptAvatar.h" #include "CrashHandler.h" #include "devices/DdeFaceTracker.h" #include "devices/EyeTracker.h" diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index c8229115bd..b86de68894 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -24,6 +24,7 @@ #include "Avatar.h" #include "AvatarMotionState.h" +#include "ScriptAvatar.h" class MyAvatar; class AudioInjector; @@ -41,6 +42,10 @@ public: void init(); std::shared_ptr getMyAvatar() { return _myAvatar; } + + // Null/Default-constructed QUuids will return MyAvatar + Q_INVOKABLE virtual ScriptAvatarData* getAvatar(QUuid avatarID) override { return new ScriptAvatar(getAvatarBySessionID(avatarID)); } + AvatarSharedPointer getAvatarBySessionID(const QUuid& sessionID) const override; int getNumAvatarsUpdated() const { return _numAvatarsUpdated; } diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 4e748037a4..4c6aa10d12 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -73,10 +73,17 @@ void Head::reset() { void Head::simulate(float deltaTime, bool isMine) { const float NORMAL_HZ = 60.0f; // the update rate the constant values were tuned for + // grab the audio loudness from the owning avatar, if we have one + float audioLoudness = 0.0f; + + if (_owningAvatar) { + _owningAvatar->getAudioLoudness(); + } + // Update audio trailing average for rendering facial animations const float AUDIO_AVERAGING_SECS = 0.05f; const float AUDIO_LONG_TERM_AVERAGING_SECS = 30.0f; - _averageLoudness = glm::mix(_averageLoudness, _audioLoudness, glm::min(deltaTime / AUDIO_AVERAGING_SECS, 1.0f)); + _averageLoudness = glm::mix(_averageLoudness, audioLoudness, glm::min(deltaTime / AUDIO_AVERAGING_SECS, 1.0f)); if (_longTermAverageLoudness == -1.0f) { _longTermAverageLoudness = _averageLoudness; @@ -154,8 +161,8 @@ void Head::simulate(float deltaTime, bool isMine) { // Update audio attack data for facial animation (eyebrows and mouth) float audioAttackAveragingRate = (10.0f - deltaTime * NORMAL_HZ) / 10.0f; // --> 0.9 at 60 Hz _audioAttack = audioAttackAveragingRate * _audioAttack + - (1.0f - audioAttackAveragingRate) * fabs((_audioLoudness - _longTermAverageLoudness) - _lastLoudness); - _lastLoudness = (_audioLoudness - _longTermAverageLoudness); + (1.0f - audioAttackAveragingRate) * fabs((audioLoudness - _longTermAverageLoudness) - _lastLoudness); + _lastLoudness = (audioLoudness - _longTermAverageLoudness); const float BROW_LIFT_THRESHOLD = 100.0f; if (_audioAttack > BROW_LIFT_THRESHOLD) { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 2a616a7a2a..da09bfba7e 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -404,8 +404,8 @@ void MyAvatar::update(float deltaTime) { // Also get the AudioClient so we can update the avatar bounding box data // on the AudioClient side. auto audio = DependencyManager::get(); - head->setAudioLoudness(audio->getLastInputLoudness()); - head->setAudioAverageLoudness(audio->getAudioAverageInputLoudness()); + setAudioLoudness(audio->getLastInputLoudness()); + setAudioAverageLoudness(audio->getAudioAverageInputLoudness()); glm::vec3 halfBoundingBoxDimensions(_characterController.getCapsuleRadius(), _characterController.getCapsuleHalfHeight(), _characterController.getCapsuleRadius()); halfBoundingBoxDimensions += _characterController.getCapsuleLocalOffset(); diff --git a/interface/src/avatar/ScriptAvatar.cpp b/interface/src/avatar/ScriptAvatar.cpp new file mode 100644 index 0000000000..aa47abcdc0 --- /dev/null +++ b/interface/src/avatar/ScriptAvatar.cpp @@ -0,0 +1,146 @@ +// +// ScriptAvatar.cpp +// interface/src/avatars +// +// Created by Stephen Birarda on 4/10/17. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "ScriptAvatar.h" + +ScriptAvatar::ScriptAvatar(AvatarSharedPointer avatarData) : + ScriptAvatarData(avatarData) +{ + +} + +std::shared_ptr ScriptAvatar::lockAvatar() const { + if (auto lockedAvatarData = _avatarData.lock()) { + return std::dynamic_pointer_cast(lockedAvatarData); + } else { + return std::shared_ptr(); + } +} + +glm::quat ScriptAvatar::getDefaultJointRotation(int index) const { + if (auto lockedAvatar = lockAvatar()) { + return lockedAvatar->getDefaultJointRotation(index); + } else { + return glm::quat(); + } +} + +glm::vec3 ScriptAvatar::getDefaultJointTranslation(int index) const { + if (auto lockedAvatar = lockAvatar()) { + return lockedAvatar->getDefaultJointTranslation(index); + } else { + return glm::vec3(); + } +} + +glm::vec3 ScriptAvatar::getSkeletonOffset() const { + if (auto lockedAvatar = lockAvatar()) { + return lockedAvatar->getSkeletonOffset(); + } else { + return glm::vec3(); + } +} + +glm::vec3 ScriptAvatar::getJointPosition(int index) const { + if (auto lockedAvatar = lockAvatar()) { + return lockedAvatar->getJointPosition(index); + } else { + return glm::vec3(); + } +} + +glm::vec3 ScriptAvatar::getJointPosition(const QString& name) const { + if (auto lockedAvatar = lockAvatar()) { + return lockedAvatar->getJointPosition(name); + } else { + return glm::vec3(); + } +} + +glm::vec3 ScriptAvatar::getNeckPosition() const { + if (auto lockedAvatar = lockAvatar()) { + return lockedAvatar->getNeckPosition(); + } else { + return glm::vec3(); + } +} + +glm::vec3 ScriptAvatar::getAcceleration() const { + if (auto lockedAvatar = lockAvatar()) { + return lockedAvatar->getAcceleration(); + } else { + return glm::vec3(); + } +} + +QUuid ScriptAvatar::getParentID() const { + if (auto lockedAvatar = lockAvatar()) { + return lockedAvatar->getParentID(); + } else { + return QUuid(); + } +} + +quint16 ScriptAvatar::getParentJointIndex() const { + if (auto lockedAvatar = lockAvatar()) { + return lockedAvatar->getParentJointIndex(); + } else { + return INVALID_JOINT_INDEX; + } +} + +QVariantList ScriptAvatar::getSkeleton() const { + if (auto lockedAvatar = lockAvatar()) { + return lockedAvatar->getSkeleton(); + } else { + return QVariantList(); + } +} + +float ScriptAvatar::getSimulationRate(const QString& rateName) const { + if (auto lockedAvatar = lockAvatar()) { + return lockedAvatar->getSimulationRate(rateName); + } else { + return 0.0f;; + } +} + +glm::vec3 ScriptAvatar::getLeftPalmPosition() const { + if (auto lockedAvatar = lockAvatar()) { + return lockedAvatar->getLeftPalmPosition(); + } else { + return glm::vec3(); + } +} + +glm::quat ScriptAvatar::getLeftPalmRotation() const { + if (auto lockedAvatar = lockAvatar()) { + return lockedAvatar->getLeftPalmRotation(); + } else { + return glm::quat(); + } +} + +glm::vec3 ScriptAvatar::getRightPalmPosition() const { + if (auto lockedAvatar = lockAvatar()) { + return lockedAvatar->getRightPalmPosition(); + } else { + return glm::vec3(); + } +} + +glm::quat ScriptAvatar::getRightPalmRotation() const { + if (auto lockedAvatar = lockAvatar()) { + return lockedAvatar->getRightPalmRotation(); + } else { + return glm::quat(); + } +} diff --git a/interface/src/avatar/ScriptAvatar.h b/interface/src/avatar/ScriptAvatar.h new file mode 100644 index 0000000000..3bc98e72a0 --- /dev/null +++ b/interface/src/avatar/ScriptAvatar.h @@ -0,0 +1,56 @@ +// +// ScriptAvatar.h +// interface/src/avatars +// +// Created by Stephen Birarda on 4/10/17. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_ScriptAvatar_h +#define hifi_ScriptAvatar_h + +#include + +#include "Avatar.h" + +class ScriptAvatar : public ScriptAvatarData { + Q_OBJECT + + Q_PROPERTY(glm::vec3 skeletonOffset READ getSkeletonOffset) + +public: + ScriptAvatar(AvatarSharedPointer avatarData); + +public slots: + + glm::quat getDefaultJointRotation(int index) const; + glm::vec3 getDefaultJointTranslation(int index) const; + + glm::vec3 getSkeletonOffset() const; + + glm::vec3 getJointPosition(int index) const; + glm::vec3 getJointPosition(const QString& name) const; + glm::vec3 getNeckPosition() const; + + glm::vec3 getAcceleration() const; + + QUuid getParentID() const; + quint16 getParentJointIndex() const; + + QVariantList getSkeleton() const; + + float getSimulationRate(const QString& rateName = QString("")) const; + + glm::vec3 getLeftPalmPosition() const; + glm::quat getLeftPalmRotation() const; + glm::vec3 getRightPalmPosition() const; + glm::quat getRightPalmRotation() const; + +private: + std::shared_ptr lockAvatar() const; +}; + +#endif // hifi_ScriptAvatar_h diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 23aa0cd811..9802630cf5 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -352,7 +352,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent if (hasAudioLoudness) { auto startSection = destinationBuffer; auto data = reinterpret_cast(destinationBuffer); - data->audioLoudness = packFloatGainToByte(_headData->getAudioLoudness() / AUDIO_LOUDNESS_SCALE); + data->audioLoudness = packFloatGainToByte(getAudioLoudness() / AUDIO_LOUDNESS_SCALE); destinationBuffer += sizeof(AvatarDataPacket::AudioLoudness); int numBytes = destinationBuffer - startSection; @@ -836,7 +836,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { } return buffer.size(); } - _headData->setAudioLoudness(audioLoudness); + setAudioLoudness(audioLoudness); int numBytesRead = sourceBuffer - startSection; _audioLoudnessRate.increment(numBytesRead); _audioLoudnessUpdateRate.increment(); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 1327798a0a..5ade0c448e 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -448,10 +448,18 @@ public: void setHeadRoll(float value) { _headData->setBaseRoll(value); } // access to Head().set/getAverageLoudness - float getAudioLoudness() const { return _headData->getAudioLoudness(); } - void setAudioLoudness(float value) { _headData->setAudioLoudness(value); } - float getAudioAverageLoudness() const { return _headData->getAudioAverageLoudness(); } - void setAudioAverageLoudness(float value) { _headData->setAudioAverageLoudness(value); } + + float getAudioLoudness() const { return _audioLoudness; } + void setAudioLoudness(float audioLoudness) { + if (audioLoudness != _audioLoudness) { + _audioLoudnessChanged = usecTimestampNow(); + } + _audioLoudness = audioLoudness; + } + bool audioLoudnessChangedSince(quint64 time) const { return _audioLoudnessChanged >= time; } + + float getAudioAverageLoudness() const { return _audioAverageLoudness; } + void setAudioAverageLoudness(float audioAverageLoudness) { _audioAverageLoudness = audioAverageLoudness; } // Scale virtual void setTargetScale(float targetScale); @@ -642,7 +650,6 @@ protected: bool avatarBoundingBoxChangedSince(quint64 time) const { return _avatarBoundingBoxChanged >= time; } bool avatarScaleChangedSince(quint64 time) const { return _avatarScaleChanged >= time; } bool lookAtPositionChangedSince(quint64 time) const { return _headData->lookAtPositionChangedSince(time); } - bool audioLoudnessChangedSince(quint64 time) const { return _headData->audioLoudnessChangedSince(time); } bool sensorToWorldMatrixChangedSince(quint64 time) const { return _sensorToWorldMatrixChanged >= time; } bool additionalFlagsChangedSince(quint64 time) const { return _additionalFlagsChanged >= time; } bool parentInfoChangedSince(quint64 time) const { return _parentChanged >= time; } @@ -768,6 +775,10 @@ protected: int getFauxJointIndex(const QString& name) const; + float _audioLoudness { 0.0f }; + quint64 _audioLoudnessChanged { 0 }; + float _audioAverageLoudness { 0.0f }; + private: friend void avatarStateFromFrame(const QByteArray& frameData, AvatarData* _avatar); static QUrl _defaultFullAvatarModelUrl; diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index 8708030190..0d341c684e 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -30,11 +30,6 @@ QVector AvatarHashMap::getAvatarIdentifiers() { return _avatarHash.keys().toVector(); } -AvatarData* AvatarHashMap::getAvatar(QUuid avatarID) { - // Null/Default-constructed QUuids will return MyAvatar - return getAvatarBySessionID(avatarID).get(); -} - bool AvatarHashMap::isAvatarInRange(const glm::vec3& position, const float range) { auto hashCopy = getHashCopy(); foreach(const AvatarSharedPointer& sharedAvatar, hashCopy) { diff --git a/libraries/avatars/src/AvatarHashMap.h b/libraries/avatars/src/AvatarHashMap.h index 346cd36b60..87bedf8d51 100644 --- a/libraries/avatars/src/AvatarHashMap.h +++ b/libraries/avatars/src/AvatarHashMap.h @@ -25,6 +25,8 @@ #include #include +#include "ScriptAvatarData.h" + #include "AvatarData.h" class AvatarHashMap : public QObject, public Dependency { @@ -37,7 +39,9 @@ public: // Currently, your own avatar will be included as the null avatar id. Q_INVOKABLE QVector getAvatarIdentifiers(); - Q_INVOKABLE AvatarData* getAvatar(QUuid avatarID); + + // Null/Default-constructed QUuids will return MyAvatar + virtual ScriptAvatarData* getAvatar(QUuid avatarID) { return new ScriptAvatarData(getAvatarBySessionID(avatarID)); } virtual AvatarSharedPointer getAvatarBySessionID(const QUuid& sessionID) const { return findAvatar(sessionID); } int numberOfAvatarsInRange(const glm::vec3& position, float rangeMeters); diff --git a/libraries/avatars/src/HeadData.cpp b/libraries/avatars/src/HeadData.cpp index bf8593f1d9..909c6a613e 100644 --- a/libraries/avatars/src/HeadData.cpp +++ b/libraries/avatars/src/HeadData.cpp @@ -32,14 +32,12 @@ HeadData::HeadData(AvatarData* owningAvatar) : _basePitch(0.0f), _baseRoll(0.0f), _lookAtPosition(0.0f, 0.0f, 0.0f), - _audioLoudness(0.0f), _isFaceTrackerConnected(false), _isEyeTrackerConnected(false), _leftEyeBlink(0.0f), _rightEyeBlink(0.0f), _averageLoudness(0.0f), _browAudioLift(0.0f), - _audioAverageLoudness(0.0f), _owningAvatar(owningAvatar) { diff --git a/libraries/avatars/src/HeadData.h b/libraries/avatars/src/HeadData.h index cbf6c6bb32..6c468daefd 100644 --- a/libraries/avatars/src/HeadData.h +++ b/libraries/avatars/src/HeadData.h @@ -57,18 +57,6 @@ public: glm::quat getOrientation() const; void setOrientation(const glm::quat& orientation); - float getAudioLoudness() const { return _audioLoudness; } - void setAudioLoudness(float audioLoudness) { - if (audioLoudness != _audioLoudness) { - _audioLoudnessChanged = usecTimestampNow(); - } - _audioLoudness = audioLoudness; - } - bool audioLoudnessChangedSince(quint64 time) { return _audioLoudnessChanged >= time; } - - float getAudioAverageLoudness() const { return _audioAverageLoudness; } - void setAudioAverageLoudness(float audioAverageLoudness) { _audioAverageLoudness = audioAverageLoudness; } - void setBlendshape(QString name, float val); const QVector& getBlendshapeCoefficients() const { return _blendshapeCoefficients; } void setBlendshapeCoefficients(const QVector& blendshapeCoefficients) { _blendshapeCoefficients = blendshapeCoefficients; } @@ -96,16 +84,13 @@ protected: glm::vec3 _lookAtPosition; quint64 _lookAtPositionChanged { 0 }; - float _audioLoudness; - quint64 _audioLoudnessChanged { 0 }; - bool _isFaceTrackerConnected; bool _isEyeTrackerConnected; float _leftEyeBlink; float _rightEyeBlink; float _averageLoudness; float _browAudioLift; - float _audioAverageLoudness; + QVector _blendshapeCoefficients; AvatarData* _owningAvatar; diff --git a/libraries/avatars/src/ScriptAvatarData.cpp b/libraries/avatars/src/ScriptAvatarData.cpp new file mode 100644 index 0000000000..f579eb9763 --- /dev/null +++ b/libraries/avatars/src/ScriptAvatarData.cpp @@ -0,0 +1,314 @@ +// +// ScriptAvatarData.cpp +// libraries/script-engine/src +// +// Created by Zach Fox on 2017-04-10. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "ScriptAvatarData.h" + +ScriptAvatarData::ScriptAvatarData(AvatarSharedPointer avatarData) : + _avatarData(avatarData) +{ + QObject::connect(avatarData.get(), &AvatarData::displayNameChanged, this, &ScriptAvatarData::displayNameChanged); +} + +// +// PHYSICAL PROPERTIES: POSITION AND ORIENTATION +// START +// +glm::vec3 ScriptAvatarData::getPosition() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getPosition(); + } else { + return glm::vec3(); + } +} +float ScriptAvatarData::getTargetScale() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getTargetScale(); + } else { + return 0.0f; + } +} +glm::vec3 ScriptAvatarData::getHandPosition() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getHandPosition(); + } else { + return glm::vec3(); + } +} +float ScriptAvatarData::getBodyPitch() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getBodyPitch(); + } else { + return 0.0f; + } +} +float ScriptAvatarData::getBodyYaw() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getBodyYaw(); + } else { + return 0.0f; + } +} +float ScriptAvatarData::getBodyRoll() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getBodyRoll(); + } else { + return 0.0f; + } +} +glm::quat ScriptAvatarData::getOrientation() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getOrientation(); + } else { + return glm::quat(); + } +} +glm::quat ScriptAvatarData::getHeadOrientation() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getHeadOrientation(); + } else { + return glm::quat(); + } +} +float ScriptAvatarData::getHeadPitch() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getHeadPitch(); + } else { + return 0.0f; + } +} +float ScriptAvatarData::getHeadYaw() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getHeadYaw(); + } else { + return 0.0f; + } +} +float ScriptAvatarData::getHeadRoll() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getHeadRoll(); + } else { + return 0.0f; + } +} +// +// PHYSICAL PROPERTIES: POSITION AND ORIENTATION +// END +// + +// +// PHYSICAL PROPERTIES: VELOCITY +// START +// +glm::vec3 ScriptAvatarData::getVelocity() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getVelocity(); + } else { + return glm::vec3(); + } +} +glm::vec3 ScriptAvatarData::getAngularVelocity() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getAngularVelocity(); + } else { + return glm::vec3(); + } +} +// +// PHYSICAL PROPERTIES: VELOCITY +// END +// + + +// +// IDENTIFIER PROPERTIES +// START +// +QUuid ScriptAvatarData::getSessionUUID() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getSessionUUID(); + } else { + return QUuid(); + } +} +QString ScriptAvatarData::getDisplayName() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getDisplayName(); + } else { + return QString(); + } +} +QString ScriptAvatarData::getSessionDisplayName() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getSessionDisplayName(); + } else { + return QString(); + } +} +// +// IDENTIFIER PROPERTIES +// END +// + +// +// ATTACHMENT AND JOINT PROPERTIES +// START +// +QString ScriptAvatarData::getSkeletonModelURLFromScript() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getSkeletonModelURLFromScript(); + } else { + return QString(); + } +} +char ScriptAvatarData::getHandState() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getHandState(); + } else { + return -1; + } +} +glm::quat ScriptAvatarData::getJointRotation(int index) const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getJointRotation(index); + } else { + return glm::quat(); + } +} +glm::vec3 ScriptAvatarData::getJointTranslation(int index) const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getJointTranslation(index); + } else { + return glm::vec3(); + } +} +glm::quat ScriptAvatarData::getJointRotation(const QString& name) const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getJointRotation(name); + } else { + return glm::quat(); + } +} +glm::vec3 ScriptAvatarData::getJointTranslation(const QString& name) const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getJointTranslation(name); + } else { + return glm::vec3(); + } +} +QVector ScriptAvatarData::getJointRotations() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getJointRotations(); + } else { + return QVector(); + } +} +bool ScriptAvatarData::isJointDataValid(const QString& name) const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->isJointDataValid(name); + } else { + return false; + } +} +int ScriptAvatarData::getJointIndex(const QString& name) const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getJointIndex(name); + } else { + return -1; + } +} +QStringList ScriptAvatarData::getJointNames() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getJointNames(); + } else { + return QStringList(); + } +} +QVector ScriptAvatarData::getAttachmentData() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getAttachmentData(); + } else { + return QVector(); + } +} +// +// ATTACHMENT AND JOINT PROPERTIES +// END +// + + +// +// AUDIO PROPERTIES +// START +// +float ScriptAvatarData::getAudioLoudness() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getAudioLoudness(); + } else { + return 0.0f; + } +} +float ScriptAvatarData::getAudioAverageLoudness() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getAudioAverageLoudness(); + } else { + return 0.0f; + } +} +// +// AUDIO PROPERTIES +// END +// + +// +// MATRIX PROPERTIES +// START +// +glm::mat4 ScriptAvatarData::getSensorToWorldMatrix() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getSensorToWorldMatrix(); + } else { + return glm::mat4(); + } +} +glm::mat4 ScriptAvatarData::getControllerLeftHandMatrix() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getControllerLeftHandMatrix(); + } else { + return glm::mat4(); + } +} +glm::mat4 ScriptAvatarData::getControllerRightHandMatrix() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getControllerRightHandMatrix(); + } else { + return glm::mat4(); + } +} +// +// MATRIX PROPERTIES +// END +// + +glm::quat ScriptAvatarData::getAbsoluteJointRotationInObjectFrame(int index) const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getAbsoluteJointRotationInObjectFrame(index); + } else { + return glm::quat(); + } +} + +glm::vec3 ScriptAvatarData::getAbsoluteJointTranslationInObjectFrame(int index) const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getAbsoluteJointTranslationInObjectFrame(index); + } else { + return glm::vec3(); + } +} diff --git a/libraries/avatars/src/ScriptAvatarData.h b/libraries/avatars/src/ScriptAvatarData.h new file mode 100644 index 0000000000..683306e847 --- /dev/null +++ b/libraries/avatars/src/ScriptAvatarData.h @@ -0,0 +1,138 @@ +// +// ScriptAvatarData.h +// libraries/script-engine/src +// +// Created by Zach Fox on 2017-04-10. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_ScriptAvatarData_h +#define hifi_ScriptAvatarData_h + +#include + +#include "AvatarData.h" + +class ScriptAvatarData : public QObject { + Q_OBJECT + + // + // PHYSICAL PROPERTIES: POSITION AND ORIENTATION + // + Q_PROPERTY(glm::vec3 position READ getPosition) + Q_PROPERTY(float scale READ getTargetScale) + Q_PROPERTY(glm::vec3 handPosition READ getHandPosition) + Q_PROPERTY(float bodyPitch READ getBodyPitch) + Q_PROPERTY(float bodyYaw READ getBodyYaw) + Q_PROPERTY(float bodyRoll READ getBodyRoll) + Q_PROPERTY(glm::quat orientation READ getOrientation) + Q_PROPERTY(glm::quat headOrientation READ getHeadOrientation) + Q_PROPERTY(float headPitch READ getHeadPitch) + Q_PROPERTY(float headYaw READ getHeadYaw) + Q_PROPERTY(float headRoll READ getHeadRoll) + // + // PHYSICAL PROPERTIES: VELOCITY + // + Q_PROPERTY(glm::vec3 velocity READ getVelocity) + Q_PROPERTY(glm::vec3 angularVelocity READ getAngularVelocity) + + // + // IDENTIFIER PROPERTIES + // + Q_PROPERTY(QUuid sessionUUID READ getSessionUUID) + Q_PROPERTY(QString displayName READ getDisplayName NOTIFY displayNameChanged) + Q_PROPERTY(QString sessionDisplayName READ getSessionDisplayName) + + // + // ATTACHMENT AND JOINT PROPERTIES + // + Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript) + Q_PROPERTY(QVector attachmentData READ getAttachmentData) + Q_PROPERTY(QStringList jointNames READ getJointNames) + + // + // AUDIO PROPERTIES + // + Q_PROPERTY(float audioLoudness READ getAudioLoudness) + Q_PROPERTY(float audioAverageLoudness READ getAudioAverageLoudness) + + // + // MATRIX PROPERTIES + // + Q_PROPERTY(glm::mat4 sensorToWorldMatrix READ getSensorToWorldMatrix) + Q_PROPERTY(glm::mat4 controllerLeftHandMatrix READ getControllerLeftHandMatrix) + Q_PROPERTY(glm::mat4 controllerRightHandMatrix READ getControllerRightHandMatrix) + +public: + ScriptAvatarData(AvatarSharedPointer avatarData); + + // + // PHYSICAL PROPERTIES: POSITION AND ORIENTATION + // + glm::vec3 getPosition() const; + float getTargetScale() const; + glm::vec3 getHandPosition() const; + float getBodyPitch() const; + float getBodyYaw() const; + float getBodyRoll() const; + glm::quat getOrientation() const; + glm::quat getHeadOrientation() const; + float getHeadPitch() const; + float getHeadYaw() const; + float getHeadRoll() const; + // + // PHYSICAL PROPERTIES: VELOCITY + // + glm::vec3 getVelocity() const; + glm::vec3 getAngularVelocity() const; + + // + // IDENTIFIER PROPERTIES + // + QUuid getSessionUUID() const; + QString getDisplayName() const; + QString getSessionDisplayName() const; + + // + // ATTACHMENT AND JOINT PROPERTIES + // + QString getSkeletonModelURLFromScript() const; + Q_INVOKABLE char getHandState() const; + Q_INVOKABLE glm::quat getJointRotation(int index) const; + Q_INVOKABLE glm::vec3 getJointTranslation(int index) const; + Q_INVOKABLE glm::quat getJointRotation(const QString& name) const; + Q_INVOKABLE glm::vec3 getJointTranslation(const QString& name) const; + Q_INVOKABLE QVector getJointRotations() const; + Q_INVOKABLE bool isJointDataValid(const QString& name) const; + Q_INVOKABLE int getJointIndex(const QString& name) const; + Q_INVOKABLE QStringList getJointNames() const; + Q_INVOKABLE QVector getAttachmentData() const; + + // + // AUDIO PROPERTIES + // + float getAudioLoudness() const; + float getAudioAverageLoudness() const; + + // + // MATRIX PROPERTIES + // + glm::mat4 getSensorToWorldMatrix() const; + glm::mat4 getControllerLeftHandMatrix() const; + glm::mat4 getControllerRightHandMatrix() const; + +signals: + void displayNameChanged(); + +public slots: + glm::quat getAbsoluteJointRotationInObjectFrame(int index) const; + glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const; + +protected: + std::weak_ptr _avatarData; +}; + +#endif // hifi_ScriptAvatarData_h diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index caa42bea5e..525928897d 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -59,6 +60,7 @@ #include "FileScriptingInterface.h" // unzip project #include "MenuItemProperties.h" #include "ScriptAudioInjector.h" +#include "ScriptAvatarData.h" #include "ScriptCache.h" #include "ScriptEngineLogging.h" #include "ScriptEngine.h" @@ -111,14 +113,6 @@ static QScriptValue debugPrint(QScriptContext* context, QScriptEngine* engine) { return QScriptValue(); } -QScriptValue avatarDataToScriptValue(QScriptEngine* engine, AvatarData* const &in) { - return engine->newQObject(in, QScriptEngine::QtOwnership, DEFAULT_QOBJECT_WRAP_OPTIONS); -} - -void avatarDataFromScriptValue(const QScriptValue &object, AvatarData* &out) { - out = qobject_cast(object.toQObject()); -} - Q_DECLARE_METATYPE(controller::InputController*) //static int inputControllerPointerId = qRegisterMetaType(); @@ -542,6 +536,16 @@ static QScriptValue createScriptableResourcePrototype(QScriptEngine* engine) { return prototype; } +QScriptValue avatarDataToScriptValue(QScriptEngine* engine, ScriptAvatarData* const& in) { + return engine->newQObject(in, QScriptEngine::ScriptOwnership, DEFAULT_QOBJECT_WRAP_OPTIONS); +} + +void avatarDataFromScriptValue(const QScriptValue& object, ScriptAvatarData*& out) { + // This is not implemented because there are no slots/properties that take an AvatarSharedPointer from a script + assert(false); + out = nullptr; +} + void ScriptEngine::resetModuleCache(bool deleteScriptCache) { if (QThread::currentThread() != thread()) { executeOnScriptThread([=]() { resetModuleCache(deleteScriptCache); });