From ecae89489ee7ee3bff8145637c0d5a44ddccdb9f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 25 Apr 2014 14:13:44 -0700 Subject: [PATCH 01/27] mispelled slot --- interface/src/Menu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 4aeb4dd203..eaa2b29645 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -188,7 +188,7 @@ Menu::Menu() : addDisabledActionAndSeparator(editMenu, "Physics"); QObject* avatar = appInstance->getAvatar(); addCheckableActionToQMenuAndActionHash(editMenu, MenuOption::ObeyGravity, Qt::SHIFT | Qt::Key_G, true, - avatar, SLOT(updateMotionBehaviorFlags())); + avatar, SLOT(updateMotionBehaviors())); addAvatarCollisionSubMenu(editMenu); From 2d5bfc81cdef5b16cd1cd47a5fbcc281fe95d5a7 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 25 Apr 2014 14:14:34 -0700 Subject: [PATCH 02/27] add Vec3.distance(Vec3, Vec3) for JS --- libraries/script-engine/src/Vec3.cpp | 4 ++++ libraries/script-engine/src/Vec3.h | 1 + 2 files changed, 5 insertions(+) diff --git a/libraries/script-engine/src/Vec3.cpp b/libraries/script-engine/src/Vec3.cpp index bab529df1f..badc980913 100644 --- a/libraries/script-engine/src/Vec3.cpp +++ b/libraries/script-engine/src/Vec3.cpp @@ -36,6 +36,10 @@ float Vec3::length(const glm::vec3& v) { return glm::length(v); } +float Vec3::distance(const glm::vec3& v1, const glm::vec3& v2) { + return glm::distance(v1, v2); +} + glm::vec3 Vec3::normalize(const glm::vec3& v) { return glm::normalize(v); } diff --git a/libraries/script-engine/src/Vec3.h b/libraries/script-engine/src/Vec3.h index b30e274d89..e401cd71bd 100644 --- a/libraries/script-engine/src/Vec3.h +++ b/libraries/script-engine/src/Vec3.h @@ -31,6 +31,7 @@ public slots: glm::vec3 sum(const glm::vec3& v1, const glm::vec3& v2); glm::vec3 subtract(const glm::vec3& v1, const glm::vec3& v2); float length(const glm::vec3& v); + float distance(const glm::vec3& v1, const glm::vec3& v2); glm::vec3 normalize(const glm::vec3& v); void print(const QString& lable, const glm::vec3& v); }; From 357aac833e9e8f3eafc1aa1ed3580bc8bc489e0e Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 25 Apr 2014 14:15:40 -0700 Subject: [PATCH 03/27] expose AVATAR_MOTION_OBEY_GRAVITY const to JS --- libraries/script-engine/src/ScriptEngine.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index b923427307..4141b278a2 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -239,6 +239,8 @@ void ScriptEngine::init() { globalObject.setProperty("COLLISION_GROUP_VOXELS", _engine.newVariant(QVariant(COLLISION_GROUP_VOXELS))); globalObject.setProperty("COLLISION_GROUP_PARTICLES", _engine.newVariant(QVariant(COLLISION_GROUP_PARTICLES))); + globalObject.setProperty("AVATAR_MOTION_OBEY_GRAVITY", _engine.newVariant(QVariant(AVATAR_MOTION_OBEY_GRAVITY))); + // let the VoxelPacketSender know how frequently we plan to call it _voxelsScriptingInterface.getVoxelPacketSender()->setProcessCallIntervalHint(SCRIPT_DATA_CALLBACK_USECS); _particlesScriptingInterface.getParticlePacketSender()->setProcessCallIntervalHint(SCRIPT_DATA_CALLBACK_USECS); From c2f1507df12961d9fa726c9d9450bcb5742f3363 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 25 Apr 2014 14:16:42 -0700 Subject: [PATCH 04/27] move AVATAR_MOTION_OBEY_GRAVITY to libs --- interface/src/avatar/MyAvatar.h | 2 -- libraries/avatars/src/AvatarData.h | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 9b6b13568f..8d0b4b99d9 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -25,8 +25,6 @@ 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) diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 250ae07b01..494d86ebda 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -50,6 +50,9 @@ typedef unsigned long long quint64; #include "HeadData.h" #include "HandData.h" +// avatar motion behaviors +const quint32 AVATAR_MOTION_OBEY_GRAVITY = 1U << 0; + // First bitset const int KEY_STATE_START_BIT = 0; // 1st and 2nd bits const int HAND_STATE_START_BIT = 2; // 3rd and 4th bits From 39252a833943685766f161eeabccdc9c1d0a5199 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 25 Apr 2014 14:17:39 -0700 Subject: [PATCH 05/27] swissArmyJetpack.js now toggles "obey gravity" --- examples/swissArmyJetpack.js | 82 ++++++++++++++++++++++++++++-------- 1 file changed, 65 insertions(+), 17 deletions(-) diff --git a/examples/swissArmyJetpack.js b/examples/swissArmyJetpack.js index 9bb5bea267..719a6f620c 100644 --- a/examples/swissArmyJetpack.js +++ b/examples/swissArmyJetpack.js @@ -13,6 +13,9 @@ // var numberOfButtons = 3; +var DOWN = { x: 0.0, y: -1.0, z: 0.0 }; +var MAX_VOXEL_SCAN_DISTANCE = 20.0; +var MIN_FLYING_SPEED = 1.0; var enabledColors = new Array(); enabledColors[0] = { red: 255, green: 0, blue: 0}; @@ -35,26 +38,42 @@ var groupBits = 0; var buttonStates = new Array(); -var disabledOffsetT = 0; -var enabledOffsetT = 55; +var disabledOffsetT = 12; +var enabledOffsetT = 55 + 12; -var buttonX = 50; -var buttonY = 200; -var buttonWidth = 30; -var buttonHeight = 54; -var textX = buttonX + buttonWidth + 10; +var UI_BUFFER = 1; +var OFFSET_X = UI_BUFFER; +var OFFSET_Y = 200; +var BUTTON_WIDTH = 30; +var BUTTON_HEIGHT = 30; +var textX = OFFSET_X + BUTTON_WIDTH + UI_BUFFER; +var TEXT_HEIGHT = BUTTON_HEIGHT; +var TEXT_WIDTH = 210; + +var speedometer = Overlays.addOverlay("text", { + x: OFFSET_X, + y: OFFSET_Y - BUTTON_HEIGHT, + width: BUTTON_WIDTH + UI_BUFFER + TEXT_WIDTH, + height: TEXT_HEIGHT, + color: { red: 0, green: 0, blue: 0 }, + textColor: { red: 255, green: 0, blue: 0}, + topMargin: 4, + leftMargin: 4, + text: "Speed: 0.0" + }); +var speed = 0.0; +var lastPosition = MyAvatar.position; 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 }, + x: OFFSET_X, + y: OFFSET_Y + (BUTTON_HEIGHT * i), + width: BUTTON_WIDTH, + height: BUTTON_HEIGHT, + subImage: { x: offsetS, y: offsetT, width: BUTTON_WIDTH, height: BUTTON_HEIGHT }, imageURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/testing-swatches.svg", color: disabledColors[i], alpha: 1, @@ -62,9 +81,9 @@ for (i = 0; i < numberOfButtons; i++) { labels[i] = Overlays.addOverlay("text", { x: textX, - y: buttonY + (buttonHeight * i) + 12, - width: 150, - height: 50, + y: OFFSET_Y + (BUTTON_HEIGHT * i), + width: TEXT_WIDTH, + height: TEXT_HEIGHT, color: { red: 0, green: 0, blue: 0}, textColor: { red: 255, green: 0, blue: 0}, topMargin: 4, @@ -75,6 +94,10 @@ for (i = 0; i < numberOfButtons; i++) { buttonStates[i] = false; } +// avatar state +var velocity = { x: 0.0, y: 0.0, z: 0.0 }; +var standing = false; + function updateButton(i, enabled) { var offsetY = disabledOffsetT; var buttonColor = disabledColors[i]; @@ -108,13 +131,18 @@ function updateButton(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]); } + Overlays.deleteOverlay(speedometer); } Script.scriptEnding.connect(scriptEnding); +function updateSpeedometerDisplay() { + Overlays.editOverlay(speedometer, { text: "Speed: " + speed.toFixed(2) }); +} + +var multiple_timer = Script.setInterval(updateSpeedometerDisplay, 100); // Our update() function is called at approximately 60fps, and we will use it to animate our various overlays function update(deltaTime) { @@ -124,6 +152,26 @@ function update(deltaTime) { updateButton(1, groupBits & COLLISION_GROUP_VOXELS); updateButton(2, groupBits & COLLISION_GROUP_PARTICLES); } + + // measure speed + var distance = Vec3.distance(MyAvatar.position, lastPosition); + speed = 0.9 * speed + 0.1 * distance / deltaTime; + lastPosition = MyAvatar.position; + + // scan for landing platform + if (speed < MIN_FLYING_SPEED && !(MyAvatar.motionBehaviors & AVATAR_MOTION_OBEY_GRAVITY)) { + ray = { origin: MyAvatar.position, direction: DOWN }; + var intersection = Voxels.findRayIntersection(ray); + if (intersection.intersects) { + var v = intersection.voxel; + var maxCorner = Vec3.sum({ x: v.x, y: v.y, z: v.z }, {x: v.s, y: v.s, z: v.s }); + var distance = lastPosition.y - maxCorner.y; + if (distance < MAX_VOXEL_SCAN_DISTANCE) { + MyAvatar.motionBehaviors = AVATAR_MOTION_OBEY_GRAVITY; + } + //print("voxel corner = <" + v.x + ", " + v.y + ", " + v.z + "> " + " scale = " + v.s + " dt = " + deltaTime); + } + } } Script.update.connect(update); From f829a5b323c54db870d829b9b5e94736a538b1dd Mon Sep 17 00:00:00 2001 From: Konstantin Date: Sun, 27 Apr 2014 00:29:38 +0200 Subject: [PATCH 06/27] Fix CustomUrl Fixed custom url so that hifi://domain/ works. Also goes earlier to the location. --- interface/src/Application.cpp | 53 ++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 97b5c05f25..ee4862d515 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -316,6 +316,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : Particle::setVoxelEditPacketSender(&_voxelEditSender); Particle::setParticleEditPacketSender(&_particleEditSender); + // when -url in command line, teleport to location + urlGoTo(argc, constArgv); + // For now we're going to set the PPS for outbound packets to be super high, this is // probably not the right long term solution. But for now, we're going to do this to // allow you to move a particle around in your hand @@ -352,8 +355,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : QMutexLocker locker(&_settingsMutex); _previousScriptLocation = _settings->value("LastScriptLocation", QVariant("")).toString(); } - //When -url in command line, teleport to location - urlGoTo(argc, constArgv); } Application::~Application() { @@ -3576,34 +3577,34 @@ void Application::takeSnapshot() { void Application::urlGoTo(int argc, const char * constArgv[]) { //Gets the url (hifi://domain/destination/orientation) QString customUrl = getCmdOption(argc, constArgv, "-url"); + QStringList urlParts = customUrl.remove(0, CUSTOM_URL_SCHEME.length() + 2).split('/', QString::SkipEmptyParts); + if (urlParts.count() == 1) { + // location coordinates or place name + QString domain = urlParts[0]; + Menu::goToDomain(domain); + // as there are no coordinates, go to 0,0,0 + QString destination = "0,0,0"; + Menu::goTo(destination); + } else if (urlParts.count() > 1) { + // if url has 2 or more parts, the first one is domain name + QString domain = urlParts[0]; - if (customUrl.startsWith("hifi://")) { - QStringList urlParts = customUrl.remove(0, CUSTOM_URL_SCHEME.length() + 2).split('/', QString::SkipEmptyParts); - if (urlParts.count() > 1) { - // if url has 2 or more parts, the first one is domain name - QString domain = urlParts[0]; + // second part is either a destination coordinate or + // a place name + QString destination = urlParts[1]; - // second part is either a destination coordinate or - // a place name - QString destination = urlParts[1]; + // any third part is an avatar orientation. + QString orientation = urlParts.count() > 2 ? urlParts[2] : QString(); - // any third part is an avatar orientation. - QString orientation = urlParts.count() > 2 ? urlParts[2] : QString(); - - Menu::goToDomain(domain); + Menu::goToDomain(domain); - // goto either @user, #place, or x-xx,y-yy,z-zz - // style co-ordinate. - Menu::goTo(destination); + // goto either @user, #place, or x-xx,y-yy,z-zz + // style co-ordinate. + Menu::goTo(destination); - if (!orientation.isEmpty()) { - // location orientation - Menu::goToOrientation(orientation); - } - } else if (urlParts.count() == 1) { - // location coordinates or place name - QString destination = urlParts[0]; - Menu::goTo(destination); + if (!orientation.isEmpty()) { + // location orientation + Menu::goToOrientation(orientation); } - } + } } From ec410d105b524d864f1fc63461e512050a48116c Mon Sep 17 00:00:00 2001 From: Konstantin Date: Sun, 27 Apr 2014 00:31:28 +0200 Subject: [PATCH 07/27] Fix CustomUrl Fixed custom url so that hifi://domain/ works. --- interface/src/Menu.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 44117df55c..524e496acc 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -931,7 +931,15 @@ void Menu::goTo() { if (desiredDestination.startsWith(CUSTOM_URL_SCHEME + "//")) { QStringList urlParts = desiredDestination.remove(0, CUSTOM_URL_SCHEME.length() + 2).split('/', QString::SkipEmptyParts); - if (urlParts.count() > 1) { + if (urlParts.count() == 1) { + // location coordinates or place name + QString domain = urlParts[0]; + goToDomain(domain); + // as there are no coordinates, go to 0,0,0 + QString destination = "0,0,0"; + goTo(destination); + } + else if (urlParts.count() > 1) { // if url has 2 or more parts, the first one is domain name QString domain = urlParts[0]; @@ -952,12 +960,7 @@ void Menu::goTo() { // location orientation goToOrientation(orientation); } - } else if (urlParts.count() == 1) { - // location coordinates or place name - QString destination = urlParts[0]; - goTo(destination); } - } else { goToUser(gotoDialog.textValue()); } From 23397a4b10f84db17c484d57a4bbebac47c9880c Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 28 Apr 2014 08:55:03 -0700 Subject: [PATCH 08/27] Add LoginDialog --- interface/resources/images/hifi-logo.png | Bin 0 -> 5408 bytes interface/resources/images/login.svg | 18 + interface/src/ui/LoginDialog.cpp | 98 ++++++ interface/src/ui/LoginDialog.h | 43 +++ interface/ui/loginDialog.ui | 410 +++++++++++++++++++++++ 5 files changed, 569 insertions(+) create mode 100644 interface/resources/images/hifi-logo.png create mode 100644 interface/resources/images/login.svg create mode 100644 interface/src/ui/LoginDialog.cpp create mode 100644 interface/src/ui/LoginDialog.h create mode 100644 interface/ui/loginDialog.ui diff --git a/interface/resources/images/hifi-logo.png b/interface/resources/images/hifi-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..dde423ff8be878a2418b179b62dbb3d21f354bfa GIT binary patch literal 5408 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 + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp new file mode 100644 index 0000000000..67c99ad53d --- /dev/null +++ b/interface/src/ui/LoginDialog.cpp @@ -0,0 +1,98 @@ +// +// LoginDialog.cpp +// interface/src/ui +// +// Created by Ryan Huffman on 4/23/14. +// Copyright 2014 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 +// + + +#include +#include +#include + +#include "Application.h" +#include "Menu.h" +#include "AccountManager.h" +#include "ui_loginDialog.h" + +#include "LoginDialog.h" + +const QString FORGOT_PASSWORD_URL = "http://highfidelity.io"; + +LoginDialog::LoginDialog(QWidget* parent) : + FramelessDialog(parent, 0, FramelessDialog::POSITION_TOP), + _ui(new Ui::LoginDialog) { + + _ui->setupUi(this); + _ui->errorLabel->hide(); + _ui->emailLineEdit->setFocus(); + _ui->logoLabel->setPixmap(QPixmap(Application::resourcesPath() + "images/hifi-logo.png")); + _ui->loginButton->setIcon(QIcon(Application::resourcesPath() + "images/login.svg")); + _ui->infoLabel->setVisible(false); + _ui->errorLabel->setVisible(false); + + setModal(true); + setHideOnBlur(false); + + connect(&AccountManager::getInstance(), &AccountManager::loginComplete, + this, &LoginDialog::handleLoginCompleted); + connect(&AccountManager::getInstance(), &AccountManager::loginFailed, + this, &LoginDialog::handleLoginFailed); + connect(_ui->loginButton, &QPushButton::clicked, + this, &LoginDialog::handleLoginClicked); + connect(_ui->closeButton, &QPushButton::clicked, + this, &LoginDialog::close); + connect(_ui->forgotPasswordButton, &QPushButton::clicked, + this, &LoginDialog::handleForgotPasswordClicked); +}; + +LoginDialog::~LoginDialog() { + delete _ui; +}; + +void LoginDialog::handleLoginCompleted(const QUrl& authURL) { + _ui->infoLabel->setVisible(false); + _ui->errorLabel->setVisible(false); + close(); +}; + +void LoginDialog::handleLoginFailed() { + _ui->errorLabel->setText("Login Failure: Invalid username or password"); + + _ui->infoLabel->setVisible(false); + _ui->errorLabel->setVisible(true); + + _ui->errorLabel->show(); + _ui->loginAreaContainer->setDisabled(false); + _ui->emailLineEdit->setFocus(); + _ui->emailLineEdit->setSelection(0, _ui->emailLineEdit->maxLength()); +}; + +void LoginDialog::handleLoginClicked() { + // If the email or password inputs are empty, move focus to them, otherwise attempt to login. + if (_ui->emailLineEdit->text().isEmpty()) { + _ui->emailLineEdit->setFocus(); + } else if (_ui->passwordLineEdit->text().isEmpty()) { + _ui->passwordLineEdit->setFocus(); + } else { + _ui->infoLabel->setText("Authenticating..."); + _ui->infoLabel->setVisible(true); + _ui->errorLabel->setVisible(false); + + _ui->loginAreaContainer->setDisabled(true); + AccountManager::getInstance().requestAccessToken(_ui->emailLineEdit->text(), _ui->passwordLineEdit->text()); + } +}; + +void LoginDialog::handleForgotPasswordClicked() { + Menu::getInstance()->openUrl(FORGOT_PASSWORD_URL); +}; + +void LoginDialog::moveEvent(QMoveEvent* event) { + // Modal dialogs seemed to get repositioned automatically. Combat this by moving the window if needed. + resizeAndPosition(); +}; diff --git a/interface/src/ui/LoginDialog.h b/interface/src/ui/LoginDialog.h new file mode 100644 index 0000000000..91634559ee --- /dev/null +++ b/interface/src/ui/LoginDialog.h @@ -0,0 +1,43 @@ +// +// LoginDialog.h +// interface/src/ui +// +// Created by Ryan Huffman on 4/23/14. +// Copyright 2014 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_LoginDialog_h +#define hifi_LoginDialog_h + +#include +#include "FramelessDialog.h" + +namespace Ui { + class LoginDialog; +} + +class LoginDialog : public FramelessDialog { + Q_OBJECT + +public: + LoginDialog(QWidget* parent); + ~LoginDialog(); + +public slots: + void handleLoginClicked(); + void handleForgotPasswordClicked(); + void handleLoginCompleted(const QUrl& authURL); + void handleLoginFailed(); + +protected: + void moveEvent(QMoveEvent* event); + +private: + Ui::LoginDialog* _ui; + +}; + +#endif // hifi_LoginDialog_h diff --git a/interface/ui/loginDialog.ui b/interface/ui/loginDialog.ui new file mode 100644 index 0000000000..2764815c1e --- /dev/null +++ b/interface/ui/loginDialog.ui @@ -0,0 +1,410 @@ + + + LoginDialog + + + + 0 + 0 + 1159 + 130 + + + + + 0 + 130 + + + + Dialog + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 0 + 30 + + + + + 5 + + + 0 + + + 6 + + + 10 + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 18 + + + + Message + + + + + + + true + + + + 18 + + + + color: red + + + Error + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 16 + 16 + + + + + 16 + 16 + + + + SplitHCursor + + + + + + + + + + ../resources/images/close.svg../resources/images/close.svg + + + true + + + + + + + + + + true + + + + 0 + 0 + + + + + 0 + 102 + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 30 + + + + + + 0 + 0 + + + + + 931 + 60 + + + + QLineEdit { + padding: 10px; +border-width: 1px; border-style: solid; border-radius: 3px; border-color: #aaa; +} + + + + 12 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + ../resources/images/hifi-logo.png + + + + + + + + 0 + 0 + + + + + 300 + 54 + + + + + 20 + + + + + + + + + + Username or Email + + + + + + + + 0 + 0 + + + + + 300 + 54 + + + + + 20 + + + + + + + + + + QLineEdit::Password + + + Password + + + + + + + + 0 + 0 + + + + + 141 + 54 + + + + + 20 + + + + PointingHandCursor + + + +background: #0e7077; +color: #fff; +border-radius: 4px; + + + Login + + + + ../resources/images/login.svg../resources/images/login.svg + + + + 32 + 32 + + + + true + + + true + + + + + + + + 0 + 0 + + + + + 141 + 26 + + + + + 15 + + + + PointingHandCursor + + + color: #0e7077; +background: rgba(0, 0, 0, 0); +border-radius: 4px; + + + Recover Password? + + + false + + + true + + + + + + + + + + + + + + From 9bf3b3c6bf02362720dfbe4023e513f5f2bbb930 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 28 Apr 2014 08:59:28 -0700 Subject: [PATCH 09/27] Add hideOnBlur and TOP position to FramelessDialog --- interface/src/ui/FramelessDialog.cpp | 42 ++++++++++++++++++++-------- interface/src/ui/FramelessDialog.h | 15 +++++----- 2 files changed, 38 insertions(+), 19 deletions(-) diff --git a/interface/src/ui/FramelessDialog.cpp b/interface/src/ui/FramelessDialog.cpp index 4919e99db6..4566353af1 100644 --- a/interface/src/ui/FramelessDialog.cpp +++ b/interface/src/ui/FramelessDialog.cpp @@ -19,7 +19,8 @@ FramelessDialog::FramelessDialog(QWidget *parent, Qt::WindowFlags flags, Positio _isResizing(false), _resizeInitialWidth(0), _selfHidden(false), - _position(position) { + _position(position), + _hideOnBlur(true) { setAttribute(Qt::WA_DeleteOnClose); @@ -43,7 +44,7 @@ bool FramelessDialog::eventFilter(QObject* sender, QEvent* event) { } break; case QEvent::WindowStateChange: - if (parentWidget()->isMinimized()) { + if (_hideOnBlur && parentWidget()->isMinimized()) { if (isVisible()) { _selfHidden = true; setHidden(true); @@ -55,7 +56,7 @@ bool FramelessDialog::eventFilter(QObject* sender, QEvent* event) { break; case QEvent::ApplicationDeactivate: // hide on minimize and focus lost - if (isVisible()) { + if (_hideOnBlur && isVisible()) { _selfHidden = true; setHidden(true); } @@ -84,18 +85,23 @@ void FramelessDialog::setStyleSheetFile(const QString& fileName) { void FramelessDialog::showEvent(QShowEvent* event) { resizeAndPosition(); + QDialog::showEvent(event); } void FramelessDialog::resizeAndPosition(bool resizeParent) { - // keep full app height - setFixedHeight(parentWidget()->size().height()); + // keep full app height or width depending on position + if (_position == POSITION_LEFT || _position == POSITION_RIGHT) { + setFixedHeight(parentWidget()->size().height()); + } else { + setFixedWidth(parentWidget()->size().width()); + } // resize parrent if width is smaller than this dialog if (resizeParent && parentWidget()->size().width() < size().width()) { parentWidget()->resize(size().width(), parentWidget()->size().height()); } - if (_position == POSITION_LEFT) { + if (_position == POSITION_LEFT || _position == POSITION_TOP) { // move to upper left corner move(parentWidget()->geometry().topLeft()); } else if (_position == POSITION_RIGHT) { @@ -104,16 +110,26 @@ void FramelessDialog::resizeAndPosition(bool resizeParent) { pos.setX(pos.x() - size().width()); move(pos); } + repaint(); } void FramelessDialog::mousePressEvent(QMouseEvent* mouseEvent) { if (mouseEvent->button() == Qt::LeftButton) { - bool hitLeft = _position == POSITION_LEFT && abs(mouseEvent->pos().x() - size().width()) < RESIZE_HANDLE_WIDTH; - bool hitRight = _position == POSITION_RIGHT && mouseEvent->pos().x() < RESIZE_HANDLE_WIDTH; - if (hitLeft || hitRight) { - _isResizing = true; - _resizeInitialWidth = size().width(); - QApplication::setOverrideCursor(Qt::SizeHorCursor); + if (_position == POSITION_LEFT || _position == POSITION_RIGHT) { + bool hitLeft = _position == POSITION_LEFT && abs(mouseEvent->pos().x() - size().width()) < RESIZE_HANDLE_WIDTH; + bool hitRight = _position == POSITION_RIGHT && mouseEvent->pos().x() < RESIZE_HANDLE_WIDTH; + if (hitLeft || hitRight) { + _isResizing = true; + _resizeInitialWidth = size().width(); + QApplication::setOverrideCursor(Qt::SizeHorCursor); + } + } else { + bool hitTop = _position == POSITION_TOP && abs(mouseEvent->pos().y() - size().height()) < RESIZE_HANDLE_WIDTH; + if (hitTop) { + _isResizing = true; + _resizeInitialWidth = size().height(); + QApplication::setOverrideCursor(Qt::SizeHorCursor); + } } } } @@ -133,6 +149,8 @@ void FramelessDialog::mouseMoveEvent(QMouseEvent* mouseEvent) { resizeAndPosition(); _resizeInitialWidth = size().width(); setUpdatesEnabled(true); + } else if (_position == POSITION_TOP) { + resize(size().width(), mouseEvent->pos().y()); } } } diff --git a/interface/src/ui/FramelessDialog.h b/interface/src/ui/FramelessDialog.h index 22666cca63..2265f3c9e4 100644 --- a/interface/src/ui/FramelessDialog.h +++ b/interface/src/ui/FramelessDialog.h @@ -17,13 +17,15 @@ class FramelessDialog : public QDialog { Q_OBJECT - -public: - enum Position { POSITION_LEFT, POSITION_RIGHT }; - FramelessDialog(QWidget* parent = 0, Qt::WindowFlags flags = 0, - Position position = POSITION_LEFT); +public: + enum Position { POSITION_LEFT, POSITION_RIGHT, POSITION_TOP }; + + FramelessDialog(QWidget* parent, Qt::WindowFlags flags = 0, Position position = POSITION_LEFT); void setStyleSheetFile(const QString& fileName); + void setHideOnBlur(bool hideOnBlur) { _hideOnBlur = hideOnBlur; }; + bool getHideOnBlur() { return _hideOnBlur; }; + void resizeAndPosition(bool resizeParent = true); protected: virtual void mouseMoveEvent(QMouseEvent* mouseEvent); @@ -34,12 +36,11 @@ protected: bool eventFilter(QObject* sender, QEvent* event); private: - void resizeAndPosition(bool resizeParent = true); - bool _isResizing; int _resizeInitialWidth; bool _selfHidden; ///< true when the dialog itself because of a window event (deactivation or minimization) Position _position; + bool _hideOnBlur; }; From cbd5fbe9b36ba2f90753d49d1f243ec68b8700f3 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 28 Apr 2014 08:59:44 -0700 Subject: [PATCH 10/27] Add loginFailed signal to AccountManager --- libraries/networking/src/AccountManager.cpp | 1 + libraries/networking/src/AccountManager.h | 1 + 2 files changed, 2 insertions(+) diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index d1e4edf2ea..33891b73c7 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -334,6 +334,7 @@ void AccountManager::requestFinished() { } else { // TODO: error handling qDebug() << "Error in response for password grant -" << rootObject["error_description"].toString(); + emit loginFailed(); } } diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index cb76786f4e..8df75195cf 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -71,6 +71,7 @@ signals: void usernameChanged(const QString& username); void accessTokenChanged(); void loginComplete(const QUrl& authURL); + void loginFailed(); void logoutComplete(); private slots: void processReply(); From 81a0cbe761dcbdd27cb0991dd57bfc7dbc58b23e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 28 Apr 2014 09:01:13 -0700 Subject: [PATCH 11/27] Update Menu to use new login dialog --- interface/src/Menu.cpp | 36 ++++-------------------------------- 1 file changed, 4 insertions(+), 32 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 0dbd272e9c..21826976e5 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -40,6 +40,7 @@ #include "ui/InfoView.h" #include "ui/MetavoxelEditor.h" #include "ui/ModelsBrowser.h" +#include "ui/LoginDialog.h" Menu* Menu::_instance = NULL; @@ -815,38 +816,9 @@ const int QLINE_MINIMUM_WIDTH = 400; const float DIALOG_RATIO_OF_WINDOW = 0.30f; void Menu::loginForCurrentDomain() { - QDialog loginDialog(Application::getInstance()->getWindow()); - loginDialog.setWindowTitle("Login"); - - QBoxLayout* layout = new QBoxLayout(QBoxLayout::TopToBottom); - loginDialog.setLayout(layout); - loginDialog.setWindowFlags(Qt::Sheet); - - QFormLayout* form = new QFormLayout(); - layout->addLayout(form, 1); - - QLineEdit* loginLineEdit = new QLineEdit(); - loginLineEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH); - form->addRow("Login:", loginLineEdit); - - QLineEdit* passwordLineEdit = new QLineEdit(); - passwordLineEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH); - passwordLineEdit->setEchoMode(QLineEdit::Password); - form->addRow("Password:", passwordLineEdit); - - QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - loginDialog.connect(buttons, SIGNAL(accepted()), SLOT(accept())); - loginDialog.connect(buttons, SIGNAL(rejected()), SLOT(reject())); - layout->addWidget(buttons); - - int dialogReturn = loginDialog.exec(); - - if (dialogReturn == QDialog::Accepted && !loginLineEdit->text().isEmpty() && !passwordLineEdit->text().isEmpty()) { - // attempt to get an access token given this username and password - AccountManager::getInstance().requestAccessToken(loginLineEdit->text(), passwordLineEdit->text()); - } - - sendFakeEnterEvent(); + LoginDialog* loginDialog = new LoginDialog(Application::getInstance()->getWindow()); + loginDialog->show(); + loginDialog->resizeAndPosition(false); } void Menu::editPreferences() { From 01f66420de660104dd7fc12ac1aa78fbcb6b284d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 28 Apr 2014 09:11:09 -0700 Subject: [PATCH 12/27] Fix issue with icon being disabled on login window while authenticating --- interface/src/ui/LoginDialog.cpp | 4 +- interface/ui/loginDialog.ui | 81 +++++++++++++++++++++++++++----- 2 files changed, 72 insertions(+), 13 deletions(-) diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 67c99ad53d..639e99f6af 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -67,7 +67,7 @@ void LoginDialog::handleLoginFailed() { _ui->errorLabel->setVisible(true); _ui->errorLabel->show(); - _ui->loginAreaContainer->setDisabled(false); + _ui->loginArea->setDisabled(false); _ui->emailLineEdit->setFocus(); _ui->emailLineEdit->setSelection(0, _ui->emailLineEdit->maxLength()); }; @@ -83,7 +83,7 @@ void LoginDialog::handleLoginClicked() { _ui->infoLabel->setVisible(true); _ui->errorLabel->setVisible(false); - _ui->loginAreaContainer->setDisabled(true); + _ui->loginArea->setDisabled(true); AccountManager::getInstance().requestAccessToken(_ui->emailLineEdit->text(), _ui->passwordLineEdit->text()); } }; diff --git a/interface/ui/loginDialog.ui b/interface/ui/loginDialog.ui index 2764815c1e..2fee9a221e 100644 --- a/interface/ui/loginDialog.ui +++ b/interface/ui/loginDialog.ui @@ -6,7 +6,7 @@ 0 0 - 1159 + 1003 130 @@ -201,6 +201,62 @@ 30 + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + + + 0 + + + 0 + + + 12 + + + 0 + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + + + ../resources/images/hifi-logo.png + + + + + + @@ -237,16 +293,6 @@ border-width: 1px; border-style: solid; border-radius: 3px; border-color: #aaa; 0 - - - - - - - ../resources/images/hifi-logo.png - - - @@ -400,6 +446,19 @@ border-radius: 4px; + + + + Qt::Horizontal + + + + 40 + 20 + + + + From fb42d9ccc6aebd5e50dc24be0b2e94246af5b91e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 28 Apr 2014 09:21:37 -0700 Subject: [PATCH 13/27] Update login to move focus to password on fail --- interface/src/ui/LoginDialog.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 639e99f6af..83b61bd75d 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -68,8 +68,10 @@ void LoginDialog::handleLoginFailed() { _ui->errorLabel->show(); _ui->loginArea->setDisabled(false); - _ui->emailLineEdit->setFocus(); - _ui->emailLineEdit->setSelection(0, _ui->emailLineEdit->maxLength()); + + // Move focus to password and select the entire line + _ui->passwordLineEdit->setFocus(); + _ui->passwordLineEdit->setSelection(0, _ui->emailLineEdit->maxLength()); }; void LoginDialog::handleLoginClicked() { From 6f502777a5ba03d1e181888bc89e424cb6fc6453 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 28 Apr 2014 12:03:54 -0700 Subject: [PATCH 14/27] Update forgot password URL --- interface/src/ui/LoginDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 83b61bd75d..1ff291036f 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -21,7 +21,7 @@ #include "LoginDialog.h" -const QString FORGOT_PASSWORD_URL = "http://highfidelity.io"; +const QString FORGOT_PASSWORD_URL = "https://data-web.highfidelity.io/password/new"; LoginDialog::LoginDialog(QWidget* parent) : FramelessDialog(parent, 0, FramelessDialog::POSITION_TOP), From d5d440eec585614f79290600bc2af8390f8d8a0a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 28 Apr 2014 12:04:28 -0700 Subject: [PATCH 15/27] Update font on login window --- interface/ui/loginDialog.ui | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/interface/ui/loginDialog.ui b/interface/ui/loginDialog.ui index 2fee9a221e..d111e107b1 100644 --- a/interface/ui/loginDialog.ui +++ b/interface/ui/loginDialog.ui @@ -19,6 +19,9 @@ Dialog + + font-family: Helvetica, Arial, sans-serif; + 0 @@ -57,7 +60,7 @@ 0 - 6 + 10 10 @@ -82,6 +85,7 @@ + Helvetica,Arial,sans-serif 18 @@ -97,6 +101,7 @@ + Helvetica,Arial,sans-serif 18 @@ -309,11 +314,12 @@ border-width: 1px; border-style: solid; border-radius: 3px; border-color: #aaa; + Helvetica,Arial,sans-serif 20 - + padding-top: 14px; @@ -339,11 +345,12 @@ border-width: 1px; border-style: solid; border-radius: 3px; border-color: #aaa; + Helvetica,Arial,sans-serif 20 - + padding-top: 14px; @@ -372,6 +379,7 @@ border-width: 1px; border-style: solid; border-radius: 3px; border-color: #aaa; + Helvetica,Arial,sans-serif 20 @@ -382,7 +390,7 @@ border-width: 1px; border-style: solid; border-radius: 3px; border-color: #aaa; background: #0e7077; color: #fff; -border-radius: 4px; +border-radius: 4px; padding-top: 1px; Login @@ -421,7 +429,8 @@ border-radius: 4px; - 15 + Helvetica,Arial,sans-serif + 16 From ea2e96ac6fc09ca15a19e6e1e4a622de44fb9b77 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 28 Apr 2014 13:02:54 -0700 Subject: [PATCH 16/27] toggle collision and gravity with timers --- examples/swissArmyJetpack.js | 158 ++++++++++++++++++++++++----------- 1 file changed, 107 insertions(+), 51 deletions(-) diff --git a/examples/swissArmyJetpack.js b/examples/swissArmyJetpack.js index 719a6f620c..4963ecba09 100644 --- a/examples/swissArmyJetpack.js +++ b/examples/swissArmyJetpack.js @@ -12,44 +12,44 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -var numberOfButtons = 3; +// misc global constants +var NUMBER_OF_BUTTONS = 3; var DOWN = { x: 0.0, y: -1.0, z: 0.0 }; var MAX_VOXEL_SCAN_DISTANCE = 20.0; + +// behavior transition thresholds var MIN_FLYING_SPEED = 1.0; +var MIN_COLLISIONLESS_SPEED = 5.0; +var MAX_WALKING_SPEED = 10.0; +var MAX_COLLIDABLE_SPEED = 25.0; -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 = 12; -var enabledOffsetT = 55 + 12; - +// button URL and geometry/UI tuning +var BUTTON_IMAGE_URL = "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/testing-swatches.svg"; +var DISABLED_OFFSET_Y = 12; +var ENABLED_OFFSET_Y = 55 + 12; var UI_BUFFER = 1; var OFFSET_X = UI_BUFFER; var OFFSET_Y = 200; var BUTTON_WIDTH = 30; var BUTTON_HEIGHT = 30; -var textX = OFFSET_X + BUTTON_WIDTH + UI_BUFFER; +var TEXT_OFFSET_X = OFFSET_X + BUTTON_WIDTH + UI_BUFFER; var TEXT_HEIGHT = BUTTON_HEIGHT; var TEXT_WIDTH = 210; +var MSEC_PER_SECOND = 1000; +var EXPIRY_PERIOD = 2 * MSEC_PER_SECOND; + +var dater = new Date(); +var collisionOnExpiry = dater.getTime() + EXPIRY_PERIOD; +var gravityOnExpiry = dater.getTime() + EXPIRY_PERIOD; + +// avatar state +var velocity = { x: 0.0, y: 0.0, z: 0.0 }; +var standing = false; + +// speedometer globals +var speed = 0.0; +var lastPosition = MyAvatar.position; var speedometer = Overlays.addOverlay("text", { x: OFFSET_X, y: OFFSET_Y - BUTTON_HEIGHT, @@ -61,12 +61,32 @@ var speedometer = Overlays.addOverlay("text", { leftMargin: 4, text: "Speed: 0.0" }); -var speed = 0.0; -var lastPosition = MyAvatar.position; -for (i = 0; i < numberOfButtons; i++) { +// collision group buttons +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 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 buttonStates = new Array(); + +for (i = 0; i < NUMBER_OF_BUTTONS; i++) { var offsetS = 12 - var offsetT = disabledOffsetT; + var offsetT = DISABLED_OFFSET_Y; buttons[i] = Overlays.addOverlay("image", { x: OFFSET_X, @@ -74,13 +94,13 @@ for (i = 0; i < numberOfButtons; i++) { width: BUTTON_WIDTH, height: BUTTON_HEIGHT, subImage: { x: offsetS, y: offsetT, width: BUTTON_WIDTH, height: BUTTON_HEIGHT }, - imageURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/testing-swatches.svg", + imageURL: BUTTON_IMAGE_URL, color: disabledColors[i], alpha: 1, }); labels[i] = Overlays.addOverlay("text", { - x: textX, + x: TEXT_OFFSET_X, y: OFFSET_Y + (BUTTON_HEIGHT * i), width: TEXT_WIDTH, height: TEXT_HEIGHT, @@ -94,16 +114,14 @@ for (i = 0; i < numberOfButtons; i++) { buttonStates[i] = false; } -// avatar state -var velocity = { x: 0.0, y: 0.0, z: 0.0 }; -var standing = false; + +// functions function updateButton(i, enabled) { - var offsetY = disabledOffsetT; + var offsetY = DISABLED_OFFSET_Y; var buttonColor = disabledColors[i]; - groupBits if (enabled) { - offsetY = enabledOffsetT; + offsetY = ENABLED_OFFSET_Y; buttonColor = enabledColors[i]; if (i == 0) { groupBits |= COLLISION_GROUP_AVATARS; @@ -121,16 +139,19 @@ function updateButton(i, enabled) { groupBits &= ~COLLISION_GROUP_PARTICLES; } } - MyAvatar.collisionGroups = groupBits; + if (groupBits != MyAvatar.collisionGroups) { + 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++) { + for (i = 0; i < NUMBER_OF_BUTTONS; i++) { Overlays.deleteOverlay(buttons[i]); Overlays.deleteOverlay(labels[i]); } @@ -138,11 +159,12 @@ function scriptEnding() { } Script.scriptEnding.connect(scriptEnding); + function updateSpeedometerDisplay() { Overlays.editOverlay(speedometer, { text: "Speed: " + speed.toFixed(2) }); } +Script.setInterval(updateSpeedometerDisplay, 100); -var multiple_timer = Script.setInterval(updateSpeedometerDisplay, 100); // Our update() function is called at approximately 60fps, and we will use it to animate our various overlays function update(deltaTime) { @@ -155,21 +177,55 @@ function update(deltaTime) { // measure speed var distance = Vec3.distance(MyAvatar.position, lastPosition); - speed = 0.9 * speed + 0.1 * distance / deltaTime; + speed = 0.8 * speed + 0.2 * distance / deltaTime; lastPosition = MyAvatar.position; - // scan for landing platform - if (speed < MIN_FLYING_SPEED && !(MyAvatar.motionBehaviors & AVATAR_MOTION_OBEY_GRAVITY)) { + dater = new Date(); + var now = dater.getTime(); + + if (speed < MIN_FLYING_SPEED) { + // scan for landing platform ray = { origin: MyAvatar.position, direction: DOWN }; var intersection = Voxels.findRayIntersection(ray); if (intersection.intersects) { - var v = intersection.voxel; - var maxCorner = Vec3.sum({ x: v.x, y: v.y, z: v.z }, {x: v.s, y: v.s, z: v.s }); - var distance = lastPosition.y - maxCorner.y; - if (distance < MAX_VOXEL_SCAN_DISTANCE) { - MyAvatar.motionBehaviors = AVATAR_MOTION_OBEY_GRAVITY; + if (!(MyAvatar.motionBehaviors & AVATAR_MOTION_OBEY_GRAVITY)) { + var v = intersection.voxel; + var maxCorner = Vec3.sum({ x: v.x, y: v.y, z: v.z }, {x: v.s, y: v.s, z: v.s }); + var distance = lastPosition.y - maxCorner.y; + if ((gravityOnExpiry < now) && (distance < MAX_VOXEL_SCAN_DISTANCE)) { + MyAvatar.motionBehaviors = MyAvatar.motionBehaviors | AVATAR_MOTION_OBEY_GRAVITY; + } } - //print("voxel corner = <" + v.x + ", " + v.y + ", " + v.z + "> " + " scale = " + v.s + " dt = " + deltaTime); + } else { + if (MyAvatar.motionBehaviors & AVATAR_MOTION_OBEY_GRAVITY) { + MyAvatar.motionBehaviors = MyAvatar.motionBehaviors & ~AVATAR_MOTION_OBEY_GRAVITY; + } + gravityOnExpiry = now + EXPIRY_PERIOD; + } + } else { + gravityOnExpiry = now + EXPIRY_PERIOD; + } + if (speed < MIN_COLLISIONLESS_SPEED) { + if (collisionOnExpiry < now && !(MyAvatar.collisionGroups & COLLISION_GROUP_VOXELS)) { + // TODO: check to make sure not already colliding + // enable collision with voxels + groupBits |= COLLISION_GROUP_VOXELS; + updateButton(1, groupBits & COLLISION_GROUP_VOXELS); + } + } else { + collisionOnExpiry = now + EXPIRY_PERIOD; + } + if (speed > MAX_WALKING_SPEED) { + if (MyAvatar.motionBehaviors & AVATAR_MOTION_OBEY_GRAVITY) { + // turn off gravity + MyAvatar.motionBehaviors = MyAvatar.motionBehaviors & ~AVATAR_MOTION_OBEY_GRAVITY; + } + } + if (speed > MAX_COLLIDABLE_SPEED) { + if (MyAvatar.collisionGroups & COLLISION_GROUP_VOXELS) { + // disable collisions with voxels + groupBits &= ~COLLISION_GROUP_VOXELS; + updateButton(1, groupBits & COLLISION_GROUP_VOXELS); } } } @@ -179,7 +235,7 @@ 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++) { + for (i = 0; i < NUMBER_OF_BUTTONS; i++) { if (clickedOverlay == buttons[i]) { var enabled = !(buttonStates[i]); updateButton(i, enabled); From 46d4a31f01a17a9280b496601eb1948f4a512ffa Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 28 Apr 2014 13:16:06 -0700 Subject: [PATCH 17/27] Update login images --- interface/resources/images/hifi-logo.png | Bin 5408 -> 0 bytes interface/resources/images/hifi-logo.svg | 58 +++++++++++++++++++++++ interface/resources/images/login.svg | 35 +++++++------- 3 files changed, 75 insertions(+), 18 deletions(-) delete mode 100644 interface/resources/images/hifi-logo.png create mode 100644 interface/resources/images/hifi-logo.svg diff --git a/interface/resources/images/hifi-logo.png b/interface/resources/images/hifi-logo.png deleted file mode 100644 index dde423ff8be878a2418b179b62dbb3d21f354bfa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5408 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/interface/resources/images/login.svg b/interface/resources/images/login.svg index 1a5b254055..f45097b8e3 100644 --- a/interface/resources/images/login.svg +++ b/interface/resources/images/login.svg @@ -1,18 +1,17 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + From 24350761ac594d0196acb14c94fb50af08bbf4f6 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 28 Apr 2014 13:16:50 -0700 Subject: [PATCH 18/27] Update layout of login messages and move text to .ui file --- interface/src/ui/LoginDialog.cpp | 11 +-- interface/src/ui/LoginDialog.h | 1 - interface/ui/loginDialog.ui | 133 +++++++++++++++++-------------- 3 files changed, 74 insertions(+), 71 deletions(-) diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 1ff291036f..993f355c47 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -30,7 +30,7 @@ LoginDialog::LoginDialog(QWidget* parent) : _ui->setupUi(this); _ui->errorLabel->hide(); _ui->emailLineEdit->setFocus(); - _ui->logoLabel->setPixmap(QPixmap(Application::resourcesPath() + "images/hifi-logo.png")); + _ui->logoLabel->setPixmap(QPixmap(Application::resourcesPath() + "images/hifi-logo.svg")); _ui->loginButton->setIcon(QIcon(Application::resourcesPath() + "images/login.svg")); _ui->infoLabel->setVisible(false); _ui->errorLabel->setVisible(false); @@ -46,8 +46,6 @@ LoginDialog::LoginDialog(QWidget* parent) : this, &LoginDialog::handleLoginClicked); connect(_ui->closeButton, &QPushButton::clicked, this, &LoginDialog::close); - connect(_ui->forgotPasswordButton, &QPushButton::clicked, - this, &LoginDialog::handleForgotPasswordClicked); }; LoginDialog::~LoginDialog() { @@ -61,8 +59,6 @@ void LoginDialog::handleLoginCompleted(const QUrl& authURL) { }; void LoginDialog::handleLoginFailed() { - _ui->errorLabel->setText("Login Failure: Invalid username or password"); - _ui->infoLabel->setVisible(false); _ui->errorLabel->setVisible(true); @@ -81,7 +77,6 @@ void LoginDialog::handleLoginClicked() { } else if (_ui->passwordLineEdit->text().isEmpty()) { _ui->passwordLineEdit->setFocus(); } else { - _ui->infoLabel->setText("Authenticating..."); _ui->infoLabel->setVisible(true); _ui->errorLabel->setVisible(false); @@ -90,10 +85,6 @@ void LoginDialog::handleLoginClicked() { } }; -void LoginDialog::handleForgotPasswordClicked() { - Menu::getInstance()->openUrl(FORGOT_PASSWORD_URL); -}; - void LoginDialog::moveEvent(QMoveEvent* event) { // Modal dialogs seemed to get repositioned automatically. Combat this by moving the window if needed. resizeAndPosition(); diff --git a/interface/src/ui/LoginDialog.h b/interface/src/ui/LoginDialog.h index 91634559ee..b4aad06614 100644 --- a/interface/src/ui/LoginDialog.h +++ b/interface/src/ui/LoginDialog.h @@ -28,7 +28,6 @@ public: public slots: void handleLoginClicked(); - void handleForgotPasswordClicked(); void handleLoginCompleted(const QUrl& authURL); void handleLoginFailed(); diff --git a/interface/ui/loginDialog.ui b/interface/ui/loginDialog.ui index d111e107b1..d54b3c833f 100644 --- a/interface/ui/loginDialog.ui +++ b/interface/ui/loginDialog.ui @@ -69,7 +69,7 @@ 0 - + Qt::Horizontal @@ -82,38 +82,71 @@ - - - - Helvetica,Arial,sans-serif - 18 - - - - Message - - - - - - - true - - - - Helvetica,Arial,sans-serif - 18 - - - - color: red - - - Error - - - Qt::AlignCenter + + + + 825 + 0 + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + Helvetica,Arial,sans-serif + 17 + + + + Authenticating... + + + + + + + true + + + + Helvetica,Arial,sans-serif + 17 + + + + color: #992800; + + + <style type="text/css"> + a { text-decoration: none; color: #267077;} +</style> +Invalid username or password. <a href="https://data-web.highfidelity.io/password/new">Recover?</a> + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + true + + + + @@ -389,7 +422,7 @@ border-width: 1px; border-style: solid; border-radius: 3px; border-color: #aaa; background: #0e7077; -color: #fff; +color: #e7eeee; border-radius: 4px; padding-top: 1px; @@ -414,40 +447,20 @@ border-radius: 4px; padding-top: 1px; - - - - 0 - 0 - - - - - 141 - 26 - - + Helvetica,Arial,sans-serif - 16 + 17 - - PointingHandCursor - - - color: #0e7077; -background: rgba(0, 0, 0, 0); -border-radius: 4px; - - Recover Password? + <style type="text/css"> + a { text-decoration: none; color: #267077;} +</style> +<a href="https://data-web.highfidelity.io/password/new">Recover password?</a> - - false - - + true From 9f070406ed2fe152dd7fb28249e8ba892d3e4c9f Mon Sep 17 00:00:00 2001 From: Stojce Slavkovski Date: Tue, 29 Apr 2014 00:02:24 +0200 Subject: [PATCH 19/27] missing 'extra debugging' check icon; fix font --- interface/resources/styles/log_dialog.qss | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/resources/styles/log_dialog.qss b/interface/resources/styles/log_dialog.qss index b7387c1ee7..330356e750 100644 --- a/interface/resources/styles/log_dialog.qss +++ b/interface/resources/styles/log_dialog.qss @@ -33,6 +33,7 @@ QPushButton#searchButton { } QPushButton#revealLogButton { + font-family: Helvetica, Arial, sans-serif; background: url(styles/txt-file.svg); background-repeat: none; background-position: left center; @@ -50,9 +51,9 @@ QCheckBox { } QCheckBox::indicator:unchecked { - image: url(:/styles/unchecked.svg); + image: url(styles/unchecked.svg); } QCheckBox::indicator:checked { - image: url(:/styles/checked.svg); + image: url(styles/checked.svg); } \ No newline at end of file From c7dbc5984f315d575ce0ab99d3a5008da04e360c Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 28 Apr 2014 16:40:22 -0700 Subject: [PATCH 20/27] add local gravity option parameter for MyAvatar --- examples/swissArmyJetpack.js | 13 +++-- interface/src/Application.cpp | 2 +- interface/src/Menu.cpp | 2 +- interface/src/Menu.h | 2 +- interface/src/avatar/MyAvatar.cpp | 58 +++++++++++++------- interface/src/avatar/MyAvatar.h | 6 +- libraries/avatars/src/AvatarData.h | 3 +- libraries/script-engine/src/ScriptEngine.cpp | 3 +- 8 files changed, 56 insertions(+), 33 deletions(-) diff --git a/examples/swissArmyJetpack.js b/examples/swissArmyJetpack.js index 4963ecba09..a7fab772dc 100644 --- a/examples/swissArmyJetpack.js +++ b/examples/swissArmyJetpack.js @@ -188,17 +188,18 @@ function update(deltaTime) { ray = { origin: MyAvatar.position, direction: DOWN }; var intersection = Voxels.findRayIntersection(ray); if (intersection.intersects) { - if (!(MyAvatar.motionBehaviors & AVATAR_MOTION_OBEY_GRAVITY)) { + if (!(MyAvatar.motionBehaviors & AVATAR_MOTION_OBEY_LOCAL_GRAVITY)) { var v = intersection.voxel; var maxCorner = Vec3.sum({ x: v.x, y: v.y, z: v.z }, {x: v.s, y: v.s, z: v.s }); var distance = lastPosition.y - maxCorner.y; if ((gravityOnExpiry < now) && (distance < MAX_VOXEL_SCAN_DISTANCE)) { - MyAvatar.motionBehaviors = MyAvatar.motionBehaviors | AVATAR_MOTION_OBEY_GRAVITY; + // NOTE: setting the gravity automatically sets the AVATAR_MOTION_OBEY_LOCAL_GRAVITY behavior bit. + MyAvatar.gravity = DOWN; } } } else { - if (MyAvatar.motionBehaviors & AVATAR_MOTION_OBEY_GRAVITY) { - MyAvatar.motionBehaviors = MyAvatar.motionBehaviors & ~AVATAR_MOTION_OBEY_GRAVITY; + if (MyAvatar.motionBehaviors & AVATAR_MOTION_OBEY_LOCAL_GRAVITY) { + MyAvatar.motionBehaviors = MyAvatar.motionBehaviors & ~AVATAR_MOTION_OBEY_LOCAL_GRAVITY; } gravityOnExpiry = now + EXPIRY_PERIOD; } @@ -216,9 +217,9 @@ function update(deltaTime) { collisionOnExpiry = now + EXPIRY_PERIOD; } if (speed > MAX_WALKING_SPEED) { - if (MyAvatar.motionBehaviors & AVATAR_MOTION_OBEY_GRAVITY) { + if (MyAvatar.motionBehaviors & AVATAR_MOTION_OBEY_LOCAL_GRAVITY) { // turn off gravity - MyAvatar.motionBehaviors = MyAvatar.motionBehaviors & ~AVATAR_MOTION_OBEY_GRAVITY; + MyAvatar.motionBehaviors = MyAvatar.motionBehaviors & ~AVATAR_MOTION_OBEY_LOCAL_GRAVITY; } } if (speed > MAX_COLLIDABLE_SPEED) { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 97b5c05f25..558ba31d80 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::ObeyGravity); + Menu::getInstance()->triggerOption(MenuOption::ObeyEnvironmentalGravity); } break; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index e488733e2a..ff3c6a1f43 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -188,7 +188,7 @@ Menu::Menu() : addDisabledActionAndSeparator(editMenu, "Physics"); QObject* avatar = appInstance->getAvatar(); - addCheckableActionToQMenuAndActionHash(editMenu, MenuOption::ObeyGravity, Qt::SHIFT | Qt::Key_G, true, + addCheckableActionToQMenuAndActionHash(editMenu, MenuOption::ObeyEnvironmentalGravity, Qt::SHIFT | Qt::Key_G, true, avatar, SLOT(updateMotionBehaviors())); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index bc70f8f83f..bbd3aa13ae 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 ObeyGravity = "Obey Gravity"; + const QString ObeyEnvironmentalGravity = "Obey Environmental Gravity"; const QString HandsCollideWithSelf = "Collide With Self"; const QString HeadMouse = "Head Mouse"; const QString IncreaseAvatarSize = "Increase Avatar Size"; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 26dbc09d5b..0a3e788042 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -125,10 +125,8 @@ void MyAvatar::update(float deltaTime) { head->setAudioLoudness(audio->getLastInputLoudness()); head->setAudioAverageLoudness(audio->getAudioAverageInputLoudness()); - if (_motionBehaviors & AVATAR_MOTION_OBEY_GRAVITY) { - setGravity(Application::getInstance()->getEnvironment()->getGravity(getPosition())); - } else { - setGravity(glm::vec3(0.0f, 0.0f, 0.0f)); + if (_motionBehaviors & AVATAR_MOTION_OBEY_ENVIRONMENTAL_GRAVITY) { + _gravity = Application::getInstance()->getEnvironment()->getGravity(getPosition()); } simulate(deltaTime); @@ -463,6 +461,27 @@ void MyAvatar::renderHeadMouse() const { */ } +void MyAvatar::setLocalGravity(glm::vec3 gravity) { + _motionBehaviors |= AVATAR_MOTION_OBEY_LOCAL_GRAVITY; + // Environmental and Local gravities are incompatible. Since Local is being set here + // the environmental setting must be removed. + _motionBehaviors &= ~AVATAR_MOTION_OBEY_ENVIRONMENTAL_GRAVITY; + setGravity(gravity); +} + +void MyAvatar::setGravity(const glm::vec3& gravity) { + _gravity = gravity; + getHead()->setGravity(_gravity); + + // use the gravity to determine the new world up direction, if possible + float gravityLength = glm::length(gravity); + if (gravityLength > EPSILON) { + _worldUpDirection = _gravity / -gravityLength; + } else { + _worldUpDirection = DEFAULT_UP_DIRECTION; + } +} + void MyAvatar::saveData(QSettings* settings) { settings->beginGroup("Avatar"); @@ -1046,19 +1065,6 @@ void MyAvatar::maybeUpdateBillboard() { sendBillboardPacket(); } -void MyAvatar::setGravity(glm::vec3 gravity) { - _gravity = gravity; - getHead()->setGravity(_gravity); - - // use the gravity to determine the new world up direction, if possible - float gravityLength = glm::length(gravity); - if (gravityLength > EPSILON) { - _worldUpDirection = _gravity / -gravityLength; - } else { - _worldUpDirection = DEFAULT_UP_DIRECTION; - } -} - void MyAvatar::goHome() { qDebug("Going Home!"); setPosition(START_LOCATION); @@ -1147,8 +1153,13 @@ void MyAvatar::goToLocationFromResponse(const QJsonObject& jsonObject) { void MyAvatar::updateMotionBehaviors() { _motionBehaviors = 0; - if (Menu::getInstance()->isOptionChecked(MenuOption::ObeyGravity)) { - _motionBehaviors |= AVATAR_MOTION_OBEY_GRAVITY; + if (Menu::getInstance()->isOptionChecked(MenuOption::ObeyEnvironmentalGravity)) { + _motionBehaviors |= AVATAR_MOTION_OBEY_ENVIRONMENTAL_GRAVITY; + // Environmental and Local gravities are incompatible. Environmental setting trumps local. + _motionBehaviors &= ~AVATAR_MOTION_OBEY_LOCAL_GRAVITY; + } + if (! (_motionBehaviors & (AVATAR_MOTION_OBEY_ENVIRONMENTAL_GRAVITY | AVATAR_MOTION_OBEY_LOCAL_GRAVITY))) { + _gravity = glm::vec3(0.0f); } } @@ -1164,7 +1175,14 @@ void MyAvatar::setCollisionGroups(quint32 collisionGroups) { void MyAvatar::setMotionBehaviors(quint32 flags) { _motionBehaviors = flags; Menu* menu = Menu::getInstance(); - menu->setIsOptionChecked(MenuOption::ObeyGravity, (bool)(_motionBehaviors & AVATAR_MOTION_OBEY_GRAVITY)); + menu->setIsOptionChecked(MenuOption::ObeyEnvironmentalGravity, (bool)(_motionBehaviors & AVATAR_MOTION_OBEY_ENVIRONMENTAL_GRAVITY)); + // Environmental and Local gravities are incompatible. Environmental setting trumps local. + if (_motionBehaviors & AVATAR_MOTION_OBEY_ENVIRONMENTAL_GRAVITY) { + _motionBehaviors &= ~AVATAR_MOTION_OBEY_LOCAL_GRAVITY; + setGravity(Application::getInstance()->getEnvironment()->getGravity(getPosition())); + } else if (! (_motionBehaviors & (AVATAR_MOTION_OBEY_ENVIRONMENTAL_GRAVITY | AVATAR_MOTION_OBEY_LOCAL_GRAVITY))) { + _gravity = glm::vec3(0.0f); + } } 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 8d0b4b99d9..a5312b0016 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -29,6 +29,7 @@ class MyAvatar : public Avatar { Q_OBJECT Q_PROPERTY(bool shouldRenderLocally READ getShouldRenderLocally WRITE setShouldRenderLocally) Q_PROPERTY(quint32 motionBehaviors READ getMotionBehaviors WRITE setMotionBehaviors) + Q_PROPERTY(glm::vec3 gravity READ getGravity WRITE setLocalGravity) public: MyAvatar(); @@ -50,8 +51,7 @@ public: void setMousePressed(bool mousePressed) { _mousePressed = mousePressed; } void setVelocity(const glm::vec3 velocity) { _velocity = velocity; } void setLeanScale(float scale) { _leanScale = scale; } - void setGravity(glm::vec3 gravity); - void setMoveTarget(const glm::vec3 moveTarget); + void setLocalGravity(glm::vec3 gravity); void setShouldRenderLocally(bool shouldRender) { _shouldRender = shouldRender; } // getters @@ -121,6 +121,7 @@ private: bool _shouldJump; float _driveKeys[MAX_DRIVE_KEYS]; glm::vec3 _gravity; + glm::vec3 _environmentGravity; float _distanceToNearestAvatar; // How close is the nearest avatar? // motion stuff @@ -149,6 +150,7 @@ private: void updateCollisionSound(const glm::vec3& penetration, float deltaTime, float frequency); void updateChatCircle(float deltaTime); void maybeUpdateBillboard(); + void setGravity(const glm::vec3& gravity); }; #endif // hifi_MyAvatar_h diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 494d86ebda..be47aed1ba 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -51,7 +51,8 @@ typedef unsigned long long quint64; #include "HandData.h" // avatar motion behaviors -const quint32 AVATAR_MOTION_OBEY_GRAVITY = 1U << 0; +const quint32 AVATAR_MOTION_OBEY_ENVIRONMENTAL_GRAVITY = 1U << 0; +const quint32 AVATAR_MOTION_OBEY_LOCAL_GRAVITY = 1U << 1; // First bitset const int KEY_STATE_START_BIT = 0; // 1st and 2nd bits diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 7c57cc92e4..b8b755e099 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -239,7 +239,8 @@ void ScriptEngine::init() { globalObject.setProperty("COLLISION_GROUP_VOXELS", _engine.newVariant(QVariant(COLLISION_GROUP_VOXELS))); globalObject.setProperty("COLLISION_GROUP_PARTICLES", _engine.newVariant(QVariant(COLLISION_GROUP_PARTICLES))); - globalObject.setProperty("AVATAR_MOTION_OBEY_GRAVITY", _engine.newVariant(QVariant(AVATAR_MOTION_OBEY_GRAVITY))); + globalObject.setProperty("AVATAR_MOTION_OBEY_LOCAL_GRAVITY", _engine.newVariant(QVariant(AVATAR_MOTION_OBEY_LOCAL_GRAVITY))); + globalObject.setProperty("AVATAR_MOTION_OBEY_ENVIRONMENTAL_GRAVITY", _engine.newVariant(QVariant(AVATAR_MOTION_OBEY_ENVIRONMENTAL_GRAVITY))); // let the VoxelPacketSender know how frequently we plan to call it _voxelsScriptingInterface.getVoxelPacketSender()->setProcessCallIntervalHint(SCRIPT_DATA_CALLBACK_USECS); From ae3b58a33f6172693293deca12a914a93044cebf Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 28 Apr 2014 16:46:16 -0700 Subject: [PATCH 21/27] use setGravity() instead of setting it directly --- interface/src/avatar/MyAvatar.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 0a3e788042..40e350dcb7 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -126,7 +126,7 @@ void MyAvatar::update(float deltaTime) { head->setAudioAverageLoudness(audio->getAudioAverageInputLoudness()); if (_motionBehaviors & AVATAR_MOTION_OBEY_ENVIRONMENTAL_GRAVITY) { - _gravity = Application::getInstance()->getEnvironment()->getGravity(getPosition()); + setGravity(Application::getInstance()->getEnvironment()->getGravity(getPosition())); } simulate(deltaTime); @@ -1159,7 +1159,7 @@ void MyAvatar::updateMotionBehaviors() { _motionBehaviors &= ~AVATAR_MOTION_OBEY_LOCAL_GRAVITY; } if (! (_motionBehaviors & (AVATAR_MOTION_OBEY_ENVIRONMENTAL_GRAVITY | AVATAR_MOTION_OBEY_LOCAL_GRAVITY))) { - _gravity = glm::vec3(0.0f); + setGravity(glm::vec3(0.0f)); } } @@ -1181,7 +1181,7 @@ void MyAvatar::setMotionBehaviors(quint32 flags) { _motionBehaviors &= ~AVATAR_MOTION_OBEY_LOCAL_GRAVITY; setGravity(Application::getInstance()->getEnvironment()->getGravity(getPosition())); } else if (! (_motionBehaviors & (AVATAR_MOTION_OBEY_ENVIRONMENTAL_GRAVITY | AVATAR_MOTION_OBEY_LOCAL_GRAVITY))) { - _gravity = glm::vec3(0.0f); + setGravity(glm::vec3(0.0f)); } } From 4937a0af2e9606a2cdfa548f7a4e176b07fc4678 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 28 Apr 2014 17:29:44 -0700 Subject: [PATCH 22/27] add status button for local gravity --- examples/swissArmyJetpack.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/examples/swissArmyJetpack.js b/examples/swissArmyJetpack.js index a7fab772dc..db3368d251 100644 --- a/examples/swissArmyJetpack.js +++ b/examples/swissArmyJetpack.js @@ -13,15 +13,16 @@ // // misc global constants -var NUMBER_OF_BUTTONS = 3; +var NUMBER_OF_COLLISION_BUTTONS = 3; +var NUMBER_OF_BUTTONS = 4; var DOWN = { x: 0.0, y: -1.0, z: 0.0 }; -var MAX_VOXEL_SCAN_DISTANCE = 20.0; +var MAX_VOXEL_SCAN_DISTANCE = 30.0; // behavior transition thresholds var MIN_FLYING_SPEED = 1.0; var MIN_COLLISIONLESS_SPEED = 5.0; -var MAX_WALKING_SPEED = 10.0; -var MAX_COLLIDABLE_SPEED = 25.0; +var MAX_WALKING_SPEED = 30.0; +var MAX_COLLIDABLE_SPEED = 35.0; // button URL and geometry/UI tuning var BUTTON_IMAGE_URL = "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/testing-swatches.svg"; @@ -70,17 +71,20 @@ var labelContents = new Array(); labelContents[0] = "Collide with Avatars"; labelContents[1] = "Collide with Voxels"; labelContents[2] = "Collide with Particles"; +labelContents[3] = "Use local gravity"; var groupBits = 0; 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}; +enabledColors[3] = { red: 255, green: 255, blue: 0}; 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}; +disabledColors[2] = { red: 75, green: 75, blue: 90}; +disabledColors[3] = { red: 90, green: 90, blue: 75}; var buttonStates = new Array(); @@ -195,11 +199,13 @@ function update(deltaTime) { if ((gravityOnExpiry < now) && (distance < MAX_VOXEL_SCAN_DISTANCE)) { // NOTE: setting the gravity automatically sets the AVATAR_MOTION_OBEY_LOCAL_GRAVITY behavior bit. MyAvatar.gravity = DOWN; + updateButton(3, true); } } } else { if (MyAvatar.motionBehaviors & AVATAR_MOTION_OBEY_LOCAL_GRAVITY) { MyAvatar.motionBehaviors = MyAvatar.motionBehaviors & ~AVATAR_MOTION_OBEY_LOCAL_GRAVITY; + updateButton(3, false); } gravityOnExpiry = now + EXPIRY_PERIOD; } @@ -220,6 +226,7 @@ function update(deltaTime) { if (MyAvatar.motionBehaviors & AVATAR_MOTION_OBEY_LOCAL_GRAVITY) { // turn off gravity MyAvatar.motionBehaviors = MyAvatar.motionBehaviors & ~AVATAR_MOTION_OBEY_LOCAL_GRAVITY; + updateButton(3, false); } } if (speed > MAX_COLLIDABLE_SPEED) { @@ -236,7 +243,7 @@ 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 < NUMBER_OF_BUTTONS; i++) { + for (i = 0; i < NUMBER_OF_COLLISION_BUTTONS; i++) { if (clickedOverlay == buttons[i]) { var enabled = !(buttonStates[i]); updateButton(i, enabled); From 87c10e70cd52d4bf5d77e5a422e92aac6ad37593 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 28 Apr 2014 18:31:50 -0700 Subject: [PATCH 23/27] Add parentheses around conditionals for clarity --- interface/src/ui/FramelessDialog.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/FramelessDialog.cpp b/interface/src/ui/FramelessDialog.cpp index 4566353af1..71c58078d2 100644 --- a/interface/src/ui/FramelessDialog.cpp +++ b/interface/src/ui/FramelessDialog.cpp @@ -116,15 +116,15 @@ void FramelessDialog::resizeAndPosition(bool resizeParent) { void FramelessDialog::mousePressEvent(QMouseEvent* mouseEvent) { if (mouseEvent->button() == Qt::LeftButton) { if (_position == POSITION_LEFT || _position == POSITION_RIGHT) { - bool hitLeft = _position == POSITION_LEFT && abs(mouseEvent->pos().x() - size().width()) < RESIZE_HANDLE_WIDTH; - bool hitRight = _position == POSITION_RIGHT && mouseEvent->pos().x() < RESIZE_HANDLE_WIDTH; + bool hitLeft = (_position == POSITION_LEFT) && (abs(mouseEvent->pos().x() - size().width()) < RESIZE_HANDLE_WIDTH); + bool hitRight = (_position == POSITION_RIGHT) && (mouseEvent->pos().x() < RESIZE_HANDLE_WIDTH); if (hitLeft || hitRight) { _isResizing = true; _resizeInitialWidth = size().width(); QApplication::setOverrideCursor(Qt::SizeHorCursor); } } else { - bool hitTop = _position == POSITION_TOP && abs(mouseEvent->pos().y() - size().height()) < RESIZE_HANDLE_WIDTH; + bool hitTop = (_position == POSITION_TOP) && (abs(mouseEvent->pos().y() - size().height()) < RESIZE_HANDLE_WIDTH); if (hitTop) { _isResizing = true; _resizeInitialWidth = size().height(); From 2c7fcada3b3d6fa928d91145c1e7a9b2c4ff8c76 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 29 Apr 2014 10:00:12 -0700 Subject: [PATCH 24/27] make gravity transitions faster --- examples/swissArmyJetpack.js | 91 +++++++++++++++++++++++++----------- 1 file changed, 64 insertions(+), 27 deletions(-) diff --git a/examples/swissArmyJetpack.js b/examples/swissArmyJetpack.js index db3368d251..fb4dc1dc04 100644 --- a/examples/swissArmyJetpack.js +++ b/examples/swissArmyJetpack.js @@ -19,7 +19,7 @@ var DOWN = { x: 0.0, y: -1.0, z: 0.0 }; var MAX_VOXEL_SCAN_DISTANCE = 30.0; // behavior transition thresholds -var MIN_FLYING_SPEED = 1.0; +var MIN_FLYING_SPEED = 3.0; var MIN_COLLISIONLESS_SPEED = 5.0; var MAX_WALKING_SPEED = 30.0; var MAX_COLLIDABLE_SPEED = 35.0; @@ -38,11 +38,16 @@ var TEXT_HEIGHT = BUTTON_HEIGHT; var TEXT_WIDTH = 210; var MSEC_PER_SECOND = 1000; -var EXPIRY_PERIOD = 2 * MSEC_PER_SECOND; +var RAYCAST_EXPIRY_PERIOD = MSEC_PER_SECOND / 16; +var COLLISION_EXPIRY_PERIOD = 2 * MSEC_PER_SECOND; +var GRAVITY_ON_EXPIRY_PERIOD = MSEC_PER_SECOND / 2; +var GRAVITY_OFF_EXPIRY_PERIOD = MSEC_PER_SECOND / 8; var dater = new Date(); -var collisionOnExpiry = dater.getTime() + EXPIRY_PERIOD; -var gravityOnExpiry = dater.getTime() + EXPIRY_PERIOD; +var raycastExpiry = dater.getTime() + RAYCAST_EXPIRY_PERIOD; +var gravityOnExpiry = dater.getTime() + GRAVITY_ON_EXPIRY_PERIOD; +var gravityOffExpiry = dater.getTime() + GRAVITY_OFF_EXPIRY_PERIOD; +var collisionOnExpiry = dater.getTime() + COLLISION_EXPIRY_PERIOD; // avatar state var velocity = { x: 0.0, y: 0.0, z: 0.0 }; @@ -169,6 +174,19 @@ function updateSpeedometerDisplay() { } Script.setInterval(updateSpeedometerDisplay, 100); +function disableArtificialGravity() { + MyAvatar.motionBehaviors = MyAvatar.motionBehaviors & ~AVATAR_MOTION_OBEY_LOCAL_GRAVITY; + updateButton(3, false); +} + +function enableArtificialGravity() { + // NOTE: setting the gravity automatically sets the AVATAR_MOTION_OBEY_LOCAL_GRAVITY behavior bit. + MyAvatar.gravity = DOWN; + updateButton(3, true); + // also enable collisions with voxels + groupBits |= COLLISION_GROUP_VOXELS; + updateButton(1, groupBits & COLLISION_GROUP_VOXELS); +} // Our update() function is called at approximately 60fps, and we will use it to animate our various overlays function update(deltaTime) { @@ -187,31 +205,57 @@ function update(deltaTime) { dater = new Date(); var now = dater.getTime(); - if (speed < MIN_FLYING_SPEED) { + // transition gravity + if (raycastExpiry < now) { // scan for landing platform ray = { origin: MyAvatar.position, direction: DOWN }; var intersection = Voxels.findRayIntersection(ray); + // NOTE: it is possible for intersection.intersects to be false when it should be true + // (perhaps the raycast failed to lock the octree thread?). To workaround this problem + // we only transition on repeated failures. + if (intersection.intersects) { - if (!(MyAvatar.motionBehaviors & AVATAR_MOTION_OBEY_LOCAL_GRAVITY)) { - var v = intersection.voxel; - var maxCorner = Vec3.sum({ x: v.x, y: v.y, z: v.z }, {x: v.s, y: v.s, z: v.s }); - var distance = lastPosition.y - maxCorner.y; - if ((gravityOnExpiry < now) && (distance < MAX_VOXEL_SCAN_DISTANCE)) { - // NOTE: setting the gravity automatically sets the AVATAR_MOTION_OBEY_LOCAL_GRAVITY behavior bit. - MyAvatar.gravity = DOWN; - updateButton(3, true); + // compute distance to voxel + var v = intersection.voxel; + var maxCorner = Vec3.sum({ x: v.x, y: v.y, z: v.z }, {x: v.s, y: v.s, z: v.s }); + var distance = lastPosition.y - maxCorner.y; + + if (distance < MAX_VOXEL_SCAN_DISTANCE) { + if (speed < MIN_FLYING_SPEED && + gravityOnExpiry < now && + !(MyAvatar.motionBehaviors & AVATAR_MOTION_OBEY_LOCAL_GRAVITY)) { + enableArtificialGravity(); } + if (speed < MAX_WALKING_SPEED) { + gravityOffExpiry = now + GRAVITY_OFF_EXPIRY_PERIOD; + } else if (gravityOffExpiry < now && MyAvatar.motionBehaviors & AVATAR_MOTION_OBEY_LOCAL_GRAVITY) { + disableArtificialGravity(); + } + } else { + // distance too far + if (gravityOffExpiry < now && MyAvatar.motionBehaviors & AVATAR_MOTION_OBEY_LOCAL_GRAVITY) { + disableArtificialGravity(); + } + gravityOnExpiry = now + GRAVITY_ON_EXPIRY_PERIOD; } } else { - if (MyAvatar.motionBehaviors & AVATAR_MOTION_OBEY_LOCAL_GRAVITY) { - MyAvatar.motionBehaviors = MyAvatar.motionBehaviors & ~AVATAR_MOTION_OBEY_LOCAL_GRAVITY; - updateButton(3, false); + // no intersection + if (gravityOffExpiry < now && MyAvatar.motionBehaviors & AVATAR_MOTION_OBEY_LOCAL_GRAVITY) { + disableArtificialGravity(); } - gravityOnExpiry = now + EXPIRY_PERIOD; + gravityOnExpiry = now + GRAVITY_ON_EXPIRY_PERIOD; } - } else { - gravityOnExpiry = now + EXPIRY_PERIOD; } + if (speed > MAX_WALKING_SPEED && gravityOffExpiry < now) { + if (MyAvatar.motionBehaviors & AVATAR_MOTION_OBEY_LOCAL_GRAVITY) { + // turn off gravity + MyAvatar.motionBehaviors = MyAvatar.motionBehaviors & ~AVATAR_MOTION_OBEY_LOCAL_GRAVITY; + updateButton(3, false); + } + gravityOnExpiry = now + GRAVITY_ON_EXPIRY_PERIOD; + } + + // transition collidability with voxels if (speed < MIN_COLLISIONLESS_SPEED) { if (collisionOnExpiry < now && !(MyAvatar.collisionGroups & COLLISION_GROUP_VOXELS)) { // TODO: check to make sure not already colliding @@ -220,14 +264,7 @@ function update(deltaTime) { updateButton(1, groupBits & COLLISION_GROUP_VOXELS); } } else { - collisionOnExpiry = now + EXPIRY_PERIOD; - } - if (speed > MAX_WALKING_SPEED) { - if (MyAvatar.motionBehaviors & AVATAR_MOTION_OBEY_LOCAL_GRAVITY) { - // turn off gravity - MyAvatar.motionBehaviors = MyAvatar.motionBehaviors & ~AVATAR_MOTION_OBEY_LOCAL_GRAVITY; - updateButton(3, false); - } + collisionOnExpiry = now + COLLISION_EXPIRY_PERIOD; } if (speed > MAX_COLLIDABLE_SPEED) { if (MyAvatar.collisionGroups & COLLISION_GROUP_VOXELS) { From ac8adad0e07d3d088813bb31047a6820884f6953 Mon Sep 17 00:00:00 2001 From: Konstantin Date: Tue, 29 Apr 2014 20:49:20 +0200 Subject: [PATCH 25/27] Remove 0,0,0 entry. --- interface/src/Menu.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 524e496acc..8ae2380aa3 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -935,9 +935,6 @@ void Menu::goTo() { // location coordinates or place name QString domain = urlParts[0]; goToDomain(domain); - // as there are no coordinates, go to 0,0,0 - QString destination = "0,0,0"; - goTo(destination); } else if (urlParts.count() > 1) { // if url has 2 or more parts, the first one is domain name From 14b91aa04bced778e1ef886ec176bf2d9daf7fdc Mon Sep 17 00:00:00 2001 From: Konstantin Date: Tue, 29 Apr 2014 20:49:40 +0200 Subject: [PATCH 26/27] Remove 0,0,0 entry --- interface/src/Application.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ee4862d515..1138c6b183 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3582,9 +3582,6 @@ void Application::urlGoTo(int argc, const char * constArgv[]) { // location coordinates or place name QString domain = urlParts[0]; Menu::goToDomain(domain); - // as there are no coordinates, go to 0,0,0 - QString destination = "0,0,0"; - Menu::goTo(destination); } else if (urlParts.count() > 1) { // if url has 2 or more parts, the first one is domain name QString domain = urlParts[0]; From 65706ae5f73fa0dc043bde2ea96e5c369c07c41f Mon Sep 17 00:00:00 2001 From: Konstantin Date: Tue, 29 Apr 2014 20:59:33 +0200 Subject: [PATCH 27/27] Re-add customUrl.startWith --- interface/src/Application.cpp | 56 ++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1138c6b183..457f884c8c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3577,31 +3577,33 @@ void Application::takeSnapshot() { void Application::urlGoTo(int argc, const char * constArgv[]) { //Gets the url (hifi://domain/destination/orientation) QString customUrl = getCmdOption(argc, constArgv, "-url"); - QStringList urlParts = customUrl.remove(0, CUSTOM_URL_SCHEME.length() + 2).split('/', QString::SkipEmptyParts); - if (urlParts.count() == 1) { - // location coordinates or place name - QString domain = urlParts[0]; - Menu::goToDomain(domain); - } else if (urlParts.count() > 1) { - // if url has 2 or more parts, the first one is domain name - QString domain = urlParts[0]; - - // second part is either a destination coordinate or - // a place name - QString destination = urlParts[1]; - - // any third part is an avatar orientation. - QString orientation = urlParts.count() > 2 ? urlParts[2] : QString(); - - Menu::goToDomain(domain); - - // goto either @user, #place, or x-xx,y-yy,z-zz - // style co-ordinate. - Menu::goTo(destination); - - if (!orientation.isEmpty()) { - // location orientation - Menu::goToOrientation(orientation); - } - } + if(customUrl.startsWith(CUSTOM_URL_SCHEME + "//")) { + QStringList urlParts = customUrl.remove(0, CUSTOM_URL_SCHEME.length() + 2).split('/', QString::SkipEmptyParts); + if (urlParts.count() == 1) { + // location coordinates or place name + QString domain = urlParts[0]; + Menu::goToDomain(domain); + } else if (urlParts.count() > 1) { + // if url has 2 or more parts, the first one is domain name + QString domain = urlParts[0]; + + // second part is either a destination coordinate or + // a place name + QString destination = urlParts[1]; + + // any third part is an avatar orientation. + QString orientation = urlParts.count() > 2 ? urlParts[2] : QString(); + + Menu::goToDomain(domain); + + // goto either @user, #place, or x-xx,y-yy,z-zz + // style co-ordinate. + Menu::goTo(destination); + + if (!orientation.isEmpty()) { + // location orientation + Menu::goToOrientation(orientation); + } + } + } }