diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 2003dd7a5f..2ada31e1ed 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -79,6 +79,8 @@ float DEFAULT_SCRIPTED_MOTOR_TIMESCALE = 1.0e6f; const int SCRIPTED_MOTOR_CAMERA_FRAME = 0; const int SCRIPTED_MOTOR_AVATAR_FRAME = 1; const int SCRIPTED_MOTOR_WORLD_FRAME = 2; +const int SCRIPTED_MOTOR_SIMPLE_MODE = 0; +const int SCRIPTED_MOTOR_DYNAMIC_MODE = 1; const QString& DEFAULT_AVATAR_COLLISION_SOUND_URL = "https://hifi-public.s3.amazonaws.com/sounds/Collisions-otherorganic/Body_Hits_Impact.wav"; const float MyAvatar::ZOOM_MIN = 0.5f; @@ -92,6 +94,7 @@ MyAvatar::MyAvatar(QThread* thread) : _pitchSpeed(PITCH_SPEED_DEFAULT), _scriptedMotorTimescale(DEFAULT_SCRIPTED_MOTOR_TIMESCALE), _scriptedMotorFrame(SCRIPTED_MOTOR_CAMERA_FRAME), + _scriptedMotorMode(SCRIPTED_MOTOR_SIMPLE_MODE), _motionBehaviors(AVATAR_MOTION_DEFAULTS), _characterController(this), _eyeContactTarget(LEFT_EYE), @@ -1625,20 +1628,27 @@ controller::Pose MyAvatar::getControllerPoseInAvatarFrame(controller::Action act void MyAvatar::updateMotors() { _characterController.clearMotors(); glm::quat motorRotation; + + const float FLYING_MOTOR_TIMESCALE = 0.05f; + const float WALKING_MOTOR_TIMESCALE = 0.2f; + const float INVALID_MOTOR_TIMESCALE = 1.0e6f; + + float horizontalMotorTimescale; + float verticalMotorTimescale; + + if (_characterController.getState() == CharacterController::State::Hover || + _characterController.computeCollisionGroup() == BULLET_COLLISION_GROUP_COLLISIONLESS) { + horizontalMotorTimescale = FLYING_MOTOR_TIMESCALE; + verticalMotorTimescale = FLYING_MOTOR_TIMESCALE; + } else { + horizontalMotorTimescale = WALKING_MOTOR_TIMESCALE; + verticalMotorTimescale = INVALID_MOTOR_TIMESCALE; + } + if (_motionBehaviors & AVATAR_MOTION_ACTION_MOTOR_ENABLED) { - - const float FLYING_MOTOR_TIMESCALE = 0.05f; - const float WALKING_MOTOR_TIMESCALE = 0.2f; - const float INVALID_MOTOR_TIMESCALE = 1.0e6f; - - float horizontalMotorTimescale; - float verticalMotorTimescale; - if (_characterController.getState() == CharacterController::State::Hover || _characterController.computeCollisionGroup() == BULLET_COLLISION_GROUP_COLLISIONLESS) { motorRotation = getMyHead()->getHeadOrientation(); - horizontalMotorTimescale = FLYING_MOTOR_TIMESCALE; - verticalMotorTimescale = FLYING_MOTOR_TIMESCALE; } else { // non-hovering = walking: follow camera twist about vertical but not lift // we decompose camera's rotation and store the twist part in motorRotation @@ -1649,8 +1659,6 @@ void MyAvatar::updateMotors() { glm::quat liftRotation; swingTwistDecomposition(headOrientation, Vectors::UNIT_Y, liftRotation, motorRotation); motorRotation = orientation * motorRotation; - horizontalMotorTimescale = WALKING_MOTOR_TIMESCALE; - verticalMotorTimescale = INVALID_MOTOR_TIMESCALE; } if (_isPushing || _isBraking || !_isBeingPushed) { @@ -1670,7 +1678,12 @@ void MyAvatar::updateMotors() { // world-frame motorRotation = glm::quat(); } - _characterController.addMotor(_scriptedMotorVelocity, motorRotation, _scriptedMotorTimescale); + if (_scriptedMotorMode == SCRIPTED_MOTOR_SIMPLE_MODE) { + _characterController.addMotor(_scriptedMotorVelocity, motorRotation, _scriptedMotorTimescale); + } else { + // dynamic mode + _characterController.addMotor(_scriptedMotorVelocity, motorRotation, horizontalMotorTimescale, verticalMotorTimescale); + } } // legacy support for 'MyAvatar::applyThrust()', which has always been implemented as a @@ -1754,6 +1767,14 @@ QString MyAvatar::getScriptedMotorFrame() const { return frame; } +QString MyAvatar::getScriptedMotorMode() const { + QString mode = "simple"; + if (_scriptedMotorMode == SCRIPTED_MOTOR_DYNAMIC_MODE) { + mode = "dynamic"; + } + return mode; +} + void MyAvatar::setScriptedMotorVelocity(const glm::vec3& velocity) { float MAX_SCRIPTED_MOTOR_SPEED = 500.0f; _scriptedMotorVelocity = velocity; @@ -1780,6 +1801,14 @@ void MyAvatar::setScriptedMotorFrame(QString frame) { } } +void MyAvatar::setScriptedMotorMode(QString mode) { + if (mode.toLower() == "simple") { + _scriptedMotorMode = SCRIPTED_MOTOR_SIMPLE_MODE; + } else if (mode.toLower() == "dynamic") { + _scriptedMotorMode = SCRIPTED_MOTOR_DYNAMIC_MODE; + } +} + void MyAvatar::clearScriptableSettings() { _scriptedMotorVelocity = Vectors::ZERO; _scriptedMotorTimescale = DEFAULT_SCRIPTED_MOTOR_TIMESCALE; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index a62bc1a109..2615f8fa0f 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -69,6 +69,7 @@ class MyAvatar : public Avatar { * @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 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. @@ -124,6 +125,7 @@ class MyAvatar : public Avatar { 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) @@ -662,9 +664,11 @@ private: 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); 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, @@ -704,6 +708,7 @@ private: 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;