15 #ifndef hifi_AvatarData_h
16 #define hifi_AvatarData_h
24 #include <glm/glm.hpp>
25 #include <glm/gtc/quaternion.hpp>
28 #include <QElapsedTimer>
32 #include <QStringList>
35 #include <QVariantMap>
37 #include <QReadWriteLock>
39 #include <AvatarConstants.h>
40 #include <JointData.h>
43 #include <NumericalConstants.h>
45 #include <RegisteredMetaTypes.h>
46 #include <SharedUtil.h>
47 #include <SimpleMovingAverage.h>
48 #include <SpatiallyNestable.h>
49 #include <ThreadSafeValueCache.h>
50 #include <ViewFrustum.h>
51 #include <shared/RateCounter.h>
52 #include <udt/SequenceNumber.h>
53 #include <Scriptable.h>
54 #include <ScriptValue.h>
57 #include "AvatarTraits.h"
59 #include "PathUtils.h"
63 using AvatarSharedPointer = std::shared_ptr<AvatarData>;
64 using AvatarWeakPointer = std::weak_ptr<AvatarData>;
65 using AvatarHash = QHash<QUuid, AvatarSharedPointer>;
67 using AvatarEntityMap = QMap<QUuid, QByteArray>;
68 using PackedAvatarEntityMap = QMap<QUuid, QByteArray>;
69 using AvatarEntityIDs = QSet<QUuid>;
71 using AvatarGrabDataMap = QMap<QUuid, QByteArray>;
73 using AvatarDataSequenceNumber = uint16_t;
75 const int MAX_NUM_AVATAR_ENTITIES = 42;
78 const quint32 AVATAR_MOTION_ACTION_MOTOR_ENABLED = 1U << 0;
79 const quint32 AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED = 1U << 1;
81 const quint32 AVATAR_MOTION_DEFAULTS =
82 AVATAR_MOTION_ACTION_MOTOR_ENABLED |
83 AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED;
86 const quint32 AVATAR_MOTION_SCRIPTABLE_BITS =
87 AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED;
110 const int KEY_STATE_START_BIT = 0;
111 const int HAND_STATE_START_BIT = 2;
112 const int HAS_SCRIPTED_BLENDSHAPES = 4;
113 const int HAS_PROCEDURAL_EYE_MOVEMENT = 5;
114 const int HAS_REFERENTIAL = 6;
115 const int HAND_STATE_FINGER_POINTING_BIT = 7;
116 const int AUDIO_ENABLED_FACE_MOVEMENT = 8;
117 const int PROCEDURAL_EYE_FACE_MOVEMENT = 9;
118 const int PROCEDURAL_BLINK_FACE_MOVEMENT = 10;
119 const int COLLIDE_WITH_OTHER_AVATARS = 11;
120 const int HAS_HERO_PRIORITY = 12;
139 const char HAND_STATE_NULL = 0;
140 const char LEFT_HAND_POINTING_FLAG = 1;
141 const char RIGHT_HAND_POINTING_FLAG = 2;
142 const char IS_FINGER_POINTING_FLAG = 4;
146 const char AVATARDATA_FLAGS_MINIMUM = 0;
148 using SmallFloat = uint16_t;
150 namespace AvatarSkeletonTrait {
158 PACKED_BEGIN
struct Header {
159 float maxTranslationDimension;
160 float maxScaleDimension;
162 uint16_t stringTableLength;
165 PACKED_BEGIN
struct JointData {
166 uint16_t stringStart;
167 uint8_t stringLength;
169 uint8_t defaultTranslation[6];
170 uint8_t defaultRotation[6];
171 uint16_t defaultScale;
173 uint16_t parentIndex;
176 struct UnpackedJointData {
180 glm::vec3 defaultTranslation;
181 glm::quat defaultRotation;
189 namespace AvatarDataPacket {
197 using HasFlags = uint16_t;
198 const HasFlags PACKET_HAS_AVATAR_GLOBAL_POSITION = 1U << 0;
199 const HasFlags PACKET_HAS_AVATAR_BOUNDING_BOX = 1U << 1;
200 const HasFlags PACKET_HAS_AVATAR_ORIENTATION = 1U << 2;
201 const HasFlags PACKET_HAS_AVATAR_SCALE = 1U << 3;
202 const HasFlags PACKET_HAS_LOOK_AT_POSITION = 1U << 4;
203 const HasFlags PACKET_HAS_AUDIO_LOUDNESS = 1U << 5;
204 const HasFlags PACKET_HAS_SENSOR_TO_WORLD_MATRIX = 1U << 6;
205 const HasFlags PACKET_HAS_ADDITIONAL_FLAGS = 1U << 7;
206 const HasFlags PACKET_HAS_PARENT_INFO = 1U << 8;
207 const HasFlags PACKET_HAS_AVATAR_LOCAL_POSITION = 1U << 9;
208 const HasFlags PACKET_HAS_HAND_CONTROLLERS = 1U << 10;
209 const HasFlags PACKET_HAS_FACE_TRACKER_INFO = 1U << 11;
210 const HasFlags PACKET_HAS_JOINT_DATA = 1U << 12;
211 const HasFlags PACKET_HAS_JOINT_DEFAULT_POSE_FLAGS = 1U << 13;
212 const HasFlags PACKET_HAS_GRAB_JOINTS = 1U << 14;
213 const size_t AVATAR_HAS_FLAGS_SIZE = 2;
215 using SixByteQuat = uint8_t[6];
216 using SixByteTrans = uint8_t[6];
220 PACKED_BEGIN
struct Header {
221 HasFlags packetHasFlags;
223 const size_t HEADER_SIZE = 2;
224 static_assert(
sizeof(Header) == HEADER_SIZE,
"AvatarDataPacket::Header size doesn't match.");
226 PACKED_BEGIN
struct AvatarGlobalPosition {
227 float globalPosition[3];
229 const size_t AVATAR_GLOBAL_POSITION_SIZE = 12;
230 static_assert(
sizeof(AvatarGlobalPosition) == AVATAR_GLOBAL_POSITION_SIZE,
"AvatarDataPacket::AvatarGlobalPosition size doesn't match.");
232 PACKED_BEGIN
struct AvatarBoundingBox {
233 float avatarDimensions[3];
234 float boundOriginOffset[3];
236 const size_t AVATAR_BOUNDING_BOX_SIZE = 24;
237 static_assert(
sizeof(AvatarBoundingBox) == AVATAR_BOUNDING_BOX_SIZE,
"AvatarDataPacket::AvatarBoundingBox size doesn't match.");
239 PACKED_BEGIN
struct AvatarOrientation {
240 SixByteQuat avatarOrientation;
242 const size_t AVATAR_ORIENTATION_SIZE = 6;
243 static_assert(
sizeof(AvatarOrientation) == AVATAR_ORIENTATION_SIZE,
"AvatarDataPacket::AvatarOrientation size doesn't match.");
245 PACKED_BEGIN
struct AvatarScale {
248 const size_t AVATAR_SCALE_SIZE = 2;
249 static_assert(
sizeof(AvatarScale) == AVATAR_SCALE_SIZE,
"AvatarDataPacket::AvatarScale size doesn't match.");
251 PACKED_BEGIN
struct LookAtPosition {
252 float lookAtPosition[3];
260 const size_t LOOK_AT_POSITION_SIZE = 12;
261 static_assert(
sizeof(LookAtPosition) == LOOK_AT_POSITION_SIZE,
"AvatarDataPacket::LookAtPosition size doesn't match.");
263 PACKED_BEGIN
struct AudioLoudness {
264 uint8_t audioLoudness;
266 const size_t AUDIO_LOUDNESS_SIZE = 1;
267 static_assert(
sizeof(AudioLoudness) == AUDIO_LOUDNESS_SIZE,
"AvatarDataPacket::AudioLoudness size doesn't match.");
269 PACKED_BEGIN
struct SensorToWorldMatrix {
275 SixByteQuat sensorToWorldQuat;
276 uint16_t sensorToWorldScale;
277 float sensorToWorldTrans[3];
281 const size_t SENSOR_TO_WORLD_SIZE = 20;
282 static_assert(
sizeof(SensorToWorldMatrix) == SENSOR_TO_WORLD_SIZE,
"AvatarDataPacket::SensorToWorldMatrix size doesn't match.");
284 PACKED_BEGIN
struct AdditionalFlags {
287 const size_t ADDITIONAL_FLAGS_SIZE = 2;
288 static_assert(
sizeof(AdditionalFlags) == ADDITIONAL_FLAGS_SIZE,
"AvatarDataPacket::AdditionalFlags size doesn't match.");
291 PACKED_BEGIN
struct ParentInfo {
292 uint8_t parentUUID[16];
293 uint16_t parentJointIndex;
295 const size_t PARENT_INFO_SIZE = 18;
296 static_assert(
sizeof(ParentInfo) == PARENT_INFO_SIZE,
"AvatarDataPacket::ParentInfo size doesn't match.");
300 PACKED_BEGIN
struct AvatarLocalPosition {
301 float localPosition[3];
304 const size_t AVATAR_LOCAL_POSITION_SIZE = 12;
305 static_assert(
sizeof(AvatarLocalPosition) == AVATAR_LOCAL_POSITION_SIZE,
"AvatarDataPacket::AvatarLocalPosition size doesn't match.");
307 PACKED_BEGIN
struct HandControllers {
308 SixByteQuat leftHandRotation;
309 SixByteTrans leftHandTranslation;
310 SixByteQuat rightHandRotation;
311 SixByteTrans rightHandTranslation;
313 static const size_t HAND_CONTROLLERS_SIZE = 24;
314 static_assert(
sizeof(HandControllers) == HAND_CONTROLLERS_SIZE,
"AvatarDataPacket::HandControllers size doesn't match.");
316 const size_t MAX_CONSTANT_HEADER_SIZE = HEADER_SIZE +
317 AVATAR_GLOBAL_POSITION_SIZE +
318 AVATAR_BOUNDING_BOX_SIZE +
319 AVATAR_ORIENTATION_SIZE +
321 LOOK_AT_POSITION_SIZE +
322 AUDIO_LOUDNESS_SIZE +
323 SENSOR_TO_WORLD_SIZE +
324 ADDITIONAL_FLAGS_SIZE +
326 AVATAR_LOCAL_POSITION_SIZE +
327 HAND_CONTROLLERS_SIZE;
332 PACKED_BEGIN
struct FaceTrackerInfo {
335 float averageLoudness;
337 uint8_t numBlendshapeCoefficients;
340 const size_t FACE_TRACKER_INFO_SIZE = 17;
341 static_assert(
sizeof(FaceTrackerInfo) == FACE_TRACKER_INFO_SIZE,
"AvatarDataPacket::FaceTrackerInfo size doesn't match.");
342 size_t maxFaceTrackerInfoSize(
size_t numBlendshapeCoefficients);
358 size_t maxJointDataSize(
size_t numJoints);
359 size_t minJointDataSize(
size_t numJoints);
368 size_t maxJointDefaultPoseFlagsSize(
size_t numJoints);
370 PACKED_BEGIN
struct FarGrabJoints {
371 float leftFarGrabPosition[3];
372 float leftFarGrabRotation[4];
373 float rightFarGrabPosition[3];
374 float rightFarGrabRotation[4];
375 float mouseFarGrabPosition[3];
376 float mouseFarGrabRotation[4];
378 const size_t FAR_GRAB_JOINTS_SIZE = 84;
379 static_assert(
sizeof(FarGrabJoints) == FAR_GRAB_JOINTS_SIZE,
"AvatarDataPacket::FarGrabJoints size doesn't match.");
381 static const size_t MIN_BULK_PACKET_SIZE = NUM_BYTES_RFC4122_UUID + HEADER_SIZE;
384 enum class IdentityFlag: quint32 {none, isReplicated = 0x1, lookAtSnapping = 0x2, verificationFailed = 0x4};
385 Q_DECLARE_FLAGS(IdentityFlags, IdentityFlag)
388 HasFlags itemFlags { 0 };
389 bool sendUUID {
false };
390 int rotationsSent { 0 };
391 int translationsSent { 0 };
392 operator bool() {
return itemFlags == 0; }
396 const float MAX_AUDIO_LOUDNESS = 1000.0f;
399 const QString DEFAULT_FULL_AVATAR_MODEL_NAME = QString(
"Default");
402 const float AVATAR_SEND_FULL_UPDATE_RATIO = 0.02f;
404 const float AVATAR_MIN_ROTATION_DOT = 0.9999999f;
405 const float AVATAR_MIN_TRANSLATION = 0.0001f;
408 const float ROTATION_CHANGE_2D = 0.99984770f;
409 const float ROTATION_CHANGE_4D = 0.99939083f;
410 const float ROTATION_CHANGE_6D = 0.99862953f;
411 const float ROTATION_CHANGE_15D = 0.99144486f;
412 const float ROTATION_CHANGE_179D = 0.00872653f;
415 const float AVATAR_DISTANCE_LEVEL_1 = 12.5f;
416 const float AVATAR_DISTANCE_LEVEL_2 = 16.6f;
417 const float AVATAR_DISTANCE_LEVEL_3 = 25.0f;
418 const float AVATAR_DISTANCE_LEVEL_4 = 50.0f;
419 const float AVATAR_DISTANCE_LEVEL_5 = 200.0f;
423 const glm::vec3 START_LOCATION(6270, 211, 6000);
426 const float AVATAR_TRANSIT_MIN_TRIGGER_DISTANCE = 1.0f;
427 const float AVATAR_TRANSIT_MAX_TRIGGER_DISTANCE = 30.0f;
428 const int AVATAR_TRANSIT_FRAME_COUNT = 5;
429 const float AVATAR_TRANSIT_FRAMES_PER_METER = 0.5f;
430 const float AVATAR_TRANSIT_ABORT_DISTANCE = 0.1f;
431 const bool AVATAR_TRANSIT_DISTANCE_BASED =
false;
432 const float AVATAR_TRANSIT_FRAMES_PER_SECOND = 30.0f;
433 const float AVATAR_PRE_TRANSIT_FRAME_COUNT = 10.0f;
434 const float AVATAR_POST_TRANSIT_FRAME_COUNT = 27.0f;
442 enum KillAvatarReason : uint8_t {
446 TheirAvatarEnteredYourBubble,
447 YourAvatarEnteredTheirBubble
450 Q_DECLARE_METATYPE(KillAvatarReason);
454 class AttachmentData;
456 using TransformPointer = std::shared_ptr<Transform>;
458 class AvatarDataRate {
460 RateCounter<> globalPositionRate;
461 RateCounter<> localPositionRate;
462 RateCounter<> handControllersRate;
463 RateCounter<> avatarBoundingBoxRate;
464 RateCounter<> avatarOrientationRate;
465 RateCounter<> avatarScaleRate;
466 RateCounter<> lookAtPositionRate;
467 RateCounter<> audioLoudnessRate;
468 RateCounter<> sensorToWorldRate;
469 RateCounter<> additionalFlagsRate;
470 RateCounter<> parentInfoRate;
471 RateCounter<> faceTrackerRate;
472 RateCounter<> jointDataRate;
473 RateCounter<> jointDefaultPoseFlagsRate;
474 RateCounter<> farGrabJointRate;
477 class AvatarPriority {
479 AvatarPriority(AvatarSharedPointer a,
float p) : avatar(a), priority(p) {}
480 AvatarSharedPointer avatar;
483 bool operator<(
const AvatarPriority& other)
const {
return priority < other.priority; }
486 class ClientTraitsHandler;
488 class AvatarData :
public QObject,
public SpatiallyNestable {
557 Q_PROPERTY(glm::vec3 position READ getWorldPosition WRITE setPositionViaScript)
558 Q_PROPERTY(
float scale READ getDomainLimitedScale WRITE setTargetScale)
559 Q_PROPERTY(
float density READ getDensity)
560 Q_PROPERTY(glm::vec3 handPosition READ getHandPosition WRITE setHandPosition)
561 Q_PROPERTY(
float bodyYaw READ getBodyYaw WRITE setBodyYaw)
562 Q_PROPERTY(
float bodyPitch READ getBodyPitch WRITE setBodyPitch)
563 Q_PROPERTY(
float bodyRoll READ getBodyRoll WRITE setBodyRoll)
565 Q_PROPERTY(glm::quat orientation READ getWorldOrientation WRITE setOrientationViaScript)
566 Q_PROPERTY(glm::quat headOrientation READ getHeadOrientation WRITE setHeadOrientation)
567 Q_PROPERTY(
float headPitch READ getHeadPitch WRITE setHeadPitch)
568 Q_PROPERTY(
float headYaw READ getHeadYaw WRITE setHeadYaw)
569 Q_PROPERTY(
float headRoll READ getHeadRoll WRITE setHeadRoll)
571 Q_PROPERTY(glm::vec3 velocity READ getWorldVelocity WRITE setWorldVelocity)
572 Q_PROPERTY(glm::vec3 angularVelocity READ getWorldAngularVelocity WRITE setWorldAngularVelocity)
574 Q_PROPERTY(
float audioLoudness READ getAudioLoudness WRITE setAudioLoudness)
575 Q_PROPERTY(
float audioAverageLoudness READ getAudioAverageLoudness WRITE setAudioAverageLoudness)
577 Q_PROPERTY(QString displayName READ getDisplayName WRITE setDisplayName NOTIFY displayNameChanged)
580 Q_PROPERTY(QString sessionDisplayName READ getSessionDisplayName WRITE setSessionDisplayName NOTIFY sessionDisplayNameChanged)
581 Q_PROPERTY(
bool lookAtSnappingEnabled MEMBER _lookAtSnappingEnabled NOTIFY lookAtSnappingChanged)
582 Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript WRITE setSkeletonModelURLFromScript NOTIFY skeletonModelURLChanged)
583 Q_PROPERTY(QVector<AttachmentData> attachmentData READ getAttachmentData WRITE setAttachmentData)
585 Q_PROPERTY(QStringList jointNames READ getJointNames)
587 Q_PROPERTY(QUuid sessionUUID READ getSessionUUID NOTIFY sessionUUIDChanged)
589 Q_PROPERTY(glm::mat4 sensorToWorldMatrix READ getSensorToWorldMatrix)
590 Q_PROPERTY(glm::mat4 controllerLeftHandMatrix READ getControllerLeftHandMatrix)
591 Q_PROPERTY(glm::mat4 controllerRightHandMatrix READ getControllerRightHandMatrix)
593 Q_PROPERTY(
float sensorToWorldScale READ getSensorToWorldScale)
595 Q_PROPERTY(
bool hasPriority READ getHasPriority)
597 Q_PROPERTY(
bool hasScriptedBlendshapes READ getHasScriptedBlendshapes WRITE setHasScriptedBlendshapes)
598 Q_PROPERTY(
bool hasProceduralBlinkFaceMovement READ getHasProceduralBlinkFaceMovement WRITE setHasProceduralBlinkFaceMovement)
599 Q_PROPERTY(
bool hasProceduralEyeFaceMovement READ getHasProceduralEyeFaceMovement WRITE setHasProceduralEyeFaceMovement)
600 Q_PROPERTY(
bool hasAudioEnabledFaceMovement READ getHasAudioEnabledFaceMovement WRITE setHasAudioEnabledFaceMovement)
603 virtual QString getName()
const override {
return QString(
"Avatar:") + _displayName; }
605 static const QString FRAME_NAME;
607 static void fromFrame(
const QByteArray& frameData, AvatarData& avatar,
bool useFrameSkeleton =
true);
608 static QByteArray toFrame(
const AvatarData& avatar);
611 virtual ~AvatarData();
613 virtual bool isMyAvatarURLProtected()
const {
return false; }
615 static const QUrl& defaultFullAvatarModelUrl();
617 const QUuid getSessionUUID()
const {
return getID(); }
619 glm::vec3 getHandPosition()
const;
620 void setHandPosition(
const glm::vec3& handPosition);
631 virtual QByteArray toByteArrayStateful(AvatarDataDetail dataDetail,
bool dropFaceTracking =
false);
633 virtual QByteArray toByteArray(AvatarDataDetail dataDetail, quint64 lastSentTime,
const QVector<JointData>& lastSentJointData,
634 AvatarDataPacket::SendStatus& sendStatus,
bool dropFaceTracking,
bool distanceAdjust, glm::vec3 viewerPosition,
635 QVector<JointData>* sentJointDataOut,
int maxDataSize = 0, AvatarDataRate* outboundDataRateOut =
nullptr)
const;
637 virtual void doneEncoding(
bool cullSmallChanges);
640 bool shouldLogError(
const quint64& now);
645 virtual int parseDataFromBuffer(
const QByteArray& buffer);
647 virtual void setCollisionWithOtherAvatarsFlags() {};
650 float getBodyYaw()
const;
651 void setBodyYaw(
float bodyYaw);
652 float getBodyPitch()
const;
653 void setBodyPitch(
float bodyPitch);
654 float getBodyRoll()
const;
655 void setBodyRoll(
float bodyRoll);
657 virtual void setPositionViaScript(
const glm::vec3& position);
658 virtual void setOrientationViaScript(
const glm::quat& orientation);
660 virtual void updateAttitude(
const glm::quat& orientation) {}
662 glm::quat getHeadOrientation()
const {
664 return _headData->getOrientation();
666 void setHeadOrientation(
const glm::quat& orientation) {
668 _headData->setOrientation(orientation);
672 void setLookAtPosition(
const glm::vec3& lookAtPosition) {
674 _headData->setLookAtPosition(lookAtPosition);
678 void setBlendshapeCoefficients(
const QVector<float>& blendshapeCoefficients) {
680 _headData->setBlendshapeCoefficients(blendshapeCoefficients);
685 float getHeadPitch()
const {
return _headData->getBasePitch(); }
686 void setHeadPitch(
float value) { _headData->setBasePitch(value); }
688 float getHeadYaw()
const {
return _headData->getBaseYaw(); }
689 void setHeadYaw(
float value) { _headData->setBaseYaw(value); }
691 float getHeadRoll()
const {
return _headData->getBaseRoll(); }
692 void setHeadRoll(
float value) { _headData->setBaseRoll(value); }
696 float getAudioLoudness()
const {
return _audioLoudness; }
697 void setAudioLoudness(
float audioLoudness) {
698 if (audioLoudness != _audioLoudness) {
699 _audioLoudnessChanged = usecTimestampNow();
701 _audioLoudness = audioLoudness;
703 bool audioLoudnessChangedSince(quint64 time)
const {
return _audioLoudnessChanged >= time; }
705 float getAudioAverageLoudness()
const {
return _audioAverageLoudness; }
706 void setAudioAverageLoudness(
float audioAverageLoudness) { _audioAverageLoudness = audioAverageLoudness; }
709 virtual void setTargetScale(
float targetScale);
711 float getDomainLimitedScale()
const;
713 void setHasScriptedBlendshapes(
bool hasScriptedBlendshapes);
714 bool getHasScriptedBlendshapes()
const;
715 void setHasProceduralBlinkFaceMovement(
bool hasProceduralBlinkFaceMovement);
716 bool getHasProceduralBlinkFaceMovement()
const;
717 void setHasProceduralEyeFaceMovement(
bool hasProceduralEyeFaceMovement);
718 bool getHasProceduralEyeFaceMovement()
const;
719 void setHasAudioEnabledFaceMovement(
bool hasAudioEnabledFaceMovement);
720 bool getHasAudioEnabledFaceMovement()
const;
728 Q_INVOKABLE
float getDomainMinScale()
const;
736 Q_INVOKABLE
float getDomainMaxScale()
const;
740 virtual float getUnscaledEyeHeight()
const {
return DEFAULT_AVATAR_EYE_HEIGHT; }
744 virtual bool canMeasureEyeHeight()
const {
return false; }
752 Q_INVOKABLE
virtual float getEyeHeight()
const {
return _targetScale * getUnscaledEyeHeight(); }
760 Q_INVOKABLE
virtual float getHeight()
const;
762 float getUnscaledHeight()
const;
764 void setDomainMinimumHeight(
float domainMinimumHeight);
765 void setDomainMaximumHeight(
float domainMaximumHeight);
773 Q_INVOKABLE
void setHandState(
char s) { _handState = s; }
781 Q_INVOKABLE
char getHandState()
const {
return _handState; }
812 Q_INVOKABLE
virtual void setJointData(
int index,
const glm::quat& rotation,
const glm::vec3& translation);
825 Q_INVOKABLE
virtual void setJointRotation(
int index,
const glm::quat& rotation);
839 Q_INVOKABLE
virtual void setJointTranslation(
int index,
const glm::vec3& translation);
848 Q_INVOKABLE
virtual void clearJointData(
int index);
856 Q_INVOKABLE
bool isJointDataValid(
int index)
const;
865 Q_INVOKABLE
virtual glm::quat getJointRotation(
int index)
const;
876 Q_INVOKABLE
virtual glm::vec3 getJointTranslation(
int index)
const;
891 Q_INVOKABLE
virtual void setJointData(
const QString& name,
const glm::quat& rotation,
const glm::vec3& translation);
924 Q_INVOKABLE
virtual void setJointRotation(
const QString& name,
const glm::quat& rotation);
950 Q_INVOKABLE
virtual void setJointTranslation(
const QString& name,
const glm::vec3& translation);
969 Q_INVOKABLE
virtual void clearJointData(
const QString& name);
977 Q_INVOKABLE
virtual bool isJointDataValid(
const QString& name)
const;
990 Q_INVOKABLE
virtual glm::quat getJointRotation(
const QString& name)
const;
1005 Q_INVOKABLE
virtual glm::vec3 getJointTranslation(
const QString& name)
const;
1017 Q_INVOKABLE
virtual QVector<glm::quat> getJointRotations()
const;
1028 Q_INVOKABLE
virtual QVector<glm::vec3> getJointTranslations()
const;
1066 Q_INVOKABLE
virtual void setJointRotations(
const QVector<glm::quat>& jointRotations);
1082 Q_INVOKABLE
virtual void setJointTranslations(
const QVector<glm::vec3>& jointTranslations);
1104 Q_INVOKABLE
virtual void clearJointsData();
1118 Q_INVOKABLE
virtual int getJointIndex(
const QString& name)
const;
1129 Q_INVOKABLE
virtual QStringList getJointNames()
const;
1146 Q_INVOKABLE
void setBlendshape(QString name,
float val) { _headData->setBlendshape(name, val); }
1156 Q_INVOKABLE
virtual QVariantList getAttachmentsVariant()
const;
1167 Q_INVOKABLE
virtual void setAttachmentsVariant(
const QVariantList& variant);
1169 virtual void storeAvatarEntityDataPayload(
const QUuid& entityID,
const QByteArray& payload);
1177 Q_INVOKABLE
virtual void updateAvatarEntity(
const QUuid& entityID,
const QByteArray& entityData);
1185 Q_INVOKABLE
virtual void clearAvatarEntity(
const QUuid& entityID,
bool requiresRemovalFromTree =
true);
1188 virtual void clearAvatarEntityInternal(
const QUuid& entityID);
1190 void clearAvatarEntities();
1192 QList<QUuid> getAvatarEntityIDs()
const;
1203 Q_INVOKABLE
void setForceFaceTrackerConnected(
bool connected) { setHasScriptedBlendshapes(connected); }
1206 void setKeyState(KeyState s) { _keyState = s; }
1207 KeyState keyState()
const {
return _keyState; }
1209 const HeadData* getHeadData()
const {
return _headData; }
1212 QVector<AttachmentData> attachmentData;
1213 QString displayName;
1214 QString sessionDisplayName;
1216 bool lookAtSnappingEnabled;
1217 AvatarDataPacket::IdentityFlags identityFlags;
1222 void processAvatarIdentity(QDataStream& packetStream,
bool& identityChanged,
bool& displayNameChanged);
1224 QByteArray packTrait(AvatarTraits::TraitType traitType)
const;
1225 QByteArray packTraitInstance(AvatarTraits::TraitType traitType, AvatarTraits::TraitInstanceID instanceID);
1227 void processTrait(AvatarTraits::TraitType traitType, QByteArray traitBinaryData);
1228 void processTraitInstance(AvatarTraits::TraitType traitType,
1229 AvatarTraits::TraitInstanceID instanceID, QByteArray traitBinaryData);
1230 void processDeletedTraitInstance(AvatarTraits::TraitType traitType, AvatarTraits::TraitInstanceID instanceID);
1232 void prepareResetTraitInstances();
1234 QByteArray identityByteArray(
bool setIsReplicated =
false)
const;
1236 QUrl getWireSafeSkeletonModelURL()
const;
1237 virtual const QUrl& getSkeletonModelURL()
const;
1239 const QString& getDisplayName()
const {
return _displayName; }
1240 const QString& getSessionDisplayName()
const {
return _sessionDisplayName; }
1241 bool getLookAtSnappingEnabled()
const {
return _lookAtSnappingEnabled; }
1248 Q_INVOKABLE
virtual void setSkeletonModelURL(
const QUrl& skeletonModelURL);
1250 virtual void setDisplayName(
const QString& displayName);
1251 virtual void setSessionDisplayName(
const QString& sessionDisplayName) {
1252 _sessionDisplayName = sessionDisplayName;
1253 markIdentityDataChanged();
1255 virtual bool isCertifyFailed()
const {
return _verificationFailed; }
1270 Q_INVOKABLE
virtual QVector<AttachmentData> getAttachmentData()
const;
1294 Q_INVOKABLE
virtual void setAttachmentData(
const QVector<AttachmentData>& attachmentData);
1335 Q_INVOKABLE
virtual void attach(
const QString& modelURL,
const QString& jointName = QString(),
1336 const glm::vec3& translation = glm::vec3(),
const glm::quat& rotation = glm::quat(),
1337 float scale = 1.0f,
bool isSoft =
false,
1338 bool allowDuplicates =
false,
bool useSaved =
true);
1348 Q_INVOKABLE
virtual void detachOne(
const QString& modelURL,
const QString& jointName = QString());
1358 Q_INVOKABLE
virtual void detachAll(
const QString& modelURL,
const QString& jointName = QString());
1360 QString getSkeletonModelURLFromScript()
const;
1361 void setSkeletonModelURLFromScript(
const QString& skeletonModelString) { setSkeletonModelURL(QUrl(skeletonModelString)); }
1363 void setOwningAvatarMixer(
const QWeakPointer<Node>& owningAvatarMixer) { _owningAvatarMixer = owningAvatarMixer; }
1365 int getAverageBytesReceivedPerSecond()
const;
1366 int getReceiveRate()
const;
1369 bool getHasPriority()
const {
return _hasPriority; }
1371 void setHasPriority(
bool hasPriority) {
1372 if (_hasPriority != hasPriority) {
1373 _additionalFlagsChanged = usecTimestampNow();
1374 _hasPriority = hasPriority;
1378 void setHasPriorityWithoutTimestampReset(
bool hasPriority) { _hasPriority = hasPriority; }
1380 const glm::vec3& getTargetVelocity()
const {
return _targetVelocity; }
1382 void clearRecordingBasis();
1383 TransformPointer getRecordingBasis()
const;
1384 void setRecordingBasis(TransformPointer recordingBasis = TransformPointer());
1385 void createRecordingIDs();
1386 virtual void avatarEntityDataToJson(QJsonObject& root)
const;
1387 QJsonObject toJson()
const;
1388 void fromJson(
const QJsonObject& json,
bool useFrameSkeleton =
true);
1390 glm::vec3 getClientGlobalPosition()
const {
return _globalPosition; }
1391 AABox getGlobalBoundingBox()
const {
return AABox(_globalPosition + _globalBoundingBoxOffset - _globalBoundingBoxDimensions, _globalBoundingBoxDimensions); }
1392 AABox getDefaultBubbleBox()
const;
1398 Q_INVOKABLE
virtual AvatarEntityMap getAvatarEntityData()
const;
1401 virtual AvatarEntityMap getAvatarEntityDataNonDefault()
const;
1406 Q_INVOKABLE
virtual void setAvatarEntityData(
const AvatarEntityMap& avatarEntityData);
1408 void setAvatarEntityDataChanged(
bool value) { _avatarEntityDataChanged = value; }
1409 AvatarEntityIDs getAndClearRecentlyRemovedIDs();
1426 Q_INVOKABLE glm::mat4 getSensorToWorldMatrix()
const;
1435 Q_INVOKABLE
float getSensorToWorldScale()
const;
1451 Q_INVOKABLE glm::mat4 getControllerLeftHandMatrix()
const;
1459 Q_INVOKABLE glm::mat4 getControllerRightHandMatrix()
const;
1468 Q_INVOKABLE
float getDataRate(
const QString& rateName = QString(
""))
const;
1476 Q_INVOKABLE
float getUpdateRate(
const QString& rateName = QString(
""))
const;
1478 int getJointCount()
const {
return _jointData.size(); }
1480 QVector<JointData> getLastSentJointData() {
1481 QReadLocker readLock(&_jointDataLock);
1482 _lastSentJointData.resize(_jointData.size());
1483 return _lastSentJointData;
1487 virtual glm::quat getOrientationOutbound()
const;
1491 static float _avatarSortCoefficientSize;
1492 static float _avatarSortCoefficientCenter;
1493 static float _avatarSortCoefficientAge;
1495 bool getIdentityDataChanged()
const {
return _identityDataChanged; }
1496 void markIdentityDataChanged() { _identityDataChanged =
true; }
1498 void pushIdentitySequenceNumber() { ++_identitySequenceNumber; };
1499 bool hasProcessedFirstIdentity()
const {
return _hasProcessedFirstIdentity; }
1501 float getDensity()
const {
return _density; }
1503 bool getIsReplicated()
const {
return _isReplicated; }
1505 void setReplicaIndex(
int replicaIndex) { _replicaIndex = replicaIndex; }
1506 int getReplicaIndex() {
return _replicaIndex; }
1508 static const float DEFAULT_BUBBLE_SCALE;
1509 AABox computeBubbleBox(
float bubbleScale = DEFAULT_BUBBLE_SCALE)
const;
1511 void setIsNewAvatar(
bool isNewAvatar) { _isNewAvatar = isNewAvatar; }
1512 bool getIsNewAvatar() {
return _isNewAvatar; }
1513 void setIsClientAvatar(
bool isClientAvatar) { _isClientAvatar = isClientAvatar; }
1514 void setSkeletonData(
const std::vector<AvatarSkeletonTrait::UnpackedJointData>& skeletonData);
1515 std::vector<AvatarSkeletonTrait::UnpackedJointData> getSkeletonData()
const;
1516 void sendSkeletonData()
const;
1517 QVector<JointData> getJointData()
const;
1518 glm::vec3 getHeadJointFrontVector()
const;
1533 void displayNameChanged();
1546 void sessionDisplayNameChanged();
1559 void skeletonModelURLChanged();
1573 void lookAtSnappingChanged(
bool enabled);
1586 void sessionUUIDChanged();
1596 virtual int sendAvatarDataPacket(
bool sendAll =
false);
1603 int sendIdentityPacket();
1610 virtual void setSessionUUID(
const QUuid& sessionUUID) {
1611 if (sessionUUID != getID()) {
1612 if (sessionUUID == QUuid()) {
1613 setID(AVATAR_SELF_ID);
1617 emit sessionUUIDChanged();
1629 virtual glm::quat getAbsoluteJointRotationInObjectFrame(
int index)
const override;
1638 virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(
int index)
const override;
1648 virtual bool setAbsoluteJointRotationInObjectFrame(
int index,
const glm::quat& rotation)
override {
return false; }
1658 virtual bool setAbsoluteJointTranslationInObjectFrame(
int index,
const glm::vec3& translation)
override {
return false; }
1671 float getTargetScale()
const {
return _targetScale; }
1677 void resetLastSent() { _lastToByteArray = 0; }
1680 void insertRemovedEntityID(
const QUuid entityID);
1681 void lazyInitHeadData()
const;
1683 float getDistanceBasedMinRotationDOT(glm::vec3 viewerPosition)
const;
1684 float getDistanceBasedMinTranslationDistance(glm::vec3 viewerPosition)
const;
1686 bool avatarBoundingBoxChangedSince(quint64 time)
const {
return _avatarBoundingBoxChanged >= time; }
1687 bool avatarScaleChangedSince(quint64 time)
const {
return _avatarScaleChanged >= time; }
1688 bool lookAtPositionChangedSince(quint64 time)
const {
return _headData->lookAtPositionChangedSince(time); }
1689 bool sensorToWorldMatrixChangedSince(quint64 time)
const {
return _sensorToWorldMatrixChanged >= time; }
1690 bool additionalFlagsChangedSince(quint64 time)
const {
return _additionalFlagsChanged >= time; }
1691 bool parentInfoChangedSince(quint64 time)
const {
return _parentChanged >= time; }
1692 bool faceTrackerInfoChangedSince(quint64 time)
const {
return true; }
1694 bool hasParent()
const {
return !getParentID().isNull(); }
1696 QByteArray packSkeletonData()
const;
1697 QByteArray packSkeletonModelURL()
const;
1698 QByteArray packAvatarEntityTraitInstance(AvatarTraits::TraitInstanceID traitInstanceID);
1699 QByteArray packGrabTraitInstance(AvatarTraits::TraitInstanceID traitInstanceID);
1701 const QVector<JointData>& getRawJointData()
const {
return _jointData; }
1702 void setRawJointData(QVector<JointData> data);
1704 void unpackSkeletonModelURL(
const QByteArray& data);
1705 void unpackSkeletonData(
const QByteArray& data);
1709 bool _isReplicated{
false };
1711 glm::vec3 _handPosition;
1712 virtual const QString& getSessionDisplayNameForTransport()
const {
return _sessionDisplayName; }
1713 virtual void maybeUpdateSessionDisplayNameFromTransport(
const QString& sessionDisplayName) { }
1717 float _domainMinimumHeight { MIN_AVATAR_HEIGHT };
1718 float _domainMaximumHeight { MAX_AVATAR_HEIGHT };
1723 QVector<JointData> _jointData;
1724 QVector<JointData> _lastSentJointData;
1725 mutable QReadWriteLock _jointDataLock;
1730 bool _hasNewJointData {
true };
1732 mutable HeadData* _headData {
nullptr };
1734 QUrl _skeletonModelURL;
1735 QVector<AttachmentData> _attachmentData;
1736 QVector<AttachmentData> _oldAttachmentData;
1737 QString _displayName;
1738 QString _sessionDisplayName { };
1739 bool _lookAtSnappingEnabled {
true };
1740 bool _verificationFailed {
false };
1742 quint64 _errorLogExpiry;
1744 QWeakPointer<Node> _owningAvatarMixer;
1746 glm::vec3 _targetVelocity;
1748 SimpleMovingAverage _averageBytesReceived;
1752 TransformPointer _recordingBasis;
1757 glm::vec3 _globalPosition { 0, 0, 0 };
1758 glm::vec3 _serverPosition { 0, 0, 0 };
1760 quint64 _globalPositionChanged { 0 };
1761 quint64 _avatarBoundingBoxChanged { 0 };
1762 quint64 _avatarScaleChanged { 0 };
1763 quint64 _sensorToWorldMatrixChanged { 0 };
1764 quint64 _additionalFlagsChanged { 0 };
1765 quint64 _parentChanged { 0 };
1767 quint64 _lastToByteArray { 0 };
1770 RateCounter<> _parseBufferRate;
1771 RateCounter<> _globalPositionRate;
1772 RateCounter<> _localPositionRate;
1773 RateCounter<> _handControllersRate;
1774 RateCounter<> _avatarBoundingBoxRate;
1775 RateCounter<> _avatarOrientationRate;
1776 RateCounter<> _avatarScaleRate;
1777 RateCounter<> _lookAtPositionRate;
1778 RateCounter<> _audioLoudnessRate;
1779 RateCounter<> _sensorToWorldRate;
1780 RateCounter<> _additionalFlagsRate;
1781 RateCounter<> _parentInfoRate;
1782 RateCounter<> _faceTrackerRate;
1783 RateCounter<> _jointDataRate;
1784 RateCounter<> _jointDefaultPoseFlagsRate;
1785 RateCounter<> _farGrabJointRate;
1788 RateCounter<> _parseBufferUpdateRate;
1789 RateCounter<> _globalPositionUpdateRate;
1790 RateCounter<> _localPositionUpdateRate;
1791 RateCounter<> _handControllersUpdateRate;
1792 RateCounter<> _avatarBoundingBoxUpdateRate;
1793 RateCounter<> _avatarOrientationUpdateRate;
1794 RateCounter<> _avatarScaleUpdateRate;
1795 RateCounter<> _lookAtPositionUpdateRate;
1796 RateCounter<> _audioLoudnessUpdateRate;
1797 RateCounter<> _sensorToWorldUpdateRate;
1798 RateCounter<> _additionalFlagsUpdateRate;
1799 RateCounter<> _parentInfoUpdateRate;
1800 RateCounter<> _faceTrackerUpdateRate;
1801 RateCounter<> _jointDataUpdateRate;
1802 RateCounter<> _jointDefaultPoseFlagsUpdateRate;
1803 RateCounter<> _farGrabJointUpdateRate;
1806 AvatarDataRate _outboundDataRate;
1808 glm::vec3 _globalBoundingBoxDimensions;
1809 glm::vec3 _globalBoundingBoxOffset;
1811 AABox _defaultBubbleBox;
1812 AABox _fitBoundingBox;
1814 mutable ReadWriteLockable _avatarEntitiesLock;
1815 AvatarEntityIDs _avatarEntityRemoved;
1816 AvatarEntityIDs _avatarEntityForRecording;
1817 PackedAvatarEntityMap _packedAvatarEntityData;
1818 bool _avatarEntityDataChanged {
false };
1820 mutable ReadWriteLockable _avatarGrabsLock;
1821 AvatarGrabDataMap _avatarGrabData;
1822 bool _avatarGrabDataChanged {
false };
1824 mutable ReadWriteLockable _avatarSkeletonDataLock;
1825 std::vector<AvatarSkeletonTrait::UnpackedJointData> _avatarSkeletonData;
1828 ThreadSafeValueCache<glm::mat4> _sensorToWorldMatrixCache { glm::mat4() };
1829 ThreadSafeValueCache<glm::mat4> _controllerLeftHandMatrixCache { glm::mat4() };
1830 ThreadSafeValueCache<glm::mat4> _controllerRightHandMatrixCache { glm::mat4() };
1832 ThreadSafeValueCache<glm::mat4> _farGrabRightMatrixCache { glm::mat4() };
1833 ThreadSafeValueCache<glm::mat4> _farGrabLeftMatrixCache { glm::mat4() };
1834 ThreadSafeValueCache<glm::mat4> _farGrabMouseMatrixCache { glm::mat4() };
1836 ThreadSafeValueCache<QVariantMap> _collisionCapsuleCache{ QVariantMap() };
1838 int getFauxJointIndex(
const QString& name)
const;
1840 float _audioLoudness { 0.0f };
1841 quint64 _audioLoudnessChanged { 0 };
1842 float _audioAverageLoudness { 0.0f };
1844 bool _identityDataChanged {
false };
1845 udt::SequenceNumber _identitySequenceNumber { 0 };
1846 bool _hasProcessedFirstIdentity {
false };
1848 int _replicaIndex { 0 };
1849 bool _isNewAvatar {
true };
1850 bool _isClientAvatar {
false };
1851 bool _collideWithOtherAvatars {
true };
1852 bool _hasPriority{
false };
1855 std::unique_ptr<ClientTraitsHandler, LaterDeleter> _clientTraitsHandler;
1857 template <
typename T,
typename F>
1858 T readLockWithNamedJointIndex(
const QString& name,
const T& defaultValue, F f)
const {
1859 QReadLocker readLock(&_jointDataLock);
1860 int index = getJointIndex(name);
1862 return defaultValue;
1867 template <
typename T,
typename F>
1868 T readLockWithNamedJointIndex(
const QString& name, F f)
const {
1869 return readLockWithNamedJointIndex(name, T(), f);
1872 template <
typename F>
1873 void writeLockWithNamedJointIndex(
const QString& name, F f) {
1874 QWriteLocker writeLock(&_jointDataLock);
1875 int index = getJointIndex(name);
1879 if (_jointData.size() <= index) {
1880 _jointData.resize(index + 1);
1885 bool updateAvatarGrabData(
const QUuid& grabID,
const QByteArray& grabData);
1886 virtual void clearAvatarGrabData(
const QUuid& grabID);
1889 Q_DISABLE_COPY(AvatarData)
1891 friend void avatarStateFromFrame(
const QByteArray& frameData, AvatarData* _avatar);
1894 friend class MyAvatar;
1895 static QUrl _defaultFullAvatarModelUrl;
1897 Q_DECLARE_METATYPE(AvatarData*)
1899 QJsonValue toJsonValue(
const JointData& joint);
1900 JointData jointDataFromJsonValue(
const QJsonValue& q);
1902 class AttachmentData {
1906 glm::vec3 translation;
1908 float scale { 1.0f };
1909 bool isSoft {
false };
1911 bool isValid()
const {
return modelURL.isValid(); }
1913 bool operator==(
const AttachmentData& other)
const;
1915 QJsonObject toJson()
const;
1916 void fromJson(
const QJsonObject& json);
1918 QVariant toVariant()
const;
1919 bool fromVariant(
const QVariant& variant);
1922 QDataStream& operator<<(QDataStream& out,
const AttachmentData& attachment);
1923 QDataStream& operator>>(QDataStream& in, AttachmentData& attachment);
1925 Q_DECLARE_METATYPE(AttachmentData)
1926 Q_DECLARE_METATYPE(QVector<AttachmentData>)
1928 class AttachmentDataObject :
public QObject,
protected Scriptable {
1931 Q_PROPERTY(QString modelURL READ getModelURL WRITE setModelURL)
1932 Q_PROPERTY(QString jointName READ getJointName WRITE setJointName)
1933 Q_PROPERTY(glm::vec3 translation READ getTranslation WRITE setTranslation)
1934 Q_PROPERTY(glm::quat rotation READ getRotation WRITE setRotation)
1935 Q_PROPERTY(
float scale READ getScale WRITE setScale)
1936 Q_PROPERTY(
bool isSoft READ getIsSoft WRITE setIsSoft)
1940 Q_INVOKABLE
void setModelURL(
const QString& modelURL);
1941 Q_INVOKABLE QString getModelURL()
const;
1943 Q_INVOKABLE
void setJointName(
const QString& jointName);
1944 Q_INVOKABLE QString getJointName()
const;
1946 Q_INVOKABLE
void setTranslation(
const glm::vec3& translation);
1947 Q_INVOKABLE glm::vec3 getTranslation()
const;
1949 Q_INVOKABLE
void setRotation(
const glm::quat& rotation);
1950 Q_INVOKABLE glm::quat getRotation()
const;
1952 Q_INVOKABLE
void setScale(
float scale);
1953 Q_INVOKABLE
float getScale()
const;
1955 Q_INVOKABLE
void setIsSoft(
bool scale);
1956 Q_INVOKABLE
bool getIsSoft()
const;
1962 class RayToAvatarIntersectionResult {
1964 bool intersects {
false };
1966 float distance { FLT_MAX };
1967 BoxFace face { UNKNOWN_FACE };
1968 glm::vec3 intersection { glm::vec3(0.0f, 0.0f, 0.0f) };
1969 glm::vec3 surfaceNormal { glm::vec3(0.0f, 1.0f, 0.0f) };
1970 int jointIndex { -1 };
1971 QVariantMap extraInfo;
1973 Q_DECLARE_METATYPE(RayToAvatarIntersectionResult)
1974 ScriptValue RayToAvatarIntersectionResultToScriptValue(
ScriptEngine* engine,
const RayToAvatarIntersectionResult& results);
1975 bool RayToAvatarIntersectionResultFromScriptValue(
const ScriptValue&
object, RayToAvatarIntersectionResult& results);
1978 class ParabolaToAvatarIntersectionResult {
1980 bool intersects {
false };
1982 float distance { 0.0f };
1983 float parabolicDistance { 0.0f };
1985 glm::vec3 intersection;
1986 glm::vec3 surfaceNormal;
1987 QVariantMap extraInfo;
1990 Q_DECLARE_METATYPE(AvatarEntityMap)
1993 bool AvatarEntityMapFromScriptValue(
const ScriptValue&
object, AvatarEntityMap& value);
1996 const int NO_JOINT_INDEX = 65535;
1997 const int SENSOR_TO_WORLD_MATRIX_INDEX = 65534;
1998 const int CONTROLLER_RIGHTHAND_INDEX = 65533;
1999 const int CONTROLLER_LEFTHAND_INDEX = 65532;
2000 const int CAMERA_RELATIVE_CONTROLLER_RIGHTHAND_INDEX = 65531;
2001 const int CAMERA_RELATIVE_CONTROLLER_LEFTHAND_INDEX = 65530;
2002 const int CAMERA_MATRIX_INDEX = 65529;
2003 const int FARGRAB_RIGHTHAND_INDEX = 65528;
2004 const int FARGRAB_LEFTHAND_INDEX = 65527;
2005 const int FARGRAB_MOUSE_INDEX = 65526;
2007 const int LOWEST_PSEUDO_JOINT_INDEX = 65526;
2009 const int MAX_NUM_AVATAR_GRABS = 6;
Provides an engine-independent interface for a scripting engine.
Definition: ScriptEngine.h:93
[ScriptInterface] Provides an engine-independent interface for QScriptValue
Definition: ScriptValue.h:40
[ScriptInterface] Provides an engine-independent interface for QScriptable
Definition: Scriptable.h:29
A skeleton loaded from a model.
Definition: SkeletonModel.h:25