diff --git a/examples/swissArmyJetpack.js b/examples/swissArmyJetpack.js new file mode 100644 index 0000000000..9bb5bea267 --- /dev/null +++ b/examples/swissArmyJetpack.js @@ -0,0 +1,142 @@ +// +// swissArmyJetpack.js +// examples +// +// Created by Andrew Meadows 2014.04.24 +// Copyright 2014 High Fidelity, Inc. +// +// This is a work in progress. It will eventually be able to move the avatar around, +// toggle collision groups, modify avatar movement options, and other stuff (maybe trigger animations). +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var numberOfButtons = 3; + +var enabledColors = new Array(); +enabledColors[0] = { red: 255, green: 0, blue: 0}; +enabledColors[1] = { red: 0, green: 255, blue: 0}; +enabledColors[2] = { red: 0, green: 0, blue: 255}; + +var disabledColors = new Array(); +disabledColors[0] = { red: 90, green: 75, blue: 75}; +disabledColors[1] = { red: 75, green: 90, blue: 75}; +disabledColors[2] = { red: 75, green: 90, blue: 90}; + +var buttons = new Array(); +var labels = new Array(); + +var labelContents = new Array(); +labelContents[0] = "Collide with Avatars"; +labelContents[1] = "Collide with Voxels"; +labelContents[2] = "Collide with Particles"; +var groupBits = 0; + +var buttonStates = new Array(); + +var disabledOffsetT = 0; +var enabledOffsetT = 55; + +var buttonX = 50; +var buttonY = 200; +var buttonWidth = 30; +var buttonHeight = 54; +var textX = buttonX + buttonWidth + 10; + +for (i = 0; i < numberOfButtons; i++) { + var offsetS = 12 + var offsetT = disabledOffsetT; + + buttons[i] = Overlays.addOverlay("image", { + //x: buttonX + (buttonWidth * i), + x: buttonX, + y: buttonY + (buttonHeight * i), + width: buttonWidth, + height: buttonHeight, + subImage: { x: offsetS, y: offsetT, width: buttonWidth, height: buttonHeight }, + imageURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/testing-swatches.svg", + color: disabledColors[i], + alpha: 1, + }); + + labels[i] = Overlays.addOverlay("text", { + x: textX, + y: buttonY + (buttonHeight * i) + 12, + width: 150, + height: 50, + color: { red: 0, green: 0, blue: 0}, + textColor: { red: 255, green: 0, blue: 0}, + topMargin: 4, + leftMargin: 4, + text: labelContents[i] + }); + + buttonStates[i] = false; +} + +function updateButton(i, enabled) { + var offsetY = disabledOffsetT; + var buttonColor = disabledColors[i]; + groupBits + if (enabled) { + offsetY = enabledOffsetT; + buttonColor = enabledColors[i]; + if (i == 0) { + groupBits |= COLLISION_GROUP_AVATARS; + } else if (i == 1) { + groupBits |= COLLISION_GROUP_VOXELS; + } else if (i == 2) { + groupBits |= COLLISION_GROUP_PARTICLES; + } + } else { + if (i == 0) { + groupBits &= ~COLLISION_GROUP_AVATARS; + } else if (i == 1) { + groupBits &= ~COLLISION_GROUP_VOXELS; + } else if (i == 2) { + groupBits &= ~COLLISION_GROUP_PARTICLES; + } + } + MyAvatar.collisionGroups = groupBits; + + Overlays.editOverlay(buttons[i], { subImage: { y: offsetY } } ); + Overlays.editOverlay(buttons[i], { color: buttonColor } ); + buttonStates[i] = enabled; +} + +// When our script shuts down, we should clean up all of our overlays +function scriptEnding() { + for (i = 0; i < numberOfButtons; i++) { + print("adebug deleting overlay " + i); + Overlays.deleteOverlay(buttons[i]); + Overlays.deleteOverlay(labels[i]); + } +} +Script.scriptEnding.connect(scriptEnding); + + +// Our update() function is called at approximately 60fps, and we will use it to animate our various overlays +function update(deltaTime) { + if (groupBits != MyAvatar.collisionGroups) { + groupBits = MyAvatar.collisionGroups; + updateButton(0, groupBits & COLLISION_GROUP_AVATARS); + updateButton(1, groupBits & COLLISION_GROUP_VOXELS); + updateButton(2, groupBits & COLLISION_GROUP_PARTICLES); + } +} +Script.update.connect(update); + + +// we also handle click detection in our mousePressEvent() +function mousePressEvent(event) { + var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); + for (i = 0; i < numberOfButtons; i++) { + if (clickedOverlay == buttons[i]) { + var enabled = !(buttonStates[i]); + updateButton(i, enabled); + } + } +} +Controller.mousePressEvent.connect(mousePressEvent); + diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ab505ede93..97b5c05f25 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -857,7 +857,7 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_G: if (isShifted) { - Menu::getInstance()->triggerOption(MenuOption::Gravity); + Menu::getInstance()->triggerOption(MenuOption::ObeyGravity); } break; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 5006bec608..44117df55c 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -187,9 +187,9 @@ Menu::Menu() : QAction::PreferencesRole); addDisabledActionAndSeparator(editMenu, "Physics"); - addCheckableActionToQMenuAndActionHash(editMenu, MenuOption::Gravity, Qt::SHIFT | Qt::Key_G, false); - - + QObject* avatar = appInstance->getAvatar(); + addCheckableActionToQMenuAndActionHash(editMenu, MenuOption::ObeyGravity, Qt::SHIFT | Qt::Key_G, true, + avatar, SLOT(updateMotionBehaviorFlags())); addAvatarCollisionSubMenu(editMenu); @@ -508,7 +508,7 @@ 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. MyAvatar* myAvatar = Application::getInstance()->getAvatar(); - myAvatar->updateCollisionFlags(); + myAvatar->updateCollisionGroups(); if (lockedSettings) { Application::getInstance()->unlockSettings(); @@ -1381,13 +1381,13 @@ void Menu::addAvatarCollisionSubMenu(QMenu* overMenu) { Application* appInstance = Application::getInstance(); QObject* avatar = appInstance->getAvatar(); addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithEnvironment, - 0, false, avatar, SLOT(updateCollisionFlags())); + 0, false, avatar, SLOT(updateCollisionGroups())); addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithAvatars, - 0, true, avatar, SLOT(updateCollisionFlags())); + 0, true, avatar, SLOT(updateCollisionGroups())); addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithVoxels, - 0, false, avatar, SLOT(updateCollisionFlags())); + 0, false, avatar, SLOT(updateCollisionGroups())); addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithParticles, - 0, true, avatar, SLOT(updateCollisionFlags())); + 0, true, avatar, SLOT(updateCollisionGroups())); } QAction* Menu::getActionFromName(const QString& menuName, QMenu* menu) { diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 88de62a260..bc70f8f83f 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -315,7 +315,7 @@ namespace MenuOption { const QString GoTo = "Go To..."; const QString GoToDomain = "Go To Domain..."; const QString GoToLocation = "Go To Location..."; - const QString Gravity = "Use Gravity"; + const QString ObeyGravity = "Obey Gravity"; const QString HandsCollideWithSelf = "Collide With Self"; const QString HeadMouse = "Head Mouse"; const QString IncreaseAvatarSize = "Increase Avatar Size"; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index fe685b89f8..b060c3421a 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -47,16 +47,14 @@ Avatar::Avatar() : AvatarData(), _skeletonModel(this), _bodyYawDelta(0.0f), - _mode(AVATAR_MODE_STANDING), _velocity(0.0f, 0.0f, 0.0f), - _thrust(0.0f, 0.0f, 0.0f), _leanScale(0.5f), _scale(1.0f), _worldUpDirection(DEFAULT_UP_DIRECTION), _mouseRayOrigin(0.0f, 0.0f, 0.0f), _mouseRayDirection(0.0f, 0.0f, 0.0f), _moving(false), - _collisionFlags(0), + _collisionGroups(0), _initialized(false), _shouldRenderBillboard(true) { @@ -138,20 +136,9 @@ void Avatar::simulate(float deltaTime) { head->simulate(deltaTime, false, _shouldRenderBillboard); } - // use speed and angular velocity to determine walking vs. standing - float speed = glm::length(_velocity); - if (speed + fabs(_bodyYawDelta) > 0.2) { - _mode = AVATAR_MODE_WALKING; - } else { - _mode = AVATAR_MODE_INTERACTING; - } - // update position by velocity, and subtract the change added earlier for gravity _position += _velocity * deltaTime; - // Zero thrust out now that we've added it to velocity in this frame - _thrust = glm::vec3(0, 0, 0); - // update animation for display name fade in/out if ( _displayNameTargetAlpha != _displayNameAlpha) { // the alpha function is @@ -166,7 +153,7 @@ void Avatar::simulate(float deltaTime) { // Fading in _displayNameAlpha = 1 - (1 - _displayNameAlpha) * coef; } - _displayNameAlpha = abs(_displayNameAlpha - _displayNameTargetAlpha) < 0.01? _displayNameTargetAlpha : _displayNameAlpha; + _displayNameAlpha = abs(_displayNameAlpha - _displayNameTargetAlpha) < 0.01f ? _displayNameTargetAlpha : _displayNameAlpha; } } @@ -563,7 +550,7 @@ bool Avatar::findCollisions(const QVector& shapes, CollisionList& } bool Avatar::findParticleCollisions(const glm::vec3& particleCenter, float particleRadius, CollisionList& collisions) { - if (_collisionFlags & COLLISION_GROUP_PARTICLES) { + if (_collisionGroups & COLLISION_GROUP_PARTICLES) { return false; } bool collided = false; @@ -753,19 +740,19 @@ void Avatar::renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, glEnd(); } -void Avatar::updateCollisionFlags() { - _collisionFlags = 0; +void Avatar::updateCollisionGroups() { + _collisionGroups = 0; if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithEnvironment)) { - _collisionFlags |= COLLISION_GROUP_ENVIRONMENT; + _collisionGroups |= COLLISION_GROUP_ENVIRONMENT; } if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithAvatars)) { - _collisionFlags |= COLLISION_GROUP_AVATARS; + _collisionGroups |= COLLISION_GROUP_AVATARS; } if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithVoxels)) { - _collisionFlags |= COLLISION_GROUP_VOXELS; + _collisionGroups |= COLLISION_GROUP_VOXELS; } if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithParticles)) { - _collisionFlags |= COLLISION_GROUP_PARTICLES; + _collisionGroups |= COLLISION_GROUP_PARTICLES; } } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index ecf1be4899..bcf3487e09 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -46,13 +46,6 @@ enum DriveKeys { MAX_DRIVE_KEYS }; -enum AvatarMode { - AVATAR_MODE_STANDING = 0, - AVATAR_MODE_WALKING, - AVATAR_MODE_INTERACTING, - NUM_AVATAR_MODES -}; - enum ScreenTintLayer { SCREEN_TINT_BEFORE_LANDSCAPE = 0, SCREEN_TINT_BEFORE_AVATARS, @@ -70,6 +63,7 @@ class Texture; class Avatar : public AvatarData { Q_OBJECT + Q_PROPERTY(quint32 collisionGroups READ getCollisionGroups WRITE setCollisionGroups) public: Avatar(); @@ -155,8 +149,11 @@ public: virtual float getBoundingRadius() const; void updateShapePositions(); + quint32 getCollisionGroups() const { return _collisionGroups; } + virtual void setCollisionGroups(quint32 collisionGroups) { _collisionGroups = (collisionGroups & VALID_COLLISION_GROUPS); } + public slots: - void updateCollisionFlags(); + void updateCollisionGroups(); signals: void collisionWithAvatar(const QUuid& myUUID, const QUuid& theirUUID, const CollisionInfo& collision); @@ -164,9 +161,7 @@ signals: protected: SkeletonModel _skeletonModel; float _bodyYawDelta; - AvatarMode _mode; glm::vec3 _velocity; - glm::vec3 _thrust; float _leanScale; float _scale; glm::vec3 _worldUpDirection; @@ -175,7 +170,7 @@ protected: float _stringLength; bool _moving; ///< set when position is changing - uint32_t _collisionFlags; + quint32 _collisionGroups; // protected methods... glm::vec3 getBodyRightDirection() const { return getOrientation() * IDENTITY_RIGHT; } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 140756e9d7..26dbc09d5b 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -55,16 +55,13 @@ MyAvatar::MyAvatar() : _shouldJump(false), _gravity(0.0f, -1.0f, 0.0f), _distanceToNearestAvatar(std::numeric_limits::max()), - _elapsedTimeMoving(0.0f), - _elapsedTimeStopped(0.0f), - _elapsedTimeSinceCollision(0.0f), _lastCollisionPosition(0, 0, 0), _speedBrakes(false), + _thrust(0.0f), _isThrustOn(false), _thrustMultiplier(1.0f), - _moveTarget(0,0,0), + _motionBehaviors(0), _lastBodyPenetration(0.0f), - _moveTargetStepCounter(0), _lookAtTargetAvatar(), _shouldRender(true), _billboardValid(false), @@ -98,11 +95,6 @@ void MyAvatar::reset() { setOrientation(glm::quat(glm::vec3(0.0f))); } -void MyAvatar::setMoveTarget(const glm::vec3 moveTarget) { - _moveTarget = moveTarget; - _moveTargetStepCounter = 0; -} - void MyAvatar::update(float deltaTime) { Head* head = getHead(); head->relaxLean(deltaTime); @@ -133,7 +125,7 @@ void MyAvatar::update(float deltaTime) { head->setAudioLoudness(audio->getLastInputLoudness()); head->setAudioAverageLoudness(audio->getAudioAverageInputLoudness()); - if (Menu::getInstance()->isOptionChecked(MenuOption::Gravity)) { + if (_motionBehaviors & AVATAR_MOTION_OBEY_GRAVITY) { setGravity(Application::getInstance()->getEnvironment()->getGravity(getPosition())); } else { setGravity(glm::vec3(0.0f, 0.0f, 0.0f)); @@ -146,17 +138,6 @@ void MyAvatar::simulate(float deltaTime) { glm::quat orientation = getOrientation(); - // Update movement timers - _elapsedTimeSinceCollision += deltaTime; - const float VELOCITY_MOVEMENT_TIMER_THRESHOLD = 0.2f; - if (glm::length(_velocity) < VELOCITY_MOVEMENT_TIMER_THRESHOLD) { - _elapsedTimeMoving = 0.0f; - _elapsedTimeStopped += deltaTime; - } else { - _elapsedTimeStopped = 0.0f; - _elapsedTimeMoving += deltaTime; - } - if (_scale != _targetScale) { float scale = (1.0f - SMOOTHING_RATIO) * _scale + SMOOTHING_RATIO * _targetScale; setScale(scale); @@ -270,34 +251,11 @@ void MyAvatar::simulate(float deltaTime) { // update the euler angles setOrientation(orientation); - const float WALKING_SPEED_THRESHOLD = 0.2f; - // use speed and angular velocity to determine walking vs. standing - float speed = glm::length(_velocity); - if (speed + fabs(_bodyYawDelta) > WALKING_SPEED_THRESHOLD) { - _mode = AVATAR_MODE_WALKING; - } else { - _mode = AVATAR_MODE_INTERACTING; - } - // update moving flag based on speed const float MOVING_SPEED_THRESHOLD = 0.01f; + float speed = glm::length(_velocity); _moving = speed > MOVING_SPEED_THRESHOLD; - // If a move target is set, update position explicitly - const float MOVE_FINISHED_TOLERANCE = 0.1f; - const float MOVE_SPEED_FACTOR = 2.0f; - const int MOVE_TARGET_MAX_STEPS = 250; - if ((glm::length(_moveTarget) > EPSILON) && (_moveTargetStepCounter < MOVE_TARGET_MAX_STEPS)) { - if (glm::length(_position - _moveTarget) > MOVE_FINISHED_TOLERANCE) { - _position += (_moveTarget - _position) * (deltaTime * MOVE_SPEED_FACTOR); - _moveTargetStepCounter++; - } else { - // Move completed - _moveTarget = glm::vec3(0,0,0); - _moveTargetStepCounter = 0; - } - } - updateChatCircle(deltaTime); _position += _velocity * deltaTime; @@ -325,10 +283,10 @@ void MyAvatar::simulate(float deltaTime) { head->simulate(deltaTime, true); // Zero thrust out now that we've added it to velocity in this frame - _thrust = glm::vec3(0.0f); + _thrust *= glm::vec3(0.0f); // now that we're done stepping the avatar forward in time, compute new collisions - if (_collisionFlags != 0) { + if (_collisionGroups != 0) { Camera* myCamera = Application::getInstance()->getCamera(); float radius = getSkeletonHeight() * COLLISION_RADIUS_SCALE; @@ -336,15 +294,15 @@ void MyAvatar::simulate(float deltaTime) { radius = myCamera->getAspectRatio() * (myCamera->getNearClip() / cos(myCamera->getFieldOfView() / 2.0f)); radius *= COLLISION_RADIUS_SCALAR; } - if (_collisionFlags) { + if (_collisionGroups) { updateShapePositions(); - if (_collisionFlags & COLLISION_GROUP_ENVIRONMENT) { + if (_collisionGroups & COLLISION_GROUP_ENVIRONMENT) { updateCollisionWithEnvironment(deltaTime, radius); } - if (_collisionFlags & COLLISION_GROUP_VOXELS) { + if (_collisionGroups & COLLISION_GROUP_VOXELS) { updateCollisionWithVoxels(deltaTime, radius); } - if (_collisionFlags & COLLISION_GROUP_AVATARS) { + if (_collisionGroups & COLLISION_GROUP_AVATARS) { updateCollisionWithAvatars(deltaTime); } } @@ -452,8 +410,6 @@ void MyAvatar::renderDebugBodyPoints() { glTranslatef(position.x, position.y, position.z); glutSolidSphere(0.15, 10, 10); glPopMatrix(); - - } // virtual @@ -831,7 +787,6 @@ void MyAvatar::applyHardCollision(const glm::vec3& penetration, float elasticity // cancel out the velocity component in the direction of penetration float penetrationLength = glm::length(penetration); if (penetrationLength > EPSILON) { - _elapsedTimeSinceCollision = 0.0f; glm::vec3 direction = penetration / penetrationLength; _velocity -= glm::dot(_velocity, direction) * direction * (1.0f + elasticity); _velocity *= glm::clamp(1.0f - damping, 0.0f, 1.0f); @@ -868,7 +823,7 @@ void MyAvatar::updateCollisionSound(const glm::vec3 &penetration, float deltaTim std::min(COLLISION_LOUDNESS * velocityTowardCollision, 1.0f), frequency * (1.0f + velocityTangentToCollision / velocityTowardCollision), std::min(velocityTangentToCollision / velocityTowardCollision * NOISE_SCALING, 1.0f), - 1.0f - DURATION_SCALING * powf(frequency, 0.5f) / velocityTowardCollision, true); + 1.0f - DURATION_SCALING * powf(frequency, 0.5f) / velocityTowardCollision, false); } } @@ -1188,7 +1143,28 @@ void MyAvatar::goToLocationFromResponse(const QJsonObject& jsonObject) { } else { QMessageBox::warning(Application::getInstance()->getWindow(), "", "That user or location could not be found."); } - +} + +void MyAvatar::updateMotionBehaviors() { + _motionBehaviors = 0; + if (Menu::getInstance()->isOptionChecked(MenuOption::ObeyGravity)) { + _motionBehaviors |= AVATAR_MOTION_OBEY_GRAVITY; + } +} + +void MyAvatar::setCollisionGroups(quint32 collisionGroups) { + Avatar::setCollisionGroups(collisionGroups & VALID_COLLISION_GROUPS); + Menu* menu = Menu::getInstance(); + menu->setIsOptionChecked(MenuOption::CollideWithEnvironment, (bool)(_collisionGroups & COLLISION_GROUP_ENVIRONMENT)); + menu->setIsOptionChecked(MenuOption::CollideWithAvatars, (bool)(_collisionGroups & COLLISION_GROUP_AVATARS)); + menu->setIsOptionChecked(MenuOption::CollideWithVoxels, (bool)(_collisionGroups & COLLISION_GROUP_VOXELS)); + menu->setIsOptionChecked(MenuOption::CollideWithParticles, (bool)(_collisionGroups & COLLISION_GROUP_PARTICLES)); +} + +void MyAvatar::setMotionBehaviors(quint32 flags) { + _motionBehaviors = flags; + Menu* menu = Menu::getInstance(); + menu->setIsOptionChecked(MenuOption::ObeyGravity, (bool)(_motionBehaviors & AVATAR_MOTION_OBEY_GRAVITY)); } void MyAvatar::applyCollision(const glm::vec3& contactPoint, const glm::vec3& penetration) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 71c74f7c91..9b6b13568f 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -25,9 +25,12 @@ enum AvatarHandState NUM_HAND_STATES }; +const quint32 AVATAR_MOTION_OBEY_GRAVITY = 1U << 0; + class MyAvatar : public Avatar { Q_OBJECT Q_PROPERTY(bool shouldRenderLocally READ getShouldRenderLocally WRITE setShouldRenderLocally) + Q_PROPERTY(quint32 motionBehaviors READ getMotionBehaviors WRITE setMotionBehaviors) public: MyAvatar(); @@ -54,10 +57,7 @@ public: void setShouldRenderLocally(bool shouldRender) { _shouldRender = shouldRender; } // getters - AvatarMode getMode() const { return _mode; } float getLeanScale() const { return _leanScale; } - float getElapsedTimeStopped() const { return _elapsedTimeStopped; } - float getElapsedTimeMoving() const { return _elapsedTimeMoving; } const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; } const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; } glm::vec3 getGravity() const { return _gravity; } @@ -91,6 +91,10 @@ public: virtual void setFaceModelURL(const QUrl& faceModelURL); virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); + virtual void setCollisionGroups(quint32 collisionGroups); + void setMotionBehaviors(quint32 flags); + quint32 getMotionBehaviors() const { return _motionBehaviors; } + void applyCollision(const glm::vec3& contactPoint, const glm::vec3& penetration); public slots: @@ -107,6 +111,8 @@ public slots: glm::vec3 getThrust() { return _thrust; }; void setThrust(glm::vec3 newThrust) { _thrust = newThrust; } + void updateMotionBehaviors(); + signals: void transformChanged(); @@ -118,16 +124,17 @@ private: float _driveKeys[MAX_DRIVE_KEYS]; glm::vec3 _gravity; float _distanceToNearestAvatar; // How close is the nearest avatar? - float _elapsedTimeMoving; // Timers to drive camera transitions when moving - float _elapsedTimeStopped; - float _elapsedTimeSinceCollision; + + // motion stuff glm::vec3 _lastCollisionPosition; bool _speedBrakes; + glm::vec3 _thrust; // final acceleration for the current frame bool _isThrustOn; float _thrustMultiplier; - glm::vec3 _moveTarget; + + quint32 _motionBehaviors; + glm::vec3 _lastBodyPenetration; - int _moveTargetStepCounter; QWeakPointer _lookAtTargetAvatar; glm::vec3 _targetAvatarPosition; bool _shouldRender; diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 09c3c63ebd..ed05658538 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -230,8 +231,13 @@ void ScriptEngine::init() { registerGlobalObject("Voxels", &_voxelsScriptingInterface); - QScriptValue treeScaleValue = _engine.newVariant(QVariant(TREE_SCALE)); - _engine.globalObject().setProperty("TREE_SCALE", treeScaleValue); + // constants + QScriptValue globalObject = _engine.globalObject(); + globalObject.setProperty("TREE_SCALE", _engine.newVariant(QVariant(TREE_SCALE))); + globalObject.setProperty("COLLISION_GROUP_ENVIRONMENT", _engine.newVariant(QVariant(COLLISION_GROUP_ENVIRONMENT))); + globalObject.setProperty("COLLISION_GROUP_AVATARS", _engine.newVariant(QVariant(COLLISION_GROUP_AVATARS))); + globalObject.setProperty("COLLISION_GROUP_VOXELS", _engine.newVariant(QVariant(COLLISION_GROUP_VOXELS))); + globalObject.setProperty("COLLISION_GROUP_PARTICLES", _engine.newVariant(QVariant(COLLISION_GROUP_PARTICLES))); // let the VoxelPacketSender know how frequently we plan to call it _voxelsScriptingInterface.getVoxelPacketSender()->setProcessCallIntervalHint(SCRIPT_DATA_CALLBACK_USECS); diff --git a/libraries/shared/src/CollisionInfo.h b/libraries/shared/src/CollisionInfo.h index 7db965fe64..510728daa6 100644 --- a/libraries/shared/src/CollisionInfo.h +++ b/libraries/shared/src/CollisionInfo.h @@ -27,6 +27,7 @@ const quint32 COLLISION_GROUP_ENVIRONMENT = 1U << 0; const quint32 COLLISION_GROUP_AVATARS = 1U << 1; const quint32 COLLISION_GROUP_VOXELS = 1U << 2; const quint32 COLLISION_GROUP_PARTICLES = 1U << 3; +const quint32 VALID_COLLISION_GROUPS = 0x0f; // CollisionInfo contains details about the collision between two things: BodyA and BodyB. // The assumption is that the context that analyzes the collision knows about BodyA but