diff --git a/interface/resources/qml/hifi/dialogs/AvatarPreferencesDialog.qml b/interface/resources/qml/hifi/dialogs/AvatarPreferencesDialog.qml index 7aa19001e7..bc5d827ead 100644 --- a/interface/resources/qml/hifi/dialogs/AvatarPreferencesDialog.qml +++ b/interface/resources/qml/hifi/dialogs/AvatarPreferencesDialog.qml @@ -7,7 +7,7 @@ PreferencesDialog { id: root objectName: "AvatarPreferencesDialog" title: "Avatar Preferences" - showCategories: [ "Avatar Basics", "Avatar Tuning" ] + showCategories: [ "Avatar Basics", "Avatar Tuning", "Avatar Camera" ] property var settings: Settings { category: root.objectName property alias x: root.x diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 7a32e81923..e5f6de3ae1 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -250,10 +250,10 @@ Menu::Menu() { // View > Mini Mirror addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::MiniMirror, 0, false); - // View > Center Player In View - addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::CenterPlayerInView, - 0, true, qApp, SLOT(rotationModeChanged()), - UNSPECIFIED_POSITION, "Advanced"); + // View > Center Player In View + addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::CenterPlayerInView, + 0, true, qApp, SLOT(rotationModeChanged()), + UNSPECIFIED_POSITION, "Advanced"); // Navigate menu ---------------------------------- diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 3e54ba99b9..40290ea188 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -56,14 +56,15 @@ using namespace std; const glm::vec3 DEFAULT_UP_DIRECTION(0.0f, 1.0f, 0.0f); -const float YAW_SPEED = 150.0f; // degrees/sec -const float PITCH_SPEED = 100.0f; // degrees/sec const float DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES = 30.0f; const float MAX_WALKING_SPEED = 2.5f; // human walking speed const float MAX_BOOST_SPEED = 0.5f * MAX_WALKING_SPEED; // keyboard motor gets additive boost below this speed const float MIN_AVATAR_SPEED = 0.05f; // speed is set to zero below this +const float YAW_SPEED_DEFAULT = 66.0f; // degrees/sec +const float PITCH_SPEED_DEFAULT = 55.0f; // degrees/sec + // TODO: normalize avatar speed for standard avatar size, then scale all motion logic // to properly follow avatar size. float MAX_AVATAR_SPEED = 30.0f; @@ -85,6 +86,8 @@ MyAvatar::MyAvatar(RigPointer rig) : _wasPushing(false), _isPushing(false), _isBraking(false), + _yawSpeed(YAW_SPEED_DEFAULT), + _pitchSpeed(PITCH_SPEED_DEFAULT), _boomLength(ZOOM_DEFAULT), _thrust(0.0f), _keyboardMotorVelocity(0.0f), @@ -1330,7 +1333,7 @@ bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const { void MyAvatar::updateOrientation(float deltaTime) { // Smoothly rotate body with arrow keys - float targetSpeed = _driveKeys[YAW] * YAW_SPEED; + float targetSpeed = _driveKeys[YAW] * _yawSpeed; if (targetSpeed != 0.0f) { const float ROTATION_RAMP_TIMESCALE = 0.1f; float blend = deltaTime / ROTATION_RAMP_TIMESCALE; @@ -1366,7 +1369,7 @@ void MyAvatar::updateOrientation(float deltaTime) { // update body orientation by movement inputs setOrientation(getOrientation() * glm::quat(glm::radians(glm::vec3(0.0f, totalBodyYaw, 0.0f)))); - getHead()->setBasePitch(getHead()->getBasePitch() + _driveKeys[PITCH] * PITCH_SPEED * deltaTime); + getHead()->setBasePitch(getHead()->getBasePitch() + _driveKeys[PITCH] * _pitchSpeed * deltaTime); if (qApp->getAvatarUpdater()->isHMDMode()) { glm::quat orientation = glm::quat_cast(getSensorToWorldMatrix()) * getHMDSensorOrientation(); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index ed6c3cb883..eac6ee3e74 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -110,10 +110,11 @@ public: // This is so the correct camera can be used for rendering. void updateSensorToWorldMatrix(); - void setLeanScale(float scale) { _leanScale = scale; } void setRealWorldFieldOfView(float realWorldFov) { _realWorldFieldOfView.set(realWorldFov); } + void setLeanScale(float scale) { _leanScale = scale; } float getLeanScale() const { return _leanScale; } + Q_INVOKABLE glm::vec3 getDefaultEyePosition() const; float getRealWorldFieldOfView() { return _realWorldFieldOfView.get(); } @@ -219,6 +220,12 @@ public: 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; @@ -323,6 +330,8 @@ private: bool _isBraking; float _boomLength; + float _yawSpeed; // degrees/sec + float _pitchSpeed; // degrees/sec glm::vec3 _thrust; // impulse accumulator for outside sources diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index b25fe6775a..d9a40e3a76 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -191,6 +191,24 @@ void setupPreferences() { preferences->addPreference(preference); } + static const QString AVATAR_CAMERA { "Avatar Camera" }; + { + auto getter = [=]()->float { return myAvatar->getPitchSpeed(); }; + auto setter = [=](float value) { myAvatar->setPitchSpeed(value); }; + auto preference = new SpinnerPreference(AVATAR_CAMERA, "Camera Pitch Speed (degrees/second)", getter, setter); + preference->setMin(1); + preference->setMax(360); + preferences->addPreference(preference); + } + { + auto getter = [=]()->float { return myAvatar->getYawSpeed(); }; + auto setter = [=](float value) { myAvatar->setYawSpeed(value); }; + auto preference = new SpinnerPreference(AVATAR_CAMERA, "Camera Yaw Speed (degrees/second)", getter, setter); + preference->setMin(1); + preference->setMax(360); + preferences->addPreference(preference); + } + static const QString AUDIO("Audio"); { auto getter = []()->bool {return DependencyManager::get()->getReceivedAudioStream().getDynamicJitterBuffers(); };