From 489871d0d6f3917d59116ff567a2b03eeb04ac34 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 16 Sep 2014 17:09:32 -0700 Subject: [PATCH] added MyAvatar.setMotorVelocity() & friends for JS --- interface/src/Application.cpp | 5 +- interface/src/Menu.cpp | 10 +- interface/src/Menu.h | 2 + interface/src/avatar/MyAvatar.cpp | 241 ++++++++++++++++++----------- interface/src/avatar/MyAvatar.h | 20 ++- libraries/avatars/src/AvatarData.h | 13 +- 6 files changed, 187 insertions(+), 104 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 371feeb612..cfd7448fca 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3890,7 +3890,7 @@ void Application::stopAllScripts(bool restart) { // HACK: ATM scripts cannot set/get their animation priorities, so we clear priorities // whenever a script stops in case it happened to have been setting joint rotations. // TODO: expose animation priorities and provide a layered animation control system. - _myAvatar->clearJointAnimationPriorities(); + _myAvatar->clearScriptableSettings(); } void Application::stopScript(const QString &scriptName) { @@ -3903,6 +3903,9 @@ void Application::stopScript(const QString &scriptName) { // TODO: expose animation priorities and provide a layered animation control system. _myAvatar->clearJointAnimationPriorities(); } + if (_scriptEnginesHash.empty()) { + _myAvatar->clearScriptableSettings(); + } } void Application::reloadAllScripts() { diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index d3d1c8c0d0..bccb9a6fed 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -268,13 +268,17 @@ Menu::Menu() : SLOT(resetSize())); QObject* avatar = appInstance->getAvatar(); + addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::KeyboardMotorControl, + Qt::CTRL | Qt::SHIFT | Qt::Key_K, true, avatar, SLOT(updateMotionBehavior())); + addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::ScriptedMotorControl, 0, true, + avatar, SLOT(updateMotionBehavior())); addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::ChatCircling, 0, false); addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::GlowWhenSpeaking, 0, true); addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::BlueSpeechSphere, 0, true); addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::ObeyEnvironmentalGravity, Qt::SHIFT | Qt::Key_G, false, - avatar, SLOT(updateMotionBehaviorsFromMenu())); + avatar, SLOT(updateMotionBehavior())); addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::StandOnNearbyFloors, 0, true, - avatar, SLOT(updateMotionBehaviorsFromMenu())); + avatar, SLOT(updateMotionBehavior())); QMenu* collisionsMenu = avatarMenu->addMenu("Collide With..."); addCheckableActionToQMenuAndActionHash(collisionsMenu, MenuOption::CollideAsRagdoll, 0, false, @@ -744,9 +748,11 @@ void Menu::loadSettings(QSettings* settings) { // MyAvatar caches some menu options, so we have to update them whenever we load settings. // TODO: cache more settings in MyAvatar that are checked with very high frequency. + setIsOptionChecked(MenuOption::KeyboardMotorControl , true); MyAvatar* myAvatar = Application::getInstance()->getAvatar(); myAvatar->updateCollisionGroups(); myAvatar->onToggleRagdoll(); + myAvatar->updateMotionBehavior(); if (lockedSettings) { Application::getInstance()->unlockSettings(); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index b43e7cb75e..54b9c8fe57 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -399,6 +399,7 @@ namespace MenuOption { const QString HeadMouse = "Head Mouse"; const QString IncreaseAvatarSize = "Increase Avatar Size"; const QString IncreaseVoxelSize = "Increase Voxel Size"; + const QString KeyboardMotorControl = "Enable Keyboard Motor Control"; const QString LoadScript = "Open and Run Script File..."; const QString LoadScriptURL = "Open and Run Script from URL..."; const QString LodTools = "LOD Tools"; @@ -437,6 +438,7 @@ namespace MenuOption { const QString RunningScripts = "Running Scripts"; const QString RunTimingTests = "Run Timing Tests"; const QString ScriptEditor = "Script Editor..."; + const QString ScriptedMotorControl = "Enable Scripted Motor Control"; const QString SettingsExport = "Export Settings"; const QString SettingsImport = "Import Settings"; const QString ShowBordersModelNodes = "Show Model Nodes"; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index a178ead3bb..3f24998566 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -54,9 +54,11 @@ const float MAX_WALKING_SPEED = 3.0f * MIN_KEYBOARD_CONTROL_SPEED; // TODO: normalize avatar speed for standard avatar size, then scale all motion logic // to properly follow avatar size. -float DEFAULT_MOTOR_TIMESCALE = 0.25f; float MAX_AVATAR_SPEED = 300.0f; -float MAX_MOTOR_SPEED = MAX_AVATAR_SPEED; +float MAX_KEYBOARD_MOTOR_SPEED = MAX_AVATAR_SPEED; +float DEFAULT_KEYBOARD_MOTOR_TIMESCALE = 0.25f; +float MIN_SCRIPTED_MOTOR_TIMESCALE = 0.005f; +float DEFAULT_SCRIPTED_MOTOR_TIMESCALE = 1.0e6f; MyAvatar::MyAvatar() : Avatar(), @@ -71,9 +73,10 @@ MyAvatar::MyAvatar() : _isBraking(false), _trapDuration(0.0f), _thrust(0.0f), - _motorVelocity(0.0f), - _motorTimescale(DEFAULT_MOTOR_TIMESCALE), - _maxMotorSpeed(MAX_MOTOR_SPEED), + _keyboardMotorVelocity(0.0f), + _keyboardMotorTimescale(DEFAULT_KEYBOARD_MOTOR_TIMESCALE), + _scriptedMotorVelocity(0.0f), + _scriptedMotorTimescale(DEFAULT_SCRIPTED_MOTOR_TIMESCALE), _motionBehaviors(AVATAR_MOTION_DEFAULTS), _lookAtTargetAvatar(), _shouldRender(true), @@ -1027,6 +1030,28 @@ void MyAvatar::setAttachmentData(const QVector& attachmentData) _billboardValid = false; } +void MyAvatar::setMotorVelocity(const glm::vec3& velocity) { + float MAX_SCRIPTED_MOTOR_SPEED = 500.0f; + _scriptedMotorVelocity = velocity; + float speed = glm::length(_scriptedMotorVelocity); + if (speed > MAX_SCRIPTED_MOTOR_SPEED) { + _scriptedMotorVelocity *= MAX_SCRIPTED_MOTOR_SPEED / speed; + } +} + +void MyAvatar::setMotorTimescale(float timescale) { + // we clamp the timescale on the large side (instead of just the low side) to prevent + // obnoxiously large values from introducing NaN into avatar's velocity + _scriptedMotorTimescale = glm::clamp(timescale, MIN_SCRIPTED_MOTOR_TIMESCALE, + DEFAULT_SCRIPTED_MOTOR_TIMESCALE); +} + +void MyAvatar::clearScriptableSettings() { + clearJointAnimationPriorities(); + _scriptedMotorVelocity = glm::vec3(0.0f); + _scriptedMotorTimescale = DEFAULT_SCRIPTED_MOTOR_TIMESCALE; +} + void MyAvatar::attach(const QString& modelURL, const QString& jointName, const glm::vec3& translation, const glm::quat& rotation, float scale, bool allowDuplicates, bool useSaved) { if (QThread::currentThread() != thread()) { @@ -1138,13 +1163,102 @@ void MyAvatar::updateOrientation(float deltaTime) { setOrientation(orientation); } +glm::vec3 MyAvatar::applyKeyboardMotor(float deltaTime, const glm::vec3& localVelocity, bool walkingOnFloor) { + if (! (_motionBehaviors & AVATAR_MOTION_KEYBOARD_MOTOR_ENABLED)) { + return localVelocity; + } + // compute motor efficiency + // The timescale of the motor is the approximate time it takes for the motor to + // accomplish its intended localVelocity. A short timescale makes the motor strong, + // and a long timescale makes it weak. The value of timescale to use depends + // on what the motor is doing: + // + // (1) braking --> short timescale (aggressive motor assertion) + // (2) pushing --> medium timescale (mild motor assertion) + // (3) inactive --> long timescale (gentle friction for low speeds) + float MIN_KEYBOARD_MOTOR_TIMESCALE = 0.125f; + float MAX_KEYBOARD_MOTOR_TIMESCALE = 0.4f; + float MIN_KEYBOARD_BRAKE_SPEED = 0.3f; + float timescale = MAX_KEYBOARD_MOTOR_TIMESCALE; + bool isThrust = (glm::length2(_thrust) > EPSILON); + if (_isPushing || isThrust || + (_scriptedMotorTimescale < MAX_KEYBOARD_MOTOR_TIMESCALE && + _motionBehaviors | AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED)) { + // we don't want to break if anything is pushing the avatar around + timescale = _keyboardMotorTimescale; + _isBraking = false; + } else { + float speed = glm::length(localVelocity); + _isBraking = _wasPushing || (_isBraking && speed > MIN_KEYBOARD_BRAKE_SPEED); + if (_isBraking) { + timescale = MIN_KEYBOARD_MOTOR_TIMESCALE; + } + } + _wasPushing = _isPushing || isThrust; + _isPushing = false; + float motorEfficiency = glm::clamp(deltaTime / timescale, 0.0f, 1.0f); + + float keyboardInput = fabsf(_driveKeys[FWD] - _driveKeys[BACK]) + + (fabsf(_driveKeys[RIGHT] - _driveKeys[LEFT])) + + fabsf(_driveKeys[UP] - _driveKeys[DOWN]); + if (keyboardInput) { + // Compute keyboard input + glm::vec3 front = (_driveKeys[FWD] - _driveKeys[BACK]) * IDENTITY_FRONT; + glm::vec3 right = (_driveKeys[RIGHT] - _driveKeys[LEFT]) * IDENTITY_RIGHT; + glm::vec3 up = (_driveKeys[UP] - _driveKeys[DOWN]) * IDENTITY_UP; + + glm::vec3 direction = front + right + up; + float directionLength = glm::length(direction); + + // Compute motor magnitude + if (directionLength > EPSILON) { + direction /= directionLength; + + // Compute the target keyboard velocity (which ramps up slowly, and damps very quickly) + // the max magnitude of which depends on what we're doing: + float finalMaxMotorSpeed = walkingOnFloor ? _scale * MAX_WALKING_SPEED : _scale * MAX_KEYBOARD_MOTOR_SPEED; + float motorLength = glm::length(_keyboardMotorVelocity); + if (motorLength < _scale * MIN_KEYBOARD_CONTROL_SPEED) { + // an active keyboard motor should never be slower than this + _keyboardMotorVelocity = _scale * MIN_KEYBOARD_CONTROL_SPEED * direction; + motorEfficiency = 1.0f; + } else { + float KEYBOARD_MOTOR_LENGTH_TIMESCALE = 2.0f; + float INCREASE_FACTOR = 1.8f; + motorLength *= 1.0f + glm::clamp(deltaTime / KEYBOARD_MOTOR_LENGTH_TIMESCALE, 0.0f, 1.0f) * INCREASE_FACTOR; + if (motorLength > finalMaxMotorSpeed) { + motorLength = finalMaxMotorSpeed; + } + _keyboardMotorVelocity = motorLength * direction; + } + _isPushing = true; + } + } else { + _keyboardMotorVelocity = glm::vec3(0.0f); + } + + // apply keyboard motor + return localVelocity + motorEfficiency * (_keyboardMotorVelocity - localVelocity); +} + +glm::vec3 MyAvatar::applyScriptedMotor(float deltaTime, const glm::vec3& localVelocity) { + if (! (_motionBehaviors & AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED)) { + return localVelocity; + } + float motorEfficiency = glm::clamp(deltaTime / _scriptedMotorTimescale, 0.0f, 1.0f); + return localVelocity + motorEfficiency * (_scriptedMotorVelocity - localVelocity); +} + const float NEARBY_FLOOR_THRESHOLD = 5.0f; void MyAvatar::updatePosition(float deltaTime) { // check for floor by casting a ray straight down from avatar's position float heightAboveFloor = FLT_MAX; + bool walkingOnFloor = false; const CapsuleShape& boundingShape = _skeletonModel.getBoundingShape(); + const float maxFloorDistance = boundingShape.getBoundingRadius() * NEARBY_FLOOR_THRESHOLD; + RayIntersectionInfo intersection; // NOTE: avatar is center of PhysicsSimulation, so rayStart is the origin for the purposes of the raycast intersection._rayStart = glm::vec3(0.0f); @@ -1153,26 +1267,28 @@ void MyAvatar::updatePosition(float deltaTime) { if (_physicsSimulation.findFloorRayIntersection(intersection)) { // NOTE: heightAboveFloor is the distance between the bottom of the avatar and the floor heightAboveFloor = intersection._hitDistance - boundingShape.getBoundingRadius(); + if (heightAboveFloor < maxFloorDistance) { + walkingOnFloor = true; + } } // velocity is initialized to the measured _velocity but will be modified by friction, external thrust, etc glm::vec3 velocity = _velocity; - bool pushingUp = (_driveKeys[UP] - _driveKeys[DOWN] > 0.0f); - bool walkingOnFloor = false; + bool pushingUp = (_driveKeys[UP] - _driveKeys[DOWN] > 0.0f) || _scriptedMotorVelocity.y > 0.0f; if (_motionBehaviors & AVATAR_MOTION_STAND_ON_NEARBY_FLOORS) { const float MAX_SPEED_UNDER_GRAVITY = 2.0f * _scale * MAX_WALKING_SPEED; if (pushingUp || glm::length2(velocity) > MAX_SPEED_UNDER_GRAVITY * MAX_SPEED_UNDER_GRAVITY) { // we're pushing up or moving quickly, so disable gravity setLocalGravity(glm::vec3(0.0f)); + walkingOnFloor = false; } else { - const float maxFloorDistance = boundingShape.getBoundingRadius() * NEARBY_FLOOR_THRESHOLD; if (heightAboveFloor > maxFloorDistance) { // disable local gravity when floor is too far away setLocalGravity(glm::vec3(0.0f)); + walkingOnFloor = false; } else { // enable gravity - walkingOnFloor = true; setLocalGravity(-_worldUpDirection); } } @@ -1195,59 +1311,23 @@ void MyAvatar::updatePosition(float deltaTime) { velocity += (deltaTime * GRAVITY_EARTH) * _gravity; } - float motorEfficiency = glm::clamp(deltaTime / computeMotorTimescale(velocity), 0.0f, 1.0f); + // rotate velocity into camera frame + glm::quat rotation = getHead()->getCameraOrientation(); + glm::vec3 localVelocity = glm::inverse(rotation) * velocity; - if (_motionBehaviors & AVATAR_MOTION_MOTOR_KEYBOARD_ENABLED) { - float keyboardInput = fabsf(_driveKeys[FWD] - _driveKeys[BACK]) + - (fabsf(_driveKeys[RIGHT] - _driveKeys[LEFT])) + - fabsf(_driveKeys[UP] - _driveKeys[DOWN]); - if (keyboardInput) { - // Compute keyboard input - glm::vec3 front = (_driveKeys[FWD] - _driveKeys[BACK]) * IDENTITY_FRONT; - glm::vec3 right = (_driveKeys[RIGHT] - _driveKeys[LEFT]) * IDENTITY_RIGHT; - glm::vec3 up = (_driveKeys[UP] - _driveKeys[DOWN]) * IDENTITY_UP; - - glm::vec3 direction = front + right + up; - float directionLength = glm::length(direction); - - // Compute motor magnitude - if (directionLength > EPSILON) { - direction /= directionLength; - - // Compute the target keyboard velocity (which ramps up slowly, and damps very quickly) - // the max magnitude of which depends on what we're doing: - float finalMaxMotorSpeed = walkingOnFloor ? _scale * MAX_WALKING_SPEED : _scale * _maxMotorSpeed; - float motorLength = glm::length(_motorVelocity); - if (motorLength < _scale * MIN_KEYBOARD_CONTROL_SPEED) { - // an active keyboard motor should never be slower than this - _motorVelocity = _scale * MIN_KEYBOARD_CONTROL_SPEED * direction; - motorEfficiency = 1.0f; - } else { - float MOTOR_LENGTH_TIMESCALE = 2.0f; - float INCREASE_FACTOR = 1.8f; - motorLength *= 1.0f + glm::clamp(deltaTime / MOTOR_LENGTH_TIMESCALE, 0.0f, 1.0f) * INCREASE_FACTOR; - if (motorLength > finalMaxMotorSpeed) { - motorLength = finalMaxMotorSpeed; - } - _motorVelocity = motorLength * direction; - } - _isPushing = true; - } - } else { - _motorVelocity = glm::vec3(0.0f); - } - } - - glm::vec3 targetVelocity = getHead()->getCameraOrientation() * _motorVelocity; - glm::vec3 deltaVelocity = targetVelocity - velocity; + // apply motors in camera frame + glm::vec3 newLocalVelocity = applyKeyboardMotor(deltaTime, localVelocity, walkingOnFloor); + newLocalVelocity = applyScriptedMotor(deltaTime, newLocalVelocity); if (walkingOnFloor && !pushingUp) { - // remove vertical component of deltaVelocity + // remove any delta component that points into floor + glm::vec3 deltaVelocity = newLocalVelocity - localVelocity; deltaVelocity -= glm::dot(deltaVelocity, _worldUpDirection) * _worldUpDirection; + newLocalVelocity = localVelocity + deltaVelocity; } - // apply motor - velocity += motorEfficiency * deltaVelocity; + // rotate back into world-frame + velocity = rotation * newLocalVelocity; // apply thrust velocity += _thrust * deltaTime; @@ -1282,37 +1362,6 @@ void MyAvatar::updatePosition(float deltaTime) { measureMotionDerivatives(deltaTime); } -float MyAvatar::computeMotorTimescale(const glm::vec3& velocity) { - // The timescale of the motor is the approximate time it takes for the motor to - // accomplish its intended velocity. A short timescale makes the motor strong, - // and a long timescale makes it weak. The value of timescale to use depends - // on what the motor is doing: - // - // (1) braking --> short timescale (aggressive motor assertion) - // (2) pushing --> medium timescale (mild motor assertion) - // (3) inactive --> long timescale (gentle friction for low speeds) - - float MIN_MOTOR_TIMESCALE = 0.125f; - float MAX_MOTOR_TIMESCALE = 0.4f; - float MIN_BRAKE_SPEED = 0.3f; - - float timescale = MAX_MOTOR_TIMESCALE; - bool isThrust = (glm::length2(_thrust) > EPSILON); - if (_isPushing || isThrust) { - timescale = _motorTimescale; - _isBraking = false; - } else { - float speed = glm::length(velocity); - _isBraking = _wasPushing || (_isBraking && speed > MIN_BRAKE_SPEED); - if (_isBraking) { - timescale = MIN_MOTOR_TIMESCALE; - } - } - _wasPushing = _isPushing || isThrust; - _isPushing = false; - return timescale; -} - void MyAvatar::updateCollisionWithEnvironment(float deltaTime, float radius) { glm::vec3 up = getBodyUpDirection(); const float ENVIRONMENT_SURFACE_ELASTICITY = 0.0f; @@ -1432,10 +1481,10 @@ void MyAvatar::updateCollisionWithVoxels(float deltaTime, float radius) { if (highestStep > MIN_STEP_HEIGHT && highestStep < MAX_STEP_HEIGHT && verticalPenetration <= 0.0f) { // we're colliding against an edge - // rotate _motorVelocity into world frame - glm::vec3 targetVelocity = _motorVelocity; + // rotate _keyboardMotorVelocity into world frame + glm::vec3 targetVelocity = _keyboardMotorVelocity; glm::quat rotation = getHead()->getCameraOrientation(); - targetVelocity = rotation * _motorVelocity; + targetVelocity = rotation * _keyboardMotorVelocity; if (_wasPushing && glm::dot(targetVelocity, totalPenetration) > EPSILON) { // we're puhing into the edge, so we want to lift @@ -1786,7 +1835,7 @@ void MyAvatar::goToLocation(const glm::vec3& newPosition, bool hasOrientation, c emit transformChanged(); } -void MyAvatar::updateMotionBehaviorsFromMenu() { +void MyAvatar::updateMotionBehavior() { Menu* menu = Menu::getInstance(); if (menu->isOptionChecked(MenuOption::ObeyEnvironmentalGravity)) { _motionBehaviors |= AVATAR_MOTION_OBEY_ENVIRONMENTAL_GRAVITY; @@ -1809,6 +1858,16 @@ void MyAvatar::updateMotionBehaviorsFromMenu() { if (!(_collisionGroups | COLLISION_GROUP_VOXELS)) { _voxelShapeManager.clearShapes(); } + if (menu->isOptionChecked(MenuOption::KeyboardMotorControl)) { + _motionBehaviors |= AVATAR_MOTION_KEYBOARD_MOTOR_ENABLED; + } else { + _motionBehaviors &= ~AVATAR_MOTION_KEYBOARD_MOTOR_ENABLED; + } + if (menu->isOptionChecked(MenuOption::ScriptedMotorControl)) { + _motionBehaviors |= AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED; + } else { + _motionBehaviors &= ~AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED; + } } void MyAvatar::onToggleRagdoll() { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index d86829ea91..43b0f5fc2c 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -131,6 +131,14 @@ public: void clearJointAnimationPriorities(); + Q_INVOKABLE glm::vec3 getMotorVelocity() const { return _scriptedMotorVelocity; } + Q_INVOKABLE float getTimescale() const { return _scriptedMotorTimescale; } + + Q_INVOKABLE void setMotorVelocity(const glm::vec3& velocity); + Q_INVOKABLE void setMotorTimescale(float timescale); + + void clearScriptableSettings(); + 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 allowDuplicates = false, bool useSaved = true); @@ -163,7 +171,7 @@ public slots: void setVelocity(const glm::vec3 velocity) { _velocity = velocity; } - void updateMotionBehaviorsFromMenu(); + void updateMotionBehavior(); void onToggleRagdoll(); glm::vec3 getLeftPalmPosition(); @@ -202,9 +210,10 @@ private: float _trapDuration; // seconds that avatar has been trapped by collisions glm::vec3 _thrust; // impulse accumulator for outside sources - glm::vec3 _motorVelocity; // intended velocity of avatar motion (relative to what it's standing on) - float _motorTimescale; // timescale for avatar motor to achieve its desired velocity - float _maxMotorSpeed; + glm::vec3 _keyboardMotorVelocity; // target local-frame velocity of avatar (keyboard) + float _keyboardMotorTimescale; // timescale for avatar to achieve its target velocity + glm::vec3 _scriptedMotorVelocity; // target local-frame velocity of avatar (script) + float _scriptedMotorTimescale; // timescale for avatar to achieve its target velocity quint32 _motionBehaviors; QWeakPointer _lookAtTargetAvatar; @@ -221,8 +230,9 @@ private: // private methods void updateOrientation(float deltaTime); + glm::vec3 applyKeyboardMotor(float deltaTime, const glm::vec3& velocity, bool walkingOnFloor); + glm::vec3 applyScriptedMotor(float deltaTime, const glm::vec3& velocity); void updatePosition(float deltaTime); - float computeMotorTimescale(const glm::vec3& velocity); void updateCollisionWithAvatars(float deltaTime); void updateCollisionWithEnvironment(float deltaTime, float radius); void updateCollisionWithVoxels(float deltaTime, float radius); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 5b0c6b97dd..b0b2690fbe 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -55,18 +55,21 @@ typedef unsigned long long quint64; #include "HandData.h" // avatar motion behaviors -const quint32 AVATAR_MOTION_MOTOR_KEYBOARD_ENABLED = 1U << 0; +const quint32 AVATAR_MOTION_KEYBOARD_MOTOR_ENABLED = 1U << 0; +const quint32 AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED = 1U << 1; -const quint32 AVATAR_MOTION_OBEY_ENVIRONMENTAL_GRAVITY = 1U << 1; -const quint32 AVATAR_MOTION_OBEY_LOCAL_GRAVITY = 1U << 2; -const quint32 AVATAR_MOTION_STAND_ON_NEARBY_FLOORS = 1U << 3; +const quint32 AVATAR_MOTION_OBEY_ENVIRONMENTAL_GRAVITY = 1U << 2; +const quint32 AVATAR_MOTION_OBEY_LOCAL_GRAVITY = 1U << 3; +const quint32 AVATAR_MOTION_STAND_ON_NEARBY_FLOORS = 1U << 4; const quint32 AVATAR_MOTION_DEFAULTS = - AVATAR_MOTION_MOTOR_KEYBOARD_ENABLED | + AVATAR_MOTION_KEYBOARD_MOTOR_ENABLED | + AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED | AVATAR_MOTION_STAND_ON_NEARBY_FLOORS; // these bits will be expanded as features are exposed const quint32 AVATAR_MOTION_SCRIPTABLE_BITS = + AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED | AVATAR_MOTION_OBEY_ENVIRONMENTAL_GRAVITY | AVATAR_MOTION_OBEY_LOCAL_GRAVITY | AVATAR_MOTION_STAND_ON_NEARBY_FLOORS;