mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-05-30 10:41:45 +02:00
2007 lines
89 KiB
C++
Executable file
2007 lines
89 KiB
C++
Executable file
//
|
|
// MyAvatar.h
|
|
// interface/src/avatar
|
|
//
|
|
// Created by Mark Peng on 8/16/13.
|
|
// Copyright 2012 High Fidelity, Inc.
|
|
//
|
|
// Distributed under the Apache License, Version 2.0.
|
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
//
|
|
|
|
#ifndef hifi_MyAvatar_h
|
|
#define hifi_MyAvatar_h
|
|
|
|
#include <bitset>
|
|
|
|
#include <glm/glm.hpp>
|
|
|
|
#include <QUuid>
|
|
|
|
#include <AvatarConstants.h>
|
|
#include <avatars-renderer/Avatar.h>
|
|
#include <avatars-renderer/ScriptAvatar.h>
|
|
#include <controllers/Pose.h>
|
|
#include <controllers/Actions.h>
|
|
#include <EntityItem.h>
|
|
#include <ThreadSafeValueCache.h>
|
|
#include <Rig.h>
|
|
#include <ScriptEngine.h>
|
|
#include <SettingHandle.h>
|
|
#include <Sound.h>
|
|
|
|
#include "AtRestDetector.h"
|
|
#include "MyCharacterController.h"
|
|
#include "RingBufferHistory.h"
|
|
|
|
class AvatarActionHold;
|
|
class ModelItemID;
|
|
class MyHead;
|
|
|
|
enum eyeContactTarget {
|
|
LEFT_EYE,
|
|
RIGHT_EYE,
|
|
MOUTH
|
|
};
|
|
|
|
enum AudioListenerMode {
|
|
FROM_HEAD = 0,
|
|
FROM_CAMERA,
|
|
CUSTOM
|
|
};
|
|
|
|
Q_DECLARE_METATYPE(AudioListenerMode);
|
|
|
|
class MyAvatar : public Avatar {
|
|
Q_OBJECT
|
|
friend class AnimStats;
|
|
|
|
/**jsdoc
|
|
* Your avatar is your in-world representation of you. The <code>MyAvatar</code> 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.
|
|
*
|
|
* @namespace MyAvatar
|
|
*
|
|
* @hifi-interface
|
|
* @hifi-client-entity
|
|
*
|
|
* @property {Vec3} qmlPosition - A synonym for <code>position</code> for use by QML.
|
|
* @property {boolean} shouldRenderLocally=true - If <code>true</code> then your avatar is rendered for you in Interface,
|
|
* otherwise it is not rendered for you (but it is still rendered for other users).
|
|
* @property {Vec3} motorVelocity=Vec3.ZERO - The target velocity of your avatar to be achieved by a scripted motor.
|
|
* @property {number} motorTimescale=1000000 - The timescale for the scripted motor to achieve the target
|
|
* <code>motorVelocity</code> avatar velocity. Smaller values result in higher acceleration.
|
|
* @property {string} motorReferenceFrame="camera" - Reference frame of the <code>motorVelocity</code>. Must be one of the
|
|
* following: <code>"camera"</code>, <code>"avatar"</code>, and <code>"world"</code>.
|
|
* @property {string} motorMode="simple" - The Type of scripted motor behavior: <code>"simple"</code> to use the
|
|
* <code>motorTimescale</code> time scale; <code>"dynamic"</code> to use character controller timescales.
|
|
* @property {string} collisionSoundURL="Body_Hits_Impact.wav" - The sound that's played when the avatar experiences a
|
|
* collision. It can be a mono or stereo 16-bit WAV file running at either 24kHz or 48kHz. The latter is down-sampled
|
|
* by the audio mixer, so all audio effectively plays back at a 24khz. 48kHz RAW files are also supported.
|
|
* @property {number} audioListenerMode=0 - Specifies the listening position when hearing spatialized audio. Must be one
|
|
* of the following property values:<br />
|
|
* <code>audioListenerModeHead</code><br />
|
|
* <code>audioListenerModeCamera</code><br />
|
|
* <code>audioListenerModeCustom</code>
|
|
* @property {number} audioListenerModeHead=0 - The audio listening position is at the avatar's head. <em>Read-only.</em>
|
|
* @property {number} audioListenerModeCamera=1 - The audio listening position is at the camera. <em>Read-only.</em>
|
|
* @property {number} audioListenerModeCustom=2 - The audio listening position is at a the position specified by set by the
|
|
* <code>customListenPosition</code> and <code>customListenOrientation</code> property values. <em>Read-only.</em>
|
|
* @property {boolean} hasScriptedBlendshapes=false - Blendshapes will be transmitted over the network if set to true.
|
|
* @property {boolean} hasProceduralBlinkFaceMovement=true - procedural blinking will be turned on if set to true.
|
|
* @property {boolean} hasProceduralEyeFaceMovement=true - procedural eye movement will be turned on if set to true.
|
|
* @property {boolean} hasAudioEnabledFaceMovement=true - If set to true, voice audio will move the mouth Blendshapes while MyAvatar.hasScriptedBlendshapes is enabled.
|
|
* @property {Vec3} customListenPosition=Vec3.ZERO - The listening position used when the <code>audioListenerMode</code>
|
|
* property value is <code>audioListenerModeCustom</code>.
|
|
* @property {Quat} customListenOrientation=Quat.IDENTITY - The listening orientation used when the
|
|
* <code>audioListenerMode</code> property value is <code>audioListenerModeCustom</code>.
|
|
* @property {Vec3} leftHandPosition - The position of the left hand in avatar coordinates if it's being positioned by
|
|
* controllers, otherwise {@link Vec3(0)|Vec3.ZERO}. <em>Read-only.</em>
|
|
* @property {Vec3} rightHandPosition - The position of the right hand in avatar coordinates if it's being positioned by
|
|
* controllers, otherwise {@link Vec3(0)|Vec3.ZERO}. <em>Read-only.</em>
|
|
|
|
* @property {Vec3} leftHandTipPosition - The position 30cm offset from the left hand in avatar coordinates if it's being
|
|
* positioned by controllers, otherwise {@link Vec3(0)|Vec3.ZERO}. <em>Read-only.</em>
|
|
* @property {Vec3} rightHandTipPosition - The position 30cm offset from the right hand in avatar coordinates if it's being
|
|
* positioned by controllers, otherwise {@link Vec3(0)|Vec3.ZERO}. <em>Read-only.</em>
|
|
* @property {Pose} leftHandPose - The pose of the left hand as determined by the hand controllers. <em>Read-only.</em>
|
|
* @property {Pose} rightHandPose - The pose right hand position as determined by the hand controllers. <em>Read-only.</em>
|
|
* @property {Pose} leftHandTipPose - The pose of the left hand as determined by the hand controllers, with the position
|
|
* by 30cm. <em>Read-only.</em>
|
|
* @property {Pose} rightHandTipPose - The pose of the right hand as determined by the hand controllers, with the position
|
|
* by 30cm. <em>Read-only.</em>
|
|
* @property {boolean} centerOfGravityModelEnabled=true - If <code>true</code> then the avatar hips are placed according to the center of
|
|
* gravity model that balance the center of gravity over the base of support of the feet. Setting the value <code>false</code>
|
|
* will result in the default behaviour where the hips are placed under the head.
|
|
* @property {boolean} hmdLeanRecenterEnabled=true - If <code>true</code> then the avatar is re-centered to be under the
|
|
* head's position. In room-scale VR, this behavior is what causes your avatar to follow your HMD as you walk around
|
|
* the room. Setting the value <code>false</code> is useful if you want to pin the avatar to a fixed position.
|
|
* @property {boolean} collisionsEnabled - Set to <code>true</code> to enable collisions for the avatar, <code>false</code>
|
|
* to disable collisions. May return <code>true</code> even though the value was set <code>false</code> because the
|
|
* zone may disallow collisionless avatars.
|
|
* @property {boolean} characterControllerEnabled - Synonym of <code>collisionsEnabled</code>.
|
|
* <strong>Deprecated:</strong> Use <code>collisionsEnabled</code> instead.
|
|
* @property {boolean} useAdvancedMovementControls - Returns and sets the value of the Interface setting, Settings >
|
|
* Walking and teleporting. Note: Setting the value has no effect unless Interface is restarted.
|
|
* @property {boolean} showPlayArea - Returns and sets the value of the Interface setting, Settings > Show room boundaries
|
|
* while teleporting. Note: Setting the value has no effect unless Interface is restarted.
|
|
* @property {number} yawSpeed=75
|
|
* @property {number} pitchSpeed=50
|
|
* @property {boolean} hmdRollControlEnabled=true - If <code>true</code>, the roll angle of your HMD turns your avatar
|
|
* while flying.
|
|
* @property {number} hmdRollControlDeadZone=8 - The amount of HMD roll, in degrees, required before your avatar turns if
|
|
* <code>hmdRollControlEnabled</code> is enabled.
|
|
* @property {number} hmdRollControlRate If hmdRollControlEnabled is true, this value determines the maximum turn rate of
|
|
* your avatar when rolling your HMD in degrees per second.
|
|
* @property {number} userHeight=1.75 - The height of the user in sensor space.
|
|
* @property {number} userEyeHeight=1.65 - The estimated height of the user's eyes in sensor space. <em>Read-only.</em>
|
|
* @property {Uuid} SELF_ID - 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.
|
|
* <em>Read-only.</em>
|
|
* @property {number} walkSpeed
|
|
* @property {number} walkBackwardSpeed
|
|
* @property {number} sprintSpeed
|
|
* @property {number} isInSittingState
|
|
* @property {number} userRecenterModel
|
|
*
|
|
* @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 - Returns the clamped scale of the avatar.
|
|
* @property {number} density <em>Read-only.</em>
|
|
* @property {Vec3} handPosition
|
|
* @property {number} bodyYaw - The rotation left or right about an axis running from the head to the feet of the avatar.
|
|
* Yaw is sometimes called "heading".
|
|
* @property {number} bodyPitch - The rotation about an axis running from shoulder to shoulder of the avatar. 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. <em>Read-only.</em>
|
|
* @property {Uuid} sessionUUID <em>Read-only.</em>
|
|
* @property {Mat4} sensorToWorldMatrix <em>Read-only.</em>
|
|
* @property {Mat4} controllerLeftHandMatrix <em>Read-only.</em>
|
|
* @property {Mat4} controllerRightHandMatrix <em>Read-only.</em>
|
|
* @property {number} sensorToWorldScale <em>Read-only.</em>
|
|
*/
|
|
// 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); }
|
|
|
|
Q_PROPERTY(bool shouldRenderLocally READ getShouldRenderLocally WRITE setShouldRenderLocally)
|
|
Q_PROPERTY(glm::vec3 motorVelocity READ getScriptedMotorVelocity WRITE setScriptedMotorVelocity)
|
|
Q_PROPERTY(float motorTimescale READ getScriptedMotorTimescale WRITE setScriptedMotorTimescale)
|
|
Q_PROPERTY(QString motorReferenceFrame READ getScriptedMotorFrame WRITE setScriptedMotorFrame)
|
|
Q_PROPERTY(QString motorMode READ getScriptedMotorMode WRITE setScriptedMotorMode)
|
|
Q_PROPERTY(QString collisionSoundURL READ getCollisionSoundURL WRITE setCollisionSoundURL)
|
|
Q_PROPERTY(AudioListenerMode audioListenerMode READ getAudioListenerMode WRITE setAudioListenerMode)
|
|
Q_PROPERTY(glm::vec3 customListenPosition READ getCustomListenPosition WRITE setCustomListenPosition)
|
|
Q_PROPERTY(glm::quat customListenOrientation READ getCustomListenOrientation WRITE setCustomListenOrientation)
|
|
Q_PROPERTY(AudioListenerMode audioListenerModeHead READ getAudioListenerModeHead)
|
|
Q_PROPERTY(AudioListenerMode audioListenerModeCamera READ getAudioListenerModeCamera)
|
|
Q_PROPERTY(AudioListenerMode audioListenerModeCustom READ getAudioListenerModeCustom)
|
|
Q_PROPERTY(bool hasScriptedBlendshapes READ getHasScriptedBlendshapes WRITE setHasScriptedBlendshapes)
|
|
Q_PROPERTY(bool hasProceduralBlinkFaceMovement READ getHasProceduralBlinkFaceMovement WRITE setHasProceduralBlinkFaceMovement)
|
|
Q_PROPERTY(bool hasProceduralEyeFaceMovement READ getHasProceduralEyeFaceMovement WRITE setHasProceduralEyeFaceMovement)
|
|
Q_PROPERTY(bool hasAudioEnabledFaceMovement READ getHasAudioEnabledFaceMovement WRITE setHasAudioEnabledFaceMovement)
|
|
Q_PROPERTY(float rotationRecenterFilterLength READ getRotationRecenterFilterLength WRITE setRotationRecenterFilterLength)
|
|
Q_PROPERTY(float rotationThreshold READ getRotationThreshold WRITE setRotationThreshold)
|
|
Q_PROPERTY(bool enableStepResetRotation READ getEnableStepResetRotation WRITE setEnableStepResetRotation)
|
|
Q_PROPERTY(bool enableDrawAverageFacing READ getEnableDrawAverageFacing WRITE setEnableDrawAverageFacing)
|
|
//TODO: make gravity feature work Q_PROPERTY(glm::vec3 gravity READ getGravity WRITE setGravity)
|
|
|
|
Q_PROPERTY(glm::vec3 leftHandPosition READ getLeftHandPosition)
|
|
Q_PROPERTY(glm::vec3 rightHandPosition READ getRightHandPosition)
|
|
Q_PROPERTY(glm::vec3 leftHandTipPosition READ getLeftHandTipPosition)
|
|
Q_PROPERTY(glm::vec3 rightHandTipPosition READ getRightHandTipPosition)
|
|
|
|
Q_PROPERTY(controller::Pose leftHandPose READ getLeftHandPose)
|
|
Q_PROPERTY(controller::Pose rightHandPose READ getRightHandPose)
|
|
Q_PROPERTY(controller::Pose leftHandTipPose READ getLeftHandTipPose)
|
|
Q_PROPERTY(controller::Pose rightHandTipPose READ getRightHandTipPose)
|
|
|
|
Q_PROPERTY(float energy READ getEnergy WRITE setEnergy)
|
|
Q_PROPERTY(bool isAway READ getIsAway WRITE setAway)
|
|
|
|
Q_PROPERTY(bool centerOfGravityModelEnabled READ getCenterOfGravityModelEnabled WRITE setCenterOfGravityModelEnabled)
|
|
Q_PROPERTY(bool hmdLeanRecenterEnabled READ getHMDLeanRecenterEnabled WRITE setHMDLeanRecenterEnabled)
|
|
Q_PROPERTY(bool collisionsEnabled READ getCollisionsEnabled WRITE setCollisionsEnabled)
|
|
Q_PROPERTY(bool otherAvatarsCollisionsEnabled READ getOtherAvatarsCollisionsEnabled WRITE setOtherAvatarsCollisionsEnabled)
|
|
Q_PROPERTY(bool characterControllerEnabled READ getCharacterControllerEnabled WRITE setCharacterControllerEnabled)
|
|
Q_PROPERTY(bool useAdvancedMovementControls READ useAdvancedMovementControls WRITE setUseAdvancedMovementControls)
|
|
Q_PROPERTY(bool showPlayArea READ getShowPlayArea WRITE setShowPlayArea)
|
|
|
|
Q_PROPERTY(float yawSpeed MEMBER _yawSpeed)
|
|
Q_PROPERTY(float pitchSpeed MEMBER _pitchSpeed)
|
|
|
|
Q_PROPERTY(bool hmdRollControlEnabled READ getHMDRollControlEnabled WRITE setHMDRollControlEnabled)
|
|
Q_PROPERTY(float hmdRollControlDeadZone READ getHMDRollControlDeadZone WRITE setHMDRollControlDeadZone)
|
|
Q_PROPERTY(float hmdRollControlRate READ getHMDRollControlRate WRITE setHMDRollControlRate)
|
|
|
|
Q_PROPERTY(float userHeight READ getUserHeight WRITE setUserHeight)
|
|
Q_PROPERTY(float userEyeHeight READ getUserEyeHeight)
|
|
|
|
Q_PROPERTY(QUuid SELF_ID READ getSelfID CONSTANT)
|
|
|
|
Q_PROPERTY(float walkSpeed READ getWalkSpeed WRITE setWalkSpeed);
|
|
Q_PROPERTY(float walkBackwardSpeed READ getWalkBackwardSpeed WRITE setWalkBackwardSpeed);
|
|
Q_PROPERTY(float sprintSpeed READ getSprintSpeed WRITE setSprintSpeed);
|
|
Q_PROPERTY(bool isInSittingState READ getIsInSittingState WRITE setIsInSittingState);
|
|
Q_PROPERTY(MyAvatar::SitStandModelType userRecenterModel READ getUserRecenterModel WRITE setUserRecenterModel);
|
|
Q_PROPERTY(bool isSitStandStateLocked READ getIsSitStandStateLocked WRITE setIsSitStandStateLocked);
|
|
Q_PROPERTY(bool allowTeleporting READ getAllowTeleporting)
|
|
|
|
const QString DOMINANT_LEFT_HAND = "left";
|
|
const QString DOMINANT_RIGHT_HAND = "right";
|
|
|
|
using Clock = std::chrono::system_clock;
|
|
using TimePoint = Clock::time_point;
|
|
|
|
public:
|
|
enum DriveKeys {
|
|
TRANSLATE_X = 0,
|
|
TRANSLATE_Y,
|
|
TRANSLATE_Z,
|
|
YAW,
|
|
STEP_TRANSLATE_X,
|
|
STEP_TRANSLATE_Y,
|
|
STEP_TRANSLATE_Z,
|
|
STEP_YAW,
|
|
PITCH,
|
|
ZOOM,
|
|
DELTA_YAW,
|
|
DELTA_PITCH,
|
|
MAX_DRIVE_KEYS
|
|
};
|
|
Q_ENUM(DriveKeys)
|
|
|
|
enum SitStandModelType {
|
|
ForceSit = 0,
|
|
ForceStand,
|
|
Auto,
|
|
DisableHMDLean,
|
|
NumSitStandTypes
|
|
};
|
|
Q_ENUM(SitStandModelType)
|
|
|
|
explicit MyAvatar(QThread* thread);
|
|
virtual ~MyAvatar();
|
|
|
|
void instantiableAvatar() override {};
|
|
void registerMetaTypes(ScriptEnginePointer engine);
|
|
|
|
virtual void simulateAttachments(float deltaTime) override;
|
|
|
|
AudioListenerMode getAudioListenerModeHead() const { return FROM_HEAD; }
|
|
AudioListenerMode getAudioListenerModeCamera() const { return FROM_CAMERA; }
|
|
AudioListenerMode getAudioListenerModeCustom() const { return CUSTOM; }
|
|
|
|
void reset(bool andRecenter = false, bool andReload = true, bool andHead = true);
|
|
|
|
void setCollisionWithOtherAvatarsFlags() override;
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.resetSensorsAndBody
|
|
*/
|
|
Q_INVOKABLE void resetSensorsAndBody();
|
|
|
|
/**jsdoc
|
|
* Moves and orients the avatar, such that it is directly underneath the HMD, with toes pointed forward.
|
|
* @function MyAvatar.centerBody
|
|
*/
|
|
Q_INVOKABLE void centerBody(); // thread-safe
|
|
|
|
|
|
/**jsdoc
|
|
* The internal inverse-kinematics system maintains a record of which joints are "locked". Sometimes it is useful to forget this history, to prevent
|
|
* contorted joints.
|
|
* @function MyAvatar.clearIKJointLimitHistory
|
|
*/
|
|
Q_INVOKABLE void clearIKJointLimitHistory(); // thread-safe
|
|
|
|
void update(float deltaTime);
|
|
virtual void postUpdate(float deltaTime, const render::ScenePointer& scene) override;
|
|
void preDisplaySide(const RenderArgs* renderArgs);
|
|
|
|
const glm::mat4& getHMDSensorMatrix() const { return _hmdSensorMatrix; }
|
|
const glm::vec3& getHMDSensorPosition() const { return _hmdSensorPosition; }
|
|
const glm::quat& getHMDSensorOrientation() const { return _hmdSensorOrientation; }
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.setOrientationVar
|
|
* @param {object} newOrientationVar
|
|
*/
|
|
Q_INVOKABLE void setOrientationVar(const QVariant& newOrientationVar);
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.getOrientationVar
|
|
* @returns {object}
|
|
*/
|
|
Q_INVOKABLE QVariant getOrientationVar() const;
|
|
|
|
// A method intended to be overriden by MyAvatar for polling orientation for network transmission.
|
|
glm::quat getOrientationOutbound() const override;
|
|
|
|
// Pass a recent sample of the HMD to the avatar.
|
|
// This can also update the avatar's position to follow the HMD
|
|
// as it moves through the world.
|
|
void updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix);
|
|
|
|
// compute the hip to hand average azimuth.
|
|
glm::vec2 computeHandAzimuth() const;
|
|
|
|
// read the location of a hand controller and save the transform
|
|
void updateJointFromController(controller::Action poseKey, ThreadSafeValueCache<glm::mat4>& matrixCache);
|
|
|
|
// best called at end of main loop, just before rendering.
|
|
// update sensor to world matrix from current body position and hmd sensor.
|
|
// This is so the correct camera can be used for rendering.
|
|
void updateSensorToWorldMatrix();
|
|
|
|
void setRealWorldFieldOfView(float realWorldFov) { _realWorldFieldOfView.set(realWorldFov); }
|
|
|
|
/**jsdoc
|
|
* 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
|
|
* @returns {Vec3} Default position between your avatar's eyes in world coordinates.
|
|
* @example <caption>Report your avatar's default eye position.</caption>
|
|
* var defaultEyePosition = MyAvatar.getDefaultEyePosition();
|
|
* print(JSON.stringify(defaultEyePosition));
|
|
*/
|
|
Q_INVOKABLE glm::vec3 getDefaultEyePosition() const;
|
|
|
|
float getRealWorldFieldOfView() { return _realWorldFieldOfView.get(); }
|
|
|
|
/**jsdoc
|
|
* 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 set of specified animations. To end these animations and restore the default animations, use
|
|
* {@link MyAvatar.restoreAnimation}.<br />
|
|
* <p>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
|
|
* <a href="https://docs.highfidelity.com/create-and-explore/avatars/avatar-standards">Avatar Standards</a>.</p>
|
|
* @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 <caption> Play a clapping animation on your avatar for three seconds. </caption>
|
|
* // 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";
|
|
* MyAvatar.overrideAnimation(ANIM_URL, 30, true, 0, 53);
|
|
* Script.setTimeout(function () {
|
|
* MyAvatar.restoreAnimation();
|
|
* }, 3000);
|
|
*/
|
|
Q_INVOKABLE void overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
|
|
|
|
/**jsdoc
|
|
* 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.). Playing your own custom animations will override the default animations.
|
|
* restoreAnimation() is used to restore all motion from the default animation system including inverse kinematics for hand and head
|
|
* controllers. If you aren't currently playing an override animation, this function will have no effect.
|
|
* @function MyAvatar.restoreAnimation
|
|
* @example <caption> Play a clapping animation on your avatar for three seconds. </caption>
|
|
* // 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";
|
|
* MyAvatar.overrideAnimation(ANIM_URL, 30, true, 0, 53);
|
|
* Script.setTimeout(function () {
|
|
* MyAvatar.restoreAnimation();
|
|
* }, 3000);
|
|
*/
|
|
Q_INVOKABLE void restoreAnimation();
|
|
|
|
/**jsdoc
|
|
* Each avatar has an avatar-animation.json file that defines which animations are used and how they are blended together with procedural data
|
|
* (such as look at vectors, hand sensors etc.). Each animation specified in the avatar-animation.json file is known as an animation role.
|
|
* 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
|
|
* @returns {string[]} Array of role strings.
|
|
* @example <caption>Print the list of animation roles defined in the avatar's avatar-animation.json file to the debug log.</caption>
|
|
* var roles = MyAvatar.getAnimationRoles();
|
|
* print("Animation Roles:");
|
|
* for (var i = 0; i < roles.length; i++) {
|
|
* print(roles[i]);
|
|
* }
|
|
*/
|
|
Q_INVOKABLE QStringList getAnimationRoles();
|
|
|
|
/**jsdoc
|
|
* Each avatar has an avatar-animation.json file that defines a set of animation roles. Animation roles map to easily understandable actions
|
|
* 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. To end
|
|
* the animations and restore the default animations, use {@link MyAvatar.restoreRoleAnimation}.<br />
|
|
* <p>Note: Hand roles only affect the hand. Other 'main' roles, like 'idleStand', 'idleTalk', 'takeoffStand' are full body.</p>
|
|
* <p>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
|
|
* <a href="https://docs.highfidelity.com/create-and-explore/avatars/avatar-standards">Avatar Standards</a>.
|
|
* @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 <caption>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.</caption>
|
|
* // 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);
|
|
* Script.setTimeout(function () {
|
|
* MyAvatar.restoreRoleAnimation();
|
|
* }, 30000);
|
|
*/
|
|
Q_INVOKABLE void overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
|
|
|
|
/**jsdoc
|
|
* Each avatar has an avatar-animation.json file that defines a set of animation roles. Animation roles map to easily understandable actions 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.). You can change the animation clip (.FBX) associated with a specified animation
|
|
* role using overrideRoleAnimation().
|
|
* 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.
|
|
*/
|
|
Q_INVOKABLE void restoreRoleAnimation(const QString& role);
|
|
|
|
// Adds handler(animStateDictionaryIn) => animStateDictionaryOut, which will be invoked just before each animGraph state update.
|
|
// The handler will be called with an animStateDictionaryIn that has all those properties specified by the (possibly empty)
|
|
// propertiesList argument. However for debugging, if the properties argument is null, all internal animGraph state is provided.
|
|
// The animStateDictionaryOut can be a different object than animStateDictionaryIn. Any properties set in animStateDictionaryOut
|
|
// will override those of the internal animation machinery.
|
|
// The animStateDictionaryIn may be shared among multiple handlers, and thus may contain additional properties specified when
|
|
// adding one of the other handlers. While any handler may change a value in animStateDictionaryIn (or supply different values in animStateDictionaryOut)
|
|
// a handler must not remove properties from animStateDictionaryIn, nor change property values that it does not intend to change.
|
|
// It is not specified in what order multiple handlers are called.
|
|
Q_INVOKABLE QScriptValue addAnimationStateHandler(QScriptValue handler, QScriptValue propertiesList) { return _skeletonModel->getRig().addAnimationStateHandler(handler, propertiesList); }
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.removeAnimationStateHandler
|
|
* @param {number} handler
|
|
*/
|
|
// Removes a handler previously added by addAnimationStateHandler.
|
|
Q_INVOKABLE void removeAnimationStateHandler(QScriptValue handler) { _skeletonModel->getRig().removeAnimationStateHandler(handler); }
|
|
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.getSnapTurn
|
|
* @returns {boolean}
|
|
*/
|
|
Q_INVOKABLE bool getSnapTurn() const { return _useSnapTurn; }
|
|
/**jsdoc
|
|
* @function MyAvatar.setSnapTurn
|
|
* @param {boolean} on
|
|
*/
|
|
Q_INVOKABLE void setSnapTurn(bool on) { _useSnapTurn = on; }
|
|
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.setDominantHand
|
|
* @param {string} hand
|
|
*/
|
|
Q_INVOKABLE void setDominantHand(const QString& hand);
|
|
/**jsdoc
|
|
* @function MyAvatar.getDominantHand
|
|
* @returns {string}
|
|
*/
|
|
Q_INVOKABLE QString getDominantHand() const { return _dominantHand; }
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.setCenterOfGravityModelEnabled
|
|
* @param {boolean} enabled
|
|
*/
|
|
Q_INVOKABLE void setCenterOfGravityModelEnabled(bool value) { _centerOfGravityModelEnabled = value; }
|
|
/**jsdoc
|
|
* @function MyAvatar.getCenterOfGravityModelEnabled
|
|
* @returns {boolean}
|
|
*/
|
|
Q_INVOKABLE bool getCenterOfGravityModelEnabled() const { return _centerOfGravityModelEnabled; }
|
|
/**jsdoc
|
|
* @function MyAvatar.setHMDLeanRecenterEnabled
|
|
* @param {boolean} enabled
|
|
*/
|
|
Q_INVOKABLE void setHMDLeanRecenterEnabled(bool value) { _hmdLeanRecenterEnabled = value; }
|
|
/**jsdoc
|
|
* @function MyAvatar.getHMDLeanRecenterEnabled
|
|
* @returns {boolean}
|
|
*/
|
|
Q_INVOKABLE bool getHMDLeanRecenterEnabled() const { return _hmdLeanRecenterEnabled; }
|
|
/**jsdoc
|
|
* Request to enable hand touch effect globally
|
|
* @function MyAvatar.requestEnableHandTouch
|
|
*/
|
|
Q_INVOKABLE void requestEnableHandTouch();
|
|
/**jsdoc
|
|
* Request to disable hand touch effect globally
|
|
* @function MyAvatar.requestDisableHandTouch
|
|
*/
|
|
Q_INVOKABLE void requestDisableHandTouch();
|
|
/**jsdoc
|
|
* Disables hand touch effect on a specific entity
|
|
* @function MyAvatar.disableHandTouchForID
|
|
* @param {Uuid} entityID - ID of the entity that will disable hand touch effect
|
|
*/
|
|
Q_INVOKABLE void disableHandTouchForID(const QUuid& entityID);
|
|
/**jsdoc
|
|
* Enables hand touch effect on a specific entity
|
|
* @function MyAvatar.enableHandTouchForID
|
|
* @param {Uuid} entityID - ID of the entity that will enable hand touch effect
|
|
*/
|
|
Q_INVOKABLE void enableHandTouchForID(const QUuid& entityID);
|
|
|
|
bool useAdvancedMovementControls() const { return _useAdvancedMovementControls.get(); }
|
|
void setUseAdvancedMovementControls(bool useAdvancedMovementControls)
|
|
{ _useAdvancedMovementControls.set(useAdvancedMovementControls); }
|
|
|
|
bool getAllowTeleporting() { return _allowTeleportingSetting.get(); }
|
|
void setAllowTeleporting(bool allowTeleporting) { _allowTeleportingSetting.set(allowTeleporting); }
|
|
|
|
bool getShowPlayArea() const { return _showPlayArea.get(); }
|
|
void setShowPlayArea(bool showPlayArea) { _showPlayArea.set(showPlayArea); }
|
|
|
|
void setHMDRollControlEnabled(bool value) { _hmdRollControlEnabled = value; }
|
|
bool getHMDRollControlEnabled() const { return _hmdRollControlEnabled; }
|
|
void setHMDRollControlDeadZone(float value) { _hmdRollControlDeadZone = value; }
|
|
float getHMDRollControlDeadZone() const { return _hmdRollControlDeadZone; }
|
|
void setHMDRollControlRate(float value) { _hmdRollControlRate = value; }
|
|
float getHMDRollControlRate() const { return _hmdRollControlRate; }
|
|
|
|
// get/set avatar data
|
|
void resizeAvatarEntitySettingHandles(uint32_t maxIndex);
|
|
void saveData();
|
|
void saveAvatarEntityDataToSettings();
|
|
void loadData();
|
|
void loadAvatarEntityDataFromSettings();
|
|
|
|
void saveAttachmentData(const AttachmentData& attachment) const;
|
|
AttachmentData loadAttachmentData(const QUrl& modelURL, const QString& jointName = QString()) const;
|
|
|
|
// Set what driving keys are being pressed to control thrust levels
|
|
void clearDriveKeys();
|
|
void setDriveKey(DriveKeys key, float val);
|
|
void setSprintMode(bool sprint);
|
|
float getDriveKey(DriveKeys key) const;
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.getRawDriveKey
|
|
* @param {DriveKeys} key
|
|
* @returns {number}
|
|
*/
|
|
Q_INVOKABLE float getRawDriveKey(DriveKeys key) const;
|
|
|
|
void relayDriveKeysToCharacterController();
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.disableDriveKey
|
|
* @param {DriveKeys} key
|
|
*/
|
|
Q_INVOKABLE void disableDriveKey(DriveKeys key);
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.enableDriveKey
|
|
* @param {DriveKeys} key
|
|
*/
|
|
Q_INVOKABLE void enableDriveKey(DriveKeys key);
|
|
/**jsdoc
|
|
* @function MyAvatar.isDriveKeyDisabled
|
|
* @param {DriveKeys} key
|
|
* @returns {boolean}
|
|
*/
|
|
Q_INVOKABLE bool isDriveKeyDisabled(DriveKeys key) const;
|
|
|
|
|
|
/**jsdoc
|
|
* Recenter the avatar in the vertical direction, if <code>{@link MyAvatar|MyAvatar.hmdLeanRecenterEnabled}</code> is
|
|
* <code>false</code>.
|
|
* @function MyAvatar.triggerVerticalRecenter
|
|
*/
|
|
Q_INVOKABLE void triggerVerticalRecenter();
|
|
|
|
/**jsdoc
|
|
* Recenter the avatar in the horizontal direction, if <code>{@link MyAvatar|MyAvatar.hmdLeanRecenterEnabled}</code> is
|
|
* <code>false</code>.
|
|
* @ function MyAvatar.triggerHorizontalRecenter
|
|
*/
|
|
Q_INVOKABLE void triggerHorizontalRecenter();
|
|
|
|
/**jsdoc
|
|
* Recenter the avatar's rotation, if <code>{@link MyAvatar|MyAvatar.hmdLeanRecenterEnabled}</code> is <code>false</code>.
|
|
* @function MyAvatar.triggerRotationRecenter
|
|
*/
|
|
Q_INVOKABLE void triggerRotationRecenter();
|
|
|
|
/**jsdoc
|
|
*The isRecenteringHorizontally function returns true if MyAvatar
|
|
*is translating the root of the Avatar to keep the center of gravity under the head.
|
|
*isActive(Horizontal) is returned.
|
|
*@function MyAvatar.isRecenteringHorizontally
|
|
*/
|
|
Q_INVOKABLE bool isRecenteringHorizontally() const;
|
|
|
|
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 <caption>Report the current position of your avatar's head.</caption>
|
|
* print(JSON.stringify(MyAvatar.getHeadPosition()));
|
|
*/
|
|
Q_INVOKABLE glm::vec3 getHeadPosition() const { return getHead()->getPosition(); }
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.getHeadFinalYaw
|
|
* @returns {number}
|
|
*/
|
|
Q_INVOKABLE float getHeadFinalYaw() const { return getHead()->getFinalYaw(); }
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.getHeadFinalRoll
|
|
* @returns {number}
|
|
*/
|
|
Q_INVOKABLE float getHeadFinalRoll() const { return getHead()->getFinalRoll(); }
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.getHeadFinalPitch
|
|
* @returns {number}
|
|
*/
|
|
Q_INVOKABLE float getHeadFinalPitch() const { return getHead()->getFinalPitch(); }
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.getHeadDeltaPitch
|
|
* @returns {number}
|
|
*/
|
|
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 <caption>Report your avatar's current eye position.</caption>
|
|
* 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 <caption>Report the position of the avatar you're currently looking at.</caption>
|
|
* print(JSON.stringify(MyAvatar.getTargetAvatarPosition()));
|
|
*/
|
|
Q_INVOKABLE glm::vec3 getTargetAvatarPosition() const { return _targetAvatarPosition; }
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.getTargetAvatar
|
|
* @returns {AvatarData}
|
|
*/
|
|
Q_INVOKABLE ScriptAvatarData* getTargetAvatar() const;
|
|
|
|
|
|
/**jsdoc
|
|
* Get the position of the avatar's left hand as positioned by a hand controller (e.g., Oculus Touch or Vive).<br />
|
|
* <p>Note: The Leap Motion isn't part of the hand controller input system. (Instead, it manipulates the avatar's joints
|
|
* for hand animation.)</p>
|
|
* @function MyAvatar.getLeftHandPosition
|
|
* @returns {Vec3} The position of the left hand in avatar coordinates if positioned by a hand controller, otherwise
|
|
* <code>{@link Vec3(0)|Vec3.ZERO}</code>.
|
|
* @example <caption>Report the position of your left hand relative to your avatar.</caption>
|
|
* print(JSON.stringify(MyAvatar.getLeftHandPosition()));
|
|
*/
|
|
Q_INVOKABLE glm::vec3 getLeftHandPosition() const;
|
|
|
|
/**jsdoc
|
|
* Get the position of the avatar's right hand as positioned by a hand controller (e.g., Oculus Touch or Vive).<br />
|
|
* <p>Note: The Leap Motion isn't part of the hand controller input system. (Instead, it manipulates the avatar's joints
|
|
* for hand animation.)</p>
|
|
* @function MyAvatar.getRightHandPosition
|
|
* @returns {Vec3} The position of the right hand in avatar coordinates if positioned by a hand controller, otherwise
|
|
* <code>{@link Vec3(0)|Vec3.ZERO}</code>.
|
|
* @example <caption>Report the position of your right hand relative to your avatar.</caption>
|
|
* print(JSON.stringify(MyAvatar.getLeftHandPosition()));
|
|
*/
|
|
Q_INVOKABLE glm::vec3 getRightHandPosition() const;
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.getLeftHandTipPosition
|
|
* @returns {Vec3}
|
|
*/
|
|
Q_INVOKABLE glm::vec3 getLeftHandTipPosition() const;
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.getRightHandTipPosition
|
|
* @returns {Vec3}
|
|
*/
|
|
Q_INVOKABLE glm::vec3 getRightHandTipPosition() const;
|
|
|
|
|
|
/**jsdoc
|
|
* Get the pose (position, rotation, velocity, and angular velocity) of the avatar's left hand as positioned by a
|
|
* hand controller (e.g., Oculus Touch or Vive).<br />
|
|
* <p>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 <code>valid</code> property will be
|
|
* <code>false</code> and any pose values returned will not be meaningful.</p>
|
|
* @function MyAvatar.getLeftHandPose
|
|
* @returns {Pose}
|
|
* @example <caption>Report the pose of your avatar's left hand.</caption>
|
|
* 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 positioned by a
|
|
* hand controller (e.g., Oculus Touch or Vive).<br />
|
|
* <p>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 <code>valid</code> property will be
|
|
* <code>false</code> and any pose values returned will not be meaningful.</p>
|
|
* @function MyAvatar.getRightHandPose
|
|
* @returns {Pose}
|
|
* @example <caption>Report the pose of your avatar's right hand.</caption>
|
|
* print(JSON.stringify(MyAvatar.getRightHandPose()));
|
|
*/
|
|
Q_INVOKABLE controller::Pose getRightHandPose() const;
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.getLeftHandTipPose
|
|
* @returns {Pose}
|
|
*/
|
|
Q_INVOKABLE controller::Pose getLeftHandTipPose() const;
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.getRightHandTipPose
|
|
* @returns {Pose}
|
|
*/
|
|
Q_INVOKABLE controller::Pose getRightHandTipPose() const;
|
|
|
|
// world-space to avatar-space rigconversion functions
|
|
/**jsdoc
|
|
* @function MyAvatar.worldToJointPoint
|
|
* @param {Vec3} position
|
|
* @param {number} [jointIndex=-1]
|
|
* @returns {Vec3}
|
|
*/
|
|
Q_INVOKABLE glm::vec3 worldToJointPoint(const glm::vec3& position, const int jointIndex = -1) const;
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.worldToJointDirection
|
|
* @param {Vec3} direction
|
|
* @param {number} [jointIndex=-1]
|
|
* @returns {Vec3}
|
|
*/
|
|
Q_INVOKABLE glm::vec3 worldToJointDirection(const glm::vec3& direction, const int jointIndex = -1) const;
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.worldToJointRotation
|
|
* @param {Quat} rotation
|
|
* @param {number} [jointIndex=-1]
|
|
* @returns {Quat}
|
|
*/
|
|
Q_INVOKABLE glm::quat worldToJointRotation(const glm::quat& rotation, const int jointIndex = -1) const;
|
|
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.jointToWorldPoint
|
|
* @param {vec3} position
|
|
* @param {number} [jointIndex=-1]
|
|
* @returns {Vec3}
|
|
*/
|
|
Q_INVOKABLE glm::vec3 jointToWorldPoint(const glm::vec3& position, const int jointIndex = -1) const;
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.jointToWorldDirection
|
|
* @param {Vec3} direction
|
|
* @param {number} [jointIndex=-1]
|
|
* @returns {Vec3}
|
|
*/
|
|
Q_INVOKABLE glm::vec3 jointToWorldDirection(const glm::vec3& direction, const int jointIndex = -1) const;
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.jointToWorldRotation
|
|
* @param {Quat} rotation
|
|
* @param {number} [jointIndex=-1]
|
|
* @returns {Quat}
|
|
*/
|
|
Q_INVOKABLE glm::quat jointToWorldRotation(const glm::quat& rotation, const int jointIndex = -1) const;
|
|
|
|
AvatarWeakPointer getLookAtTargetAvatar() const { return _lookAtTargetAvatar; }
|
|
void updateLookAtTargetAvatar();
|
|
void computeMyLookAtTarget(const AvatarHash& hash);
|
|
void snapOtherAvatarLookAtTargetsToMe(const AvatarHash& hash);
|
|
void clearLookAtTargetAvatar();
|
|
|
|
virtual void setJointRotations(const QVector<glm::quat>& jointRotations) override;
|
|
virtual void setJointData(int index, const glm::quat& rotation, const glm::vec3& translation) override;
|
|
virtual void setJointRotation(int index, const glm::quat& rotation) override;
|
|
virtual void setJointTranslation(int index, const glm::vec3& translation) override;
|
|
virtual void clearJointData(int index) override;
|
|
|
|
virtual void setJointData(const QString& name, const glm::quat& rotation, const glm::vec3& translation) override;
|
|
virtual void setJointRotation(const QString& name, const glm::quat& rotation) override;
|
|
virtual void setJointTranslation(const QString& name, const glm::vec3& translation) override;
|
|
virtual void clearJointData(const QString& name) override;
|
|
virtual void clearJointsData() override;
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.pinJoint
|
|
* @param {number} index
|
|
* @param {Vec3} position
|
|
* @param {Quat} orientation
|
|
* @returns {boolean}
|
|
*/
|
|
Q_INVOKABLE bool pinJoint(int index, const glm::vec3& position, const glm::quat& orientation);
|
|
|
|
bool isJointPinned(int index);
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.clearPinOnJoint
|
|
* @param {number} index
|
|
* @returns {boolean}
|
|
*/
|
|
Q_INVOKABLE bool clearPinOnJoint(int index);
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.getIKErrorOnLastSolve
|
|
* @returns {number}
|
|
*/
|
|
Q_INVOKABLE float getIKErrorOnLastSolve() const;
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.useFullAvatarURL
|
|
* @param {string} fullAvatarURL
|
|
* @param {string} [modelName=""]
|
|
*/
|
|
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 <caption>Report the URL for the current avatar.</caption>
|
|
* 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 <caption>Report the current full avatar model name.</caption>
|
|
* print(MyAvatar.getFullAvatarModelName());
|
|
*/
|
|
Q_INVOKABLE QString getFullAvatarModelName() const { return _fullAvatarModelName; }
|
|
|
|
void resetFullAvatarURL();
|
|
|
|
MyCharacterController* getCharacterController() { return &_characterController; }
|
|
const MyCharacterController* getCharacterController() const { return &_characterController; }
|
|
|
|
void updateMotors();
|
|
void prepareForPhysicsSimulation();
|
|
void nextAttitude(glm::vec3 position, glm::quat orientation); // Can be safely called at any time.
|
|
void harvestResultsFromPhysicsSimulation(float deltaTime);
|
|
|
|
const QString& getCollisionSoundURL() { return _collisionSoundURL; }
|
|
void setCollisionSoundURL(const QString& url);
|
|
|
|
SharedSoundPointer getCollisionSound();
|
|
void setCollisionSound(SharedSoundPointer sound) { _collisionSound = sound; }
|
|
|
|
void clearScriptableSettings();
|
|
|
|
float getBoomLength() const { return _boomLength; }
|
|
void setBoomLength(float boomLength) { _boomLength = boomLength; }
|
|
|
|
float getPitchSpeed() const { return _pitchSpeed; }
|
|
void setPitchSpeed(float speed) { _pitchSpeed = speed; }
|
|
|
|
float getYawSpeed() const { return _yawSpeed; }
|
|
void setYawSpeed(float speed) { _yawSpeed = speed; }
|
|
|
|
static const float ZOOM_MIN;
|
|
static const float ZOOM_MAX;
|
|
static const float ZOOM_DEFAULT;
|
|
|
|
void destroyAnimGraph();
|
|
|
|
AudioListenerMode getAudioListenerMode() { return _audioListenerMode; }
|
|
void setAudioListenerMode(AudioListenerMode audioListenerMode);
|
|
glm::vec3 getCustomListenPosition() { return _customListenPosition; }
|
|
void setCustomListenPosition(glm::vec3 customListenPosition) { _customListenPosition = customListenPosition; }
|
|
glm::quat getCustomListenOrientation() { return _customListenOrientation; }
|
|
void setCustomListenOrientation(glm::quat customListenOrientation) { _customListenOrientation = customListenOrientation; }
|
|
|
|
virtual void rebuildCollisionShape() override;
|
|
|
|
const glm::vec2& getHipToHandController() const { return _hipToHandController; }
|
|
void setHipToHandController(glm::vec2 currentHipToHandController) { _hipToHandController = currentHipToHandController; }
|
|
const glm::vec2& getHeadControllerFacing() const { return _headControllerFacing; }
|
|
void setHeadControllerFacing(glm::vec2 currentHeadControllerFacing) { _headControllerFacing = currentHeadControllerFacing; }
|
|
const glm::vec2& getHeadControllerFacingMovingAverage() const { return _headControllerFacingMovingAverage; }
|
|
void setHeadControllerFacingMovingAverage(glm::vec2 currentHeadControllerFacing) { _headControllerFacingMovingAverage = currentHeadControllerFacing; }
|
|
float getCurrentStandingHeight() const { return _currentStandingHeight; }
|
|
void setCurrentStandingHeight(float newMode) { _currentStandingHeight = newMode; }
|
|
const glm::quat getAverageHeadRotation() const { return _averageHeadRotation; }
|
|
void setAverageHeadRotation(glm::quat rotation) { _averageHeadRotation = rotation; }
|
|
bool getResetMode() const { return _resetMode; }
|
|
void setResetMode(bool hasBeenReset) { _resetMode = hasBeenReset; }
|
|
|
|
void setControllerPoseInSensorFrame(controller::Action action, const controller::Pose& pose);
|
|
controller::Pose getControllerPoseInSensorFrame(controller::Action action) const;
|
|
controller::Pose getControllerPoseInWorldFrame(controller::Action action) const;
|
|
controller::Pose getControllerPoseInAvatarFrame(controller::Action action) const;
|
|
|
|
bool hasDriveInput() const;
|
|
|
|
/**jsdoc
|
|
* Function returns list of avatar entities
|
|
* @function MyAvatar.getAvatarEntitiesVariant()
|
|
* @returns {object[]}
|
|
*/
|
|
Q_INVOKABLE QVariantList getAvatarEntitiesVariant();
|
|
void removeWornAvatarEntity(const EntityItemID& entityID);
|
|
void clearWornAvatarEntities();
|
|
|
|
/**jsdoc
|
|
* Check whether your avatar is flying or not.
|
|
* @function MyAvatar.isFlying
|
|
* @returns {boolean} <code>true</code> if your avatar is flying and not taking off or falling, otherwise
|
|
* <code>false</code>.
|
|
*/
|
|
Q_INVOKABLE bool isFlying();
|
|
|
|
/**jsdoc
|
|
* Check whether your avatar is in the air or not.
|
|
* @function MyAvatar.isInAir
|
|
* @returns {boolean} <code>true</code> if your avatar is taking off, flying, or falling, otherwise <code>false</code>
|
|
* because your avatar is on the ground.
|
|
*/
|
|
Q_INVOKABLE bool isInAir();
|
|
|
|
/**jsdoc
|
|
* Set your preference for flying in your current desktop or HMD display mode. Note that your ability to fly also depends
|
|
* on whether the domain you're in allows you to fly.
|
|
* @function MyAvatar.setFlyingEnabled
|
|
* @param {boolean} enabled - Set <code>true</code> if you want to enable flying in your current desktop or HMD display
|
|
* mode, otherwise set <code>false</code>.
|
|
*/
|
|
Q_INVOKABLE void setFlyingEnabled(bool enabled);
|
|
|
|
/**jsdoc
|
|
* Get your preference for flying in your current desktop or HMD display mode. Note that your ability to fly also depends
|
|
* on whether the domain you're in allows you to fly.
|
|
* @function MyAvatar.getFlyingEnabled
|
|
* @returns {boolean} <code>true</code> if your preference is to enable flying in your current desktop or HMD display mode,
|
|
* otherwise <code>false</code>.
|
|
*/
|
|
Q_INVOKABLE bool getFlyingEnabled();
|
|
|
|
/**jsdoc
|
|
* Set your preference for flying in desktop display mode. Note that your ability to fly also depends on whether the domain
|
|
* you're in allows you to fly.
|
|
* @function MyAvatar.setFlyingDesktopPref
|
|
* @param {boolean} enabled - Set <code>true</code> if you want to enable flying in desktop display mode, otherwise set
|
|
* <code>false</code>.
|
|
*/
|
|
Q_INVOKABLE void setFlyingDesktopPref(bool enabled);
|
|
|
|
/**jsdoc
|
|
* Get your preference for flying in desktop display mode. Note that your ability to fly also depends on whether the domain
|
|
* you're in allows you to fly.
|
|
* @function MyAvatar.getFlyingDesktopPref
|
|
* @returns {boolean} <code>true</code> if your preference is to enable flying in desktop display mode, otherwise
|
|
* <code>false</code>.
|
|
*/
|
|
Q_INVOKABLE bool getFlyingDesktopPref();
|
|
|
|
/**jsdoc
|
|
* Set your preference for flying in HMD display mode. Note that your ability to fly also depends on whether the domain
|
|
* you're in allows you to fly.
|
|
* @function MyAvatar.setFlyingHMDPref
|
|
* @param {boolean} enabled - Set <code>true</code> if you want to enable flying in HMD display mode, otherwise set
|
|
* <code>false</code>.
|
|
*/
|
|
Q_INVOKABLE void setFlyingHMDPref(bool enabled);
|
|
|
|
/**jsdoc
|
|
* Get your preference for flying in HMD display mode. Note that your ability to fly also depends on whether the domain
|
|
* you're in allows you to fly.
|
|
* @function MyAvatar.getFlyingHMDPref
|
|
* @returns {boolean} <code>true</code> if your preference is to enable flying in HMD display mode, otherwise
|
|
* <code>false</code>.
|
|
*/
|
|
Q_INVOKABLE bool getFlyingHMDPref();
|
|
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.getAvatarScale
|
|
* @returns {number}
|
|
*/
|
|
Q_INVOKABLE float getAvatarScale();
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.setAvatarScale
|
|
* @param {number} scale
|
|
*/
|
|
Q_INVOKABLE void setAvatarScale(float scale);
|
|
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.setCollisionsEnabled
|
|
* @param {boolean} enabled
|
|
*/
|
|
Q_INVOKABLE void setCollisionsEnabled(bool enabled);
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.getCollisionsEnabled
|
|
* @returns {boolean}
|
|
*/
|
|
Q_INVOKABLE bool getCollisionsEnabled();
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.setOtherAvatarsCollisionsEnabled
|
|
* @param {boolean} enabled
|
|
*/
|
|
Q_INVOKABLE void setOtherAvatarsCollisionsEnabled(bool enabled);
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.getOtherAvatarsCollisionsEnabled
|
|
* @returns {boolean}
|
|
*/
|
|
Q_INVOKABLE bool getOtherAvatarsCollisionsEnabled();
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.getCollisionCapsule
|
|
* @returns {object}
|
|
*/
|
|
Q_INVOKABLE QVariantMap getCollisionCapsule() const;
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.setCharacterControllerEnabled
|
|
* @param {boolean} enabled
|
|
* @deprecated
|
|
*/
|
|
Q_INVOKABLE void setCharacterControllerEnabled(bool enabled); // deprecated
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.getCharacterControllerEnabled
|
|
* @returns {boolean}
|
|
* @deprecated
|
|
*/
|
|
Q_INVOKABLE bool getCharacterControllerEnabled(); // deprecated
|
|
|
|
virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override;
|
|
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override;
|
|
|
|
// all calibration matrices are in absolute sensor space.
|
|
glm::mat4 getCenterEyeCalibrationMat() const;
|
|
glm::mat4 getHeadCalibrationMat() const;
|
|
glm::mat4 getSpine2CalibrationMat() const;
|
|
glm::mat4 getHipsCalibrationMat() const;
|
|
glm::mat4 getLeftFootCalibrationMat() const;
|
|
glm::mat4 getRightFootCalibrationMat() const;
|
|
glm::mat4 getRightArmCalibrationMat() const;
|
|
glm::mat4 getLeftArmCalibrationMat() const;
|
|
glm::mat4 getLeftHandCalibrationMat() const;
|
|
glm::mat4 getRightHandCalibrationMat() const;
|
|
|
|
void addHoldAction(AvatarActionHold* holdAction); // thread-safe
|
|
void removeHoldAction(AvatarActionHold* holdAction); // thread-safe
|
|
void updateHoldActions(const AnimPose& prePhysicsPose, const AnimPose& postUpdatePose);
|
|
|
|
|
|
// derive avatar body position and orientation from the current HMD Sensor location.
|
|
// results are in sensor frame (-z forward)
|
|
glm::mat4 deriveBodyFromHMDSensor() const;
|
|
|
|
glm::mat4 getSpine2RotationRigSpace() const;
|
|
|
|
glm::vec3 computeCounterBalance();
|
|
|
|
// derive avatar body position and orientation from using the current HMD Sensor location in relation to the previous
|
|
// location of the base of support of the avatar.
|
|
// results are in sensor frame (-z foward)
|
|
glm::mat4 deriveBodyUsingCgModel();
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.isUp
|
|
* @param {Vec3} direction
|
|
* @returns {boolean}
|
|
*/
|
|
Q_INVOKABLE bool isUp(const glm::vec3& direction) { return glm::dot(direction, _worldUpDirection) > 0.0f; }; // true iff direction points up wrt avatar's definition of up.
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.isDown
|
|
* @param {Vec3} direction
|
|
* @returns {boolean}
|
|
*/
|
|
Q_INVOKABLE bool isDown(const glm::vec3& direction) { return glm::dot(direction, _worldUpDirection) < 0.0f; };
|
|
|
|
void setUserHeight(float value);
|
|
float getUserHeight() const;
|
|
float getUserEyeHeight() const;
|
|
|
|
virtual SpatialParentTree* getParentTree() const override;
|
|
|
|
const QUuid& getSelfID() const { return AVATAR_SELF_ID; }
|
|
|
|
void setIsInWalkingState(bool isWalking);
|
|
bool getIsInWalkingState() const;
|
|
void setIsInSittingState(bool isSitting);
|
|
bool getIsInSittingState() const;
|
|
void setUserRecenterModel(MyAvatar::SitStandModelType modelName);
|
|
MyAvatar::SitStandModelType getUserRecenterModel() const;
|
|
void setIsSitStandStateLocked(bool isLocked);
|
|
bool getIsSitStandStateLocked() const;
|
|
void setWalkSpeed(float value);
|
|
float getWalkSpeed() const;
|
|
void setWalkBackwardSpeed(float value);
|
|
float getWalkBackwardSpeed() const;
|
|
void setSprintSpeed(float value);
|
|
float getSprintSpeed() const;
|
|
void setSitStandStateChange(bool stateChanged);
|
|
float getSitStandStateChange() const;
|
|
void updateSitStandState(float newHeightReading, float dt);
|
|
|
|
QVector<QString> getScriptUrls();
|
|
|
|
bool isReadyForPhysics() const;
|
|
|
|
float computeStandingHeightMode(const controller::Pose& head);
|
|
glm::quat computeAverageHeadRotation(const controller::Pose& head);
|
|
|
|
virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData) override;
|
|
virtual QVector<AttachmentData> getAttachmentData() const override;
|
|
|
|
virtual QVariantList getAttachmentsVariant() const override;
|
|
virtual void setAttachmentsVariant(const QVariantList& variant) override;
|
|
|
|
glm::vec3 getNextPosition() { return _goToPending ? _goToPosition : getWorldPosition(); }
|
|
void prepareAvatarEntityDataForReload();
|
|
|
|
/**jsdoc
|
|
* Create a new grab.
|
|
* @function MyAvatar.grab
|
|
* @param {Uuid} targetID - id of grabbed thing
|
|
* @param {number} parentJointIndex - avatar joint being used to grab
|
|
* @param {Vec3} offset - target's positional offset from joint
|
|
* @param {Quat} rotationalOffset - target's rotational offset from joint
|
|
* @returns {Uuid} id of the new grab
|
|
*/
|
|
Q_INVOKABLE const QUuid grab(const QUuid& targetID, int parentJointIndex,
|
|
glm::vec3 positionalOffset, glm::quat rotationalOffset);
|
|
|
|
/**jsdoc
|
|
* Release (delete) a grab.
|
|
* @function MyAvatar.releaseGrab
|
|
* @param {Uuid} grabID - id of grabbed thing
|
|
*/
|
|
Q_INVOKABLE void releaseGrab(const QUuid& grabID);
|
|
|
|
AvatarEntityMap getAvatarEntityData() const override;
|
|
void setAvatarEntityData(const AvatarEntityMap& avatarEntityData) override;
|
|
void updateAvatarEntity(const QUuid& entityID, const QByteArray& entityData) override;
|
|
void avatarEntityDataToJson(QJsonObject& root) const override;
|
|
int sendAvatarDataPacket(bool sendAll = false) override;
|
|
|
|
public slots:
|
|
|
|
/**jsdoc
|
|
* Increase the avatar's scale by five percent, up to a minimum scale of <code>1000</code>.
|
|
* @function MyAvatar.increaseSize
|
|
* @example <caption>Reset your avatar's size to default then grow it 5 times.</caption>
|
|
* 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 <code>0.25</code>.
|
|
* @function MyAvatar.decreaseSize
|
|
* @example <caption>Reset your avatar's size to default then shrink it 5 times.</caption>
|
|
* 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 <code>1.0</code>.
|
|
* @function MyAvatar.resetSize
|
|
*/
|
|
void resetSize();
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.animGraphLoaded
|
|
*/
|
|
void animGraphLoaded();
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.setGravity
|
|
* @param {number} gravity
|
|
*/
|
|
void setGravity(float gravity);
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.getGravity
|
|
* @returns {number}
|
|
*/
|
|
float getGravity();
|
|
|
|
/**jsdoc
|
|
* Move the avatar to a new position and/or orientation in the domain, while taking into account Avatar leg-length.
|
|
* @function MyAvatar.goToFeetLocation
|
|
* @param {Vec3} position - The new position for the avatar, in world coordinates.
|
|
* @param {boolean} [hasOrientation=false] - Set to <code>true</code> to set the orientation of the avatar.
|
|
* @param {Quat} [orientation=Quat.IDENTITY] - The new orientation for the avatar.
|
|
* @param {boolean} [shouldFaceLocation=false] - Set to <code>true</code> to position the avatar a short distance away from
|
|
* the new position and orientate the avatar to face the position.
|
|
*/
|
|
|
|
void goToFeetLocation(const glm::vec3& newPosition,
|
|
bool hasOrientation, const glm::quat& newOrientation,
|
|
bool shouldFaceLocation);
|
|
|
|
/**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 <code>true</code> to set the orientation of the avatar.
|
|
* @param {Quat} [orientation=Quat.IDENTITY] - The new orientation for the avatar.
|
|
* @param {boolean} [shouldFaceLocation=false] - Set to <code>true</code> to position the avatar a short distance away from
|
|
* @param {boolean} [withSafeLanding=true] - Set to <code>false</code> MyAvatar::safeLanding will not be called (used when teleporting).
|
|
* 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, bool withSafeLanding = true);
|
|
/**jsdoc
|
|
* @function MyAvatar.goToLocation
|
|
* @param {object} properties
|
|
*/
|
|
void goToLocation(const QVariant& properties);
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.goToLocationAndEnableCollisions
|
|
* @param {Vec3} position
|
|
*/
|
|
void goToLocationAndEnableCollisions(const glm::vec3& newPosition);
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.safeLanding
|
|
* @param {Vec3} position
|
|
* @returns {boolean}
|
|
*/
|
|
bool safeLanding(const glm::vec3& position);
|
|
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.restrictScaleFromDomainSettings
|
|
* @param {objecct} domainSettingsObject
|
|
*/
|
|
void restrictScaleFromDomainSettings(const QJsonObject& domainSettingsObject);
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.clearScaleRestriction
|
|
*/
|
|
void clearScaleRestriction();
|
|
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.addThrust
|
|
* @param {Vec3} thrust
|
|
*/
|
|
// Set/Get update the thrust that will move the avatar around
|
|
void addThrust(glm::vec3 newThrust) { _thrust += newThrust; };
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.getThrust
|
|
* @returns {vec3}
|
|
*/
|
|
glm::vec3 getThrust() { return _thrust; };
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.setThrust
|
|
* @param {Vec3} thrust
|
|
*/
|
|
void setThrust(glm::vec3 newThrust) { _thrust = newThrust; }
|
|
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.updateMotionBehaviorFromMenu
|
|
*/
|
|
Q_INVOKABLE void updateMotionBehaviorFromMenu();
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.setToggleHips
|
|
* @param {boolean} enabled
|
|
*/
|
|
void setToggleHips(bool followHead);
|
|
/**jsdoc
|
|
* @function MyAvatar.setEnableDebugDrawBaseOfSupport
|
|
* @param {boolean} enabled
|
|
*/
|
|
void setEnableDebugDrawBaseOfSupport(bool isEnabled);
|
|
/**jsdoc
|
|
* @function MyAvatar.setEnableDebugDrawDefaultPose
|
|
* @param {boolean} enabled
|
|
*/
|
|
void setEnableDebugDrawDefaultPose(bool isEnabled);
|
|
/**jsdoc
|
|
* @function MyAvatar.setEnableDebugDrawAnimPose
|
|
* @param {boolean} enabled
|
|
*/
|
|
void setEnableDebugDrawAnimPose(bool isEnabled);
|
|
/**jsdoc
|
|
* @function MyAvatar.setEnableDebugDrawPosition
|
|
* @param {boolean} enabled
|
|
*/
|
|
void setEnableDebugDrawPosition(bool isEnabled);
|
|
/**jsdoc
|
|
* @function MyAvatar.setEnableDebugDrawHandControllers
|
|
* @param {boolean} enabled
|
|
*/
|
|
void setEnableDebugDrawHandControllers(bool isEnabled);
|
|
/**jsdoc
|
|
* @function MyAvatar.setEnableDebugDrawSensorToWorldMatrix
|
|
* @param {boolean} enabled
|
|
*/
|
|
void setEnableDebugDrawSensorToWorldMatrix(bool isEnabled);
|
|
/**jsdoc
|
|
* @function MyAvatar.setEnableDebugDrawIKTargets
|
|
* @param {boolean} enabled
|
|
*/
|
|
void setEnableDebugDrawIKTargets(bool isEnabled);
|
|
/**jsdoc
|
|
* @function MyAvatar.setEnableDebugDrawIKConstraints
|
|
* @param {boolean} enabled
|
|
*/
|
|
void setEnableDebugDrawIKConstraints(bool isEnabled);
|
|
/**jsdoc
|
|
* @function MyAvatar.setEnableDebugDrawIKChains
|
|
* @param {boolean} enabled
|
|
*/
|
|
void setEnableDebugDrawIKChains(bool isEnabled);
|
|
/**jsdoc
|
|
* @function MyAvatar.setEnableDebugDrawDetailedCollision
|
|
* @param {boolean} enabled
|
|
*/
|
|
void setEnableDebugDrawDetailedCollision(bool isEnabled);
|
|
|
|
/**jsdoc
|
|
* Get whether or not your avatar mesh is visible.
|
|
* @function MyAvatar.getEnableMeshVisible
|
|
* @returns {boolean} <code>true</code> if your avatar's mesh is visible, otherwise <code>false</code>.
|
|
*/
|
|
bool getEnableMeshVisible() const override;
|
|
|
|
void storeAvatarEntityDataPayload(const QUuid& entityID, const QByteArray& payload) override;
|
|
void clearAvatarEntity(const QUuid& entityID, bool requiresRemovalFromTree = true) override;
|
|
void sanitizeAvatarEntityProperties(EntityItemProperties& properties) const;
|
|
|
|
/**jsdoc
|
|
* Set whether or not your avatar mesh is visible.
|
|
* @function MyAvatar.setEnableMeshVisible
|
|
* @param {boolean} visible - <code>true</code> to set your avatar mesh visible; <code>false</code> to set it invisible.
|
|
* @example <caption>Make your avatar invisible for 10s.</caption>
|
|
* MyAvatar.setEnableMeshVisible(false);
|
|
* Script.setTimeout(function () {
|
|
* MyAvatar.setEnableMeshVisible(true);
|
|
* }, 10000);
|
|
*/
|
|
virtual void setEnableMeshVisible(bool isEnabled) override;
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.setEnableInverseKinematics
|
|
* @param {boolean} enabled
|
|
*/
|
|
void setEnableInverseKinematics(bool isEnabled);
|
|
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.getAnimGraphOverrideUrl
|
|
* @returns {string}
|
|
*/
|
|
QUrl getAnimGraphOverrideUrl() const; // thread-safe
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.setAnimGraphOverrideUrl
|
|
* @param {string} url
|
|
*/
|
|
void setAnimGraphOverrideUrl(QUrl value); // thread-safe
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.getAnimGraphUrl
|
|
* @returns {string}
|
|
*/
|
|
QUrl getAnimGraphUrl() const; // thread-safe
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.setAnimGraphUrl
|
|
* @param {string} url
|
|
*/
|
|
void setAnimGraphUrl(const QUrl& url); // thread-safe
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.getPositionForAudio
|
|
* @returns {Vec3}
|
|
*/
|
|
glm::vec3 getPositionForAudio();
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.getOrientationForAudio
|
|
* @returns {Quat}
|
|
*/
|
|
glm::quat getOrientationForAudio();
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.setModelScale
|
|
* @param {number} scale
|
|
*/
|
|
virtual void setModelScale(float scale) override;
|
|
|
|
signals:
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.audioListenerModeChanged
|
|
* @returns {Signal}
|
|
*/
|
|
void audioListenerModeChanged();
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.transformChanged
|
|
* @returns {Signal}
|
|
*/
|
|
void transformChanged();
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.newCollisionSoundURL
|
|
* @param {string} url
|
|
* @returns {Signal}
|
|
*/
|
|
void newCollisionSoundURL(const QUrl& url);
|
|
|
|
/**jsdoc
|
|
* Triggered when the avatar collides with an entity.
|
|
* @function MyAvatar.collisionWithEntity
|
|
* @param {Collision} collision
|
|
* @returns {Signal}
|
|
* @example <caption>Report each time your avatar collides with an entity.</caption>
|
|
* MyAvatar.collisionWithEntity.connect(function (collision) {
|
|
* print("Your avatar collided with an entity.");
|
|
* });
|
|
*/
|
|
void collisionWithEntity(const Collision& collision);
|
|
|
|
/**jsdoc
|
|
* Triggered when collisions with avatar enabled or disabled
|
|
* @function MyAvatar.collisionsEnabledChanged
|
|
* @param {boolean} enabled
|
|
* @returns {Signal}
|
|
*/
|
|
void collisionsEnabledChanged(bool enabled);
|
|
|
|
/**jsdoc
|
|
* Triggered when collisions with other avatars enabled or disabled
|
|
* @function MyAvatar.otherAvatarsCollisionsEnabledChanged
|
|
* @param {boolean} enabled
|
|
* @returns {Signal}
|
|
*/
|
|
void otherAvatarsCollisionsEnabledChanged(bool enabled);
|
|
|
|
/**jsdoc
|
|
* Triggered when avatar's animation url changes
|
|
* @function MyAvatar.animGraphUrlChanged
|
|
* @param {url} url
|
|
* @returns {Signal}
|
|
*/
|
|
void animGraphUrlChanged(const QUrl& url);
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.energyChanged
|
|
* @param {number} energy
|
|
* @returns {Signal}
|
|
*/
|
|
void energyChanged(float newEnergy);
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.positionGoneTo
|
|
* @returns {Signal}
|
|
*/
|
|
// FIXME: Better name would be goneToLocation().
|
|
void positionGoneTo();
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.onLoadComplete
|
|
* @returns {Signal}
|
|
*/
|
|
void onLoadComplete();
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.wentAway
|
|
* @returns {Signal}
|
|
*/
|
|
void wentAway();
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.wentActive
|
|
* @returns {Signal}
|
|
*/
|
|
void wentActive();
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.skeletonChanged
|
|
* @returns {Signal}
|
|
*/
|
|
void skeletonChanged();
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.dominantHandChanged
|
|
* @param {string} hand
|
|
* @returns {Signal}
|
|
*/
|
|
void dominantHandChanged(const QString& hand);
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.sensorToWorldScaleChanged
|
|
* @param {number} scale
|
|
* @returns {Signal}
|
|
*/
|
|
void sensorToWorldScaleChanged(float sensorToWorldScale);
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.attachmentsChanged
|
|
* @returns {Signal}
|
|
*/
|
|
void attachmentsChanged();
|
|
|
|
/**jsdoc
|
|
* @function MyAvatar.scaleChanged
|
|
* @returns {Signal}
|
|
*/
|
|
void scaleChanged();
|
|
|
|
/**jsdoc
|
|
* Triggered when hand touch is globally enabled or disabled
|
|
* @function MyAvatar.shouldDisableHandTouchChanged
|
|
* @param {boolean} shouldDisable
|
|
* @returns {Signal}
|
|
*/
|
|
void shouldDisableHandTouchChanged(bool shouldDisable);
|
|
|
|
/**jsdoc
|
|
* Triggered when hand touch is enabled or disabled for an specific entity
|
|
* @function MyAvatar.disableHandTouchForIDChanged
|
|
* @param {Uuid} entityID - ID of the entity that will enable hand touch effect
|
|
* @param {boolean} disable
|
|
* @returns {Signal}
|
|
*/
|
|
void disableHandTouchForIDChanged(const QUuid& entityID, bool disable);
|
|
|
|
private slots:
|
|
void leaveDomain();
|
|
void updateCollisionCapsuleCache();
|
|
|
|
protected:
|
|
void handleChangedAvatarEntityData();
|
|
virtual void beParentOfChild(SpatiallyNestablePointer newChild) const override;
|
|
virtual void forgetChild(SpatiallyNestablePointer newChild) const override;
|
|
virtual void recalculateChildCauterization() const override;
|
|
|
|
private:
|
|
bool updateStaleAvatarEntityBlobs() const;
|
|
|
|
bool requiresSafeLanding(const glm::vec3& positionIn, glm::vec3& positionOut);
|
|
|
|
virtual QByteArray toByteArrayStateful(AvatarDataDetail dataDetail, bool dropFaceTracking) override;
|
|
|
|
void simulate(float deltaTime, bool inView) override;
|
|
void updateFromTrackers(float deltaTime);
|
|
void saveAvatarUrl();
|
|
virtual void render(RenderArgs* renderArgs) override;
|
|
virtual bool shouldRenderHead(const RenderArgs* renderArgs) const override;
|
|
void setShouldRenderLocally(bool shouldRender) { _shouldRender = shouldRender; setEnableMeshVisible(shouldRender); }
|
|
bool getShouldRenderLocally() const { return _shouldRender; }
|
|
void setHasScriptedBlendshapes(bool hasScriptedBlendshapes);
|
|
bool getHasScriptedBlendshapes() const override { return _hasScriptedBlendShapes; }
|
|
void setHasProceduralBlinkFaceMovement(bool hasProceduralBlinkFaceMovement);
|
|
bool getHasProceduralBlinkFaceMovement() const override { return _headData->getHasProceduralBlinkFaceMovement(); }
|
|
void setHasProceduralEyeFaceMovement(bool hasProceduralEyeFaceMovement);
|
|
bool getHasProceduralEyeFaceMovement() const override { return _headData->getHasProceduralEyeFaceMovement(); }
|
|
void setHasAudioEnabledFaceMovement(bool hasAudioEnabledFaceMovement);
|
|
bool getHasAudioEnabledFaceMovement() const override { return _headData->getHasAudioEnabledFaceMovement(); }
|
|
void setRotationRecenterFilterLength(float length);
|
|
float getRotationRecenterFilterLength() const { return _rotationRecenterFilterLength; }
|
|
void setRotationThreshold(float angleRadians);
|
|
float getRotationThreshold() const { return _rotationThreshold; }
|
|
void setEnableStepResetRotation(bool stepReset) { _stepResetRotationEnabled = stepReset; }
|
|
bool getEnableStepResetRotation() const { return _stepResetRotationEnabled; }
|
|
void setEnableDrawAverageFacing(bool drawAverage) { _drawAverageFacingEnabled = drawAverage; }
|
|
bool getEnableDrawAverageFacing() const { return _drawAverageFacingEnabled; }
|
|
bool isMyAvatar() const override { return true; }
|
|
virtual int parseDataFromBuffer(const QByteArray& buffer) override;
|
|
virtual glm::vec3 getSkeletonPosition() const override;
|
|
int _skeletonModelChangeCount { 0 };
|
|
|
|
void saveAvatarScale();
|
|
|
|
glm::vec3 getScriptedMotorVelocity() const { return _scriptedMotorVelocity; }
|
|
float getScriptedMotorTimescale() const { return _scriptedMotorTimescale; }
|
|
QString getScriptedMotorFrame() const;
|
|
QString getScriptedMotorMode() const;
|
|
void setScriptedMotorVelocity(const glm::vec3& velocity);
|
|
void setScriptedMotorTimescale(float timescale);
|
|
void setScriptedMotorFrame(QString frame);
|
|
void setScriptedMotorMode(QString mode);
|
|
|
|
// Attachments
|
|
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) override;
|
|
|
|
virtual void detachOne(const QString& modelURL, const QString& jointName = QString()) override;
|
|
virtual void detachAll(const QString& modelURL, const QString& jointName = QString()) override;
|
|
|
|
// Attachments/Avatar Entity
|
|
void attachmentDataToEntityProperties(const AttachmentData& data, EntityItemProperties& properties);
|
|
AttachmentData entityPropertiesToAttachmentData(const EntityItemProperties& properties) const;
|
|
bool findAvatarEntity(const QString& modelURL, const QString& jointName, QUuid& entityID);
|
|
|
|
bool cameraInsideHead(const glm::vec3& cameraPosition) const;
|
|
|
|
void updateEyeContactTarget(float deltaTime);
|
|
|
|
// These are made private for MyAvatar so that you will use the "use" methods instead
|
|
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override;
|
|
|
|
virtual void updatePalms() override {}
|
|
void lateUpdatePalms();
|
|
|
|
void clampTargetScaleToDomainLimits();
|
|
void clampScaleChangeToDomainLimits(float desiredScale);
|
|
glm::mat4 computeCameraRelativeHandControllerMatrix(const glm::mat4& controllerSensorMatrix) const;
|
|
|
|
std::array<float, MAX_DRIVE_KEYS> _driveKeys;
|
|
std::bitset<MAX_DRIVE_KEYS> _disabledDriveKeys;
|
|
|
|
bool _enableFlying { false };
|
|
bool _flyingPrefDesktop { true };
|
|
bool _flyingPrefHMD { false };
|
|
bool _wasPushing { false };
|
|
bool _isPushing { false };
|
|
bool _isBeingPushed { false };
|
|
bool _isBraking { false };
|
|
bool _isAway { false };
|
|
|
|
float _boomLength { ZOOM_DEFAULT };
|
|
float _yawSpeed; // degrees/sec
|
|
float _pitchSpeed; // degrees/sec
|
|
|
|
glm::vec3 _thrust { 0.0f }; // impulse accumulator for outside sources
|
|
|
|
glm::vec3 _actionMotorVelocity; // target local-frame velocity of avatar (default controller actions)
|
|
glm::vec3 _scriptedMotorVelocity; // target local-frame velocity of avatar (analog script)
|
|
float _scriptedMotorTimescale; // timescale for avatar to achieve its target velocity
|
|
int _scriptedMotorFrame;
|
|
int _scriptedMotorMode;
|
|
quint32 _motionBehaviors;
|
|
QString _collisionSoundURL;
|
|
|
|
SharedSoundPointer _collisionSound;
|
|
|
|
MyCharacterController _characterController;
|
|
int32_t _previousCollisionMask { BULLET_COLLISION_MASK_MY_AVATAR };
|
|
|
|
AvatarWeakPointer _lookAtTargetAvatar;
|
|
glm::vec3 _targetAvatarPosition;
|
|
bool _shouldRender { true };
|
|
float _oculusYawOffset;
|
|
|
|
eyeContactTarget _eyeContactTarget;
|
|
float _eyeContactTargetTimer { 0.0f };
|
|
|
|
glm::vec3 _trackedHeadPosition;
|
|
|
|
Setting::Handle<float> _realWorldFieldOfView;
|
|
Setting::Handle<bool> _useAdvancedMovementControls;
|
|
Setting::Handle<bool> _showPlayArea;
|
|
|
|
// Smoothing.
|
|
const float SMOOTH_TIME_ORIENTATION = 0.5f;
|
|
|
|
// Smoothing data for blending from one position/orientation to another on remote agents.
|
|
float _smoothOrientationTimer;
|
|
glm::quat _smoothOrientationInitial;
|
|
glm::quat _smoothOrientationTarget;
|
|
|
|
// private methods
|
|
void updateOrientation(float deltaTime);
|
|
void updateActionMotor(float deltaTime);
|
|
void updatePosition(float deltaTime);
|
|
void updateCollisionSound(const glm::vec3& penetration, float deltaTime, float frequency);
|
|
void initHeadBones();
|
|
void initAnimGraph();
|
|
|
|
// Avatar Preferences
|
|
QUrl _fullAvatarURLFromPreferences;
|
|
QString _fullAvatarModelName;
|
|
ThreadSafeValueCache<QUrl> _currentAnimGraphUrl;
|
|
ThreadSafeValueCache<QUrl> _prefOverrideAnimGraphUrl;
|
|
QUrl _fstAnimGraphOverrideUrl;
|
|
bool _useSnapTurn { true };
|
|
QString _dominantHand { DOMINANT_RIGHT_HAND };
|
|
|
|
const float ROLL_CONTROL_DEAD_ZONE_DEFAULT = 8.0f; // degrees
|
|
const float ROLL_CONTROL_RATE_DEFAULT = 114.0f; // degrees / sec
|
|
|
|
bool _hmdRollControlEnabled { true };
|
|
float _hmdRollControlDeadZone { ROLL_CONTROL_DEAD_ZONE_DEFAULT };
|
|
float _hmdRollControlRate { ROLL_CONTROL_RATE_DEFAULT };
|
|
std::atomic<bool> _hasScriptedBlendShapes { false };
|
|
std::atomic<float> _rotationRecenterFilterLength { 4.0f };
|
|
std::atomic<float> _rotationThreshold { 0.5235f }; // 30 degrees in radians
|
|
std::atomic<bool> _stepResetRotationEnabled { true };
|
|
std::atomic<bool> _drawAverageFacingEnabled { false };
|
|
|
|
// working copy -- see AvatarData for thread-safe _sensorToWorldMatrixCache, used for outward facing access
|
|
glm::mat4 _sensorToWorldMatrix { glm::mat4() };
|
|
|
|
// cache of the current HMD sensor position and orientation in sensor space.
|
|
glm::mat4 _hmdSensorMatrix;
|
|
glm::quat _hmdSensorOrientation;
|
|
glm::vec3 _hmdSensorPosition;
|
|
// cache head controller pose in sensor space
|
|
glm::vec2 _headControllerFacing; // facing vector in xz plane (sensor space)
|
|
glm::vec2 _headControllerFacingMovingAverage { 0.0f, 0.0f }; // facing vector in xz plane (sensor space)
|
|
glm::quat _averageHeadRotation { 0.0f, 0.0f, 0.0f, 1.0f };
|
|
|
|
glm::vec2 _hipToHandController { 0.0f, 1.0f }; // spine2 facing vector in xz plane (spine2 space)
|
|
|
|
float _currentStandingHeight { 0.0f };
|
|
bool _resetMode { true };
|
|
RingBufferHistory<int> _recentModeReadings;
|
|
|
|
// cache of the current body position and orientation of the avatar's body,
|
|
// in sensor space.
|
|
glm::mat4 _bodySensorMatrix;
|
|
|
|
struct FollowHelper {
|
|
FollowHelper();
|
|
|
|
enum FollowType {
|
|
Rotation = 0,
|
|
Horizontal,
|
|
Vertical,
|
|
NumFollowTypes
|
|
};
|
|
float _timeRemaining[NumFollowTypes];
|
|
|
|
void deactivate();
|
|
void deactivate(FollowType type);
|
|
void activate();
|
|
void activate(FollowType type);
|
|
bool isActive() const;
|
|
bool isActive(FollowType followType) const;
|
|
float getMaxTimeRemaining() const;
|
|
void decrementTimeRemaining(float dt);
|
|
bool shouldActivateRotation(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const;
|
|
bool shouldActivateVertical(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const;
|
|
bool shouldActivateHorizontal(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const;
|
|
bool shouldActivateHorizontalCG(MyAvatar& myAvatar) const;
|
|
void prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat4& bodySensorMatrix, const glm::mat4& currentBodyMatrix, bool hasDriveInput);
|
|
glm::mat4 postPhysicsUpdate(MyAvatar& myAvatar, const glm::mat4& currentBodyMatrix);
|
|
bool getForceActivateRotation() const;
|
|
void setForceActivateRotation(bool val);
|
|
bool getForceActivateVertical() const;
|
|
void setForceActivateVertical(bool val);
|
|
bool getForceActivateHorizontal() const;
|
|
void setForceActivateHorizontal(bool val);
|
|
bool getToggleHipsFollowing() const;
|
|
void setToggleHipsFollowing(bool followHead);
|
|
bool _squatDetected { false };
|
|
std::atomic<bool> _forceActivateRotation { false };
|
|
std::atomic<bool> _forceActivateVertical { false };
|
|
std::atomic<bool> _forceActivateHorizontal { false };
|
|
std::atomic<bool> _toggleHipsFollowing { true };
|
|
};
|
|
|
|
FollowHelper _follow;
|
|
|
|
bool isFollowActive(FollowHelper::FollowType followType) const;
|
|
|
|
bool _goToPending { false };
|
|
bool _physicsSafetyPending { false };
|
|
bool _goToSafe { true };
|
|
bool _goToFeetAjustment { false };
|
|
glm::vec3 _goToPosition;
|
|
glm::quat _goToOrientation;
|
|
|
|
std::unordered_set<int> _headBoneSet;
|
|
std::unordered_set<SpatiallyNestablePointer> _cauterizedChildrenOfHead;
|
|
bool _prevShouldDrawHead;
|
|
bool _rigEnabled { true };
|
|
|
|
bool _enableDebugDrawBaseOfSupport { false };
|
|
bool _enableDebugDrawDefaultPose { false };
|
|
bool _enableDebugDrawAnimPose { false };
|
|
bool _enableDebugDrawHandControllers { false };
|
|
bool _enableDebugDrawSensorToWorldMatrix { false };
|
|
bool _enableDebugDrawIKTargets { false };
|
|
bool _enableDebugDrawIKConstraints { false };
|
|
bool _enableDebugDrawIKChains { false };
|
|
bool _enableDebugDrawDetailedCollision { false };
|
|
|
|
mutable bool _cauterizationNeedsUpdate; // do we need to scan children and update their "cauterized" state?
|
|
|
|
AudioListenerMode _audioListenerMode;
|
|
glm::vec3 _customListenPosition;
|
|
glm::quat _customListenOrientation;
|
|
|
|
AtRestDetector _leftHandAtRestDetector;
|
|
AtRestDetector _rightHandAtRestDetector;
|
|
|
|
// all poses are in sensor-frame
|
|
std::map<controller::Action, controller::Pose> _controllerPoseMap;
|
|
mutable std::mutex _controllerPoseMapMutex;
|
|
mutable std::mutex _disableHandTouchMutex;
|
|
|
|
bool _centerOfGravityModelEnabled { true };
|
|
bool _hmdLeanRecenterEnabled { true };
|
|
bool _sprint { false };
|
|
|
|
AnimPose _prePhysicsRoomPose;
|
|
std::mutex _holdActionsMutex;
|
|
std::vector<AvatarActionHold*> _holdActions;
|
|
|
|
float AVATAR_MOVEMENT_ENERGY_CONSTANT { 0.001f };
|
|
float AUDIO_ENERGY_CONSTANT { 0.000001f };
|
|
float MAX_AVATAR_MOVEMENT_PER_FRAME { 30.0f };
|
|
float currentEnergy { 0.0f };
|
|
float energyChargeRate { 0.003f };
|
|
glm::vec3 priorVelocity;
|
|
glm::vec3 lastPosition;
|
|
float getAudioEnergy();
|
|
float getAccelerationEnergy();
|
|
float getEnergy();
|
|
void setEnergy(float value);
|
|
bool didTeleport();
|
|
bool getIsAway() const { return _isAway; }
|
|
void setAway(bool value);
|
|
|
|
std::mutex _pinnedJointsMutex;
|
|
std::vector<int> _pinnedJoints;
|
|
|
|
void updateChildCauterization(SpatiallyNestablePointer object, bool cauterize);
|
|
|
|
// height of user in sensor space, when standing erect.
|
|
ThreadSafeValueCache<float> _userHeight { DEFAULT_AVATAR_HEIGHT };
|
|
float _averageUserHeightSensorSpace { _userHeight.get() };
|
|
bool _sitStandStateChange { false };
|
|
ThreadSafeValueCache<bool> _lockSitStandState { false };
|
|
|
|
// max unscaled forward movement speed
|
|
ThreadSafeValueCache<float> _walkSpeed { DEFAULT_AVATAR_MAX_WALKING_SPEED };
|
|
ThreadSafeValueCache<float> _walkBackwardSpeed { DEFAULT_AVATAR_MAX_WALKING_BACKWARD_SPEED };
|
|
ThreadSafeValueCache<float> _sprintSpeed { AVATAR_SPRINT_SPEED_SCALAR };
|
|
float _walkSpeedScalar { AVATAR_WALK_SPEED_SCALAR };
|
|
bool _isInWalkingState { false };
|
|
ThreadSafeValueCache<bool> _isInSittingState { false };
|
|
ThreadSafeValueCache<MyAvatar::SitStandModelType> _userRecenterModel { MyAvatar::SitStandModelType::Auto };
|
|
float _sitStandStateTimer { 0.0f };
|
|
float _squatTimer { 0.0f };
|
|
float _tippingPoint { _userHeight.get() };
|
|
|
|
// load avatar scripts once when rig is ready
|
|
bool _shouldLoadScripts { false };
|
|
|
|
bool _haveReceivedHeightLimitsFromDomain { false };
|
|
int _disableHandTouchCount { 0 };
|
|
bool _skeletonModelLoaded { false };
|
|
bool _reloadAvatarEntityDataFromSettings { true };
|
|
|
|
TimePoint _nextTraitsSendWindow;
|
|
|
|
Setting::Handle<QString> _dominantHandSetting;
|
|
Setting::Handle<float> _headPitchSetting;
|
|
Setting::Handle<float> _scaleSetting;
|
|
Setting::Handle<float> _yawSpeedSetting;
|
|
Setting::Handle<float> _pitchSpeedSetting;
|
|
Setting::Handle<QUrl> _fullAvatarURLSetting;
|
|
Setting::Handle<QUrl> _fullAvatarModelNameSetting;
|
|
Setting::Handle<QUrl> _animGraphURLSetting;
|
|
Setting::Handle<QString> _displayNameSetting;
|
|
Setting::Handle<QUrl> _collisionSoundURLSetting;
|
|
Setting::Handle<bool> _useSnapTurnSetting;
|
|
Setting::Handle<float> _userHeightSetting;
|
|
Setting::Handle<bool> _flyingHMDSetting;
|
|
Setting::Handle<int> _avatarEntityCountSetting;
|
|
Setting::Handle<bool> _allowTeleportingSetting { "allowTeleporting", true };
|
|
std::vector<Setting::Handle<QUuid>> _avatarEntityIDSettings;
|
|
std::vector<Setting::Handle<QByteArray>> _avatarEntityDataSettings;
|
|
|
|
// AvatarEntities stuff:
|
|
// We cache the "map of unfortunately-formatted-binary-blobs" because they are expensive to compute
|
|
// Do not confuse these with AvatarData::_packedAvatarEntityData which are in wire-format.
|
|
mutable AvatarEntityMap _cachedAvatarEntityBlobs;
|
|
|
|
// We collect changes to AvatarEntities and then handle them all in one spot per frame: updateAvatarEntities().
|
|
// Basically this is a "transaction pattern" with an extra complication: these changes can come from two
|
|
// "directions" and the "authoritative source" of each direction is different, so maintain two distinct sets of
|
|
// transaction lists;
|
|
//
|
|
// The _entitiesToDelete/Add/Update lists are for changes whose "authoritative sources" are already
|
|
// correctly stored in _cachedAvatarEntityBlobs. These come from loadAvatarEntityDataFromSettings() and
|
|
// setAvatarEntityData(). These changes need to be extracted from _cachedAvatarEntityBlobs and applied to
|
|
// real EntityItems.
|
|
std::vector<QUuid> _entitiesToDelete;
|
|
std::vector<QUuid> _entitiesToAdd;
|
|
std::vector<QUuid> _entitiesToUpdate;
|
|
//
|
|
// The _cachedAvatarEntityBlobsToDelete/Add/Update lists are for changes whose "authoritative sources" are
|
|
// already reflected in real EntityItems. These changes need to be propagated to _cachedAvatarEntityBlobs
|
|
// and eventually to settings.
|
|
std::vector<QUuid> _cachedAvatarEntityBlobsToDelete;
|
|
std::vector<QUuid> _cachedAvatarEntityBlobsToAddOrUpdate;
|
|
std::vector<QUuid> _cachedAvatarEntityBlobUpdatesToSkip;
|
|
//
|
|
// Also these lists for tracking delayed changes to blobs and Settings
|
|
mutable std::set<QUuid> _staleCachedAvatarEntityBlobs;
|
|
//
|
|
// keep a ScriptEngine around so we don't have to instantiate on the fly (these are very slow to create/delete)
|
|
QScriptEngine* _myScriptEngine { nullptr };
|
|
bool _needToSaveAvatarEntitySettings { false };
|
|
};
|
|
|
|
QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode);
|
|
void audioListenModeFromScriptValue(const QScriptValue& object, AudioListenerMode& audioListenerMode);
|
|
|
|
QScriptValue driveKeysToScriptValue(QScriptEngine* engine, const MyAvatar::DriveKeys& driveKeys);
|
|
void driveKeysFromScriptValue(const QScriptValue& object, MyAvatar::DriveKeys& driveKeys);
|
|
|
|
bool isWearableEntity(const EntityItemPointer& entity);
|
|
|
|
#endif // hifi_MyAvatar_h
|