From 719062dd9fef380ff14e2b40fca39de4e0ab0801 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 24 Apr 2018 09:10:59 +1200 Subject: [PATCH] Interim JSDoc for MyAvatar - first pass --- interface/src/avatar/MyAvatar.h | 373 ++++++++++++++---- .../src/avatars-renderer/Avatar.h | 113 ++++-- libraries/avatars/src/AvatarData.cpp | 9 + libraries/avatars/src/AvatarData.h | 349 +++++++++++++++- tools/jsdoc/plugins/hifi.js | 1 + 5 files changed, 735 insertions(+), 110 deletions(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 6f82c7dfb9..c74670bbed 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -55,68 +55,108 @@ class MyAvatar : public Avatar { Q_OBJECT /**jsdoc - * Your avatar is your in-world representation of you. The MyAvatar API is used to manipulate the avatar. - * For example, using the MyAvatar API you can customize the avatar's appearance, run custom avatar animations, + * Your avatar is your in-world representation of you. The MyAvatar API is used to manipulate the avatar. + * For example, you can customize the avatar's appearance, run custom avatar animations, * change the avatar's position within the domain, or manage the avatar's collisions with other objects. - * NOTE: MyAvatar extends Avatar and AvatarData, see those namespace for more properties/methods. * * @namespace MyAvatar - * @augments Avatar - * @property qmlPosition {Vec3} Used as a stopgap for position access by QML, as glm::vec3 is unavailable outside of scripts - * @property shouldRenderLocally {bool} Set it to true if you would like to see MyAvatar in your local interface, - * and false if you would not like to see MyAvatar in your local interface. + * @property qmlPosition {Vec3} Used as a stopgap for position access by QML, as Vec3 is unavailable outside of scripts. + * @property shouldRenderLocally {boolean} Set it to true if you would like to see MyAvatar in your local interface, + * and false if you would not like to see MyAvatar in your local interface. * @property motorVelocity {Vec3} Can be used to move the avatar with this velocity. - * @property motorTimescale {float} Specifies how quickly the avatar should accelerate to meet the motorVelocity, - * smaller values will result in higher acceleration. - * @property motorReferenceFrame {string} Reference frame of the motorVelocity, must be one of the following: "avatar", "camera", "world" - * @property motorMode {string} Type of scripted motor behavior, "simple" = use motorTimescale property (default mode) and "dynamic" = use action motor's timescales + * @property motorTimescale {number} Specifies how quickly the avatar should accelerate to meet the motorVelocity, + * smaller values will result in higher acceleration. + * @property motorReferenceFrame {string} Reference frame of the motorVelocity, must be one of the following: "avatar", + * "camera", "world". + * @property motorMode {string} Type of scripted motor behavior, "simple" = use motorTimescale property (default mode) and + * "dynamic" = use action motor's timescales. * @property collisionSoundURL {string} Specifies the sound to play when the avatar experiences a collision. - * You can provide a mono or stereo 16-bit WAV file running at either 24 Khz or 48 Khz. - * The latter is downsampled by the audio mixer, so all audio effectively plays back at a 24 Khz sample rate. - * 48 Khz RAW files are also supported. + * You can provide a mono or stereo 16-bit WAV file running at either 24 Khz or 48 Khz. + * The latter is downsampled by the audio mixer, so all audio effectively plays back at a 24 Khz sample rate. + * 48 Khz RAW files are also supported. * @property audioListenerMode {number} When hearing spatialized audio this determines where the listener placed. - * Should be one of the following values: - * MyAvatar.audioListenerModeHead - the listener located at the avatar's head. - * MyAvatar.audioListenerModeCamera - the listener is relative to the camera. - * MyAvatar.audioListenerModeCustom - the listener is at a custom location specified by the MyAvatar.customListenPosition - * and MyAvatar.customListenOrientation properties. - * @property customListenPosition {Vec3} If MyAvatar.audioListenerMode == MyAvatar.audioListenerModeHead, then this determines the position - * of audio spatialization listener. - * @property customListenOrientation {Quat} If MyAvatar.audioListenerMode == MyAvatar.audioListenerModeHead, then this determines the orientation - * of the audio spatialization listener. - * @property audioListenerModeHead {number} READ-ONLY. When passed to MyAvatar.audioListenerMode, it will set the audio listener - * around the avatar's head. - * @property audioListenerModeCamera {number} READ-ONLY. When passed to MyAvatar.audioListenerMode, it will set the audio listener - * around the camera. - * @property audioListenerModeCustom {number} READ-ONLY. When passed to MyAvatar.audioListenerMode, it will set the audio listener - * around the value specified by MyAvatar.customListenPosition and MyAvatar.customListenOrientation. - * @property leftHandPosition {Vec3} READ-ONLY. The desired position of the left wrist in avatar space, determined by the hand controllers. - * Note: only valid if hand controllers are in use. - * @property rightHandPosition {Vec3} READ-ONLY. The desired position of the right wrist in avatar space, determined by the hand controllers. - * Note: only valid if hand controllers are in use. - * @property leftHandTipPosition {Vec3} READ-ONLY. A position 30 cm offset from MyAvatar.leftHandPosition - * @property rightHandTipPosition {Vec3} READ-ONLY. A position 30 cm offset from MyAvatar.rightHandPosition - * @property leftHandPose {Pose} READ-ONLY. Returns full pose (translation, orientation, velocity & angularVelocity) of the desired - * wrist position, determined by the hand controllers. - * @property rightHandPose {Pose} READ-ONLY. Returns full pose (translation, orientation, velocity & angularVelocity) of the desired - * wrist position, determined by the hand controllers. - * @property leftHandTipPose {Pose} READ-ONLY. Returns a pose offset 30 cm from MyAvatar.leftHandPose - * @property rightHandTipPose {Pose} READ-ONLY. Returns a pose offset 30 cm from MyAvatar.rightHandPose - * @property hmdLeanRecenterEnabled {bool} This can be used disable the hmd lean recenter behavior. This behavior is what causes your avatar - * to follow your HMD as you walk around the room, in room scale VR. Disabling this is useful if you desire to pin the avatar to a fixed location. - * @property collisionsEnabled {bool} This can be used to disable collisions between the avatar and the world. - * @property useAdvancedMovementControls {bool} Stores the user preference only, does not change user mappings, this is done in the defaultScript - * "scripts/system/controllers/toggleAdvancedMovementForHandControllers.js". - * @property userHeight {number} The height of the user in sensor space. (meters). - * @property userEyeHeight {number} Estimated height of the users eyes in sensor space. (meters) - * @property SELF_ID {string} READ-ONLY. UUID representing "my avatar". Only use for local-only entities and overlays in situations where MyAvatar.sessionUUID is not available (e.g., if not connected to a domain). - * Note: Likely to be deprecated. - * @property hmdRollControlEnabled {bool} When enabled the roll angle of your HMD will turn your avatar while flying. - * @property hmdRollControlDeadZone {number} If hmdRollControlEnabled is true, this value can be used to tune what roll angle is required to begin turning. - * This angle is specified in degrees. - * @property hmdRollControlRate {number} If hmdRollControlEnabled is true, this value determines the maximum turn rate of your avatar when rolling your HMD in degrees per second. + * Should be one of the following values:
+ * MyAvatar.audioListenerModeHead - the listener located at the avatar's head.
+ * MyAvatar.audioListenerModeCamera - the listener is relative to the camera.
+ * MyAvatar.audioListenerModeCustom - the listener is at a custom location specified by the + * MyAvatar.customListenPosition and MyAvatar.customListenOrientation properties. + * @property customListenPosition {Vec3} If MyAvatar.audioListenerMode == MyAvatar.audioListenerModeHead, then this + * determines the position of audio spatialization listener. + * @property customListenOrientation {Quat} If MyAvatar.audioListenerMode == MyAvatar.audioListenerModeHead, then this + * determines the orientation of the audio spatialization listener. + * @property audioListenerModeHead {number} When passed to MyAvatar.audioListenerMode, it will set the audio listener + * around the avatar's head. Read-only. + * @property audioListenerModeCamera {number} When passed to MyAvatar.audioListenerMode, it will set the audio listener + * around the camera. Read-only. + * @property audioListenerModeCustom {number} When passed to MyAvatar.audioListenerMode, it will set the audio listener + * around the value specified by MyAvatar.customListenPosition and MyAvatar.customListenOrientation. Read-only. + * @property leftHandPosition {Vec3} The desired position of the left wrist in avatar space, determined by the hand + * controllers. Note: only valid if hand controllers are in use. Read-only. + * @property rightHandPosition {Vec3} The desired position of the right wrist in avatar space, determined by the hand + * controllers. Note: only valid if hand controllers are in use. Read-only. + * F@property leftHandTipPosition {Vec3} A position 30 cm offset from MyAvatar.leftHandPosition. Read-only. + * @property rightHandTipPosition {Vec3} A position 30 cm offset from MyAvatar.rightHandPosition. Read-only. + * @property leftHandPose {Pose} Returns full pose (translation, orientation, velocity & angularVelocity) of the desired + * wrist position, determined by the hand controllers. Read-only. + * @property rightHandPose {Pose} Returns full pose (translation, orientation, velocity & angularVelocity) of the desired + * wrist position, determined by the hand controllers. Read-only. + * @property leftHandTipPose {Pose} Returns a pose offset 30 cm from MyAvatar.leftHandPose. Read-only. + * @property rightHandTipPose {Pose} Returns a pose offset 30 cm from MyAvatar.rightHandPose. Read-only. + * @property hmdLeanRecenterEnabled {boolean} This can be used disable the hmd lean recenter behavior. This behavior is + * what causes your avatar to follow your HMD as you walk around the room, in room scale VR. Disabling this is useful + * if you desire to pin the avatar to a fixed location. + * @property collisionsEnabled {boolean} This can be used to disable collisions between the avatar and the world. + * @property useAdvancedMovementControls {boolean} Stores the user preference only, does not change user mappings, this is + * done in the default script, "toggleAdvancedMovementForHandControllers.js". + * @property userHeight {number} The height of the user in sensor space. + * @property userEyeHeight {number} Estimated height of the users eyes in sensor space. + * @property SELF_ID {string} UUID representing "my avatar". Only use for local-only entities and overlays in situations + * where MyAvatar.sessionUUID is not available (e.g., if not connected to a domain). Note: Likely to be deprecated. + * Read-only. + * @property hmdRollControlEnabled {boolean} When enabled the roll angle of your HMD will turn your avatar while flying. + * @property hmdRollControlDeadZone {number} If hmdRollControlEnabled is true, this value can be used to tune what roll + * angle is required to begin turning. This angle is specified in degrees. + * @property hmdRollControlRate {number} If hmdRollControlEnabled is true, this value determines the maximum turn rate of + * your avatar when rolling your HMD in degrees per second. + * + * @property {Vec3} skeletonOffset - Can be used to apply a translation offset between the avatar's position and the + * registration point of the 3D model. + * + * @property {Vec3} position + * @property {number} scale + * @property {number} density Read-only. + * @property {Vec3} handPosition + * @property {number} bodyYaw - The rotation left or right about an axis running from the head to the feet of MyAvatar. Yaw + * is sometimes called "heading". + * @property {number} bodyPitch - The rotation about an axis running from shoulder to shoulder of MyAvatar. Pitch is + * sometimes called "elevation". + * @property {number} bodyRoll - The rotation about an axis running from the chest to the back of the avatar. Roll is + * sometimes called "bank". + * @property {Quat} orientation + * @property {Quat} headOrientation - The orientation of the avatar's head. + * @property {number} headPitch - The rotation about an axis running from ear to ear of the avatar's head. Pitch is + * sometimes called "elevation". + * @property {number} headYaw - The rotation left or right about an axis running from the base to the crown of the avatar's + * head. Yaw is sometimes called "heading". + * @property {number} headRoll - The rotation about an axis running from the nose to the back of the avatar's head. Roll is + * sometimes called "bank". + * @property {Vec3} velocity + * @property {Vec3} angularVelocity + * @property {number} audioLoudness + * @property {number} audioAverageLoudness + * @property {string} displayName + * @property {string} sessionDisplayName - Sanitized, defaulted version displayName that is defined by the AvatarMixer + * rather than by Interface clients. The result is unique among all avatars present at the time. + * @property {boolean} lookAtSnappingEnabled + * @property {string} skeletonModelURL + * @property {AttachmentData[]} attachmentData + * @property {string[]} jointNames - The list of joints in the current avatar model. Read-only. + * @property {Uuid} sessionUUID Read-only. + * @property {Mat4} sensorToWorldMatrix Read-only. + * @property {Mat4} controllerLeftHandMatrix Read-only. + * @property {Mat4} controllerRightHandMatrix Read-only. + * @property {number} sensorToWorldScale Read-only. */ - // FIXME: `glm::vec3 position` is not accessible from QML, so this exposes position in a QML-native type Q_PROPERTY(QVector3D qmlPosition READ getQmlPosition) QVector3D getQmlPosition() { auto p = getWorldPosition(); return QVector3D(p.x, p.y, p.z); } @@ -246,12 +286,14 @@ public: void setRealWorldFieldOfView(float realWorldFov) { _realWorldFieldOfView.set(realWorldFov); } /**jsdoc - * The default position in world coordinates of the point directly between the avatar's eyes + * Get the position in world coordinates of the point directly between your avatar's eyes assuming your avatar was in its + * default pose. This is a reference position; it does not change as your avatar's head moves relative to the avatar + * position. * @function MyAvatar.getDefaultEyePosition - * @example This example gets the default eye position and prints it to the debug log. + * @returns {Vec3} Default position between your avatar's eyes in world coordinates. + * @example Report your avatar's default eye position. * var defaultEyePosition = MyAvatar.getDefaultEyePosition(); - * print (JSON.stringify(defaultEyePosition)); - * @returns {Vec3} Position between the avatar's eyes. + * print(JSON.stringify(defaultEyePosition)); */ Q_INVOKABLE glm::vec3 getDefaultEyePosition() const; @@ -261,8 +303,19 @@ public: * The avatar animation system includes a set of default animations along with rules for how those animations are blended * together with procedural data (such as look at vectors, hand sensors etc.). overrideAnimation() is used to completely * override all motion from the default animation system (including inverse kinematics for hand and head controllers) and - * play a specified animation. To end this animation and restore the default animations, use MyAvatar.restoreAnimation. + * play a specified animation. To end this animation and restore the default animations, use + * {@link MyAvatar.restoreAnimation}.
+ *

Note: When using pre-built animation data, it's critical that the joint orientation of the source animation and target + * rig are equivalent, since the animation data applies absolute values onto the joints. If the orientations are different, + * the avatar will move in unpredictable ways. For more information about avatar joint orientation standards, see the + * General Rigging Concepts section in Creating Avatars.

* @function MyAvatar.overrideAnimation + * @param url {string} The URL to the animation file. Animation files need to be .FBX format, but only need to contain the + * avatar skeleton and animation data. + * @param fps {number} The frames per second (FPS) rate for the animation playback. 30 FPS is normal speed. + * @param loop {boolean} Set to true if the animation should loop. + * @param firstFrame {number} The frame the animation should start at. + * @param lastFrame {number} The frame the animation should end at. * @example Play a clapping animation on your avatar for three seconds. * // Clap your hands for 3 seconds then restore animation back to the avatar. * var ANIM_URL = "https://s3.amazonaws.com/hifi-public/animations/ClapAnimations/ClapHands_Standing.fbx"; @@ -270,11 +323,6 @@ public: * Script.setTimeout(function () { * MyAvatar.restoreAnimation(); * }, 3000); - * @param url {string} The URL to the animation file. Animation files need to be .FBX format, but only need to contain the avatar skeleton and animation data. - * @param fps {number} The frames per second (FPS) rate for the animation playback. 30 FPS is normal speed. - * @param loop {bool} Set to true if the animation should loop. - * @param firstFrame {number} The frame the animation should start at. - * @param lastFrame {number} The frame the animation should end at. */ Q_INVOKABLE void overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame); @@ -300,13 +348,13 @@ public: * Animation roles map to easily understandable actions that the avatar can perform, such as "idleStand", "idleTalk", or "walkFwd." * getAnimationRoles() is used get the list of animation roles defined in the avatar-animation.json. * @function MyAvatar.getAnimationRoles - * @example This example prints the list of animation roles defined in the avatar's avatar-animation.json file to the debug log. + * @returns {string[]} Array of role strings. + * @example Print the list of animation roles defined in the avatar's avatar-animation.json file to the debug log. * var roles = MyAvatar.getAnimationRoles(); * print("Animation Roles:"); * for (var i = 0; i < roles.length; i++) { * print(roles[i]); * } - * @returns {string[]} Array of role strings */ Q_INVOKABLE QStringList getAnimationRoles(); @@ -315,25 +363,32 @@ public: * that the avatar can perform, such as "idleStand", "idleTalk", or "walkFwd". To get the full list of roles, use getAnimationRoles(). * For each role, the avatar-animation.json defines when the animation is used, the animation clip (.FBX) used, and how animations are blended * together with procedural data (such as look at vectors, hand sensors etc.). - * overrideRoleAnimation() is used to change the animation clip (.FBX) associated with a specified animation role. - * Note: Hand roles only affect the hand. Other 'main' roles, like 'idleStand', 'idleTalk', 'takeoffStand' are full body. + * overrideRoleAnimation() is used to change the animation clip (.FBX) associated with a specified animation role. To end + * the animation and restore the default animations, use {@link MyAvatar.restoreRoleAnimation}.
+ *

Note: Hand roles only affect the hand. Other 'main' roles, like 'idleStand', 'idleTalk', 'takeoffStand' are full body.

+ *

Note: When using pre-built animation data, it's critical that the joint orientation of the source animation and target + * rig are equivalent, since the animation data applies absolute values onto the joints. If the orientations are different, + * the avatar will move in unpredictable ways. For more information about avatar joint orientation standards, see the + * General Rigging Concepts section in Creating Avatars.

* @function MyAvatar.overrideRoleAnimation + * @param role {string} The animation role to override + * @param url {string} The URL to the animation file. Animation files need to be .FBX format, but only need to contain the avatar skeleton and animation data. + * @param fps {number} The frames per second (FPS) rate for the animation playback. 30 FPS is normal speed. + * @param loop {boolean} Set to true if the animation should loop + * @param firstFrame {number} The frame the animation should start at + * @param lastFrame {number} The frame the animation should end at * @example The default avatar-animation.json defines an "idleStand" animation role. This role specifies that when the avatar is not moving, * an animation clip of the avatar idling with hands hanging at its side will be used. It also specifies that when the avatar moves, the animation * will smoothly blend to the walking animation used by the "walkFwd" animation role. * In this example, the "idleStand" role animation clip has been replaced with a clapping animation clip. Now instead of standing with its arms * hanging at its sides when it is not moving, the avatar will stand and clap its hands. Note that just as it did before, as soon as the avatar * starts to move, the animation will smoothly blend into the walk animation used by the "walkFwd" animation role. - * // An animation of the avatar clapping its hands while standing + * // An animation of the avatar clapping its hands while standing. Restore default after 30s. * var ANIM_URL = "https://s3.amazonaws.com/hifi-public/animations/ClapAnimations/ClapHands_Standing.fbx"; * MyAvatar.overrideRoleAnimation("idleStand", ANIM_URL, 30, true, 0, 53); - * // To restore the default animation, use MyAvatar.restoreRoleAnimation(). - * @param role {string} The animation role to override - * @param url {string} The URL to the animation file. Animation files need to be .FBX format, but only need to contain the avatar skeleton and animation data. - * @param fps {number} The frames per second (FPS) rate for the animation playback. 30 FPS is normal speed. - * @param loop {bool} Set to true if the animation should loop - * @param firstFrame {number} The frame the animation should start at - * @param lastFrame {number} The frame the animation should end at + * Script.setTimeout(function () { + * MyAvatar.restoreRoleAnimation(); + * }, 30000); */ Q_INVOKABLE void overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame); @@ -346,7 +401,7 @@ public: * restoreRoleAnimation() is used to restore a specified animation role's default animation clip. If you have not specified an override animation * for the specified role, this function will have no effect. * @function MyAvatar.restoreRoleAnimation - * @param role {string} The animation role clip to restore + * @param role {string} The animation role clip to restore. */ Q_INVOKABLE void restoreRoleAnimation(const QString& role); @@ -409,8 +464,8 @@ public: *behaviour in the vertical direction. This call is only takes effect when the property *MyAvatar.hmdLeanRecenterEnabled is set to false. *@function MyAvatar.triggerVerticalRecenter - * */ + Q_INVOKABLE void triggerVerticalRecenter(); /**jsdoc *The triggerHorizontalRecenter function activates one time the recentering behaviour @@ -418,6 +473,7 @@ public: *MyAvatar.hmdLeanRecenterEnabled is set to false. *@function MyAvatar.triggerHorizontalRecenter */ + Q_INVOKABLE void triggerHorizontalRecenter(); /**jsdoc *The triggerRotationRecenter function activates one time the recentering behaviour @@ -425,31 +481,96 @@ public: *MyAvatar.hmdLeanRecenterEnabled is set to false. *@function MyAvatar.triggerRotationRecenter */ - - Q_INVOKABLE void triggerVerticalRecenter(); - Q_INVOKABLE void triggerHorizontalRecenter(); Q_INVOKABLE void triggerRotationRecenter(); eyeContactTarget getEyeContactTarget(); const MyHead* getMyHead() const; + + /**jsdoc + * Get the current position of the avatar's "Head" joint. + * @function MyAvatar.getHeadPosition + * @returns {Vec3} The current position of the avatar's "Head" joint. + * @example Report the current position of your avatar's head. + * print(JSON.stringify(MyAvatar.getHeadPosition())); + */ Q_INVOKABLE glm::vec3 getHeadPosition() const { return getHead()->getPosition(); } Q_INVOKABLE float getHeadFinalYaw() const { return getHead()->getFinalYaw(); } Q_INVOKABLE float getHeadFinalRoll() const { return getHead()->getFinalRoll(); } Q_INVOKABLE float getHeadFinalPitch() const { return getHead()->getFinalPitch(); } Q_INVOKABLE float getHeadDeltaPitch() const { return getHead()->getDeltaPitch(); } + /**jsdoc + * Get the current position of the point directly between the avatar's eyes. + * @function MyAvatar.getEyePosition + * @returns {Vec3} The current position of the point directly between the avatar's eyes. + * @example Report your avatar's current eye position. + * var eyePosition = MyAvatar.getEyePosition(); + * print(JSON.stringify(eyePosition)); + */ Q_INVOKABLE glm::vec3 getEyePosition() const { return getHead()->getEyePosition(); } + /**jsdoc + * @function MyAvatar.getTargetAvatarPosition + * @returns {Vec3} The position of the avatar you're currently looking at. + * @example Report the position of the avatar you're currently looking at. + * print(JSON.stringify(MyAvatar.getTargetAvatarPosition())); + */ Q_INVOKABLE glm::vec3 getTargetAvatarPosition() const { return _targetAvatarPosition; } Q_INVOKABLE ScriptAvatarData* getTargetAvatar() const; + + /**jsdoc + * Get the position of the avatar's left hand as it is controlled by a hand controller (e.g., Oculus Touch or Vive).
+ *

Note: The Leap Motion isn't part of the hand controller input system. (Instead, it manipulates the avatar's joints + * for hand animation.) If you are using the Leap Motion, the return value's valid property will be + * false and any pose values returned will not be meaningful.

+ * @function MyAvatar.getLeftHandPosition + * @returns {Vec3} The position of the left hand in avatar coordinates. + * @example Report the position of your left hand relative to your avatar. + * print(JSON.stringify(MyAvatar.getLeftHandPosition())); + */ Q_INVOKABLE glm::vec3 getLeftHandPosition() const; + + /**jsdoc + * Get the position of the avatar's right hand as it is controlled by a hand controller (e.g., Oculus Touch or Vive).
+ *

Note: The Leap Motion isn't part of the hand controller input system. (Instead, it manipulates the avatar's joints + * for hand animation.) If you are using the Leap Motion, the return value's valid property will be + * false and any pose values returned will not be meaningful.

+ * @function MyAvatar.getRightHandPosition + * @returns {Vec3} The position of the right hand in avatar coordinates. + * @example Report the position of your right hand relative to your avatar. + * print(JSON.stringify(MyAvatar.getLeftHandPosition())); + */ Q_INVOKABLE glm::vec3 getRightHandPosition() const; Q_INVOKABLE glm::vec3 getLeftHandTipPosition() const; Q_INVOKABLE glm::vec3 getRightHandTipPosition() const; + + /**jsdoc + * Get the pose (position, rotation, velocity, and angular velocity) of the avatar's left hand as it is controlled by a + * hand controller (e.g., Oculus Touch or Vive).
+ *

Note: The Leap Motion isn't part of the hand controller input system. (Instead, it manipulates the avatar's joints + * for hand animation.) If you are using the Leap Motion, the return value's valid property will be + * false and any pose values returned will not be meaningful.

+ * @function MyAvatar.getLeftHandPose + * @returns {Pose} + * @example Report the pose of your avatar's left hand. + * print(JSON.stringify(MyAvatar.getLeftHandPose())); + */ Q_INVOKABLE controller::Pose getLeftHandPose() const; + + /**jsdoc + * Get the pose (position, rotation, velocity, and angular velocity) of the avatar's left hand as it is controlled by a + * hand controller (e.g., Oculus Touch or Vive).
+ *

Note: The Leap Motion isn't part of the hand controller input system. (Instead, it manipulates the avatar's joints + * for hand animation.) If you are using the Leap Motion, the return value's valid property will be + * false and any pose values returned will not be meaningful.

+ * @function MyAvatar.getRightHandPose + * @returns {Pose} + * @example Report the pose of your avatar's right hand. + * print(JSON.stringify(MyAvatar.getRightHandPose())); + */ Q_INVOKABLE controller::Pose getRightHandPose() const; Q_INVOKABLE controller::Pose getLeftHandTipPose() const; Q_INVOKABLE controller::Pose getRightHandTipPose() const; @@ -486,8 +607,26 @@ public: Q_INVOKABLE float getIKErrorOnLastSolve() const; Q_INVOKABLE void useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName = QString()); + + /**jsdoc + * Get the complete URL for the current avatar. + * @function MyAvatar.getFullAvatarURLFromPreferences + * @returns {string} The full avatar model name. + * @example Report the URL for the current avatar. + * print(MyAvatar.getFullAvatarURLFromPreferences()); + */ Q_INVOKABLE QUrl getFullAvatarURLFromPreferences() const { return _fullAvatarURLFromPreferences; } + + /**jsdoc + * Get the full avatar model name for the current avatar. + * @function MyAvatar.getFullAvatarModelName + * @returns {string} The full avatar model name. + * @example Report the current full avatar model name. + * print(MyAvatar.getFullAvatarModelName()); + * // For example: being_of_light + */ Q_INVOKABLE QString getFullAvatarModelName() const { return _fullAvatarModelName; } + void resetFullAvatarURL(); virtual void setAttachmentData(const QVector& attachmentData) override; @@ -595,17 +734,60 @@ public: float getWalkSpeed() const; public slots: + + /**jsdoc + * Increase the avatar's scale by five percent, up to a minimum scale of 1000. + * @function MyAvatar.increaseSize + * @example Reset your avatar's size to default then grow it 5 times. + * MyAvatar.resetSize(); + * + * for (var i = 0; i < 5; i++){ + * print ("Growing by 5 percent"); + * MyAvatar.increaseSize(); + * } + */ void increaseSize(); + + /**jsdoc + * Decrease the avatar's scale by five percent, down to a minimum scale of 0.25. + * @function MyAvatar.decreaseSize + * @example Reset your avatar's size to default then shrink it 5 times. + * MyAvatar.resetSize(); + * + * for (var i = 0; i < 5; i++){ + * print ("Shrinking by 5 percent"); + * MyAvatar.decreaseSize(); + * } + */ void decreaseSize(); + + /**jsdoc + * Reset the avatar's scale back to the default scale of 1.0. + * @function MyAvatar.resetSize + */ void resetSize(); + void animGraphLoaded(); void setGravity(float gravity); float getGravity(); + /**jsdoc + * Move the avatar to a new position and/or orientation in the domain. + * @function MyAvatar.goToLocation + * @param {Vec3} position - The new position for the avatar, in world coordinates. + * @param {boolean} [hasOrientation=false] - Set to true to set the orientation of the avatar. + * @param {Quat} [orientation=Quat.IDENTITY] - The new orientation for the avatar. + * @param {boolean} [shouldFaceLocation=false] - Set to true to position the avatar a short distance away from + * the new position and orientate the avatar to face the position. + */ void goToLocation(const glm::vec3& newPosition, bool hasOrientation = false, const glm::quat& newOrientation = glm::quat(), bool shouldFaceLocation = false); + /**jsdoc + * @function MyAvatar.goToLocation + * @param {object} properties + */ void goToLocation(const QVariant& properties); void goToLocationAndEnableCollisions(const glm::vec3& newPosition); bool safeLanding(const glm::vec3& position); @@ -630,7 +812,23 @@ public slots: void setEnableDebugDrawIKChains(bool isEnabled); void setEnableDebugDrawDetailedCollision(bool isEnabled); + /**jsdoc + * Get whether or not your avatar mesh is visible. + * @function MyAvatar.getEnableMeshVisible + * @returns {boolean} true if your avatar's mesh is visible, otherwise false. + */ bool getEnableMeshVisible() const { return _skeletonModel->isVisible(); } + + /**jsdoc + * Set whether or not your avatar mesh is visible. + * @function MyAvatar.setEnableMeshVisible + * @param {boolean} visible - true to set your avatar mesh visible; false to set it invisible. + * @example Make your avatar invisible for 10s. + * MyAvatar.setEnableMeshVisible(false); + * Script.setTimeout(function () { + * MyAvatar.setEnableMeshVisible(true); + * }, 10000); + */ void setEnableMeshVisible(bool isEnabled); void setEnableInverseKinematics(bool isEnabled); @@ -648,6 +846,17 @@ signals: void audioListenerModeChanged(); void transformChanged(); void newCollisionSoundURL(const QUrl& url); + + /**jsdoc + * Triggered when the avatar collides with an entity. + * @function MyAvatar.collisionWithEntity + * @param {Collision} collision + * @returns {Signal} + * @example Report each time your aatar collides with an entity. + * MyAvatar.collisionWithEntity.connect(function (collision) { + * print("Your avatar collided with an entity."); + * }); + */ void collisionWithEntity(const Collision& collision); void energyChanged(float newEnergy); void positionGoneTo(); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index bf0adc5c05..38f72609d1 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -57,15 +57,7 @@ using AvatarPhysicsCallback = std::function; class Avatar : public AvatarData, public scriptable::ModelProvider { Q_OBJECT - /**jsdoc - * An avatar is representation of yourself or another user. The Avatar API can be used to query or manipulate the avatar of a user. - * NOTE: Avatar extends AvatarData, see those namespace for more properties/methods. - * - * @namespace Avatar - * @augments AvatarData - * - * @property skeletonOffset {Vec3} can be used to apply a translation offset between the avatar's position and the registration point of the 3d model. - */ + // This property has JSDoc in MyAvatart.h. Q_PROPERTY(glm::vec3 skeletonOffset READ getSkeletonOffset WRITE setSkeletonOffset) public: @@ -134,8 +126,8 @@ public: /**jsdoc * Provides read only access to the default joint rotations in avatar coordinates. * The default pose of the avatar is defined by the position and orientation of all bones - * in the avatar's model file. Typically this is a t-pose. - * @function Avatar.getAbsoluteDefaultJointRotationInObjectFrame + * in the avatar's model file. Typically this is a T-pose. + * @function MyAvatar.getAbsoluteDefaultJointRotationInObjectFrame * @param index {number} index number * @returns {Quat} The rotation of this joint in avatar coordinates. */ @@ -144,8 +136,8 @@ public: /**jsdoc * Provides read only access to the default joint translations in avatar coordinates. * The default pose of the avatar is defined by the position and orientation of all bones - * in the avatar's model file. Typically this is a t-pose. - * @function Avatar.getAbsoluteDefaultJointTranslationInObjectFrame + * in the avatar's model file. Typically this is a T-pose. + * @function MyAvatar.getAbsoluteDefaultJointTranslationInObjectFrame * @param index {number} index number * @returns {Vec3} The position of this joint in avatar coordinates. */ @@ -170,12 +162,59 @@ public: virtual void applyCollision(const glm::vec3& contactPoint, const glm::vec3& penetration) { } + /**jsdoc + * Set the offset applied to the current avatar. The offset adjusts the position that the avatar is rendered. For example, + * with an offset of { x: 0, y: 0.1, z: 0 }, your avatar will appear to be raised off the ground slightly. + * @function MyAvatar.setSkeletonOffset + * @param {Vec3} offset - The skeleton offset to set. + * @example Raise your avatar off the ground a little. + * // Raise your avatar off the ground a little. + * MyAvatar.setSkeletonOffset({ x: 0, y: 0.1: z: 0 }); + * + * // Restore its offset after 5s. + * Script.setTimeout(function () { + * MyAvatar.setSkeletonOffset(Vec3.ZERO); + * }, 5000); + */ Q_INVOKABLE void setSkeletonOffset(const glm::vec3& offset); + + /**jsdoc + * Get the offset applied to the current avatar. The offset adjusts the position that the avatar is rendered. For example, + * with an offset of { x: 0, y: 0.1, z: 0 }, your avatar will appear to be raised off the ground slightly. + * @function MyAvatar.getSkeletonOffset + * @returns {Vec3} The current skeleton offset. + * @example Report your avatar's current skeleton offset. + * print(JSON.stringify(MyAvatar.getSkeletonOffset()); + */ Q_INVOKABLE glm::vec3 getSkeletonOffset() { return _skeletonOffset; } + virtual glm::vec3 getSkeletonPosition() const; + /**jsdoc + * Get the position of a joint in the current avatar. + * @function MyAvatar.getJointPosition + * @param {number} index - The index of the joint. + * @returns {Vec3} The position of the joint in world coordinates. + */ Q_INVOKABLE glm::vec3 getJointPosition(int index) const; + + /**jsdoc + * Get the position of a joint in the current avatar. + * @function MyAvatar.getJointPosition + * @param {string} name - The name of the joint. + * @returns {Vec3} The position of the joint in world coordinates. + * @example Report the position of your avatar's hips. + * print(JSON.stringify(MyAvatar.getJointPosition("Hips"))); + */ Q_INVOKABLE glm::vec3 getJointPosition(const QString& name) const; + + /**jsdoc + * Get the position of the current avatar's neck in world coordinates. + * @function MyAvatar.getNeckPosition + * @returns {Vec3} The position of the neck in world coordinates. + * @example Report the position of your avatar's neck. + * print(JSON.stringify(MyAvatar.getNeckPosition())); + */ Q_INVOKABLE glm::vec3 getNeckPosition() const; Q_INVOKABLE glm::vec3 getAcceleration() const { return _acceleration; } @@ -208,17 +247,16 @@ public: Q_INVOKABLE virtual void setParentJointIndex(quint16 parentJointIndex) override; /**jsdoc - * Information about a single joint in an Avatar's skeleton hierarchy. - * @typedef Avatar.SkeletonJoint - * @property {string} name - name of joint - * @property {number} index - joint index - * @property {number} parentIndex - index of this joint's parent (-1 if no parent) + * Returns an array of joints, where each joint is an object containing name, index, and parentIndex fields. + * @function MyAvatar.getSkeleton + * @returns {MyAvatar.SkeletonJoint[]} A list of information about each joint in this avatar's skeleton. */ - /**jsdoc - * Returns an array of joints, where each joint is an object containing name, index and parentIndex fields. - * @function Avatar.getSkeleton - * @returns {Avatar.SkeletonJoint[]} returns a list of information about each joint in this avatar's skeleton. + * Information about a single joint in an Avatar's skeleton hierarchy. + * @typedef MyAvatar.SkeletonJoint + * @property {string} name - Joint name. + * @property {number} index - Joint index. + * @property {number} parentIndex - Index of this joint's parent (-1 if no parent). */ Q_INVOKABLE QList getSkeleton(); @@ -282,9 +320,40 @@ public slots: // FIXME - these should be migrated to use Pose data instead // thread safe, will return last valid palm from cache + + /**jsdoc + * Get the position of the left palm in world coordinates. + * @function MyAvatar.getLeftPalmPosition + * @returns {Vec3} The position of the left palm in world coordinates. + * @example Report the position of your avatar's left palm. + * print(JSON.stringify(MyAvatar.getLeftPalmPosition())); + */ glm::vec3 getLeftPalmPosition() const; + + /**jsdoc + * Get the rotation of the left palm in world coordinates. + * @function MyAvatar.getLeftPalmRotation + * @returns {Vec3} The rotation of the left palm in world coordinates. + * @example Report the rotation of your avatar's left palm. + * print(JSON.stringify(MyAvatar.getLeftPalmRotation())); + */ glm::quat getLeftPalmRotation() const; + /**jsdoc + * Get the position of the right palm in world coordinates. + * @function MyAvatar.getRightPalmPosition + * @returns {Vec3} The position of the right palm in world coordinates. + * @example Report the position of your avatar's right palm. + * print(JSON.stringify(MyAvatar.getRightPalmPosition())); + */ glm::vec3 getRightPalmPosition() const; + + /**jsdoc + * Get the rotation of the right palm in world coordinates. + * @function MyAvatar.getRightPalmRotation + * @returns {Vec3} The rotation of the right palm in world coordinates. + * @example Report the rotation of your avatar's right palm. + * print(JSON.stringify(MyAvatar.getRightPalmRotation())); + */ glm::quat getRightPalmRotation() const; // hooked up to Model::setURLFinished signal diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 6b974ac9ae..db38999481 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -2362,6 +2362,15 @@ glm::vec3 AvatarData::getAbsoluteJointTranslationInObjectFrame(int index) const return glm::vec3(); } +/**jsdoc + * @typedef MyAvatar.AttachmentData + * @property {string} modelUrl + * @property {string} jointName + * @property {Vec3} translation + * @property {Vec3} rotation + * @property {number} scale + * @property {boolean} soft + */ QVariant AttachmentData::toVariant() const { QVariantMap result; result["modelUrl"] = modelURL; diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 7c188019db..cc34d560b5 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -353,6 +353,7 @@ public: class AvatarData : public QObject, public SpatiallyNestable { Q_OBJECT + // The following properties have JSDoc in MyAvatar.h. Q_PROPERTY(glm::vec3 position READ getWorldPosition WRITE setPositionViaScript) Q_PROPERTY(float scale READ getTargetScale WRITE setTargetScale) Q_PROPERTY(float density READ getDensity) @@ -505,7 +506,7 @@ public: /**jsdoc * returns the minimum scale allowed for this avatar in the current domain. * This value can change as the user changes avatars or when changing domains. - * @function AvatarData.getDomainMinScale + * @function MyAvatar.getDomainMinScale * @returns {number} minimum scale allowed for this avatar in the current domain. */ Q_INVOKABLE float getDomainMinScale() const; @@ -513,7 +514,7 @@ public: /**jsdoc * returns the maximum scale allowed for this avatar in the current domain. * This value can change as the user changes avatars or when changing domains. - * @function AvatarData.getDomainMaxScale + * @function MyAvatar.getDomainMaxScale * @returns {number} maximum scale allowed for this avatar in the current domain. */ Q_INVOKABLE float getDomainMaxScale() const; @@ -529,16 +530,16 @@ public: /**jsdoc * Provides read only access to the current eye height of the avatar. * This height is only an estimate and might be incorrect for avatars that are missing standard joints. - * @function AvatarData.getEyeHeight - * @returns {number} eye height of avatar in meters + * @function MyAvatar.getEyeHeight + * @returns {number} Eye height of avatar in meters. */ Q_INVOKABLE virtual float getEyeHeight() const { return _targetScale * getUnscaledEyeHeight(); } /**jsdoc * Provides read only access to the current height of the avatar. * This height is only an estimate and might be incorrect for avatars that are missing standard joints. - * @function AvatarData.getHeight - * @returns {number} height of avatar in meters + * @function MyAvatar.getHeight + * @returns {number} Height of avatar in meters. */ Q_INVOKABLE virtual float getHeight() const; @@ -554,32 +555,287 @@ public: const QVector& getRawJointData() const { return _jointData; } Q_INVOKABLE void setRawJointData(QVector data); + /**jsdoc + * Set a specific joint's rotation and position relative to its parent. + *

Setting joint data completely overrides/replaces all motion from the default animation system including inverse + * kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints, + * the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate + * joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set + * the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.

+ * @function MyAvatar.setJointData + * @param {number} index - The index of the joint. + * @param {Quat} rotation - The rotation of the joint relative to its parent. + * @param {Vec3} translation - The translation of the joint relative to its parent. + * @example Set your avatar to it's default T-pose for a while.
+ * Avatar in T-pose + * + * // Set all joint translations and rotations to defaults. + * var i, length, rotation, translation; + * for (i = 0, length = MyAvatar.getJointNames().length; i < length; i++) { + * rotation = MyAvatar.getDefaultJointRotation(i); + * translation = MyAvatar.getDefaultJointTranslation(i); + * MyAvatar.setJointData(i, rotation, translation); + * } + * + * // Restore your avatar's motion after 5s. + * Script.setTimeout(function () { + * MyAvatar.clearJointsData(); + * }, 5000); + */ Q_INVOKABLE virtual void setJointData(int index, const glm::quat& rotation, const glm::vec3& translation); + + /**jsdoc + * Set a specific joint's rotation relative to its parent. + *

Setting joint data completely overrides/replaces all motion from the default animation system including inverse + * kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints, + * the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate + * joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set + * the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.

+ * @function MyAvatar.setJointRotation + * @param {number} index - The index of the joint. + * @param {Quat} rotation - The rotation of the joint relative to its parent. + */ Q_INVOKABLE virtual void setJointRotation(int index, const glm::quat& rotation); + + /**jsdoc + * Set a specific joint's translation relative to its parent. + *

Setting joint data completely overrides/replaces all motion from the default animation system including inverse + * kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints, + * the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate + * joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set + * the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.

+ * @function MyAvatar.setJointTranslation + * @param {number} index - The index of the joint. + * @param {Vec3} translation - The translation of the joint relative to its parent. + */ Q_INVOKABLE virtual void setJointTranslation(int index, const glm::vec3& translation); + + /**jsdoc + * Clear joint translations and rotations set by script for a specific joint. This restores all motion from the default + * animation system including inverse kinematics for that joint. + *

Note: This is slightly faster than the function variation that specifies the joint name.

+ * @function MyAvatar.clearJointData + * @param {number} index - The index of the joint. + */ Q_INVOKABLE virtual void clearJointData(int index); Q_INVOKABLE bool isJointDataValid(int index) const; + + /**jsdoc + * Get the rotation of a joint relative to its parent. For information on the joint hierarchy used, see + * avatar standards. + * @function MyAvatar.getJointRotation + * @param {number} index - The index of the joint. + * @returns {Quat} The rotation of the joint relative to its parent. + */ Q_INVOKABLE virtual glm::quat getJointRotation(int index) const; + + /**jsdoc + * Get the translation of a joint relative to its parent. For information on the joint hierarchy used, see + * avatar standards. + * @function MyAvatar.getJointTranslation + * @param {number} index - The index of the joint. + * @returns {Vec3} The translation of the joint relative to its parent. + */ Q_INVOKABLE virtual glm::vec3 getJointTranslation(int index) const; + /**jsdoc + * Set a specific joint's rotation and position relative to its parent. + *

Setting joint data completely overrides/replaces all motion from the default animation system including inverse + * kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints, + * the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate + * joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set + * the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.

+ * @function MyAvatar.setJointData + * @param {string} name - The name of the joint. + * @param {Quat} rotation - The rotation of the joint relative to its parent. + * @param {Vec3} translation - The translation of the joint relative to its parent. + */ Q_INVOKABLE virtual void setJointData(const QString& name, const glm::quat& rotation, const glm::vec3& translation); + + /**jsdoc + * Set a specific joint's rotation relative to its parent. + *

Setting joint data completely overrides/replaces all motion from the default animation system including inverse + * kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints, + * the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate + * joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set + * the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.

+ * @function MyAvatar.setJointRotation + * @param {string} name - The name of the joint. + * @param {Quat} rotation - The rotation of the joint relative to its parent. + * @example Set your avatar to its default T-pose then rotate its right arm.
+ * Avatar in T-pose with arm rotated + * // Set all joint translations and rotations to defaults. + * var i, length, rotation, translation; + * for (i = 0, length = MyAvatar.getJointNames().length; i < length; i++) { + * rotation = MyAvatar.getDefaultJointRotation(i); + * translation = MyAvatar.getDefaultJointTranslation(i); + * MyAvatar.setJointData(i, rotation, translation); + * } + * + * // Rotate the right arm. + * var newArmRotation = { x: 0.47, y: 0.22, z: -0.02, w: 0.87 }; + * MyAvatar.setJointRotation("RightArm", newArmRotation); + * + * // Restore your avatar's motion after 5s. + * Script.setTimeout(function () { + * MyAvatar.clearJointsData(); + * }, 5000); + */ Q_INVOKABLE virtual void setJointRotation(const QString& name, const glm::quat& rotation); + + /**jsdoc + * Set a specific joint's translation relative to its parent. + *

Setting joint data completely overrides/replaces all motion from the default animation system including inverse + * kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints, + * the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate + * joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set + * the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.

+ * @function MyAvatar.setJointTranslation + * @param {string} name - The name of the joint. + * @param {Vec3} translation - The translation of the joint relative to its parent. + * @example Stretch your avatar's neck. Depending on the avatar you are using, you will either see a gap between + * the head and body or you will see the neck stretched.
+ * Avatar with neck stretched + * // Stretch your avatar's neck. + * MyAvatar.setJointTranslation("Neck", { x: 0, y: 25, z: 0 }); + * + * // Restore your avatar's neck after 5s. + * Script.setTimeout(function () { + * MyAvatar.clearJointData("Neck"); + * }, 5000); + */ Q_INVOKABLE virtual void setJointTranslation(const QString& name, const glm::vec3& translation); + + /**jsdoc + * Clear joint translations and rotations set by script for a specific joint. This restores all motion from the default + * animation system including inverse kinematics for that joint. + *

Note: This is slightly slower than the function variation that specifies the joint index.

+ * @function MyAvatar.clearJointData + * @param {string} name - The name of the joint. + * @example Offset and restore the position of your avatar's head. + * // Move your avatar's head up by 25cm from where it should be. + * MyAvatar.setJointTranslation("Neck", { x: 0, y: 0.25, z: 0 }); + * + * // Restore your avatar's head to its default position after 5s. + * Script.setTimeout(function () { + * MyAvatar.clearJointData("Neck"); + * }, 5000); + */ Q_INVOKABLE virtual void clearJointData(const QString& name); Q_INVOKABLE virtual bool isJointDataValid(const QString& name) const; + + /**jsdoc + * Get the rotation of a joint relative to its parent. For information on the joint hierarchy used, see + * avatar standards. + * @function MyAvatar.getJointRotation + * @param {string} name - The name of the joint. + * @returns {Quat} The rotation of the joint relative to its parent. + * @example Report the rotation of your avatar's hips joint. + * print(JSON.stringify(MyAvatar.getJointRotation("Hips"))); + */ Q_INVOKABLE virtual glm::quat getJointRotation(const QString& name) const; + + /**jsdoc + * Get the translation of a joint relative to its parent. For information on the joint hierarchy used, see + * avatar standards. + * @function MyAvatar.getJointTranslation + * @param {number} name - The name of the joint. + * @returns {Vec3} The translation of the joint relative to its parent. + * @example Report the translation of your avatar's hips joint. + * print(JSON.stringify(MyAvatar.getJointRotation("Hips"))); + */ Q_INVOKABLE virtual glm::vec3 getJointTranslation(const QString& name) const; + /**jsdoc + * Get the rotations of all joints in the current avatar. Each joint's rotation is relative to its parent joint. + * @function MyAvatar.getJointRotations + * @returns {Quat[]} The rotations of all joints relative to each's parent. The values are in the same order as the array + * returned by {@link MyAvatar.getJointNames}. + * @example Report the rotations of all your avatar's joints. + * print(JSON.stringify(MyAvatar.getJointRotations())); + */ Q_INVOKABLE virtual QVector getJointRotations() const; Q_INVOKABLE virtual QVector getJointTranslations() const; + + /**jsdoc + * Set the rotations of all joints in the current avatar. Each joint's rotation is relative to its parent joint. + *

Setting joint data completely overrides/replaces all motion from the default animation system including inverse + * kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints, + * the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate + * joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set + * the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.

+ * @function MyAvatar.setJointRotations + * @param {Quat[]} jointRotations - The rotations for all joints in the avatar. The values are in the same order as the + * array returned by {@link MyAvatar.getJointNames}. + * @example Set your avatar to its default T-pose then rotate its right arm.
+ * Avatar in T-pose + * + * // Set all joint translations and rotations to defaults. + * var i, length, rotation, translation; + * for (i = 0, length = MyAvatar.getJointNames().length; i < length; i++) { + * rotation = MyAvatar.getDefaultJointRotation(i); + * translation = MyAvatar.getDefaultJointTranslation(i); + * MyAvatar.setJointData(i, rotation, translation); + * } + * + * // Get all join rotations. + * var jointRotations = MyAvatar.getJointRotations(); + * + * // Update the rotation of the right arm in the array. + * jointRotations[MyAvatar.getJointIndex("RightArm")] = { x: 0.47, y: 0.22, z: -0.02, w: 0.87 }; + * + * // Update all joint rotations. + * MyAvatar.setJointRotations(jointRotations); + * + * // Restore your avatar's motion after 5s. + * Script.setTimeout(function () { + * MyAvatar.clearJointsData(); + * }, 5000); + */ Q_INVOKABLE virtual void setJointRotations(const QVector& jointRotations); Q_INVOKABLE virtual void setJointTranslations(const QVector& jointTranslations); + /**jsdoc + * Clear all joint translations and rotations that have been set by script. This restores all motion from the default + * animation system including inverse kinematics for all joints. + * @function MyAvatar.clearJointsData + * @example Set your avatar to it's default T-pose for a while. + * // Set all joint translations and rotations to defaults. + * var i, length, rotation, translation; + * for (i = 0, length = MyAvatar.getJointNames().length; i < length; i++) { + * rotation = MyAvatar.getDefaultJointRotation(i); + * translation = MyAvatar.getDefaultJointTranslation(i); + * MyAvatar.setJointData(i, rotation, translation); + * } + * + * // Restore your avatar's motion after 5s. + * Script.setTimeout(function () { + * MyAvatar.clearJointsData(); + * }, 5000); + */ Q_INVOKABLE virtual void clearJointsData(); + /**jsdoc + * Get the joint index for a named joint. The joint index value is the position of the joint in the array returned by + * {@link MyAvatar.getJointNames}. + * @function MyAvatar.getJointIndex + * @param {string} name - The name of the joint. + * @returns {number} The index of the joint. + * @example Report the index of your avatar's left arm joint. + * print(JSON.stringify(MyAvatar.getJointIndex("LeftArm")); + */ /// Returns the index of the joint with the specified name, or -1 if not found/unknown. Q_INVOKABLE virtual int getJointIndex(const QString& name) const; + /**jsdoc + * Get the names of all the joints in the current avatar. + * @function MyAvatar.getJointNames + * @returns {string[]} The joint names. + * @example Report the names of all the joints in your current avatar. + * print(JSON.stringify(MyAvatar.getJointNames())); + */ Q_INVOKABLE virtual QStringList getJointNames() const; Q_INVOKABLE void setBlendshape(QString name, float val) { _headData->setBlendshape(name, val); } @@ -627,15 +883,96 @@ public: markIdentityDataChanged(); } + /**jsdoc + * Get information about all models currently attached to your avatar. + * @function MyAvatar.getAttachmentData + * @returns {MyAvatar.AttachmentData[]} Information about all models attached to your avatar. + * @example Report the URLs of all current attachments. + * var attachments = MyAvatar.getaAttachmentData(); + * for (var i = 0; i < attachments.length; i++) { + * print (attachments[i].modelURL); + * } + */ Q_INVOKABLE QVector getAttachmentData() const; + + /**jsdoc + * Set all models currently attached to your avatar. For example, if you retrieve attachment data using + * {@link MyAvatar.getAttachmentData}, make changes to it, and then want to update your avatar's attachments per the + * changed data. You can also remove all attachments by using setting attachmentData to null. + * @function MyAvatar.setAttachmentData + * @param {MyAvatar.AttachmentData[]} attachmentData - The attachment data defining the models to have attached to your avatar. Use + * null to remove all attachments. + * @example Remove a hat attachment if your avatar is wearing it. + * var hatURL = "https://s3.amazonaws.com/hifi-public/tony/cowboy-hat.fbx"; + * var attachments = MyAvatar.getAttachmentData(); + * + * for (var i = 0; i < attachments.length; i++) { + * if (attachments[i].modelURL === hatURL) { + * attachments.splice(i, 1); + * MyAvatar.setAttachmentData(attachments); + * break; + * } + * } + */ Q_INVOKABLE virtual void setAttachmentData(const QVector& attachmentData); + /**jsdoc + * Attach a model to your avatar. For example, you can give your avatar a hat to wear, a guitar to hold, or a surfboard to + * stand on. + *

Note: Attached models are models only; they are not entities and can not be manipulated using the {@link Entities} API. + * Nor can you use this function to attach an entity (such as a sphere or a box) to your avatar.

+ * @function MyAvatar.attach + * @param {string} modelURL - The URL of the model to attach. Models can be .FBX or .OBJ format. + * @param {string} [jointName=""] - The name of the avatar joint (see {@link MyAvatar.getJointNames}) to attach the model + * to. + * @param {Vec3} [translation=Vec3.ZERO] - The offset to apply to the model relative to the joint position. + * @param {Quat} [rotation=Quat.IDENTITY] - The rotation to apply to the model relative to the joint orientation. + * @param {number} [scale=1.0] - The scale to apply to the model. + * @param {boolean} [isSoft=false] - If the model has a skeleton, set this to true so that the bones of the + * attached model's skeleton are be rotated to fit the avatar's current pose. isSoft is used, for example, + * to have clothing that moves with the avatar.
+ * If true, the translation, rotation, and scale parameters are + * ignored. + * @param {boolean} [allowDuplicates=false] + * @param {boolean} [useSaved=true] + * @example Attach a cowboy hat to your avatar's head. + * var attachment = { + * modelURL: "https://s3.amazonaws.com/hifi-public/tony/cowboy-hat.fbx", + * jointName: "Head", + * translation: {"x": 0, "y": 0.25, "z": 0}, + * rotation: {"x": 0, "y": 0, "z": 0, "w": 1}, + * scale: 1, + * isSoft: false + * }; + * + * MyAvatar.attach(attachment.modelURL, + * attachment.jointName, + * attachment.translation, + * attachment.rotation, + * attachment.scale, + * attachment.isSoft); + */ 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 isSoft = false, bool allowDuplicates = false, bool useSaved = true); + /**jsdoc + * Detach the most recently attached instance of a particular model from either a specific joint or any joint. + * @function MyAvatar.detachOne + * @param {string} modelURL - The URL of the model to detach. + * @param {string} [jointName=""] - The name of the joint to detach the model from. If "", then the most + * recently attached model is removed from which ever joint it was attached to. + */ Q_INVOKABLE void detachOne(const QString& modelURL, const QString& jointName = QString()); + + /**jsdoc + * Detach all instances of a particular model from either a specific joint or all joints. + * @function MyAvatar.detachAll + * @param {string} modelURL - The URL of the model to detach. + * @param {string} [jointName=""] - The name of the joint to detach the model from. If "", then the model is + * detached from all joints. + */ Q_INVOKABLE void detachAll(const QString& modelURL, const QString& jointName = QString()); QString getSkeletonModelURLFromScript() const { return _skeletonModelURL.toString(); } diff --git a/tools/jsdoc/plugins/hifi.js b/tools/jsdoc/plugins/hifi.js index 807e31f098..d49736d7e0 100644 --- a/tools/jsdoc/plugins/hifi.js +++ b/tools/jsdoc/plugins/hifi.js @@ -23,6 +23,7 @@ exports.handlers = { '../../interface/src/raypick', '../../libraries/animation/src', '../../libraries/avatars/src', + '../../libraries/avatars-renderer/src/avatars-renderer', '../../libraries/controllers/src/controllers/', '../../libraries/controllers/src/controllers/impl/', '../../libraries/display-plugins/src/display-plugins/',