From 87358002bdc68b63901d49436bac0781e0c166de Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Sat, 9 Aug 2014 23:30:14 -0700 Subject: [PATCH 01/46] Add MyAvatar::setVelocity --- interface/src/avatar/MyAvatar.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 4f2802a35a..6e93eb8046 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -53,7 +53,6 @@ public: // setters void setMousePressed(bool mousePressed) { _mousePressed = mousePressed; } - void setVelocity(const glm::vec3 velocity) { _velocity = velocity; } void setLeanScale(float scale) { _leanScale = scale; } void setLocalGravity(glm::vec3 gravity); void setShouldRenderLocally(bool shouldRender) { _shouldRender = shouldRender; } @@ -146,6 +145,8 @@ public slots: glm::vec3 getThrust() { return _thrust; }; void setThrust(glm::vec3 newThrust) { _thrust = newThrust; } + void setVelocity(const glm::vec3 velocity) { _velocity = velocity; } + void updateMotionBehaviorsFromMenu(); glm::vec3 getLeftPalmPosition(); From 23a760dfcf88daa2f79a1e40e8eab12fcfb37220 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Sat, 9 Aug 2014 23:30:48 -0700 Subject: [PATCH 02/46] Add exstra functionality to script Window interface --- .../src/scripting/WindowScriptingInterface.cpp | 18 ++++++++++++++++++ .../src/scripting/WindowScriptingInterface.h | 4 ++++ 2 files changed, 22 insertions(+) diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index ea0eeb0dd9..c921d2b8b2 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -30,6 +30,24 @@ WindowScriptingInterface* WindowScriptingInterface::getInstance() { WindowScriptingInterface::WindowScriptingInterface() { } +QScriptValue WindowScriptingInterface::hasFocus() { + return Application::getInstance()->getGLWidget()->hasFocus(); +} + +void WindowScriptingInterface::setCursorPosition(int x, int y) { + QCursor::setPos(x, y); +} + +QScriptValue WindowScriptingInterface::getCursorPositionX() { + QPoint pos = QCursor::pos(); + return pos.x(); +} + +QScriptValue WindowScriptingInterface::getCursorPositionY() { + QPoint pos = QCursor::pos(); + return pos.y(); +} + QScriptValue WindowScriptingInterface::alert(const QString& message) { QScriptValue retVal; QMetaObject::invokeMethod(this, "showAlert", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QScriptValue, retVal), Q_ARG(const QString&, message)); diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index b04c927427..988caf57a9 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -26,6 +26,10 @@ public: int getInnerHeight(); public slots: + QScriptValue getCursorPositionX(); + QScriptValue getCursorPositionY(); + void setCursorPosition(int x, int y); + QScriptValue hasFocus(); QScriptValue alert(const QString& message = ""); QScriptValue confirm(const QString& message = ""); QScriptValue form(const QString& title, QScriptValue array); From fc82dfc958a11485a25842d0813fd34e31077cbe Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Sat, 9 Aug 2014 23:31:02 -0700 Subject: [PATCH 03/46] Add Quat::rotate --- libraries/script-engine/src/Quat.cpp | 4 ++++ libraries/script-engine/src/Quat.h | 1 + 2 files changed, 5 insertions(+) diff --git a/libraries/script-engine/src/Quat.cpp b/libraries/script-engine/src/Quat.cpp index 66281883f0..16919d55a2 100644 --- a/libraries/script-engine/src/Quat.cpp +++ b/libraries/script-engine/src/Quat.cpp @@ -42,6 +42,10 @@ glm::quat Quat::inverse(const glm::quat& q) { return glm::inverse(q); } +glm::vec3 Quat::rotate(const glm::quat& q, const glm::vec3& v) { + return glm::rotate(q, v); +} + glm::vec3 Quat::getFront(const glm::quat& orientation) { return orientation * IDENTITY_FRONT; } diff --git a/libraries/script-engine/src/Quat.h b/libraries/script-engine/src/Quat.h index faae636f02..74e80a825b 100644 --- a/libraries/script-engine/src/Quat.h +++ b/libraries/script-engine/src/Quat.h @@ -30,6 +30,7 @@ public slots: glm::quat fromPitchYawRollDegrees(float pitch, float yaw, float roll); // degrees glm::quat fromPitchYawRollRadians(float pitch, float yaw, float roll); // radians glm::quat inverse(const glm::quat& q); + glm::vec3 rotate(const glm::quat& q, const glm::vec3& v); glm::vec3 getFront(const glm::quat& orientation); glm::vec3 getRight(const glm::quat& orientation); glm::vec3 getUp(const glm::quat& orientation); From c5f672e4af9ce5e95b39d4993d564ecd02b9cebc Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Sat, 9 Aug 2014 23:31:28 -0700 Subject: [PATCH 04/46] Add gracefulControls.js --- examples/gracefulControls.js | 176 +++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 examples/gracefulControls.js diff --git a/examples/gracefulControls.js b/examples/gracefulControls.js new file mode 100644 index 0000000000..0017af65c1 --- /dev/null +++ b/examples/gracefulControls.js @@ -0,0 +1,176 @@ +// Coefficient to use for linear drag. Higher numbers will cause motion to +// slow down more quickly. +var DRAG_COEFFICIENT = 1.0; +var MAX_SPEED = 1000.0; +var MAX_LOOK_SPEED = Math.PI * 2; +var ACCELERATION = 200; + +var MOUSE_YAW_SCALE = -0.125; +var MOUSE_PITCH_SCALE = -0.125; +var MOUSE_SENSITIVITY = 1.0; + +// Adjust this to change the mouse look damping behavior. Keep it below 1. +var W = 0.9; + +// Movement keys +var KEY_FORWARD = "g"; +var KEY_BACKWARD = "b"; +var KEY_LEFT = "v"; +var KEY_RIGHT = "n"; +var KEY_UP = "y"; +var KEY_DOWN = "h"; +var CAPTURED_KEYS = [KEY_FORWARD, KEY_BACKWARD, KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN]; + +// Global Variables +var keys = {}; +var velocity = { x: 0, y: 0, z: 0 }; +var enabled = true; + +var lastX = 0; +var lastY = 0; +var yawFromMouse = 0; +var pitchFromMouse = 0; +var maxAccel = Math.PI / 1; + +var yawSpeed = 0; +var pitchSpeed = 0; + +function keyPressEvent(event) { + if (event.text == "ESC") { + disable(); + } else if (event.text == " ") { + if (Window.hasFocus()) { + enable(); + } + } + keys[event.text] = true; +} + +function keyReleaseEvent(event) { + delete keys[event.text]; +} + +function mouseMoveEvent(event) { + if (enabled) { + var MOUSE_YAW_SCALE = -0.25; + var MOUSE_PITCH_SCALE = -12.5; + var FIXED_MOUSE_TIMESTEP = 0.016; + yawFromMouse += ((event.x - lastX) * MOUSE_YAW_SCALE * FIXED_MOUSE_TIMESTEP); + pitchFromMouse += ((event.y - lastY) * MOUSE_PITCH_SCALE * FIXED_MOUSE_TIMESTEP); + lastX = event.x; + lastY = event.y; + Window.setCursorPosition(Window.innerWidth / 2, Window.innerHeight / 2); + } + +} + +var maxPerSec = 3; +var lastX = Window.getCursorPositionX(); +var lastY = Window.getCursorPositionY(); + +function update(dt) { + var maxMove = 3.0 * dt; + // print("Pos: " + yawFromMouse + ", " + pitchFromMouse); + var targetVelocity = { x: 0, y: 0, z: 0 }; + var accelY = 0; + if (keys[KEY_FORWARD]) { + targetVelocity.z -= ACCELERATION * dt; + } + if (keys[KEY_LEFT]) { + targetVelocity.x -= ACCELERATION * dt; + } + if (keys[KEY_BACKWARD]) { + targetVelocity.z += ACCELERATION * dt; + } + if (keys[KEY_RIGHT]) { + targetVelocity.x += ACCELERATION * dt; + } + if (keys[KEY_UP]) { + accelY += ACCELERATION * dt; + } + if (keys[KEY_DOWN]) { + accelY -= ACCELERATION * dt; + } + + if (enabled && Window.hasFocus()) { + var x = Window.getCursorPositionX(); + var y = Window.getCursorPositionY(); + + yawFromMouse += ((x - lastX) * MOUSE_YAW_SCALE * MOUSE_SENSITIVITY); + pitchFromMouse += ((y - lastY) * MOUSE_PITCH_SCALE * MOUSE_SENSITIVITY); + pitchFromMouse = Math.max(-180, Math.min(180, pitchFromMouse)); + + var newX = Window.innerWidth / 2; + var newY = Window.innerHeight / 2; + Window.setCursorPosition(newX, newY); + + lastX = newX; + lastY = newY; + } + + // Here we use a linear damping model - http://en.wikipedia.org/wiki/Damping#Linear_damping + // Because we are using a critically damped model (no oscillation), ζ = 1 and + // so we derive the formula: acceleration = -(2 * w0 * v) - (w0^2 * x) + yawAccel = (W * W * yawFromMouse) - (2 * W * yawSpeed); + pitchAccel = (W * W * pitchFromMouse) - (2 * W * pitchSpeed); + + yawSpeed += yawAccel * dt; + var yawMove = yawSpeed * dt; + var newOrientation = Quat.multiply(MyAvatar.orientation, Quat.fromVec3Degrees( { x: 0, y: yawMove, z: 0 } )); + MyAvatar.orientation = newOrientation; + yawFromMouse -= yawMove; + + pitchSpeed += pitchAccel * dt; + var pitchMove = pitchSpeed * dt; + var newPitch = MyAvatar.headPitch + pitchMove; + MyAvatar.headPitch = newPitch; + pitchFromMouse -= pitchMove; + + // If force isn't being applied in a direction, add drag; + if (targetVelocity.x == 0) { + targetVelocity.x -= (velocity.x * DRAG_COEFFICIENT * dt); + } + if (targetVelocity.z == 0) { + targetVelocity.z -= (velocity.z * DRAG_COEFFICIENT * dt); + } + velocity = Vec3.sum(velocity, targetVelocity); + + velocity.x = Math.max(-MAX_SPEED, Math.min(MAX_SPEED, velocity.x)); + velocity.z = Math.max(-MAX_SPEED, Math.min(MAX_SPEED, velocity.z)); + var v = Quat.rotate(MyAvatar.headOrientation, velocity); + v.y += accelY * dt; + MyAvatar.setVelocity(v); +} + +function vecToString(vec) { + return vec.x + ", " + vec.y + ", " + vec.z; +} + +function scriptEnding() { + disable(); +} + +function enable() { + enabled = true; + lastX = Window.getCursorPositionX(); + lastY = Window.getCursorPositionY(); + for (var i = 0; i < CAPTURED_KEYS.length; i++) { + Controller.captureKeyEvents({ text: CAPTURED_KEYS[i] }); + } +} + +function disable() { + enabled = false; + for (var i = 0; i < CAPTURED_KEYS.length; i++) { + Controller.releaseKeyEvents({ text: CAPTURED_KEYS[i] }); + } +} + +enable(); + +Controller.keyPressEvent.connect(keyPressEvent); +Controller.keyReleaseEvent.connect(keyReleaseEvent); + +Script.scriptEnding.connect(scriptEnding); + +Script.update.connect(update); From 082f618479ad610f24de20c17ee0d123d0970508 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 14 Aug 2014 22:27:43 -0700 Subject: [PATCH 05/46] Fix bug with KeyEvent key values on lowercase characters --- libraries/script-engine/src/EventTypes.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/script-engine/src/EventTypes.cpp b/libraries/script-engine/src/EventTypes.cpp index 9cf6c5b1a0..e1930040d3 100644 --- a/libraries/script-engine/src/EventTypes.cpp +++ b/libraries/script-engine/src/EventTypes.cpp @@ -249,7 +249,9 @@ void keyEventFromScriptValue(const QScriptValue& object, KeyEvent& event) { } else if (event.text.toUpper() == "CAPS LOCK") { event.key = Qt::Key_CapsLock; } else { - event.key = event.text.at(0).unicode(); + // Key values do not distinguish between uppercase and lowercase + // and use the uppercase key value. + event.key = event.text.toUpper().at(0).unicode(); } event.isValid = true; } From 7d11994cceef026a5efadd3b31802d402994f698 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 14 Aug 2014 22:37:23 -0700 Subject: [PATCH 06/46] Add cursor hiding to gracefulControls.js --- examples/gracefulControls.js | 4 ++-- interface/src/Application.cpp | 8 ++++++++ interface/src/Application.h | 2 ++ interface/src/scripting/WindowScriptingInterface.cpp | 4 ++++ interface/src/scripting/WindowScriptingInterface.h | 1 + 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/examples/gracefulControls.js b/examples/gracefulControls.js index 0017af65c1..8cfc25c011 100644 --- a/examples/gracefulControls.js +++ b/examples/gracefulControls.js @@ -157,6 +157,7 @@ function enable() { for (var i = 0; i < CAPTURED_KEYS.length; i++) { Controller.captureKeyEvents({ text: CAPTURED_KEYS[i] }); } + Window.setCursorVisible(false); } function disable() { @@ -164,10 +165,9 @@ function disable() { for (var i = 0; i < CAPTURED_KEYS.length; i++) { Controller.releaseKeyEvents({ text: CAPTURED_KEYS[i] }); } + Window.setCursorVisible(true); } -enable(); - Controller.keyPressEvent.connect(keyPressEvent); Controller.keyReleaseEvent.connect(keyReleaseEvent); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6f7212e68f..cc5d9a001f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4027,6 +4027,14 @@ void Application::skipVersion(QString latestVersion) { skipFile.write(latestVersion.toStdString().c_str()); } +void Application::setCursorVisible(bool visible) { + if (visible) { + restoreOverrideCursor(); + } else { + setOverrideCursor(Qt::BlankCursor); + } +} + void Application::takeSnapshot() { QMediaPlayer* player = new QMediaPlayer(); QFileInfo inf = QFileInfo(Application::resourcesPath() + "sounds/snap.wav"); diff --git a/interface/src/Application.h b/interface/src/Application.h index c898d10cbd..0cfcfba62f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -297,6 +297,8 @@ public: QStringList getRunningScripts() { return _scriptEnginesHash.keys(); } ScriptEngine* getScriptEngine(QString scriptHash) { return _scriptEnginesHash.contains(scriptHash) ? _scriptEnginesHash[scriptHash] : NULL; } + void setCursorVisible(bool visible); + signals: /// Fired when we're simulating; allows external parties to hook in. diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index c921d2b8b2..c73cbfd368 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -34,6 +34,10 @@ QScriptValue WindowScriptingInterface::hasFocus() { return Application::getInstance()->getGLWidget()->hasFocus(); } +void WindowScriptingInterface::setCursorVisible(bool visible) { + Application::getInstance()->setCursorVisible(visible); +} + void WindowScriptingInterface::setCursorPosition(int x, int y) { QCursor::setPos(x, y); } diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 988caf57a9..f55cf4c955 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -29,6 +29,7 @@ public slots: QScriptValue getCursorPositionX(); QScriptValue getCursorPositionY(); void setCursorPosition(int x, int y); + void setCursorVisible(bool visible); QScriptValue hasFocus(); QScriptValue alert(const QString& message = ""); QScriptValue confirm(const QString& message = ""); From b03c9842960ec2659942f333b229bad7c12e8f2e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 14 Aug 2014 22:38:04 -0700 Subject: [PATCH 07/46] Update keys for gracefulControls.js and a few other minor changes --- examples/gracefulControls.js | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/examples/gracefulControls.js b/examples/gracefulControls.js index 8cfc25c011..8551fcc3e1 100644 --- a/examples/gracefulControls.js +++ b/examples/gracefulControls.js @@ -13,17 +13,18 @@ var MOUSE_SENSITIVITY = 1.0; var W = 0.9; // Movement keys -var KEY_FORWARD = "g"; -var KEY_BACKWARD = "b"; -var KEY_LEFT = "v"; -var KEY_RIGHT = "n"; -var KEY_UP = "y"; -var KEY_DOWN = "h"; +var KEY_FORWARD = "w"; +var KEY_BACKWARD = "s"; +var KEY_LEFT = "a"; +var KEY_RIGHT = "d"; +var KEY_UP = "e"; +var KEY_DOWN = "c"; var CAPTURED_KEYS = [KEY_FORWARD, KEY_BACKWARD, KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN]; // Global Variables var keys = {}; var velocity = { x: 0, y: 0, z: 0 }; +var velocityVertical = 0; var enabled = true; var lastX = 0; @@ -72,7 +73,8 @@ function update(dt) { var maxMove = 3.0 * dt; // print("Pos: " + yawFromMouse + ", " + pitchFromMouse); var targetVelocity = { x: 0, y: 0, z: 0 }; - var accelY = 0; + var targetVelocityVertical = 0; + if (keys[KEY_FORWARD]) { targetVelocity.z -= ACCELERATION * dt; } @@ -86,10 +88,10 @@ function update(dt) { targetVelocity.x += ACCELERATION * dt; } if (keys[KEY_UP]) { - accelY += ACCELERATION * dt; + targetVelocityVertical += ACCELERATION * dt; } if (keys[KEY_DOWN]) { - accelY -= ACCELERATION * dt; + targetVelocityVertical -= ACCELERATION * dt; } if (enabled && Window.hasFocus()) { @@ -138,7 +140,11 @@ function update(dt) { velocity.x = Math.max(-MAX_SPEED, Math.min(MAX_SPEED, velocity.x)); velocity.z = Math.max(-MAX_SPEED, Math.min(MAX_SPEED, velocity.z)); var v = Quat.rotate(MyAvatar.headOrientation, velocity); - v.y += accelY * dt; + + velocityVertical += targetVelocityVertical; + velocityVertical = Math.max(-MAX_SPEED, Math.min(MAX_SPEED, velocityVertical)); + v.y += velocityVertical; + MyAvatar.setVelocity(v); } @@ -158,6 +164,9 @@ function enable() { Controller.captureKeyEvents({ text: CAPTURED_KEYS[i] }); } Window.setCursorVisible(false); + + Controller.keyPressEvent.connect(keyPressEvent); + Controller.keyReleaseEvent.connect(keyReleaseEvent); } function disable() { @@ -166,10 +175,10 @@ function disable() { Controller.releaseKeyEvents({ text: CAPTURED_KEYS[i] }); } Window.setCursorVisible(true); -} -Controller.keyPressEvent.connect(keyPressEvent); -Controller.keyReleaseEvent.connect(keyReleaseEvent); + Controller.keyPressEvent.disconnect(keyPressEvent); + Controller.keyReleaseEvent.disconnect(keyReleaseEvent); +} Script.scriptEnding.connect(scriptEnding); From a685bbe541b77bfe8f99256279b5f2fa6d710a57 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 14 Aug 2014 22:56:36 -0700 Subject: [PATCH 08/46] Fix bug with gracefulControls.js not enabling --- examples/gracefulControls.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/examples/gracefulControls.js b/examples/gracefulControls.js index 8551fcc3e1..f1948718c3 100644 --- a/examples/gracefulControls.js +++ b/examples/gracefulControls.js @@ -164,9 +164,7 @@ function enable() { Controller.captureKeyEvents({ text: CAPTURED_KEYS[i] }); } Window.setCursorVisible(false); - - Controller.keyPressEvent.connect(keyPressEvent); - Controller.keyReleaseEvent.connect(keyReleaseEvent); + Script.update.connect(update); } function disable() { @@ -175,11 +173,10 @@ function disable() { Controller.releaseKeyEvents({ text: CAPTURED_KEYS[i] }); } Window.setCursorVisible(true); - - Controller.keyPressEvent.disconnect(keyPressEvent); - Controller.keyReleaseEvent.disconnect(keyReleaseEvent); + Script.update.disconnect(update); } -Script.scriptEnding.connect(scriptEnding); +Controller.keyPressEvent.connect(keyPressEvent); +Controller.keyReleaseEvent.disconnect(keyReleaseEvent); -Script.update.connect(update); +Script.scriptEnding.connect(scriptEnding); From 3b60621e78db3b75e6d9b77201b72923e85f7595 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 14 Aug 2014 23:08:07 -0700 Subject: [PATCH 09/46] Fix vertical drag in gracefulControls.js --- examples/gracefulControls.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/gracefulControls.js b/examples/gracefulControls.js index f1948718c3..dd07a38916 100644 --- a/examples/gracefulControls.js +++ b/examples/gracefulControls.js @@ -141,6 +141,9 @@ function update(dt) { velocity.z = Math.max(-MAX_SPEED, Math.min(MAX_SPEED, velocity.z)); var v = Quat.rotate(MyAvatar.headOrientation, velocity); + if (velocityVertical == 0) { + targetVelocityVertical -= (velocityVertical * DRAG_COEFFICIENT * dt); + } velocityVertical += targetVelocityVertical; velocityVertical = Math.max(-MAX_SPEED, Math.min(MAX_SPEED, velocityVertical)); v.y += velocityVertical; From 02b3d130b0f2b79025d3a74c253ad39a8b88a96b Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 14 Aug 2014 23:08:21 -0700 Subject: [PATCH 10/46] Clean up gracefulControls.js --- examples/gracefulControls.js | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/examples/gracefulControls.js b/examples/gracefulControls.js index dd07a38916..b3c01a7ecd 100644 --- a/examples/gracefulControls.js +++ b/examples/gracefulControls.js @@ -1,9 +1,9 @@ // Coefficient to use for linear drag. Higher numbers will cause motion to // slow down more quickly. -var DRAG_COEFFICIENT = 1.0; -var MAX_SPEED = 1000.0; +var DRAG_COEFFICIENT = 0.3; +var MAX_SPEED = 50.0; var MAX_LOOK_SPEED = Math.PI * 2; -var ACCELERATION = 200; +var ACCELERATION = 20; var MOUSE_YAW_SCALE = -0.125; var MOUSE_PITCH_SCALE = -0.125; @@ -27,8 +27,8 @@ var velocity = { x: 0, y: 0, z: 0 }; var velocityVertical = 0; var enabled = true; -var lastX = 0; -var lastY = 0; +var lastX = Window.getCursorPositionX(); +var lastY = Window.getCursorPositionY(); var yawFromMouse = 0; var pitchFromMouse = 0; var maxAccel = Math.PI / 1; @@ -51,24 +51,6 @@ function keyReleaseEvent(event) { delete keys[event.text]; } -function mouseMoveEvent(event) { - if (enabled) { - var MOUSE_YAW_SCALE = -0.25; - var MOUSE_PITCH_SCALE = -12.5; - var FIXED_MOUSE_TIMESTEP = 0.016; - yawFromMouse += ((event.x - lastX) * MOUSE_YAW_SCALE * FIXED_MOUSE_TIMESTEP); - pitchFromMouse += ((event.y - lastY) * MOUSE_PITCH_SCALE * FIXED_MOUSE_TIMESTEP); - lastX = event.x; - lastY = event.y; - Window.setCursorPosition(Window.innerWidth / 2, Window.innerHeight / 2); - } - -} - -var maxPerSec = 3; -var lastX = Window.getCursorPositionX(); -var lastY = Window.getCursorPositionY(); - function update(dt) { var maxMove = 3.0 * dt; // print("Pos: " + yawFromMouse + ", " + pitchFromMouse); @@ -180,6 +162,6 @@ function disable() { } Controller.keyPressEvent.connect(keyPressEvent); -Controller.keyReleaseEvent.disconnect(keyReleaseEvent); +Controller.keyReleaseEvent.connect(keyReleaseEvent); Script.scriptEnding.connect(scriptEnding); From 6d29ef0f41958bae3c0e84afe5820421654cdf94 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 5 Sep 2014 10:45:22 -0700 Subject: [PATCH 11/46] Add brake to gracefulMovement.js --- examples/gracefulControls.js | 110 ++++++++++++++++++++++++----------- 1 file changed, 76 insertions(+), 34 deletions(-) diff --git a/examples/gracefulControls.js b/examples/gracefulControls.js index b3c01a7ecd..e95f4c6ccf 100644 --- a/examples/gracefulControls.js +++ b/examples/gracefulControls.js @@ -1,18 +1,48 @@ // Coefficient to use for linear drag. Higher numbers will cause motion to // slow down more quickly. -var DRAG_COEFFICIENT = 0.3; +/* +var DRAG_COEFFICIENT = 0.9; var MAX_SPEED = 50.0; var MAX_LOOK_SPEED = Math.PI * 2; -var ACCELERATION = 20; +var ACCELERATION = 15; var MOUSE_YAW_SCALE = -0.125; var MOUSE_PITCH_SCALE = -0.125; -var MOUSE_SENSITIVITY = 1.0; +var MOUSE_SENSITIVITY = 0.5; -// Adjust this to change the mouse look damping behavior. Keep it below 1. -var W = 0.9; +var W = 4.2; +*/ + +var DEFAULT_PARAMETERS = { + DRAG_COEFFICIENT: 0.9, + MAX_SPEED: 50.0, + MAX_LOOK_SPEED: Math.PI * 2, + ACCELERATION: 15, + + MOUSE_YAW_SCALE: -0.125, + MOUSE_PITCH_SCALE: -0.125, + MOUSE_SENSITIVITY: 0.5, + + W: 4.2, +} + +var BRAKE_PARAMETERS = { + DRAG_COEFFICIENT: 4.9, + MAX_SPEED: DEFAULT_PARAMETERS.MAX_SPEED, + MAX_LOOK_SPEED: Math.PI * 2, + ACCELERATION: 15, + + MOUSE_YAW_SCALE: -0.125, + MOUSE_PITCH_SCALE: -0.125, + MOUSE_SENSITIVITY: 0.5, + + W: 1.0, +} + +var movementParameters = DEFAULT_PARAMETERS; // Movement keys +var KEY_BRAKE = "q"; var KEY_FORWARD = "w"; var KEY_BACKWARD = "s"; var KEY_LEFT = "a"; @@ -25,13 +55,12 @@ var CAPTURED_KEYS = [KEY_FORWARD, KEY_BACKWARD, KEY_LEFT, KEY_RIGHT, KEY_UP, KEY var keys = {}; var velocity = { x: 0, y: 0, z: 0 }; var velocityVertical = 0; -var enabled = true; +var enabled = false; var lastX = Window.getCursorPositionX(); var lastY = Window.getCursorPositionY(); var yawFromMouse = 0; var pitchFromMouse = 0; -var maxAccel = Math.PI / 1; var yawSpeed = 0; var pitchSpeed = 0; @@ -39,15 +68,21 @@ var pitchSpeed = 0; function keyPressEvent(event) { if (event.text == "ESC") { disable(); - } else if (event.text == " ") { + } else if (event.text == "SPACE") { if (Window.hasFocus()) { enable(); } + } else if (event.text == KEY_BRAKE) { + movementParameters = BRAKE_PARAMETERS; } keys[event.text] = true; } function keyReleaseEvent(event) { + if (event.text == KEY_BRAKE) { + movementParameters = DEFAULT_PARAMETERS; + } + delete keys[event.text]; } @@ -56,32 +91,33 @@ function update(dt) { // print("Pos: " + yawFromMouse + ", " + pitchFromMouse); var targetVelocity = { x: 0, y: 0, z: 0 }; var targetVelocityVertical = 0; + var acceleration = movementParameters.ACCELERATION; if (keys[KEY_FORWARD]) { - targetVelocity.z -= ACCELERATION * dt; + targetVelocity.z -= acceleration * dt; } if (keys[KEY_LEFT]) { - targetVelocity.x -= ACCELERATION * dt; + targetVelocity.x -= acceleration * dt; } if (keys[KEY_BACKWARD]) { - targetVelocity.z += ACCELERATION * dt; + targetVelocity.z += acceleration * dt; } if (keys[KEY_RIGHT]) { - targetVelocity.x += ACCELERATION * dt; + targetVelocity.x += acceleration * dt; } if (keys[KEY_UP]) { - targetVelocityVertical += ACCELERATION * dt; + targetVelocityVertical += acceleration * dt; } if (keys[KEY_DOWN]) { - targetVelocityVertical -= ACCELERATION * dt; + targetVelocityVertical -= acceleration * dt; } if (enabled && Window.hasFocus()) { var x = Window.getCursorPositionX(); var y = Window.getCursorPositionY(); - yawFromMouse += ((x - lastX) * MOUSE_YAW_SCALE * MOUSE_SENSITIVITY); - pitchFromMouse += ((y - lastY) * MOUSE_PITCH_SCALE * MOUSE_SENSITIVITY); + yawFromMouse += ((x - lastX) * movementParameters.MOUSE_YAW_SCALE * movementParameters.MOUSE_SENSITIVITY); + pitchFromMouse += ((y - lastY) * movementParameters.MOUSE_PITCH_SCALE * movementParameters.MOUSE_SENSITIVITY); pitchFromMouse = Math.max(-180, Math.min(180, pitchFromMouse)); var newX = Window.innerWidth / 2; @@ -95,6 +131,7 @@ function update(dt) { // Here we use a linear damping model - http://en.wikipedia.org/wiki/Damping#Linear_damping // Because we are using a critically damped model (no oscillation), ζ = 1 and // so we derive the formula: acceleration = -(2 * w0 * v) - (w0^2 * x) + var W = movementParameters.W; yawAccel = (W * W * yawFromMouse) - (2 * W * yawSpeed); pitchAccel = (W * W * pitchFromMouse) - (2 * W * pitchSpeed); @@ -112,22 +149,23 @@ function update(dt) { // If force isn't being applied in a direction, add drag; if (targetVelocity.x == 0) { - targetVelocity.x -= (velocity.x * DRAG_COEFFICIENT * dt); + targetVelocity.x -= (velocity.x * movementParameters.DRAG_COEFFICIENT * dt); } if (targetVelocity.z == 0) { - targetVelocity.z -= (velocity.z * DRAG_COEFFICIENT * dt); + targetVelocity.z -= (velocity.z * movementParameters.DRAG_COEFFICIENT * dt); } velocity = Vec3.sum(velocity, targetVelocity); - velocity.x = Math.max(-MAX_SPEED, Math.min(MAX_SPEED, velocity.x)); - velocity.z = Math.max(-MAX_SPEED, Math.min(MAX_SPEED, velocity.z)); + var maxSpeed = movementParameters.MAX_SPEED; + velocity.x = Math.max(-maxSpeed, Math.min(maxSpeed, velocity.x)); + velocity.z = Math.max(-maxSpeed, Math.min(maxSpeed, velocity.z)); var v = Quat.rotate(MyAvatar.headOrientation, velocity); if (velocityVertical == 0) { - targetVelocityVertical -= (velocityVertical * DRAG_COEFFICIENT * dt); + targetVelocityVertical -= (velocityVertical * movementParameters.DRAG_COEFFICIENT * dt); } velocityVertical += targetVelocityVertical; - velocityVertical = Math.max(-MAX_SPEED, Math.min(MAX_SPEED, velocityVertical)); + velocityVertical = Math.max(-maxSpeed, Math.min(maxSpeed, velocityVertical)); v.y += velocityVertical; MyAvatar.setVelocity(v); @@ -142,23 +180,27 @@ function scriptEnding() { } function enable() { - enabled = true; - lastX = Window.getCursorPositionX(); - lastY = Window.getCursorPositionY(); - for (var i = 0; i < CAPTURED_KEYS.length; i++) { - Controller.captureKeyEvents({ text: CAPTURED_KEYS[i] }); + if (!enabled) { + enabled = true; + lastX = Window.getCursorPositionX(); + lastY = Window.getCursorPositionY(); + for (var i = 0; i < CAPTURED_KEYS.length; i++) { + Controller.captureKeyEvents({ text: CAPTURED_KEYS[i] }); + } + Window.setCursorVisible(false); + Script.update.connect(update); } - Window.setCursorVisible(false); - Script.update.connect(update); } function disable() { - enabled = false; - for (var i = 0; i < CAPTURED_KEYS.length; i++) { - Controller.releaseKeyEvents({ text: CAPTURED_KEYS[i] }); + if (enabled) { + enabled = false; + for (var i = 0; i < CAPTURED_KEYS.length; i++) { + Controller.releaseKeyEvents({ text: CAPTURED_KEYS[i] }); + } + Window.setCursorVisible(true); + //Script.update.disconnect(update); } - Window.setCursorVisible(true); - Script.update.disconnect(update); } Controller.keyPressEvent.connect(keyPressEvent); From 4aecb4b5eb03893c2d06adc58d4183c5c00d19fd Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 5 Sep 2014 11:37:57 -0700 Subject: [PATCH 12/46] Reenable disabling of update in gracefulControls.js --- examples/gracefulControls.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gracefulControls.js b/examples/gracefulControls.js index e95f4c6ccf..ef5ca67349 100644 --- a/examples/gracefulControls.js +++ b/examples/gracefulControls.js @@ -199,7 +199,7 @@ function disable() { Controller.releaseKeyEvents({ text: CAPTURED_KEYS[i] }); } Window.setCursorVisible(true); - //Script.update.disconnect(update); + Script.update.disconnect(update); } } From 9f977ecebd4400c44b758ad55b27ecab121c8e74 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 5 Sep 2014 11:42:38 -0700 Subject: [PATCH 13/46] Fix gracefulControls not resetting movement when enabled --- examples/gracefulControls.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/examples/gracefulControls.js b/examples/gracefulControls.js index ef5ca67349..0584cb401e 100644 --- a/examples/gracefulControls.js +++ b/examples/gracefulControls.js @@ -182,8 +182,20 @@ function scriptEnding() { function enable() { if (!enabled) { enabled = true; - lastX = Window.getCursorPositionX(); - lastY = Window.getCursorPositionY(); + + // Reset mouse position + var newX = Window.innerWidth / 2; + var newY = Window.innerHeight / 2; + Window.setCursorPosition(newX, newY); + lastX = newX; + lastY = newY; + + // Reset movement variables + yawFromMouse = 0; + pitchFromMouse = 0; + yawSpeed = 0; + pitchSpeed = 0; + for (var i = 0; i < CAPTURED_KEYS.length; i++) { Controller.captureKeyEvents({ text: CAPTURED_KEYS[i] }); } From 1088550ed764f8e85e796b5b2a1f4a96454ad6fa Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 5 Sep 2014 11:49:36 -0700 Subject: [PATCH 14/46] Add Window.x/y --- interface/src/scripting/WindowScriptingInterface.cpp | 8 ++++++++ interface/src/scripting/WindowScriptingInterface.h | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 417342b39e..df9c9a7ef4 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -358,3 +358,11 @@ int WindowScriptingInterface::getInnerWidth() { int WindowScriptingInterface::getInnerHeight() { return Application::getInstance()->getWindow()->geometry().height(); } + +int WindowScriptingInterface::getX() { + return Application::getInstance()->getWindow()->x(); +} + +int WindowScriptingInterface::getY() { + return Application::getInstance()->getWindow()->y(); +} diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 571d6c9586..1c4da0249d 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -20,10 +20,14 @@ class WindowScriptingInterface : public QObject { Q_OBJECT Q_PROPERTY(int innerWidth READ getInnerWidth) Q_PROPERTY(int innerHeight READ getInnerHeight) + Q_PROPERTY(int x READ getX) + Q_PROPERTY(int y READ getY) public: static WindowScriptingInterface* getInstance(); int getInnerWidth(); int getInnerHeight(); + int getX(); + int getY(); public slots: QScriptValue getCursorPositionX(); From 5bde350ca656bf5730fd393b8b386d8469f9f072 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 5 Sep 2014 11:51:05 -0700 Subject: [PATCH 15/46] Update gracefulControls.js to work correctly with multiple monitors --- examples/gracefulControls.js | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/examples/gracefulControls.js b/examples/gracefulControls.js index 0584cb401e..8207a4df5e 100644 --- a/examples/gracefulControls.js +++ b/examples/gracefulControls.js @@ -120,12 +120,7 @@ function update(dt) { pitchFromMouse += ((y - lastY) * movementParameters.MOUSE_PITCH_SCALE * movementParameters.MOUSE_SENSITIVITY); pitchFromMouse = Math.max(-180, Math.min(180, pitchFromMouse)); - var newX = Window.innerWidth / 2; - var newY = Window.innerHeight / 2; - Window.setCursorPosition(newX, newY); - - lastX = newX; - lastY = newY; + resetCursorPosition(); } // Here we use a linear damping model - http://en.wikipedia.org/wiki/Damping#Linear_damping @@ -179,16 +174,19 @@ function scriptEnding() { disable(); } +function resetCursorPosition() { + var newX = Window.x + Window.innerWidth / 2; + var newY = Window.y + Window.innerHeight / 2; + Window.setCursorPosition(newX, newY); + lastX = newX; + lastY = newY; +} + function enable() { if (!enabled) { enabled = true; - // Reset mouse position - var newX = Window.innerWidth / 2; - var newY = Window.innerHeight / 2; - Window.setCursorPosition(newX, newY); - lastX = newX; - lastY = newY; + resetCursorPosition(); // Reset movement variables yawFromMouse = 0; From 50c8b964e7248e0e0c82ea86e9c26233661bf260 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 5 Sep 2014 11:55:31 -0700 Subject: [PATCH 16/46] Update gracefulControls.js braking behavior --- examples/gracefulControls.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/gracefulControls.js b/examples/gracefulControls.js index 8207a4df5e..afbdebb18f 100644 --- a/examples/gracefulControls.js +++ b/examples/gracefulControls.js @@ -30,7 +30,7 @@ var BRAKE_PARAMETERS = { DRAG_COEFFICIENT: 4.9, MAX_SPEED: DEFAULT_PARAMETERS.MAX_SPEED, MAX_LOOK_SPEED: Math.PI * 2, - ACCELERATION: 15, + ACCELERATION: 0, MOUSE_YAW_SCALE: -0.125, MOUSE_PITCH_SCALE: -0.125, @@ -49,7 +49,8 @@ var KEY_LEFT = "a"; var KEY_RIGHT = "d"; var KEY_UP = "e"; var KEY_DOWN = "c"; -var CAPTURED_KEYS = [KEY_FORWARD, KEY_BACKWARD, KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN]; +var KEY_ENABLE = "SPACE"; +var CAPTURED_KEYS = [KEY_BRAKE, KEY_FORWARD, KEY_BACKWARD, KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN, KEY_ENABLE]; // Global Variables var keys = {}; @@ -68,7 +69,7 @@ var pitchSpeed = 0; function keyPressEvent(event) { if (event.text == "ESC") { disable(); - } else if (event.text == "SPACE") { + } else if (event.text == KEY_ENABLE) { if (Window.hasFocus()) { enable(); } @@ -88,7 +89,6 @@ function keyReleaseEvent(event) { function update(dt) { var maxMove = 3.0 * dt; - // print("Pos: " + yawFromMouse + ", " + pitchFromMouse); var targetVelocity = { x: 0, y: 0, z: 0 }; var targetVelocityVertical = 0; var acceleration = movementParameters.ACCELERATION; From ee6a90dd546d4ca3b454e9f77f7a5dddd4a08bf3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 10 Sep 2014 15:13:02 -0700 Subject: [PATCH 17/46] allow domain to pass down its ID from config --- domain-server/src/DomainServer.cpp | 6 ++++++ libraries/networking/src/NodeList.cpp | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 56570a4b82..d17caf24f0 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -189,6 +189,12 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { populateDefaultStaticAssignmentsExcludingTypes(parsedTypes); LimitedNodeList* nodeList = LimitedNodeList::createInstance(domainServerPort, domainServerDTLSPort); + + const QString DOMAIN_CONFIG_ID_KEY = "id"; + + // set our LimitedNodeList UUID to match the UUID from our config + // nodes will currently use this to add resources to data-web that relate to our domain + nodeList->setSessionUUID(_argumentVariantMap.value(DOMAIN_CONFIG_ID_KEY).toString()); connect(nodeList, &LimitedNodeList::nodeAdded, this, &DomainServer::nodeAdded); connect(nodeList, &LimitedNodeList::nodeKilled, this, &DomainServer::nodeKilled); diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index d77ef321a8..79a399c621 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -397,7 +397,10 @@ int NodeList::processDomainServerList(const QByteArray& packet) { _numNoReplyDomainCheckIns = 0; // if this was the first domain-server list from this domain, we've now connected - _domainHandler.setIsConnected(true); + if (!_domainHandler.isConnected()) { + _domainHandler.setUUID(uuidFromPacketHeader(packet)); + _domainHandler.setIsConnected(true); + } int readNodes = 0; From 71f2c0b542d088a3034b49dc4822f07dccf8c3a1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 11 Sep 2014 10:14:00 -0700 Subject: [PATCH 18/46] initial addition of the AddressManager with location switch hooked up --- interface/src/Application.cpp | 13 +- interface/src/Menu.cpp | 126 ++----------------- interface/src/Menu.h | 12 +- interface/src/avatar/MyAvatar.cpp | 56 ++++----- interface/src/avatar/MyAvatar.h | 3 +- interface/src/location/LocationManager.cpp | 86 ++++++++----- interface/src/location/LocationManager.h | 7 +- interface/src/ui/ChatMessageArea.cpp | 4 +- interface/src/ui/ChatWindow.cpp | 2 +- interface/src/ui/UserLocationsDialog.cpp | 2 +- libraries/networking/src/AddressManager.cpp | 108 ++++++++++++++++ libraries/networking/src/AddressManager.h | 33 +++++ libraries/networking/src/LimitedNodeList.cpp | 2 +- 13 files changed, 249 insertions(+), 205 deletions(-) create mode 100644 libraries/networking/src/AddressManager.cpp create mode 100644 libraries/networking/src/AddressManager.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 05a195c904..5b1110fbad 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -51,6 +51,7 @@ #include #include +#include #include #include #include @@ -421,6 +422,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : MIDIManager& midiManagerInstance = MIDIManager::getInstance(); midiManagerInstance.openDefaultPort(); #endif + + AddressManager::getInstance().handleLookupString("1.5,2.5,0.0/0.0,-161.98,0.02"); } Application::~Application() { @@ -809,7 +812,7 @@ bool Application::event(QEvent* event) { QFileOpenEvent* fileEvent = static_cast(event); bool isHifiSchemeURL = !fileEvent->url().isEmpty() && fileEvent->url().toLocalFile().startsWith(CUSTOM_URL_SCHEME); if (isHifiSchemeURL) { - Menu::getInstance()->goToURL(fileEvent->url().toLocalFile()); +// Menu::getInstance()->goToURL(fileEvent->url().toLocalFile()); } return false; } @@ -1059,7 +1062,7 @@ void Application::keyPressEvent(QKeyEvent* event) { break; case Qt::Key_At: - Menu::getInstance()->goTo(); +// Menu::getInstance()->goTo(); break; default: event->ignore(); @@ -3360,7 +3363,7 @@ void Application::updateWindowTitle(){ #ifndef WIN32 // crashes with vs2013/win32 qDebug("Application title set to: %s", title.toStdString().c_str()); -#endif !WIN32 +#endif _window->setWindowTitle(title); } @@ -4114,11 +4117,11 @@ void Application::urlGoTo(int argc, const char * constArgv[]) { // goto either @user, #place, or x-xx,y-yy,z-zz // style co-ordinate. - Menu::goTo(destination); +// Menu::goTo(destination); if (!orientation.isEmpty()) { // location orientation - Menu::goToOrientation(orientation); +// Menu::goToOrientation(orientation); } } } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index d7679968ae..48908b12a1 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -183,8 +183,6 @@ Menu::Menu() : Qt::Key_At, this, SLOT(goTo())); - connect(&LocationManager::getInstance(), &LocationManager::multipleDestinationsFound, - this, &Menu::multipleDestinationsDecision); addDisabledActionAndSeparator(fileMenu, "Upload Avatar Model"); addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadHead, 0, Application::getInstance(), SLOT(uploadHead())); @@ -1191,107 +1189,25 @@ void Menu::goToDomainDialog() { sendFakeEnterEvent(); } -void Menu::goToOrientation(QString orientation) { - LocationManager::getInstance().goToOrientation(orientation); -} +void Menu::addressBarDialog() { -bool Menu::goToDestination(QString destination) { - return LocationManager::getInstance().goToDestination(destination); -} - -void Menu::goTo(QString destination) { - LocationManager::getInstance().goTo(destination); -} - -void Menu::goTo() { - - QInputDialog gotoDialog(Application::getInstance()->getWindow()); - gotoDialog.setWindowTitle("Go to"); - gotoDialog.setLabelText("Destination or URL:\n @user, #place, hifi://domain/location/orientation"); + QInputDialog addressBarDialog(Application::getInstance()->getWindow()); + addressBarDialog.setWindowTitle("Address Bar"); + addressBarDialog.setLabelText("place, @user, hifi://domain/path, position/orientation"); QString destination = QString(); - gotoDialog.setTextValue(destination); - gotoDialog.resize(gotoDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, gotoDialog.size().height()); + addressBarDialog.setTextValue(destination); + addressBarDialog.resize(addressBarDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, + addressBarDialog.size().height()); - int dialogReturn = gotoDialog.exec(); - if (dialogReturn == QDialog::Accepted && !gotoDialog.textValue().isEmpty()) { - QString desiredDestination = gotoDialog.textValue(); - if (!goToURL(desiredDestination)) {; - goTo(desiredDestination); - } + int dialogReturn = addressBarDialog.exec(); + if (dialogReturn == QDialog::Accepted && !addressBarDialog.textValue().isEmpty()) { + // let the location manager parse this out and decide what to do with it +// LocationManager::getInstance().handleAddressBarEntry(addressBarDialog.textValue()); } sendFakeEnterEvent(); } -bool Menu::goToURL(QString location) { - if (location.startsWith(CUSTOM_URL_SCHEME + "/")) { - QStringList urlParts = location.remove(0, CUSTOM_URL_SCHEME.length()).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]; - - // any third part is an avatar orientation. - QString orientation = urlParts.count() > 2 ? urlParts[2] : QString(); - - goToDomain(domain); - - // goto either @user, #place, or x-xx,y-yy,z-zz - // style co-ordinate. - goTo(destination); - - if (!orientation.isEmpty()) { - // location orientation - goToOrientation(orientation); - } - } else if (urlParts.count() == 1) { - QString destination = urlParts[0]; - - // If this starts with # or @, treat it as a user/location, otherwise treat it as a domain - if (destination[0] == '#' || destination[0] == '@') { - goTo(destination); - } else { - goToDomain(destination); - } - } - return true; - } - return false; -} - -void Menu::goToUser(const QString& user) { - LocationManager::getInstance().goTo(user); -} - -/// Open a url, shortcutting any "hifi" scheme URLs to the local application. -void Menu::openUrl(const QUrl& url) { - if (url.scheme() == "hifi") { - goToURL(url.toString()); - } else { - QDesktopServices::openUrl(url); - } -} - -void Menu::multipleDestinationsDecision(const QJsonObject& userData, const QJsonObject& placeData) { - QMessageBox msgBox; - msgBox.setText("Both user and location exists with same name"); - msgBox.setInformativeText("Where you wanna go?"); - msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Open); - msgBox.button(QMessageBox::Ok)->setText("User"); - msgBox.button(QMessageBox::Open)->setText("Place"); - int userResponse = msgBox.exec(); - - if (userResponse == QMessageBox::Ok) { - Application::getInstance()->getAvatar()->goToLocationFromAddress(userData["address"].toObject()); - } else if (userResponse == QMessageBox::Open) { - Application::getInstance()->getAvatar()->goToLocationFromAddress(placeData["address"].toObject()); - } -} - void Menu::muteEnvironment() { int headerSize = numBytesForPacketHeaderGivenPacketType(PacketTypeMuteEnvironment); int packetSize = headerSize + sizeof(glm::vec3) + sizeof(float); @@ -1316,26 +1232,6 @@ void Menu::muteEnvironment() { free(packet); } -void Menu::goToLocation() { - MyAvatar* myAvatar = Application::getInstance()->getAvatar(); - glm::vec3 avatarPos = myAvatar->getPosition(); - QString currentLocation = QString("%1, %2, %3").arg(QString::number(avatarPos.x), - QString::number(avatarPos.y), QString::number(avatarPos.z)); - - QInputDialog coordinateDialog(Application::getInstance()->getWindow()); - coordinateDialog.setWindowTitle("Go to Location"); - coordinateDialog.setLabelText("Coordinate as x,y,z:"); - coordinateDialog.setTextValue(currentLocation); - coordinateDialog.resize(coordinateDialog.parentWidget()->size().width() * 0.30, coordinateDialog.size().height()); - - int dialogReturn = coordinateDialog.exec(); - if (dialogReturn == QDialog::Accepted && !coordinateDialog.textValue().isEmpty()) { - goToDestination(coordinateDialog.textValue()); - } - - sendFakeEnterEvent(); -} - void Menu::namedLocationCreated(LocationManager::NamedLocationCreateResponse response) { if (response == LocationManager::Created) { diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 3b263add36..a9068c4b60 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -162,11 +162,8 @@ public: int menuItemLocation = UNSPECIFIED_POSITION); void removeAction(QMenu* menu, const QString& actionName); - - bool static goToDestination(QString destination); - void static goToOrientation(QString orientation); + void static goToDomain(const QString newDomain); - void static goTo(QString destination); const QByteArray& getWalletPrivateKey() const { return _walletPrivateKey; } @@ -185,11 +182,8 @@ public slots: void saveSettings(QSettings* settings = NULL); void importSettings(); void exportSettings(); - void goTo(); - bool goToURL(QString location); - void goToUser(const QString& user); + void addressBarDialog(); void pasteToVoxel(); - void openUrl(const QUrl& url); void toggleLoginMenuItem(); @@ -212,7 +206,6 @@ private slots: void editAnimations(); void changePrivateKey(); void goToDomainDialog(); - void goToLocation(); void nameLocation(); void toggleLocationList(); void bandwidthDetailsClosed(); @@ -227,7 +220,6 @@ private slots: void toggleChat(); void audioMuteToggled(); void namedLocationCreated(LocationManager::NamedLocationCreateResponse response); - void multipleDestinationsDecision(const QJsonObject& userData, const QJsonObject& placeData); void muteEnvironment(); private: diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6472ba2efa..14120a7e2c 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -91,6 +92,9 @@ MyAvatar::MyAvatar() : Ragdoll* ragdoll = _skeletonModel.buildRagdoll(); _physicsSimulation.setRagdoll(ragdoll); _physicsSimulation.addEntity(&_voxelShapeManager); + + // connect to AddressManager signal for location jumps + connect(&AddressManager::getInstance(), &AddressManager::locationChangeRequired, this, &MyAvatar::goToLocation); } MyAvatar::~MyAvatar() { @@ -1798,45 +1802,29 @@ void MyAvatar::resetSize() { qDebug("Reseted scale to %f", _targetScale); } -void MyAvatar::goToLocationFromResponse(const QJsonObject& jsonObject) { - QJsonObject locationObject = jsonObject["data"].toObject()["address"].toObject(); - bool isOnline = jsonObject["data"].toObject()["online"].toBool(); - if (isOnline ) { - goToLocationFromAddress(locationObject); - } else { - QMessageBox::warning(Application::getInstance()->getWindow(), "", "The user is not online."); - } -} - -void MyAvatar::goToLocationFromAddress(const QJsonObject& locationObject) { +void MyAvatar::goToLocation(const glm::vec3& newPosition, bool hasOrientation, const glm::vec3& newOrientation) { // send a node kill request, indicating to other clients that they should play the "disappeared" effect sendKillAvatar(); - - QString positionString = locationObject["position"].toString(); - QString orientationString = locationObject["orientation"].toString(); - QString domainHostnameString = locationObject["domain"].toString(); - - qDebug() << "Changing domain to" << domainHostnameString << - ", position to" << positionString << - ", and orientation to" << orientationString; - - QStringList coordinateItems = positionString.split(','); - QStringList orientationItems = orientationString.split(','); - - NodeList::getInstance()->getDomainHandler().setHostname(domainHostnameString); - - // orient the user to face the target - glm::quat newOrientation = glm::quat(glm::radians(glm::vec3(orientationItems[0].toFloat(), - orientationItems[1].toFloat(), - orientationItems[2].toFloat()))) - * glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)); - setOrientation(newOrientation); + + glm::quat quatOrientation = getOrientation(); + + qDebug().nospace() << "MyAvatar goToLocation - moving to " << newPosition.x << ", " + << newPosition.y << ", " << newPosition.z; + + if (hasOrientation) { + qDebug().nospace() << "MyAvatar goToLocation - new orientation is " + << newOrientation.x << ", " << newOrientation.y << ", " << newOrientation.z; + + // orient the user to face the target + glm::quat quatOrientation = glm::quat(glm::radians(newOrientation)) + * glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)); + setOrientation(quatOrientation); + } // move the user a couple units away const float DISTANCE_TO_USER = 2.0f; - glm::vec3 newPosition = glm::vec3(coordinateItems[0].toFloat(), coordinateItems[1].toFloat(), - coordinateItems[2].toFloat()) - newOrientation * IDENTITY_FRONT * DISTANCE_TO_USER; - slamPosition(newPosition); + glm::vec3 shiftedPosition = newPosition - quatOrientation * IDENTITY_FRONT * DISTANCE_TO_USER; + slamPosition(shiftedPosition); emit transformChanged(); } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index be828e0c91..86c10fdbb4 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -155,8 +155,7 @@ public slots: void decreaseSize(); void resetSize(); - void goToLocationFromResponse(const QJsonObject& jsonObject); - void goToLocationFromAddress(const QJsonObject& jsonObject); + void goToLocation(const glm::vec3& newPosition, bool hasOrientation, const glm::vec3& newOrientation); // Set/Get update the thrust that will move the avatar around void addThrust(glm::vec3 newThrust) { _thrust += newThrust; }; diff --git a/interface/src/location/LocationManager.cpp b/interface/src/location/LocationManager.cpp index 67e1b899ee..4484c50ebf 100644 --- a/interface/src/location/LocationManager.cpp +++ b/interface/src/location/LocationManager.cpp @@ -16,15 +16,9 @@ #include const QString GET_USER_ADDRESS = "/api/v1/users/%1/address"; -const QString GET_PLACE_ADDRESS = "/api/v1/places/%1"; -const QString GET_ADDRESSES = "/api/v1/addresses/%1"; +const QString GET_PLACE_ADDRESS = "/api/v1/metaverse/search/%1"; const QString POST_PLACE_CREATE = "/api/v1/places/"; - -LocationManager::LocationManager() { - -}; - LocationManager& LocationManager::getInstance() { static LocationManager sharedInstance; return sharedInstance; @@ -63,7 +57,7 @@ void LocationManager::createNamedLocation(NamedLocation* namedLocation) { void LocationManager::goTo(QString destination) { const QString USER_DESTINATION_TYPE = "user"; const QString PLACE_DESTINATION_TYPE = "place"; - const QString OTHER_DESTINATION_TYPE = "coordinate_or_username"; + const QString COORDINATE_DESTINATION_TYPE = "coordinate"; if (destination.startsWith("@")) { // remove '@' and go to user @@ -73,45 +67,37 @@ void LocationManager::goTo(QString destination) { return; } - if (destination.startsWith("#")) { - // remove '#' and go to named place - QString destinationPlace = destination.remove(0, 1); - UserActivityLogger::getInstance().wentTo(PLACE_DESTINATION_TYPE, destinationPlace); - goToPlace(destinationPlace); - return; - } - // go to coordinate destination or to Username if (!goToDestination(destination)) { destination = QString(QUrl::toPercentEncoding(destination)); - UserActivityLogger::getInstance().wentTo(OTHER_DESTINATION_TYPE, destination); + UserActivityLogger::getInstance().wentTo(PLACE_DESTINATION_TYPE, destination); JSONCallbackParameters callbackParams; callbackParams.jsonCallbackReceiver = this; - callbackParams.jsonCallbackMethod = "goToAddressFromResponse"; + callbackParams.jsonCallbackMethod = "goToPlaceFromResponse"; callbackParams.errorCallbackReceiver = this; callbackParams.errorCallbackMethod = "handleAddressLookupError"; - AccountManager::getInstance().authenticatedRequest(GET_ADDRESSES.arg(destination), + AccountManager::getInstance().authenticatedRequest(GET_PLACE_ADDRESS.arg(destination), QNetworkAccessManager::GetOperation, callbackParams); + } else { + UserActivityLogger::getInstance().wentTo(COORDINATE_DESTINATION_TYPE, destination); } } -void LocationManager::goToAddressFromResponse(const QJsonObject& responseData) { +void LocationManager::goToPlaceFromResponse(const QJsonObject& responseData) { QJsonValue status = responseData["status"]; - const QJsonObject& data = responseData["data"].toObject(); - const QJsonValue& userObject = data["user"]; - const QJsonValue& placeObject = data["place"]; + QJsonObject data = responseData["data"].toObject(); + QJsonObject domainObject = data["domain"].toObject(); - if (!placeObject.isUndefined() && !userObject.isUndefined()) { - emit multipleDestinationsFound(userObject.toObject(), placeObject.toObject()); - } else if (placeObject.isUndefined()) { - Application::getInstance()->getAvatar()->goToLocationFromAddress(userObject.toObject()["address"].toObject()); - } else { - Application::getInstance()->getAvatar()->goToLocationFromAddress(placeObject.toObject()["address"].toObject()); - } + const QString DOMAIN_NETWORK_ADDRESS_KEY = "network_address"; + + // get the network address for the domain we need to switch to + NodeList::getInstance()->getDomainHandler().setHostname(domainObject[DOMAIN_NETWORK_ADDRESS_KEY].toString()); + + // check if there is a path inside the domain we need to jump to } void LocationManager::goToUser(QString userName) { @@ -140,6 +126,46 @@ void LocationManager::goToPlace(QString placeName) { callbackParams); } +void LocationManager::goToUrl(const QUrl& url) { +// if (location.startsWith(CUSTOM_URL_SCHEME + "/")) { +// QStringList urlParts = location.remove(0, CUSTOM_URL_SCHEME.length()).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]; +// +// // any third part is an avatar orientation. +// QString orientation = urlParts.count() > 2 ? urlParts[2] : QString(); +// +// goToDomain(domain); +// +// // goto either @user, #place, or x-xx,y-yy,z-zz +// // style co-ordinate. +// goTo(destination); +// +// if (!orientation.isEmpty()) { +// // location orientation +// goToOrientation(orientation); +// } +// } else if (urlParts.count() == 1) { +// QString destination = urlParts[0]; +// +// // If this starts with # or @, treat it as a user/location, otherwise treat it as a domain +// if (destination[0] == '#' || destination[0] == '@') { +// goTo(destination); +// } else { +// goToDomain(destination); +// } +// } +// return true; +// } +// return false; +} + void LocationManager::goToOrientation(QString orientation) { if (orientation.isEmpty()) { return; diff --git a/interface/src/location/LocationManager.h b/interface/src/location/LocationManager.h index 30b4447ded..bf1c0e67e2 100644 --- a/interface/src/location/LocationManager.h +++ b/interface/src/location/LocationManager.h @@ -29,12 +29,12 @@ public: SystemError }; - LocationManager(); void createNamedLocation(NamedLocation* namedLocation); - + void goTo(QString destination); void goToUser(QString userName); void goToPlace(QString placeName); + void goToUrl(const QUrl& url); void goToOrientation(QString orientation); bool goToDestination(QString destination); @@ -46,12 +46,11 @@ private: signals: void creationCompleted(LocationManager::NamedLocationCreateResponse response); - void multipleDestinationsFound(const QJsonObject& userData, const QJsonObject& placeData); private slots: void namedLocationDataReceived(const QJsonObject& data); void errorDataReceived(QNetworkReply::NetworkError error, const QString& message); - void goToAddressFromResponse(const QJsonObject& jsonObject); + void goToPlaceFromResponse(const QJsonObject& jsonObject); }; diff --git a/interface/src/ui/ChatMessageArea.cpp b/interface/src/ui/ChatMessageArea.cpp index 1e16a8a2db..ab93c7abe9 100644 --- a/interface/src/ui/ChatMessageArea.cpp +++ b/interface/src/ui/ChatMessageArea.cpp @@ -19,8 +19,8 @@ ChatMessageArea::ChatMessageArea(bool useFixedHeight) : QTextBrowser(), _useFixe connect(document()->documentLayout(), &QAbstractTextDocumentLayout::documentSizeChanged, this, &ChatMessageArea::updateLayout); - connect(this, &QTextBrowser::anchorClicked, - Menu::getInstance(), &Menu::openUrl); +// connect(this, &QTextBrowser::anchorClicked, +// Menu::getInstance(), &Menu::openUrl); } void ChatMessageArea::setHtml(const QString& html) { diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index b9b5ed8e19..9961a84e79 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -169,7 +169,7 @@ bool ChatWindow::eventFilter(QObject* sender, QEvent* event) { } else if (event->type() == QEvent::MouseButtonRelease) { QVariant userVar = sender->property("user"); if (userVar.isValid()) { - Menu::getInstance()->goToUser("@" + userVar.toString()); +// Menu::getInstance()->goToUser("@" + userVar.toString()); return true; } } diff --git a/interface/src/ui/UserLocationsDialog.cpp b/interface/src/ui/UserLocationsDialog.cpp index f72e66ce77..ca1a9b5ad6 100644 --- a/interface/src/ui/UserLocationsDialog.cpp +++ b/interface/src/ui/UserLocationsDialog.cpp @@ -52,7 +52,7 @@ void UserLocationsDialog::updateEnabled() { void UserLocationsDialog::goToModelIndex(const QModelIndex& index) { QVariant location = _proxyModel.data(index.sibling(index.row(), UserLocationsModel::LocationColumn)); - Menu::getInstance()->goToURL(location.toString()); +// Menu::getInstance()->goToURL(location.toString()); } void UserLocationsDialog::deleteSelection() { diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp new file mode 100644 index 0000000000..6413fe6580 --- /dev/null +++ b/libraries/networking/src/AddressManager.cpp @@ -0,0 +1,108 @@ +// +// AddressManager.cpp +// libraries/networking/src +// +// Created by Stephen Birarda on 2014-09-10. +// 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 "AddressManager.h" + +AddressManager& AddressManager::getInstance() { + static AddressManager sharedInstance; + return sharedInstance; +} + +void AddressManager::handleLookupString(const QString& lookupString) { + // there are 4 possible lookup strings + + // 1. global place name (name of domain or place) - example: sanfrancisco + // 2. user name (prepended with @) - example: @philip + // 3. location string (posX,posY,posZ/eulerX,eulerY,eulerZ) + // 4. domain network address (IP or dns resolvable hostname) + + // use our regex'ed helpers to figure out what we're supposed to do with this + if (!lookupHandledAsUsername(lookupString) && + !lookupHandledAsNetworkAddress(lookupString) && + !lookupHandledAsLocationString(lookupString)) { + + } + + + +} + +bool AddressManager::lookupHandledAsNetworkAddress(const QString& lookupString) { + const QString IP_ADDRESS_REGEX_STRING = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}" + "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"; + const QString HOSTNAME_REGEX_STRING = "^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*" + "([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9])$"; + + + + return false; +} + +bool AddressManager::lookupHandledAsLocationString(const QString& lookupString) { + const QString FLOAT_REGEX_STRING = "([-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?)"; + const QString TRIPLE_FLOAT_REGEX_STRING = FLOAT_REGEX_STRING + "\\s*,\\s*" + + FLOAT_REGEX_STRING + "\\s*,\\s*" + FLOAT_REGEX_STRING + "\\s*(?:$|\\/)"; + + QRegExp tripleFloatRegex(TRIPLE_FLOAT_REGEX_STRING); + + if (tripleFloatRegex.indexIn(lookupString) != -1) { + // we have at least a position, so emit our signal to say we need to change position + glm::vec3 newPosition(tripleFloatRegex.cap(1).toFloat(), + tripleFloatRegex.cap(2).toFloat(), + tripleFloatRegex.cap(3).toFloat()); + + if (newPosition.x != NAN && newPosition.y != NAN && newPosition.z != NAN) { + glm::vec3 newOrientation; + // we may also have an orientation + if (lookupString[tripleFloatRegex.matchedLength() - 1] == QChar('/') + && tripleFloatRegex.indexIn(lookupString, tripleFloatRegex.matchedLength() - 1) != -1) { + + glm::vec3 newOrientation(tripleFloatRegex.cap(1).toFloat(), + tripleFloatRegex.cap(2).toFloat(), + tripleFloatRegex.cap(3).toFloat()); + + if (newOrientation.x != NAN && newOrientation.y != NAN && newOrientation.z != NAN) { + emit locationChangeRequired(newPosition, true, newOrientation); + return true; + } else { + qDebug() << "Orientation parsed from lookup string is invalid. Will not use for location change."; + } + } + + emit locationChangeRequired(newPosition, false, newOrientation); + + } else { + qDebug() << "Could not jump to position from lookup string because it has an invalid value."; + } + + return true; + } + + return false; +} + +bool AddressManager::lookupHandledAsUsername(const QString& lookupString) { + const QString USERNAME_REGEX_STRING = "^@(\\S+)$"; + + QRegExp usernameRegex(USERNAME_REGEX_STRING); + + if (usernameRegex.indexIn(lookupString) != -1) { + // this is a username - pull the captured name and lookup that user's address + + return true; + } + + return false; +} diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h new file mode 100644 index 0000000000..5c1a5c2e89 --- /dev/null +++ b/libraries/networking/src/AddressManager.h @@ -0,0 +1,33 @@ +// +// AddressManager.h +// libraries/networking/src +// +// Created by Stephen Birarda on 2014-09-10. +// 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_AddressManager_h +#define hifi_AddressManager_h + +#include + +#include + +class AddressManager : public QObject { + Q_OBJECT +public: + static AddressManager& getInstance(); + + void handleLookupString(const QString& lookupString); +signals: + void locationChangeRequired(const glm::vec3& newPosition, bool hasOrientationChange, const glm::vec3& newOrientation); +private: + bool lookupHandledAsNetworkAddress(const QString& lookupString); + bool lookupHandledAsLocationString(const QString& lookupString); + bool lookupHandledAsUsername(const QString& lookupString); +}; + +#endif // hifi_AddressManager_h \ No newline at end of file diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index f50f7493fb..604f8c7434 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -33,7 +33,7 @@ const char SOLO_NODE_TYPES[2] = { NodeType::AudioMixer }; -const QUrl DEFAULT_NODE_AUTH_URL = QUrl("https://data.highfidelity.io"); +const QUrl DEFAULT_NODE_AUTH_URL = QUrl("http://localhost:3000"); LimitedNodeList* LimitedNodeList::_sharedInstance = NULL; From dd1b23044f11a139152332a1f578519dde1d3c4a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 11 Sep 2014 10:24:04 -0700 Subject: [PATCH 19/46] hook meta+enter up to address bar display --- interface/src/Application.cpp | 15 +++++--- interface/src/Menu.cpp | 69 +++++------------------------------ interface/src/Menu.h | 9 +---- 3 files changed, 21 insertions(+), 72 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5b1110fbad..c123dfa1f4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -422,8 +422,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : MIDIManager& midiManagerInstance = MIDIManager::getInstance(); midiManagerInstance.openDefaultPort(); #endif - - AddressManager::getInstance().handleLookupString("1.5,2.5,0.0/0.0,-161.98,0.02"); } Application::~Application() { @@ -913,7 +911,12 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_Return: case Qt::Key_Enter: - Menu::getInstance()->triggerOption(MenuOption::Chat); + if (isMeta) { + Menu::getInstance()->triggerOption(MenuOption::AddressBar); + } else { + Menu::getInstance()->triggerOption(MenuOption::Chat); + } + break; case Qt::Key_Up: @@ -1317,7 +1320,7 @@ void Application::dropEvent(QDropEvent *event) { SnapshotMetaData* snapshotData = Snapshot::parseSnapshotData(snapshotPath); if (snapshotData) { if (!snapshotData->getDomain().isEmpty()) { - Menu::getInstance()->goToDomain(snapshotData->getDomain()); +// Menu::getInstance()->goToDomain(snapshotData->getDomain()); } _myAvatar->setPosition(snapshotData->getLocation()); @@ -4101,7 +4104,7 @@ void Application::urlGoTo(int argc, const char * constArgv[]) { if (urlParts.count() == 1) { // location coordinates or place name QString domain = urlParts[0]; - Menu::goToDomain(domain); +// 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]; @@ -4113,7 +4116,7 @@ void Application::urlGoTo(int argc, const char * constArgv[]) { // 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. diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 48908b12a1..b8835407b0 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -158,16 +159,6 @@ Menu::Menu() : Qt::CTRL | Qt::Key_G, appInstance->getAvatar(), SLOT(goHome())); - addActionToQMenuAndActionHash(fileMenu, - MenuOption::GoToDomain, - Qt::CTRL | Qt::Key_D, - this, - SLOT(goToDomainDialog())); - addActionToQMenuAndActionHash(fileMenu, - MenuOption::GoToLocation, - Qt::CTRL | Qt::SHIFT | Qt::Key_L, - this, - SLOT(goToLocation())); addActionToQMenuAndActionHash(fileMenu, MenuOption::NameLocation, Qt::CTRL | Qt::Key_N, @@ -179,10 +170,10 @@ Menu::Menu() : this, SLOT(toggleLocationList())); addActionToQMenuAndActionHash(fileMenu, - MenuOption::GoTo, - Qt::Key_At, + MenuOption::AddressBar, + Qt::CTRL | Qt::Key_Enter, this, - SLOT(goTo())); + SLOT(toggleAddressBar())); addDisabledActionAndSeparator(fileMenu, "Upload Avatar Model"); addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadHead, 0, Application::getInstance(), SLOT(uploadHead())); @@ -1149,62 +1140,22 @@ void Menu::changePrivateKey() { sendFakeEnterEvent(); } -void Menu::goToDomain(const QString newDomain) { - if (NodeList::getInstance()->getDomainHandler().getHostname() != newDomain) { - // send a node kill request, indicating to other clients that they should play the "disappeared" effect - Application::getInstance()->getAvatar()->sendKillAvatar(); - - // give our nodeList the new domain-server hostname - NodeList::getInstance()->getDomainHandler().setHostname(newDomain); - } -} - -void Menu::goToDomainDialog() { - - QString currentDomainHostname = NodeList::getInstance()->getDomainHandler().getHostname(); - - if (NodeList::getInstance()->getDomainHandler().getPort() != DEFAULT_DOMAIN_SERVER_PORT) { - // add the port to the currentDomainHostname string if it is custom - currentDomainHostname.append(QString(":%1").arg(NodeList::getInstance()->getDomainHandler().getPort())); - } - - QInputDialog domainDialog(Application::getInstance()->getWindow()); - domainDialog.setWindowTitle("Go to Domain"); - domainDialog.setLabelText("Domain server:"); - domainDialog.setTextValue(currentDomainHostname); - domainDialog.resize(domainDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, domainDialog.size().height()); - - int dialogReturn = domainDialog.exec(); - if (dialogReturn == QDialog::Accepted) { - QString newHostname(DEFAULT_DOMAIN_HOSTNAME); - - if (domainDialog.textValue().size() > 0) { - // the user input a new hostname, use that - newHostname = domainDialog.textValue(); - } - - goToDomain(newHostname); - } - - sendFakeEnterEvent(); -} - -void Menu::addressBarDialog() { +void Menu::toggleAddressBar() { QInputDialog addressBarDialog(Application::getInstance()->getWindow()); addressBarDialog.setWindowTitle("Address Bar"); - addressBarDialog.setLabelText("place, @user, hifi://domain/path, position/orientation"); - QString destination = QString(); + addressBarDialog.setWindowFlags(Qt::Sheet); + addressBarDialog.setLabelText("place, domain, @user, example.com, position/orientation"); - addressBarDialog.setTextValue(destination); addressBarDialog.resize(addressBarDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, addressBarDialog.size().height()); int dialogReturn = addressBarDialog.exec(); if (dialogReturn == QDialog::Accepted && !addressBarDialog.textValue().isEmpty()) { - // let the location manager parse this out and decide what to do with it -// LocationManager::getInstance().handleAddressBarEntry(addressBarDialog.textValue()); + // let the AddressManger figure out what to do with this + AddressManager::getInstance().handleLookupString(addressBarDialog.textValue()); } + sendFakeEnterEvent(); } diff --git a/interface/src/Menu.h b/interface/src/Menu.h index a9068c4b60..078c2b4255 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -163,8 +163,6 @@ public: void removeAction(QMenu* menu, const QString& actionName); - void static goToDomain(const QString newDomain); - const QByteArray& getWalletPrivateKey() const { return _walletPrivateKey; } signals: @@ -182,7 +180,7 @@ public slots: void saveSettings(QSettings* settings = NULL); void importSettings(); void exportSettings(); - void addressBarDialog(); + void toggleAddressBar(); void pasteToVoxel(); void toggleLoginMenuItem(); @@ -205,7 +203,6 @@ private slots: void editAttachments(); void editAnimations(); void changePrivateKey(); - void goToDomainDialog(); void nameLocation(); void toggleLocationList(); void bandwidthDetailsClosed(); @@ -307,6 +304,7 @@ private: namespace MenuOption { const QString AboutApp = "About Interface"; + const QString AddressBar = "Show Address Bar"; const QString AlignForearmsWithWrists = "Align Forearms with Wrists"; const QString AlternateIK = "Alternate IK"; const QString AmbientOcclusion = "Ambient Occlusion"; @@ -393,9 +391,6 @@ namespace MenuOption { const QString GlowMode = "Cycle Glow Mode"; const QString GlowWhenSpeaking = "Glow When Speaking"; const QString GoHome = "Go Home"; - const QString GoToDomain = "Go To Domain..."; - const QString GoTo = "Go To..."; - const QString GoToLocation = "Go To Location..."; const QString HeadMouse = "Head Mouse"; const QString IncreaseAvatarSize = "Increase Avatar Size"; const QString IncreaseVoxelSize = "Increase Voxel Size"; From aaabe6b1e1a2353a9b12a412de230ff18e6db945 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 11 Sep 2014 10:45:45 -0700 Subject: [PATCH 20/46] handle domain changes via address bar --- interface/src/Application.cpp | 12 ++++++++++++ interface/src/Application.h | 1 + interface/src/avatar/MyAvatar.cpp | 5 +---- libraries/networking/src/AddressManager.cpp | 13 +++++++++++++ libraries/networking/src/AddressManager.h | 1 + libraries/networking/src/DomainHandler.h | 3 ++- 6 files changed, 30 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c123dfa1f4..2fa9701e18 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -407,6 +407,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : connect(_window, &MainWindow::windowGeometryChanged, _runningScriptsWidget, &RunningScriptsWidget::setBoundary); + // connect to the domainChangeRequired signal on AddressManager + connect(&AddressManager::getInstance(), &AddressManager::domainChangeRequired, this, &Application::changeDomainHostname); + //When -url in command line, teleport to location urlGoTo(argc, constArgv); @@ -3391,6 +3394,15 @@ void Application::updateLocationInServer() { } } +void Application::changeDomainHostname(const QString &newDomainHostname) { + // tell the MyAvatar object to send a kill packet so that it dissapears from its old avatar mixer immediately + _myAvatar->sendKillAvatar(); + + // call the domain hostname change as a queued connection on the nodelist + QMetaObject::invokeMethod(&NodeList::getInstance()->getDomainHandler(), "setHostname", + Q_ARG(const QString&, newDomainHostname)); +} + void Application::domainChanged(const QString& domainHostname) { updateWindowTitle(); diff --git a/interface/src/Application.h b/interface/src/Application.h index f48d88d7a4..6f4bc02e94 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -313,6 +313,7 @@ signals: void importDone(); public slots: + void changeDomainHostname(const QString& newDomainHostname); void domainChanged(const QString& domainHostname); void updateWindowTitle(); void updateLocationInServer(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 14120a7e2c..b4335512ef 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1802,10 +1802,7 @@ void MyAvatar::resetSize() { qDebug("Reseted scale to %f", _targetScale); } -void MyAvatar::goToLocation(const glm::vec3& newPosition, bool hasOrientation, const glm::vec3& newOrientation) { - // send a node kill request, indicating to other clients that they should play the "disappeared" effect - sendKillAvatar(); - +void MyAvatar::goToLocation(const glm::vec3& newPosition, bool hasOrientation, const glm::vec3& newOrientation) { glm::quat quatOrientation = getOrientation(); qDebug().nospace() << "MyAvatar goToLocation - moving to " << newPosition.x << ", " diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 6413fe6580..5f6e0652c2 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -42,10 +42,23 @@ void AddressManager::handleLookupString(const QString& lookupString) { bool AddressManager::lookupHandledAsNetworkAddress(const QString& lookupString) { const QString IP_ADDRESS_REGEX_STRING = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}" "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"; + const QString HOSTNAME_REGEX_STRING = "^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*" "([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9])$"; + QRegExp hostnameRegex(HOSTNAME_REGEX_STRING); + if (hostnameRegex.indexIn(lookupString) != -1) { + emit domainChangeRequired(hostnameRegex.cap(0)); + return true; + } + + QRegExp ipAddressRegex(IP_ADDRESS_REGEX_STRING); + + if (ipAddressRegex.indexIn(lookupString) != -1) { + emit domainChangeRequired(ipAddressRegex.cap(0)); + return true; + } return false; } diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 5c1a5c2e89..e43102dd42 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -23,6 +23,7 @@ public: void handleLookupString(const QString& lookupString); signals: + void domainChangeRequired(const QString& newHostname); void locationChangeRequired(const glm::vec3& newPosition, bool hasOrientationChange, const glm::vec3& newOrientation); private: bool lookupHandledAsNetworkAddress(const QString& lookupString); diff --git a/libraries/networking/src/DomainHandler.h b/libraries/networking/src/DomainHandler.h index 91caddca22..c65d687f5f 100644 --- a/libraries/networking/src/DomainHandler.h +++ b/libraries/networking/src/DomainHandler.h @@ -40,7 +40,6 @@ public: void setUUID(const QUuid& uuid) { _uuid = uuid; } const QString& getHostname() const { return _hostname; } - void setHostname(const QString& hostname); const QHostAddress& getIP() const { return _sockAddr.getAddress(); } void setIPToLocalhost() { _sockAddr.setAddress(QHostAddress(QHostAddress::LocalHost)); } @@ -63,6 +62,8 @@ public: void parseDTLSRequirementPacket(const QByteArray& dtlsRequirementPacket); void softReset(); +public slots: + void setHostname(const QString& hostname); private slots: void completedHostnameLookup(const QHostInfo& hostInfo); From 684aa97b98c1db72eb182ab760aa918a92ab47d1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 11 Sep 2014 11:00:24 -0700 Subject: [PATCH 21/46] add port parsing for domain hostname in address bar --- libraries/networking/src/AddressManager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 5f6e0652c2..7a1848174e 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -41,10 +41,10 @@ void AddressManager::handleLookupString(const QString& lookupString) { bool AddressManager::lookupHandledAsNetworkAddress(const QString& lookupString) { const QString IP_ADDRESS_REGEX_STRING = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}" - "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"; + "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(:\\d{1,5})?$"; - const QString HOSTNAME_REGEX_STRING = "^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*" - "([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9])$"; + const QString HOSTNAME_REGEX_STRING = "^(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])" + "(?:\\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]))+(:{1}\\d{1,5})?$"; QRegExp hostnameRegex(HOSTNAME_REGEX_STRING); From 6d21c4bf0d1ffd7607c4b4a6576a7a965e2a2ee3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 11 Sep 2014 11:07:42 -0700 Subject: [PATCH 22/46] make lookup for hostnames case insensitive --- libraries/networking/src/AddressManager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 7a1848174e..40bae46c5a 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -43,10 +43,10 @@ bool AddressManager::lookupHandledAsNetworkAddress(const QString& lookupString) const QString IP_ADDRESS_REGEX_STRING = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}" "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(:\\d{1,5})?$"; - const QString HOSTNAME_REGEX_STRING = "^(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])" - "(?:\\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]))+(:{1}\\d{1,5})?$"; + const QString HOSTNAME_REGEX_STRING = "^((?:[A-Z0-9]|[A-Z0-9][A-Z0-9\\-]{0,61}[A-Z0-9])" + "(?:\\.(?:[A-Z0-9]|[A-Z0-9][A-Z0-9\\-]{0,61}[A-Z0-9]))+|localhost)(:{1}\\d{1,5})?$"; - QRegExp hostnameRegex(HOSTNAME_REGEX_STRING); + QRegExp hostnameRegex(HOSTNAME_REGEX_STRING, Qt::CaseInsensitive); if (hostnameRegex.indexIn(lookupString) != -1) { emit domainChangeRequired(hostnameRegex.cap(0)); From a733b131184e5674cf2df764b4ef5e933fb02392 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 11 Sep 2014 11:34:47 -0700 Subject: [PATCH 23/46] Fix vertical movement on gracefulControls.js --- examples/gracefulControls.js | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/examples/gracefulControls.js b/examples/gracefulControls.js index afbdebb18f..47c9978dbe 100644 --- a/examples/gracefulControls.js +++ b/examples/gracefulControls.js @@ -1,42 +1,28 @@ // Coefficient to use for linear drag. Higher numbers will cause motion to // slow down more quickly. -/* -var DRAG_COEFFICIENT = 0.9; -var MAX_SPEED = 50.0; -var MAX_LOOK_SPEED = Math.PI * 2; -var ACCELERATION = 15; - -var MOUSE_YAW_SCALE = -0.125; -var MOUSE_PITCH_SCALE = -0.125; -var MOUSE_SENSITIVITY = 0.5; - -var W = 4.2; -*/ var DEFAULT_PARAMETERS = { DRAG_COEFFICIENT: 0.9, MAX_SPEED: 50.0, - MAX_LOOK_SPEED: Math.PI * 2, ACCELERATION: 15, MOUSE_YAW_SCALE: -0.125, MOUSE_PITCH_SCALE: -0.125, MOUSE_SENSITIVITY: 0.5, + // Damping frequency, adjust to change mouse look behavior W: 4.2, } var BRAKE_PARAMETERS = { DRAG_COEFFICIENT: 4.9, MAX_SPEED: DEFAULT_PARAMETERS.MAX_SPEED, - MAX_LOOK_SPEED: Math.PI * 2, ACCELERATION: 0, + W: 1.0, MOUSE_YAW_SCALE: -0.125, MOUSE_PITCH_SCALE: -0.125, MOUSE_SENSITIVITY: 0.5, - - W: 1.0, } var movementParameters = DEFAULT_PARAMETERS; @@ -156,7 +142,7 @@ function update(dt) { velocity.z = Math.max(-maxSpeed, Math.min(maxSpeed, velocity.z)); var v = Quat.rotate(MyAvatar.headOrientation, velocity); - if (velocityVertical == 0) { + if (targetVelocityVertical == 0) { targetVelocityVertical -= (velocityVertical * movementParameters.DRAG_COEFFICIENT * dt); } velocityVertical += targetVelocityVertical; @@ -193,6 +179,7 @@ function enable() { pitchFromMouse = 0; yawSpeed = 0; pitchSpeed = 0; + velocityVertical = 0; for (var i = 0; i < CAPTURED_KEYS.length; i++) { Controller.captureKeyEvents({ text: CAPTURED_KEYS[i] }); From 23a0ef2de1f9fcd09600979023e437dcda280aa2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 11 Sep 2014 12:13:13 -0700 Subject: [PATCH 24/46] remove some spacing in AddressManager --- libraries/networking/src/AddressManager.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 40bae46c5a..63f1b59f6b 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -34,9 +34,6 @@ void AddressManager::handleLookupString(const QString& lookupString) { !lookupHandledAsLocationString(lookupString)) { } - - - } bool AddressManager::lookupHandledAsNetworkAddress(const QString& lookupString) { From 1adf3d28782490f20f98195ef590f4d871901606 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 11 Sep 2014 12:41:12 -0700 Subject: [PATCH 25/46] Go ahead and generate mipmaps for all network-loaded textures. It is the 21st century, after all. --- interface/src/renderer/TextureCache.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/interface/src/renderer/TextureCache.cpp b/interface/src/renderer/TextureCache.cpp index bb07e83980..f22e1bf7a5 100644 --- a/interface/src/renderer/TextureCache.cpp +++ b/interface/src/renderer/TextureCache.cpp @@ -497,13 +497,9 @@ void NetworkTexture::setImage(const QImage& image, bool translucent, const QColo glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width(), image.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, image.constBits()); } - if (_type == SPLAT_TEXTURE) { - // generate mipmaps for splat textures - glGenerateMipmap(GL_TEXTURE_2D); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } + // generate mipmaps + glGenerateMipmap(GL_TEXTURE_2D); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); } @@ -541,7 +537,8 @@ QSharedPointer DilatableNetworkTexture::getDilatedTexture(float dilatio glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, dilatedImage.width(), dilatedImage.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, dilatedImage.constBits()); } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glGenerateMipmap(GL_TEXTURE_2D); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); } From df192e297cef29180def5c014b119864aa0ec2d6 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 11 Sep 2014 14:01:11 -0700 Subject: [PATCH 26/46] Apply blendshapes to skeleton as well as head. --- interface/src/avatar/SkeletonModel.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index e54a8e0f42..ebcf4520cb 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -60,6 +60,7 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { setRotation(_owningAvatar->getOrientation() * refOrientation); const float MODEL_SCALE = 0.0006f; setScale(glm::vec3(1.0f, 1.0f, 1.0f) * _owningAvatar->getScale() * MODEL_SCALE); + setBlendshapeCoefficients(_owningAvatar->getHead()->getBlendshapeCoefficients()); Model::simulate(deltaTime, fullUpdate); From 50090c62f27db82899a5a0a0283fb3a89f8b1841 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 11 Sep 2014 15:16:42 -0700 Subject: [PATCH 27/46] Update MAX_SPEED and ACCELERATION in gracefulControls.js --- examples/gracefulControls.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/gracefulControls.js b/examples/gracefulControls.js index 47c9978dbe..6ccc024ba8 100644 --- a/examples/gracefulControls.js +++ b/examples/gracefulControls.js @@ -3,8 +3,8 @@ var DEFAULT_PARAMETERS = { DRAG_COEFFICIENT: 0.9, - MAX_SPEED: 50.0, - ACCELERATION: 15, + MAX_SPEED: 40.0, + ACCELERATION: 1.0, MOUSE_YAW_SCALE: -0.125, MOUSE_PITCH_SCALE: -0.125, From 3724472758d47718e7ada96c70b96202e5abcf7f Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 11 Sep 2014 15:20:41 -0700 Subject: [PATCH 28/46] Remove extra local variable in getCursorPosition --- interface/src/scripting/WindowScriptingInterface.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 8fd9291871..01a30b6d94 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -47,13 +47,11 @@ void WindowScriptingInterface::setCursorPosition(int x, int y) { } QScriptValue WindowScriptingInterface::getCursorPositionX() { - QPoint pos = QCursor::pos(); - return pos.x(); + return QCursor::pos().x(); } QScriptValue WindowScriptingInterface::getCursorPositionY() { - QPoint pos = QCursor::pos(); - return pos.y(); + return QCursor::pos().y(); } QScriptValue WindowScriptingInterface::alert(const QString& message) { From ffa47b1923441440e7d39bcbdaaec8d2d9c5d780 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 11 Sep 2014 15:22:04 -0700 Subject: [PATCH 29/46] Add header comment to gracefulControls.js --- examples/gracefulControls.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/examples/gracefulControls.js b/examples/gracefulControls.js index 6ccc024ba8..4d9e3e2f96 100644 --- a/examples/gracefulControls.js +++ b/examples/gracefulControls.js @@ -1,7 +1,17 @@ -// Coefficient to use for linear drag. Higher numbers will cause motion to -// slow down more quickly. +// +// gracefulControls.js +// examples +// +// Created by Ryan Huffman on 9/11/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 +// var DEFAULT_PARAMETERS = { + // Coefficient to use for linear drag. Higher numbers will cause motion to + // slow down more quickly. DRAG_COEFFICIENT: 0.9, MAX_SPEED: 40.0, ACCELERATION: 1.0, From 870b0c80cf5aeb756b57641b1144511b0e1b4454 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 11 Sep 2014 15:24:23 -0700 Subject: [PATCH 30/46] Default blendshape mappings for Mixamo models. --- interface/src/ModelUploader.cpp | 40 +++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index 12a4b145cc..a8be2f9f5c 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -48,6 +48,7 @@ static const QString TRANSLATION_Y_FIELD = "ty"; static const QString TRANSLATION_Z_FIELD = "tz"; static const QString JOINT_FIELD = "joint"; static const QString FREE_JOINT_FIELD = "freeJoint"; +static const QString BLENDSHAPE_FIELD = "bs"; static const QString S3_URL = "http://public.highfidelity.io"; static const QString MODEL_URL = "/api/v1/models"; @@ -192,6 +193,45 @@ bool ModelUploader::zip() { mapping.insertMulti(FREE_JOINT_FIELD, "RightForeArm"); } + // mixamo blendshapes + if (!mapping.contains(BLENDSHAPE_FIELD) && geometry.applicationName == "mixamo.com") { + QVariantHash blendshapes; + blendshapes.insert("EyeBlink_L", QVariantList() << "Blink_Left" << 1.0); + blendshapes.insert("EyeBlink_R", QVariantList() << "Blink_Right" << 1.0); + blendshapes.insert("EyeSquint_L", QVariantList() << "Squint_Left" << 1.0); + blendshapes.insert("EyeSquint_R", QVariantList() << "Squint_Right" << 1.0); + blendshapes.insert("EyeOpen_L", QVariantList() << "EyesWide_Left" << 1.0); + blendshapes.insert("EyeOpen_R", QVariantList() << "EyesWide_Right" << 1.0); + blendshapes.insert("BrowsD_L", QVariantList() << "BrowsDown_Left" << 1.0); + blendshapes.insert("BrowsD_R", QVariantList() << "BrowsDown_Right" << 1.0); + blendshapes.insert("BrowsU_L", QVariantList() << "BrowsUp_Left" << 1.0); + blendshapes.insert("BrowsU_R", QVariantList() << "BrowsUp_Right" << 1.0); + blendshapes.insert("JawFwd", QVariantList() << "JawForeward" << 1.0); + blendshapes.insert("JawOpen", QVariantList() << "Jaw_Down" << 1.0); + blendshapes.insert("JawLeft", QVariantList() << "Jaw_Left" << 1.0); + blendshapes.insert("JawRight", QVariantList() << "Jaw_Right" << 1.0); + blendshapes.insert("JawChew", QVariantList() << "Jaw_Up" << 1.0); + blendshapes.insert("MouthLeft", QVariantList() << "Midmouth_Left" << 1.0); + blendshapes.insert("MouthRight", QVariantList() << "Midmouth_Right" << 1.0); + blendshapes.insert("MouthFrown_L", QVariantList() << "Frown_Left" << 1.0); + blendshapes.insert("MouthFrown_R", QVariantList() << "Frown_Right" << 1.0); + blendshapes.insert("MouthSmile_L", QVariantList() << "Smile_Left" << 1.0); + blendshapes.insert("MouthSmile_R", QVariantList() << "Smile_Right" << 1.0); + blendshapes.insert("LipsUpperUp", QVariantList() << "UpperLipUp_Left" << 0.5); + blendshapes.insertMulti("LipsUpperUp", QVariantList() << "UpperLipUp_Right" << 0.5); + blendshapes.insert("Puff", QVariantList() << "CheekPuff_Left" << 0.5); + blendshapes.insertMulti("Puff", QVariantList() << "CheekPuff_Right" << 0.5); + blendshapes.insert("Sneer", QVariantList() << "NoseScrunch_Left" << 0.5); + blendshapes.insertMulti("Sneer", QVariantList() << "NoseScrunch_Right" << 0.5); + blendshapes.insert("CheekSquint_L", QVariantList() << "Squint_Left" << 1.0); + blendshapes.insert("CheekSquint_R", QVariantList() << "Squint_Right" << 1.0); + blendshapes.insert("LipsPucker", QVariantList() << "MouthNarrow_Left" << 0.5); + blendshapes.insertMulti("LipsPucker", QVariantList() << "MouthNarrow_Right" << 0.5); + blendshapes.insert("LipsLowerDown", QVariantList() << "LowerLipDown_Left" << 0.5); + blendshapes.insertMulti("LipsLowerDown", QVariantList() << "LowerLipDown_Right" << 0.5); + mapping.insert(BLENDSHAPE_FIELD, blendshapes); + } + // open the dialog to configure the rest ModelPropertiesDialog properties(_modelType, mapping, basePath, geometry); if (properties.exec() == QDialog::Rejected) { From b56ea5c936cdba2ca50040dd9858dde7004bb9c9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 11 Sep 2014 17:17:47 -0700 Subject: [PATCH 31/46] centralize path creation from position and orientation to AddressManager --- interface/src/Application.cpp | 65 ++++++---- interface/src/Application.h | 1 - interface/src/location/LocationManager.cpp | 79 +----------- interface/src/location/LocationManager.h | 2 - .../scripting/LocationScriptingInterface.cpp | 53 -------- .../scripting/LocationScriptingInterface.h | 48 ------- libraries/networking/src/AddressManager.cpp | 119 ++++++++++++++++-- libraries/networking/src/AddressManager.h | 25 +++- libraries/networking/src/DomainHandler.cpp | 16 +++ libraries/networking/src/DomainHandler.h | 4 +- 10 files changed, 188 insertions(+), 224 deletions(-) delete mode 100644 interface/src/scripting/LocationScriptingInterface.cpp delete mode 100644 interface/src/scripting/LocationScriptingInterface.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2fa9701e18..39c8f1a82f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -84,7 +84,6 @@ #include "scripting/MenuScriptingInterface.h" #include "scripting/SettingsScriptingInterface.h" #include "scripting/WindowScriptingInterface.h" -#include "scripting/LocationScriptingInterface.h" #include "ui/InfoView.h" #include "ui/OAuthWebViewHandler.h" @@ -408,7 +407,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _runningScriptsWidget, &RunningScriptsWidget::setBoundary); // connect to the domainChangeRequired signal on AddressManager - connect(&AddressManager::getInstance(), &AddressManager::domainChangeRequired, this, &Application::changeDomainHostname); + connect(&AddressManager::getInstance(), &AddressManager::possibleDomainChangeRequired, + this, &Application::changeDomainHostname); //When -url in command line, teleport to location urlGoTo(argc, constArgv); @@ -811,7 +811,7 @@ bool Application::event(QEvent* event) { // handle custom URL if (event->type() == QEvent::FileOpen) { QFileOpenEvent* fileEvent = static_cast(event); - bool isHifiSchemeURL = !fileEvent->url().isEmpty() && fileEvent->url().toLocalFile().startsWith(CUSTOM_URL_SCHEME); + bool isHifiSchemeURL = !fileEvent->url().isEmpty() && fileEvent->url().toLocalFile().startsWith(HIFI_URL_SCHEME); if (isHifiSchemeURL) { // Menu::getInstance()->goToURL(fileEvent->url().toLocalFile()); } @@ -3376,31 +3376,44 @@ void Application::updateWindowTitle(){ void Application::updateLocationInServer() { AccountManager& accountManager = AccountManager::getInstance(); - - if (accountManager.isLoggedIn()) { + const QUuid& domainUUID = NodeList::getInstance()->getDomainHandler().getUUID(); + + if (accountManager.isLoggedIn() && !domainUUID.isNull()) { // construct a QJsonObject given the user's current address information - QJsonObject updatedLocationObject; + QJsonObject rootObject; - QJsonObject addressObject; - addressObject.insert("position", QString(createByteArray(_myAvatar->getPosition()))); - addressObject.insert("orientation", QString(createByteArray(glm::degrees(safeEulerAngles(_myAvatar->getOrientation()))))); - addressObject.insert("domain", NodeList::getInstance()->getDomainHandler().getHostname()); + QJsonObject locationObject; + + QString pathString = AddressManager::pathForPositionAndOrientation(_myAvatar->getPosition(), + true, + _myAvatar->getOrientation()); + + const QString LOCATION_KEY_IN_ROOT = "location"; + const QString PATH_KEY_IN_LOCATION = "path"; + const QString DOMAIN_ID_KEY_IN_LOCATION = "domain_id"; + + locationObject.insert(PATH_KEY_IN_LOCATION, pathString); + locationObject.insert(DOMAIN_ID_KEY_IN_LOCATION, domainUUID.toString()); - updatedLocationObject.insert("address", addressObject); + rootObject.insert(LOCATION_KEY_IN_ROOT, locationObject); - accountManager.authenticatedRequest("/api/v1/users/address", QNetworkAccessManager::PutOperation, - JSONCallbackParameters(), QJsonDocument(updatedLocationObject).toJson()); + accountManager.authenticatedRequest("/api/v1/users/location", QNetworkAccessManager::PutOperation, + JSONCallbackParameters(), QJsonDocument(rootObject).toJson()); } } void Application::changeDomainHostname(const QString &newDomainHostname) { - // tell the MyAvatar object to send a kill packet so that it dissapears from its old avatar mixer immediately - _myAvatar->sendKillAvatar(); + NodeList* nodeList = NodeList::getInstance(); - // call the domain hostname change as a queued connection on the nodelist - QMetaObject::invokeMethod(&NodeList::getInstance()->getDomainHandler(), "setHostname", - Q_ARG(const QString&, newDomainHostname)); + if (!nodeList->getDomainHandler().isCurrentHostname(newDomainHostname)) { + // tell the MyAvatar object to send a kill packet so that it dissapears from its old avatar mixer immediately + _myAvatar->sendKillAvatar(); + + // call the domain hostname change as a queued connection on the nodelist + QMetaObject::invokeMethod(&NodeList::getInstance()->getDomainHandler(), "setHostname", + Q_ARG(const QString&, newDomainHostname)); + } } void Application::domainChanged(const QString& domainHostname) { @@ -3785,12 +3798,12 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser scriptEngine->registerGlobalObject("Overlays", &_overlays); QScriptValue windowValue = scriptEngine->registerGlobalObject("Window", WindowScriptingInterface::getInstance()); - scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter, - LocationScriptingInterface::locationSetter, windowValue); - - // register `location` on the global object. - scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter, - LocationScriptingInterface::locationSetter); +// scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter, +// LocationScriptingInterface::locationSetter, windowValue); +// +// // register `location` on the global object. +// scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter, +// LocationScriptingInterface::locationSetter); scriptEngine->registerGlobalObject("Menu", MenuScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("Settings", SettingsScriptingInterface::getInstance()); @@ -4111,8 +4124,8 @@ void Application::takeSnapshot() { void Application::urlGoTo(int argc, const char * constArgv[]) { //Gets the url (hifi://domain/destination/orientation) QString customUrl = getCmdOption(argc, constArgv, "-url"); - if(customUrl.startsWith(CUSTOM_URL_SCHEME + "//")) { - QStringList urlParts = customUrl.remove(0, CUSTOM_URL_SCHEME.length() + 2).split('/', QString::SkipEmptyParts); + if(customUrl.startsWith(HIFI_URL_SCHEME + "//")) { + QStringList urlParts = customUrl.remove(0, HIFI_URL_SCHEME.length() + 2).split('/', QString::SkipEmptyParts); if (urlParts.count() == 1) { // location coordinates or place name QString domain = urlParts[0]; diff --git a/interface/src/Application.h b/interface/src/Application.h index 6f4bc02e94..ef08cf4ec5 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -114,7 +114,6 @@ static const float NODE_KILLED_GREEN = 0.0f; static const float NODE_KILLED_BLUE = 0.0f; static const QString SNAPSHOT_EXTENSION = ".jpg"; -static const QString CUSTOM_URL_SCHEME = "hifi:"; static const float BILLBOARD_FIELD_OF_VIEW = 30.0f; // degrees static const float BILLBOARD_DISTANCE = 5.0f; // meters diff --git a/interface/src/location/LocationManager.cpp b/interface/src/location/LocationManager.cpp index 4484c50ebf..6beb1f5527 100644 --- a/interface/src/location/LocationManager.cpp +++ b/interface/src/location/LocationManager.cpp @@ -15,8 +15,7 @@ #include "LocationManager.h" #include -const QString GET_USER_ADDRESS = "/api/v1/users/%1/address"; -const QString GET_PLACE_ADDRESS = "/api/v1/metaverse/search/%1"; + const QString POST_PLACE_CREATE = "/api/v1/places/"; LocationManager& LocationManager::getInstance() { @@ -36,10 +35,6 @@ void LocationManager::namedLocationDataReceived(const QJsonObject& data) { } } -void LocationManager::errorDataReceived(QNetworkReply::NetworkError error, const QString& message) { - emit creationCompleted(LocationManager::SystemError); -} - void LocationManager::createNamedLocation(NamedLocation* namedLocation) { AccountManager& accountManager = AccountManager::getInstance(); if (accountManager.isLoggedIn()) { @@ -54,78 +49,6 @@ void LocationManager::createNamedLocation(NamedLocation* namedLocation) { } } -void LocationManager::goTo(QString destination) { - const QString USER_DESTINATION_TYPE = "user"; - const QString PLACE_DESTINATION_TYPE = "place"; - const QString COORDINATE_DESTINATION_TYPE = "coordinate"; - - if (destination.startsWith("@")) { - // remove '@' and go to user - QString destinationUser = destination.remove(0, 1); - UserActivityLogger::getInstance().wentTo(USER_DESTINATION_TYPE, destinationUser); - goToUser(destinationUser); - return; - } - - // go to coordinate destination or to Username - if (!goToDestination(destination)) { - destination = QString(QUrl::toPercentEncoding(destination)); - UserActivityLogger::getInstance().wentTo(PLACE_DESTINATION_TYPE, destination); - - JSONCallbackParameters callbackParams; - callbackParams.jsonCallbackReceiver = this; - callbackParams.jsonCallbackMethod = "goToPlaceFromResponse"; - callbackParams.errorCallbackReceiver = this; - callbackParams.errorCallbackMethod = "handleAddressLookupError"; - - AccountManager::getInstance().authenticatedRequest(GET_PLACE_ADDRESS.arg(destination), - QNetworkAccessManager::GetOperation, - callbackParams); - } else { - UserActivityLogger::getInstance().wentTo(COORDINATE_DESTINATION_TYPE, destination); - } -} - -void LocationManager::goToPlaceFromResponse(const QJsonObject& responseData) { - QJsonValue status = responseData["status"]; - - QJsonObject data = responseData["data"].toObject(); - QJsonObject domainObject = data["domain"].toObject(); - - const QString DOMAIN_NETWORK_ADDRESS_KEY = "network_address"; - - // get the network address for the domain we need to switch to - NodeList::getInstance()->getDomainHandler().setHostname(domainObject[DOMAIN_NETWORK_ADDRESS_KEY].toString()); - - // check if there is a path inside the domain we need to jump to -} - -void LocationManager::goToUser(QString userName) { - JSONCallbackParameters callbackParams; - callbackParams.jsonCallbackReceiver = Application::getInstance()->getAvatar(); - callbackParams.jsonCallbackMethod = "goToLocationFromResponse"; - callbackParams.errorCallbackReceiver = this; - callbackParams.errorCallbackMethod = "handleAddressLookupError"; - - userName = QString(QUrl::toPercentEncoding(userName)); - AccountManager::getInstance().authenticatedRequest(GET_USER_ADDRESS.arg(userName), - QNetworkAccessManager::GetOperation, - callbackParams); -} - -void LocationManager::goToPlace(QString placeName) { - JSONCallbackParameters callbackParams; - callbackParams.jsonCallbackReceiver = Application::getInstance()->getAvatar(); - callbackParams.jsonCallbackMethod = "goToLocationFromResponse"; - callbackParams.errorCallbackReceiver = this; - callbackParams.errorCallbackMethod = "handleAddressLookupError"; - - placeName = QString(QUrl::toPercentEncoding(placeName)); - AccountManager::getInstance().authenticatedRequest(GET_PLACE_ADDRESS.arg(placeName), - QNetworkAccessManager::GetOperation, - callbackParams); -} - void LocationManager::goToUrl(const QUrl& url) { // if (location.startsWith(CUSTOM_URL_SCHEME + "/")) { // QStringList urlParts = location.remove(0, CUSTOM_URL_SCHEME.length()).split('/', QString::SkipEmptyParts); diff --git a/interface/src/location/LocationManager.h b/interface/src/location/LocationManager.h index bf1c0e67e2..ec580dfc7a 100644 --- a/interface/src/location/LocationManager.h +++ b/interface/src/location/LocationManager.h @@ -49,8 +49,6 @@ signals: private slots: void namedLocationDataReceived(const QJsonObject& data); - void errorDataReceived(QNetworkReply::NetworkError error, const QString& message); - void goToPlaceFromResponse(const QJsonObject& jsonObject); }; diff --git a/interface/src/scripting/LocationScriptingInterface.cpp b/interface/src/scripting/LocationScriptingInterface.cpp deleted file mode 100644 index 9e68778942..0000000000 --- a/interface/src/scripting/LocationScriptingInterface.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// -// LocationScriptingInterface.cpp -// interface/src/scripting -// -// Created by Ryan Huffman on 4/29/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 "NodeList.h" - -#include "LocationScriptingInterface.h" - -LocationScriptingInterface* LocationScriptingInterface::getInstance() { - static LocationScriptingInterface sharedInstance; - return &sharedInstance; -} - -bool LocationScriptingInterface::isConnected() { - return NodeList::getInstance()->getDomainHandler().isConnected(); -} - -QString LocationScriptingInterface::getHref() { - return getProtocol() + "//" + getHostname() + getPathname(); -} - -QString LocationScriptingInterface::getPathname() { - const glm::vec3& position = Application::getInstance()->getAvatar()->getPosition(); - QString path; - path.sprintf("/%.4f,%.4f,%.4f", position.x, position.y, position.z); - return path; -} - -QString LocationScriptingInterface::getHostname() { - return NodeList::getInstance()->getDomainHandler().getHostname(); -} - -void LocationScriptingInterface::assign(const QString& url) { - QMetaObject::invokeMethod(Menu::getInstance(), "goToURL", Q_ARG(const QString&, url)); -} - -QScriptValue LocationScriptingInterface::locationGetter(QScriptContext* context, QScriptEngine* engine) { - return engine->newQObject(getInstance()); -} - -QScriptValue LocationScriptingInterface::locationSetter(QScriptContext* context, QScriptEngine* engine) { - LocationScriptingInterface::getInstance()->assign(context->argument(0).toString()); - return QScriptValue::UndefinedValue; -} diff --git a/interface/src/scripting/LocationScriptingInterface.h b/interface/src/scripting/LocationScriptingInterface.h deleted file mode 100644 index 20f63bceed..0000000000 --- a/interface/src/scripting/LocationScriptingInterface.h +++ /dev/null @@ -1,48 +0,0 @@ -// -// LocationScriptingInterface.h -// interface/src/scripting -// -// Created by Ryan Huffman on 4/29/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_LocationScriptingInterface_h -#define hifi_LocationScriptingInterface_h - -#include -#include -#include -#include -#include - -#include "Application.h" - -class LocationScriptingInterface : public QObject { - Q_OBJECT - Q_PROPERTY(bool isConnected READ isConnected) - Q_PROPERTY(QString href READ getHref) - Q_PROPERTY(QString protocol READ getProtocol) - Q_PROPERTY(QString hostname READ getHostname) - Q_PROPERTY(QString pathname READ getPathname) - LocationScriptingInterface() { }; -public: - static LocationScriptingInterface* getInstance(); - - bool isConnected(); - QString getHref(); - QString getProtocol() { return CUSTOM_URL_SCHEME; }; - QString getPathname(); - QString getHostname(); - - static QScriptValue locationGetter(QScriptContext* context, QScriptEngine* engine); - static QScriptValue locationSetter(QScriptContext* context, QScriptEngine* engine); - -public slots: - void assign(const QString& url); - -}; - -#endif // hifi_LocationScriptingInterface_h diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 63f1b59f6b..5e3c7f22be 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -13,6 +13,8 @@ #include #include +#include + #include "AddressManager.h" AddressManager& AddressManager::getInstance() { @@ -20,6 +22,33 @@ AddressManager& AddressManager::getInstance() { return sharedInstance; } +QString AddressManager::pathForPositionAndOrientation(const glm::vec3& position, bool hasOrientation, + const glm::quat& orientation) { + + QString pathString = "/" + createByteArray(position); + + if (hasOrientation) { + QString orientationString = createByteArray(glm::degrees(safeEulerAngles(orientation))); + pathString += "/" + orientationString; + } + + return pathString; +} + +const JSONCallbackParameters& AddressManager::apiCallbackParameters() { + static bool hasSetupParameters = false; + static JSONCallbackParameters callbackParams; + + if (!hasSetupParameters) { + callbackParams.jsonCallbackReceiver = this; + callbackParams.jsonCallbackMethod = "handleAPIResponse"; + callbackParams.errorCallbackReceiver = this; + callbackParams.errorCallbackMethod = "handleAPIError"; + } + + return callbackParams; +} + void AddressManager::handleLookupString(const QString& lookupString) { // there are 4 possible lookup strings @@ -28,15 +57,77 @@ void AddressManager::handleLookupString(const QString& lookupString) { // 3. location string (posX,posY,posZ/eulerX,eulerY,eulerZ) // 4. domain network address (IP or dns resolvable hostname) + QString sanitizedLookupString = lookupString.trimmed().remove(HIFI_URL_SCHEME + "//"); + + // use our regex'ed helpers to figure out what we're supposed to do with this - if (!lookupHandledAsUsername(lookupString) && - !lookupHandledAsNetworkAddress(lookupString) && - !lookupHandledAsLocationString(lookupString)) { - + if (!isLookupHandledAsUsername(sanitizedLookupString) && + !isLookupHandledAsNetworkAddress(sanitizedLookupString) && + !isLookupHandledAsViewpoint(sanitizedLookupString)) { + attemptPlaceNameLookup(sanitizedLookupString); } } -bool AddressManager::lookupHandledAsNetworkAddress(const QString& lookupString) { +void AddressManager::handleAPIResponse(const QJsonObject &jsonObject) { + QJsonObject dataObject = jsonObject["data"].toObject(); + + const QString ADDRESS_API_DOMAIN_KEY = "domain"; + const QString ADDRESS_API_ONLINE_KEY = "online"; + + if (!dataObject.contains(ADDRESS_API_ONLINE_KEY) + || dataObject[ADDRESS_API_ONLINE_KEY].toBool()) { + + if (dataObject.contains(ADDRESS_API_DOMAIN_KEY)) { + QJsonObject domainObject = dataObject[ADDRESS_API_DOMAIN_KEY].toObject(); + + const QString DOMAIN_NETWORK_ADDRESS_KEY = "network_address"; + QString domainHostname = domainObject[DOMAIN_NETWORK_ADDRESS_KEY].toString(); + + emit possibleDomainChangeRequired(domainHostname); + + // take the path that came back + const QString LOCATION_KEY = "location"; + const QString LOCATION_PATH_KEY = "path"; + QString returnedPath; + + if (domainObject.contains(LOCATION_PATH_KEY)) { + returnedPath = domainObject[LOCATION_PATH_KEY].toString(); + } else if (domainObject.contains(LOCATION_KEY)) { + returnedPath = domainObject[LOCATION_KEY].toObject()[LOCATION_PATH_KEY].toString(); + } + + if (!returnedPath.isEmpty()) { + // try to parse this returned path as a viewpoint, that's the only thing it could be for now + if (!isLookupHandledAsViewpoint(returnedPath)) { + qDebug() << "Received a location path that was could not be handled as a viewpoint -" << returnedPath; + } + } + + } else { + qDebug() << "Received an address manager API response with no domain key. Cannot parse."; + qDebug() << jsonObject; + } + } else { + // we've been told that this result exists but is offline, emit our signal so the application can handle + emit lookupResultIsOffline(); + } +} + +void AddressManager::handleAPIError(QNetworkReply::NetworkError error, const QString& message) { + qDebug() << "AddressManager API error -" << error << "-" << message; +} + +const QString GET_PLACE = "/api/v1/places/%1"; + +void AddressManager::attemptPlaceNameLookup(const QString& lookupString) { + // assume this is a place name and see if we can get any info on it + QString placeName = QUrl::toPercentEncoding(lookupString); + AccountManager::getInstance().authenticatedRequest(GET_PLACE.arg(placeName), + QNetworkAccessManager::GetOperation, + apiCallbackParameters()); +} + +bool AddressManager::isLookupHandledAsNetworkAddress(const QString& lookupString) { const QString IP_ADDRESS_REGEX_STRING = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}" "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(:\\d{1,5})?$"; @@ -46,23 +137,23 @@ bool AddressManager::lookupHandledAsNetworkAddress(const QString& lookupString) QRegExp hostnameRegex(HOSTNAME_REGEX_STRING, Qt::CaseInsensitive); if (hostnameRegex.indexIn(lookupString) != -1) { - emit domainChangeRequired(hostnameRegex.cap(0)); + emit possibleDomainChangeRequired(hostnameRegex.cap(0)); return true; } QRegExp ipAddressRegex(IP_ADDRESS_REGEX_STRING); if (ipAddressRegex.indexIn(lookupString) != -1) { - emit domainChangeRequired(ipAddressRegex.cap(0)); + emit possibleDomainChangeRequired(ipAddressRegex.cap(0)); return true; } return false; } -bool AddressManager::lookupHandledAsLocationString(const QString& lookupString) { +bool AddressManager::isLookupHandledAsViewpoint(const QString& lookupString) { const QString FLOAT_REGEX_STRING = "([-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?)"; - const QString TRIPLE_FLOAT_REGEX_STRING = FLOAT_REGEX_STRING + "\\s*,\\s*" + + const QString TRIPLE_FLOAT_REGEX_STRING = QString("\\/") + FLOAT_REGEX_STRING + "\\s*,\\s*" + FLOAT_REGEX_STRING + "\\s*,\\s*" + FLOAT_REGEX_STRING + "\\s*(?:$|\\/)"; QRegExp tripleFloatRegex(TRIPLE_FLOAT_REGEX_STRING); @@ -103,13 +194,19 @@ bool AddressManager::lookupHandledAsLocationString(const QString& lookupString) return false; } -bool AddressManager::lookupHandledAsUsername(const QString& lookupString) { +const QString GET_USER_LOCATION = "/api/v1/users/%1/location"; + +bool AddressManager::isLookupHandledAsUsername(const QString& lookupString) { const QString USERNAME_REGEX_STRING = "^@(\\S+)$"; QRegExp usernameRegex(USERNAME_REGEX_STRING); if (usernameRegex.indexIn(lookupString) != -1) { - // this is a username - pull the captured name and lookup that user's address + QString username = QUrl::toPercentEncoding(usernameRegex.cap(1)); + // this is a username - pull the captured name and lookup that user's location + AccountManager::getInstance().authenticatedRequest(GET_USER_LOCATION.arg(username), + QNetworkAccessManager::GetOperation, + apiCallbackParameters()); return true; } diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index e43102dd42..f1960b73f7 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -15,20 +15,37 @@ #include #include +#include + +#include "AccountManager.h" + +static const QString HIFI_URL_SCHEME = "hifi:"; + +const glm::quat EMPTY_QUAT = glm::quat(); class AddressManager : public QObject { Q_OBJECT public: static AddressManager& getInstance(); + static QString pathForPositionAndOrientation(const glm::vec3& position, bool hasOrientation = false, + const glm::quat& orientation = EMPTY_QUAT); + void handleLookupString(const QString& lookupString); + void attemptPlaceNameLookup(const QString& lookupString); +public slots: + void handleAPIResponse(const QJsonObject& jsonObject); + void handleAPIError(QNetworkReply::NetworkError error, const QString& message); signals: - void domainChangeRequired(const QString& newHostname); + void lookupResultIsOffline(); + void possibleDomainChangeRequired(const QString& newHostname); void locationChangeRequired(const glm::vec3& newPosition, bool hasOrientationChange, const glm::vec3& newOrientation); private: - bool lookupHandledAsNetworkAddress(const QString& lookupString); - bool lookupHandledAsLocationString(const QString& lookupString); - bool lookupHandledAsUsername(const QString& lookupString); + const JSONCallbackParameters& apiCallbackParameters(); + + bool isLookupHandledAsNetworkAddress(const QString& lookupString); + bool isLookupHandledAsViewpoint(const QString& lookupString); + bool isLookupHandledAsUsername(const QString& lookupString); }; #endif // hifi_AddressManager_h \ No newline at end of file diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index 91166129ad..9c0ae55d7e 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -73,6 +73,22 @@ void DomainHandler::setSockAddr(const HifiSockAddr& sockAddr, const QString& hos _hostname = hostname; } +void DomainHandler::setUUID(const QUuid& uuid) { + if (uuid != _uuid) { + _uuid = uuid; + qDebug() << "Domain uuid changed to" << uuidStringWithoutCurlyBraces(_uuid); + } +} + +QString DomainHandler::hostnameWithoutPort(const QString& hostname) { + int colonIndex = hostname.indexOf(':'); + return colonIndex > 0 ? hostname.left(colonIndex) : hostname; +} + +bool DomainHandler::isCurrentHostname(const QString& hostname) { + return hostnameWithoutPort(hostname) == _hostname; +} + void DomainHandler::setHostname(const QString& hostname) { if (hostname != _hostname) { diff --git a/libraries/networking/src/DomainHandler.h b/libraries/networking/src/DomainHandler.h index c65d687f5f..bfdb5d7f38 100644 --- a/libraries/networking/src/DomainHandler.h +++ b/libraries/networking/src/DomainHandler.h @@ -37,8 +37,10 @@ public: void clearSettings(); const QUuid& getUUID() const { return _uuid; } - void setUUID(const QUuid& uuid) { _uuid = uuid; } + void setUUID(const QUuid& uuid); + static QString hostnameWithoutPort(const QString& hostname); + bool isCurrentHostname(const QString& hostname); const QString& getHostname() const { return _hostname; } const QHostAddress& getIP() const { return _sockAddr.getAddress(); } From 7964180905adf14968455ec0c10be3fb57f93294 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 11 Sep 2014 17:33:01 -0700 Subject: [PATCH 32/46] handle place creation at new API endpoint --- interface/src/avatar/MyAvatar.h | 2 +- interface/src/location/LocationManager.cpp | 147 +----------------- interface/src/location/LocationManager.h | 14 -- interface/src/location/NamedLocation.cpp | 28 ++-- interface/src/location/NamedLocation.h | 32 ++-- interface/src/ui/ChatWindow.cpp | 3 +- interface/src/ui/OAuthWebViewHandler.cpp | 2 + interface/src/ui/ScriptEditorWidget.cpp | 2 + .../src/ui/overlays/BillboardOverlay.cpp | 4 +- 9 files changed, 43 insertions(+), 191 deletions(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 86c10fdbb4..01dd392465 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -155,7 +155,7 @@ public slots: void decreaseSize(); void resetSize(); - void goToLocation(const glm::vec3& newPosition, bool hasOrientation, const glm::vec3& newOrientation); + void goToLocation(const glm::vec3& newPosition, bool hasOrientation = false, const glm::vec3& newOrientation = glm::vec3()); // Set/Get update the thrust that will move the avatar around void addThrust(glm::vec3 newThrust) { _thrust += newThrust; }; diff --git a/interface/src/location/LocationManager.cpp b/interface/src/location/LocationManager.cpp index 6beb1f5527..1228791c98 100644 --- a/interface/src/location/LocationManager.cpp +++ b/interface/src/location/LocationManager.cpp @@ -9,14 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include +#include -#include "Application.h" #include "LocationManager.h" -#include - -const QString POST_PLACE_CREATE = "/api/v1/places/"; +const QString POST_LOCATION_CREATE = "/api/v1/locations/"; LocationManager& LocationManager::getInstance() { static LocationManager sharedInstance; @@ -44,145 +41,7 @@ void LocationManager::createNamedLocation(NamedLocation* namedLocation) { callbackParams.errorCallbackReceiver = this; callbackParams.errorCallbackMethod = "errorDataReceived"; - accountManager.authenticatedRequest(POST_PLACE_CREATE, QNetworkAccessManager::PostOperation, + accountManager.authenticatedRequest(POST_LOCATION_CREATE, QNetworkAccessManager::PostOperation, callbackParams, namedLocation->toJsonString().toUtf8()); } } - -void LocationManager::goToUrl(const QUrl& url) { -// if (location.startsWith(CUSTOM_URL_SCHEME + "/")) { -// QStringList urlParts = location.remove(0, CUSTOM_URL_SCHEME.length()).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]; -// -// // any third part is an avatar orientation. -// QString orientation = urlParts.count() > 2 ? urlParts[2] : QString(); -// -// goToDomain(domain); -// -// // goto either @user, #place, or x-xx,y-yy,z-zz -// // style co-ordinate. -// goTo(destination); -// -// if (!orientation.isEmpty()) { -// // location orientation -// goToOrientation(orientation); -// } -// } else if (urlParts.count() == 1) { -// QString destination = urlParts[0]; -// -// // If this starts with # or @, treat it as a user/location, otherwise treat it as a domain -// if (destination[0] == '#' || destination[0] == '@') { -// goTo(destination); -// } else { -// goToDomain(destination); -// } -// } -// return true; -// } -// return false; -} - -void LocationManager::goToOrientation(QString orientation) { - if (orientation.isEmpty()) { - return; - } - - QStringList orientationItems = orientation.remove(' ').split(QRegExp("_|,"), QString::SkipEmptyParts); - - const int NUMBER_OF_ORIENTATION_ITEMS = 4; - const int W_ITEM = 0; - const int X_ITEM = 1; - const int Y_ITEM = 2; - const int Z_ITEM = 3; - - if (orientationItems.size() == NUMBER_OF_ORIENTATION_ITEMS) { - - // replace last occurrence of '_' with decimal point - replaceLastOccurrence('-', '.', orientationItems[W_ITEM]); - replaceLastOccurrence('-', '.', orientationItems[X_ITEM]); - replaceLastOccurrence('-', '.', orientationItems[Y_ITEM]); - replaceLastOccurrence('-', '.', orientationItems[Z_ITEM]); - - double w = orientationItems[W_ITEM].toDouble(); - double x = orientationItems[X_ITEM].toDouble(); - double y = orientationItems[Y_ITEM].toDouble(); - double z = orientationItems[Z_ITEM].toDouble(); - - glm::quat newAvatarOrientation(w, x, y, z); - - MyAvatar* myAvatar = Application::getInstance()->getAvatar(); - glm::quat avatarOrientation = myAvatar->getOrientation(); - if (newAvatarOrientation != avatarOrientation) { - myAvatar->setOrientation(newAvatarOrientation); - emit myAvatar->transformChanged(); - } - } -} - -bool LocationManager::goToDestination(QString destination) { - - QStringList coordinateItems = destination.remove(' ').split(QRegExp("_|,"), QString::SkipEmptyParts); - - const int NUMBER_OF_COORDINATE_ITEMS = 3; - const int X_ITEM = 0; - const int Y_ITEM = 1; - const int Z_ITEM = 2; - if (coordinateItems.size() == NUMBER_OF_COORDINATE_ITEMS) { - - // replace last occurrence of '_' with decimal point - replaceLastOccurrence('-', '.', coordinateItems[X_ITEM]); - replaceLastOccurrence('-', '.', coordinateItems[Y_ITEM]); - replaceLastOccurrence('-', '.', coordinateItems[Z_ITEM]); - - double x = coordinateItems[X_ITEM].toDouble(); - double y = coordinateItems[Y_ITEM].toDouble(); - double z = coordinateItems[Z_ITEM].toDouble(); - - glm::vec3 newAvatarPos(x, y, z); - - MyAvatar* myAvatar = Application::getInstance()->getAvatar(); - glm::vec3 avatarPos = myAvatar->getPosition(); - if (newAvatarPos != avatarPos) { - // send a node kill request, indicating to other clients that they should play the "disappeared" effect - MyAvatar::sendKillAvatar(); - - qDebug("Going To Location: %f, %f, %f...", x, y, z); - myAvatar->slamPosition(newAvatarPos); - emit myAvatar->transformChanged(); - } - - return true; - } - - // no coordinates were parsed - return false; -} - -void LocationManager::handleAddressLookupError(QNetworkReply::NetworkError networkError, - const QString& errorString) { - QString messageBoxString; - - if (networkError == QNetworkReply::ContentNotFoundError) { - messageBoxString = "That address could not be found."; - } else { - messageBoxString = errorString; - } - - QMessageBox::warning(Application::getInstance()->getWindow(), "", messageBoxString); -} - -void LocationManager::replaceLastOccurrence(const QChar search, const QChar replace, QString& string) { - int lastIndex; - lastIndex = string.lastIndexOf(search); - if (lastIndex > 0) { - lastIndex = string.lastIndexOf(search); - string.replace(lastIndex, 1, replace); - } -} diff --git a/interface/src/location/LocationManager.h b/interface/src/location/LocationManager.h index ec580dfc7a..926d5d752b 100644 --- a/interface/src/location/LocationManager.h +++ b/interface/src/location/LocationManager.h @@ -14,7 +14,6 @@ #include -#include "AccountManager.h" #include "NamedLocation.h" class LocationManager : public QObject { @@ -30,19 +29,6 @@ public: }; void createNamedLocation(NamedLocation* namedLocation); - - void goTo(QString destination); - void goToUser(QString userName); - void goToPlace(QString placeName); - void goToUrl(const QUrl& url); - void goToOrientation(QString orientation); - bool goToDestination(QString destination); - -public slots: - void handleAddressLookupError(QNetworkReply::NetworkError networkError, const QString& errorString); - -private: - void replaceLastOccurrence(const QChar search, const QChar replace, QString& string); signals: void creationCompleted(LocationManager::NamedLocationCreateResponse response); diff --git a/interface/src/location/NamedLocation.cpp b/interface/src/location/NamedLocation.cpp index ed7701a391..997c36efba 100644 --- a/interface/src/location/NamedLocation.cpp +++ b/interface/src/location/NamedLocation.cpp @@ -9,19 +9,25 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include +#include + #include "NamedLocation.h" -const QString JSON_FORMAT = "{\"address\":{\"position\":\"%1,%2,%3\"," - "\"orientation\":\"%4,%5,%6,%7\",\"domain\":\"%8\"},\"name\":\"%9\"}"; +NamedLocation::NamedLocation(const QString& name, + const glm::vec3& position, const glm::quat& orientation, + const QUuid& domainID) : + _name(name), + _position(position), + _orientation(orientation), + _domainID(domainID) +{ + +} + +const QString JSON_FORMAT = "{\"location\":{\"path\":\"%1\",\"domain_id\":\"%2\"},\"name\":\"%3\"}"; QString NamedLocation::toJsonString() { - return JSON_FORMAT.arg(QString::number(_location.x), - QString::number(_location.y), - QString::number(_location.z), - QString::number(_orientation.w), - QString::number(_orientation.x), - QString::number(_orientation.y), - QString::number(_orientation.z), - _domain, - _locationName); + return JSON_FORMAT.arg(AddressManager::pathForPositionAndOrientation(_position, true, _orientation), + uuidStringWithoutCurlyBraces(_domainID), _name); } diff --git a/interface/src/location/NamedLocation.h b/interface/src/location/NamedLocation.h index ffbd157263..fca6852062 100644 --- a/interface/src/location/NamedLocation.h +++ b/interface/src/location/NamedLocation.h @@ -22,39 +22,33 @@ class NamedLocation : public QObject { Q_OBJECT public: - NamedLocation(QString locationName, glm::vec3 location, glm::quat orientation, QString domain) { - _locationName = locationName; - _location = location; - _orientation = orientation; - _domain = domain; - } + NamedLocation(const QString& name, const glm::vec3& position, const glm::quat& orientation, const QUuid& domainID); QString toJsonString(); - bool isEmpty() { return _locationName.isNull() || _locationName.isEmpty(); } + bool isEmpty() { return _name.isNull() || _name.isEmpty(); } - void setLocationName(QString locationName) { _locationName = locationName; } - QString locationName() { return _locationName; } + void setName(QString name) { _name = name; } + const QString& getName() const { return _name; } - void setLocation(glm::vec3 location) { _location = location; } - glm::vec3 location() { return _location; } + void setLocation(glm::vec3 position) { _position = position; } + const glm::vec3& getPosition() const { return _position; } - void setOrientation(glm::quat orentation) { _orientation = orentation; } - glm::quat orientation() { return _orientation; } + void setOrientation(const glm::quat& orentation) { _orientation = orentation; } + const glm::quat& getOrientation() const { return _orientation; } - void setDomain(QString domain) { _domain = domain; } - QString domain() { return _domain; } + void setDomainID(const QUuid& domainID) { _domainID = domainID; } + const QUuid& getDomainID() const { return _domainID; } signals: void dataReceived(bool locationExists); private: - - QString _locationName; + QString _name; QString _createdBy; - glm::vec3 _location; + glm::vec3 _position; glm::quat _orientation; - QString _domain; + QUuid _domainID; }; diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index 9961a84e79..cf62b75215 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -17,6 +17,8 @@ #include #include +#include + #include "Application.h" #include "ChatMessageArea.h" #include "FlowLayout.h" @@ -28,7 +30,6 @@ #include "ChatWindow.h" - const int NUM_MESSAGES_TO_TIME_STAMP = 20; const QRegularExpression regexLinks("((?:(?:ftp)|(?:https?)|(?:hifi))://\\S+)"); diff --git a/interface/src/ui/OAuthWebViewHandler.cpp b/interface/src/ui/OAuthWebViewHandler.cpp index 8ec415584d..a1dbfe9e0b 100644 --- a/interface/src/ui/OAuthWebViewHandler.cpp +++ b/interface/src/ui/OAuthWebViewHandler.cpp @@ -11,6 +11,8 @@ #include +#include + #include "Application.h" #include "OAuthWebViewHandler.h" diff --git a/interface/src/ui/ScriptEditorWidget.cpp b/interface/src/ui/ScriptEditorWidget.cpp index f99c9d5ac4..1473e4a6a0 100644 --- a/interface/src/ui/ScriptEditorWidget.cpp +++ b/interface/src/ui/ScriptEditorWidget.cpp @@ -23,6 +23,8 @@ #include #include +#include + #include "Application.h" #include "ScriptHighlighting.h" diff --git a/interface/src/ui/overlays/BillboardOverlay.cpp b/interface/src/ui/overlays/BillboardOverlay.cpp index 7d85d54fef..f29fa6ed8d 100644 --- a/interface/src/ui/overlays/BillboardOverlay.cpp +++ b/interface/src/ui/overlays/BillboardOverlay.cpp @@ -9,7 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "../../Application.h" +#include + +#include "Application.h" #include "BillboardOverlay.h" From 5f6563f4c9e8d3f32688d16af061beb28342c2ec Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 11 Sep 2014 17:42:04 -0700 Subject: [PATCH 33/46] don't allow named location creation with no domain UUID --- interface/src/Menu.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index b8835407b0..49b185fe47 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -1217,23 +1217,34 @@ void Menu::nameLocation() { // check if user is logged in or show login dialog if not AccountManager& accountManager = AccountManager::getInstance(); + if (!accountManager.isLoggedIn()) { QMessageBox msgBox; msgBox.setText("We need to tie this location to your username."); msgBox.setInformativeText("Please login first, then try naming the location again."); msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); msgBox.button(QMessageBox::Ok)->setText("Login"); + if (msgBox.exec() == QMessageBox::Ok) { loginForCurrentDomain(); } return; } + + DomainHandler& domainHandler = NodeList::getInstance()->getDomainHandler(); + if (domainHandler.getUUID().isNull()) { + const QString UNREGISTERED_DOMAIN_MESSAGE = "This domain is not registered with High Fidelity." + "\n\nYou cannot create a global location in an unregistered domain."; + QMessageBox::critical(this, "Unregistered Domain", UNREGISTERED_DOMAIN_MESSAGE); + + return; + } QInputDialog nameDialog(Application::getInstance()->getWindow()); nameDialog.setWindowTitle("Name this location"); nameDialog.setLabelText("Name this location, then share that name with others.\n" - "When they come here, they'll be in the same location and orientation\n" + "When they come here, they'll have the same viewpoint\n" "(wherever you are standing and looking now) as you.\n\n" "Location name:"); @@ -1251,7 +1262,7 @@ void Menu::nameLocation() { connect(manager, &LocationManager::creationCompleted, this, &Menu::namedLocationCreated); NamedLocation* location = new NamedLocation(locationName, myAvatar->getPosition(), myAvatar->getOrientation(), - NodeList::getInstance()->getDomainHandler().getHostname()); + domainHandler.getUUID()); manager->createNamedLocation(location); } } From 745edb8b0a9dc835b900a04c0c84c5e71b906c82 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 12 Sep 2014 09:10:47 -0700 Subject: [PATCH 34/46] fix error handling for location naming --- interface/src/Menu.cpp | 29 ++++--------- interface/src/Menu.h | 3 +- interface/src/UserLocationsModel.cpp | 8 ++-- interface/src/UserLocationsModel.h | 4 +- interface/src/avatar/MyAvatar.cpp | 5 --- interface/src/avatar/MyAvatar.h | 1 - interface/src/location/LocationManager.cpp | 46 ++++++++++++++++++++- interface/src/location/LocationManager.h | 4 +- interface/src/location/NamedLocation.cpp | 2 +- libraries/networking/src/AccountManager.cpp | 3 +- 10 files changed, 63 insertions(+), 42 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 49b185fe47..98f2986b9a 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -154,11 +154,6 @@ Menu::Menu() : appInstance, SLOT(toggleRunningScriptsWidget())); addDisabledActionAndSeparator(fileMenu, "Go"); - addActionToQMenuAndActionHash(fileMenu, - MenuOption::GoHome, - Qt::CTRL | Qt::Key_G, - appInstance->getAvatar(), - SLOT(goHome())); addActionToQMenuAndActionHash(fileMenu, MenuOption::NameLocation, Qt::CTRL | Qt::Key_N, @@ -1183,23 +1178,13 @@ void Menu::muteEnvironment() { free(packet); } -void Menu::namedLocationCreated(LocationManager::NamedLocationCreateResponse response) { +void Menu::displayNameLocationResponse(const QString& errorString) { - if (response == LocationManager::Created) { - return; - } - - QMessageBox msgBox; - switch (response) { - case LocationManager::AlreadyExists: - msgBox.setText("That name has been already claimed, try something else."); - break; - default: - msgBox.setText("An unexpected error has occurred, please try again later."); - break; - } - - msgBox.exec(); + if (!errorString.isEmpty()) { + QMessageBox msgBox; + msgBox.setText(errorString); + msgBox.exec(); + } } void Menu::toggleLocationList() { @@ -1259,7 +1244,7 @@ void Menu::nameLocation() { MyAvatar* myAvatar = Application::getInstance()->getAvatar(); LocationManager* manager = new LocationManager(); - connect(manager, &LocationManager::creationCompleted, this, &Menu::namedLocationCreated); + connect(manager, &LocationManager::creationCompleted, this, &Menu::displayNameLocationResponse); NamedLocation* location = new NamedLocation(locationName, myAvatar->getPosition(), myAvatar->getOrientation(), domainHandler.getUUID()); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 078c2b4255..d8658f956e 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -216,7 +216,7 @@ private slots: void toggleConsole(); void toggleChat(); void audioMuteToggled(); - void namedLocationCreated(LocationManager::NamedLocationCreateResponse response); + void displayNameLocationResponse(const QString& errorString); void muteEnvironment(); private: @@ -390,7 +390,6 @@ namespace MenuOption { const QString FullscreenMirror = "Fullscreen Mirror"; const QString GlowMode = "Cycle Glow Mode"; const QString GlowWhenSpeaking = "Glow When Speaking"; - const QString GoHome = "Go Home"; const QString HeadMouse = "Head Mouse"; const QString IncreaseAvatarSize = "Increase Avatar Size"; const QString IncreaseVoxelSize = "Increase Voxel Size"; diff --git a/interface/src/UserLocationsModel.cpp b/interface/src/UserLocationsModel.cpp index e84cae8f95..0a035faedd 100644 --- a/interface/src/UserLocationsModel.cpp +++ b/interface/src/UserLocationsModel.cpp @@ -75,10 +75,10 @@ void UserLocation::handleRenameResponse(const QJsonObject& responseData) { emit updated(_name); } -void UserLocation::handleRenameError(QNetworkReply::NetworkError error, const QString& errorString) { +void UserLocation::handleRenameError(QNetworkReply& errorReply) { _updating = false; - QString msg = "There was an error renaming location '" + _name + "': " + errorString; + QString msg = "There was an error renaming location '" + _name + "': " + errorReply.errorString(); qDebug() << msg; QMessageBox::warning(Application::getInstance()->getWindow(), "Error", msg); @@ -109,10 +109,10 @@ void UserLocation::handleDeleteResponse(const QJsonObject& responseData) { } } -void UserLocation::handleDeleteError(QNetworkReply::NetworkError error, const QString& errorString) { +void UserLocation::handleDeleteError(QNetworkReply& errorReply) { _updating = false; - QString msg = "There was an error deleting location '" + _name + "': " + errorString; + QString msg = "There was an error deleting location '" + _name + "': " + errorReply.errorString(); qDebug() << msg; QMessageBox::warning(Application::getInstance()->getWindow(), "Error", msg); } diff --git a/interface/src/UserLocationsModel.h b/interface/src/UserLocationsModel.h index d3f86faa5a..4a1eb9fd0a 100644 --- a/interface/src/UserLocationsModel.h +++ b/interface/src/UserLocationsModel.h @@ -31,9 +31,9 @@ public: public slots: void handleRenameResponse(const QJsonObject& responseData); - void handleRenameError(QNetworkReply::NetworkError error, const QString& errorString); + void handleRenameError(QNetworkReply& errorReply); void handleDeleteResponse(const QJsonObject& responseData); - void handleDeleteError(QNetworkReply::NetworkError error, const QString& errorString); + void handleDeleteError(QNetworkReply& errorReply); signals: void updated(const QString& name); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index b4335512ef..8238969eda 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1778,11 +1778,6 @@ void MyAvatar::maybeUpdateBillboard() { sendBillboardPacket(); } -void MyAvatar::goHome() { - qDebug("Going Home!"); - slamPosition(START_LOCATION); -} - void MyAvatar::increaseSize() { if ((1.0f + SCALING_RATIO) * _targetScale < MAX_AVATAR_SCALE) { _targetScale *= (1.0f + SCALING_RATIO); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 01dd392465..6195bcc9b7 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -150,7 +150,6 @@ public: const PlayerPointer getPlayer() const { return _player; } public slots: - void goHome(); void increaseSize(); void decreaseSize(); void resetSize(); diff --git a/interface/src/location/LocationManager.cpp b/interface/src/location/LocationManager.cpp index 1228791c98..029657996b 100644 --- a/interface/src/location/LocationManager.cpp +++ b/interface/src/location/LocationManager.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include #include "LocationManager.h" @@ -20,15 +22,17 @@ LocationManager& LocationManager::getInstance() { return sharedInstance; } +const QString UNKNOWN_ERROR_MESSAGE = "Unknown error creating named location. Please try again!"; + void LocationManager::namedLocationDataReceived(const QJsonObject& data) { if (data.isEmpty()) { return; } if (data.contains("status") && data["status"].toString() == "success") { - emit creationCompleted(LocationManager::Created); + emit creationCompleted(QString()); } else { - emit creationCompleted(LocationManager::AlreadyExists); + emit creationCompleted(UNKNOWN_ERROR_MESSAGE); } } @@ -45,3 +49,41 @@ void LocationManager::createNamedLocation(NamedLocation* namedLocation) { callbackParams, namedLocation->toJsonString().toUtf8()); } } + +void LocationManager::errorDataReceived(QNetworkReply& errorReply) { + + if (errorReply.header(QNetworkRequest::ContentTypeHeader).toString().startsWith("application/json")) { + // we have some JSON error data we can parse for our error message + QJsonDocument responseJson = QJsonDocument::fromJson(errorReply.readAll()); + + QJsonObject dataObject = responseJson.object()["data"].toObject(); + + qDebug() << dataObject; + + QString errorString = "There was a problem creating that location.\n"; + + // construct the error string from the returned attribute errors + foreach(const QString& key, dataObject.keys()) { + errorString += "\n\u2022 " + key + " - "; + + QJsonValue keyedErrorValue = dataObject[key]; + + if (keyedErrorValue.isArray()) { + foreach(const QJsonValue& attributeErrorValue, keyedErrorValue.toArray()) { + errorString += attributeErrorValue.toString() + ", "; + } + + // remove the trailing comma at end of error list + errorString.remove(errorString.length() - 2, 2); + } else if (keyedErrorValue.isString()) { + errorString += keyedErrorValue.toString(); + } + } + + // emit our creationCompleted signal with the error + emit creationCompleted(errorString); + + } else { + creationCompleted(UNKNOWN_ERROR_MESSAGE); + } +} diff --git a/interface/src/location/LocationManager.h b/interface/src/location/LocationManager.h index 926d5d752b..b6a662e323 100644 --- a/interface/src/location/LocationManager.h +++ b/interface/src/location/LocationManager.h @@ -13,6 +13,7 @@ #define hifi_LocationManager_h #include +#include #include "NamedLocation.h" @@ -31,10 +32,11 @@ public: void createNamedLocation(NamedLocation* namedLocation); signals: - void creationCompleted(LocationManager::NamedLocationCreateResponse response); + void creationCompleted(const QString& errorMessage); private slots: void namedLocationDataReceived(const QJsonObject& data); + void errorDataReceived(QNetworkReply& errorReply); }; diff --git a/interface/src/location/NamedLocation.cpp b/interface/src/location/NamedLocation.cpp index 997c36efba..7785edfea1 100644 --- a/interface/src/location/NamedLocation.cpp +++ b/interface/src/location/NamedLocation.cpp @@ -25,7 +25,7 @@ NamedLocation::NamedLocation(const QString& name, } -const QString JSON_FORMAT = "{\"location\":{\"path\":\"%1\",\"domain_id\":\"%2\"},\"name\":\"%3\"}"; +const QString JSON_FORMAT = "{\"location\":{\"path\":\"%1\",\"domain_id\":\"%2\",\"name\":\"%3\"}}"; QString NamedLocation::toJsonString() { return JSON_FORMAT.arg(AddressManager::pathForPositionAndOrientation(_position, true, _orientation), diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index 7fda9d74c9..1100371ac9 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -292,8 +292,7 @@ void AccountManager::passErrorToCallback(QNetworkReply* requestReply) { if (callbackParams.errorCallbackReceiver) { // invoke the right method on the callback receiver QMetaObject::invokeMethod(callbackParams.errorCallbackReceiver, qPrintable(callbackParams.errorCallbackMethod), - Q_ARG(QNetworkReply::NetworkError, requestReply->error()), - Q_ARG(const QString&, requestReply->errorString())); + Q_ARG(QNetworkReply&, *requestReply)); // remove the related reply-callback group from the map _pendingCallbackMap.remove(requestReply); From 74295a3869baff209f6e12db6515819249ce540d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 12 Sep 2014 09:52:34 -0700 Subject: [PATCH 35/46] repairs for new location lookup --- interface/src/Menu.h | 1 + interface/src/UserLocationsModel.cpp | 41 +++++++++++++----------- interface/src/UserLocationsModel.h | 12 +++---- interface/src/ui/UserLocationsDialog.cpp | 2 +- 4 files changed, 31 insertions(+), 25 deletions(-) diff --git a/interface/src/Menu.h b/interface/src/Menu.h index d8658f956e..fabaa0dce7 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -390,6 +390,7 @@ namespace MenuOption { const QString FullscreenMirror = "Fullscreen Mirror"; const QString GlowMode = "Cycle Glow Mode"; const QString GlowWhenSpeaking = "Glow When Speaking"; + const QString GoToUser = "Go To User"; const QString HeadMouse = "Head Mouse"; const QString IncreaseAvatarSize = "Increase Avatar Size"; const QString IncreaseVoxelSize = "Increase Voxel Size"; diff --git a/interface/src/UserLocationsModel.cpp b/interface/src/UserLocationsModel.cpp index 0a035faedd..0fae0d8800 100644 --- a/interface/src/UserLocationsModel.cpp +++ b/interface/src/UserLocationsModel.cpp @@ -18,14 +18,13 @@ #include "Application.h" #include "UserLocationsModel.h" -static const QString PLACES_GET = "/api/v1/places"; -static const QString PLACES_UPDATE = "/api/v1/places/%1"; -static const QString PLACES_DELETE= "/api/v1/places/%1"; +static const QString LOCATIONS_GET = "/api/v1/locations"; +static const QString LOCATION_UPDATE_OR_DELETE = "/api/v1/locations/%1"; -UserLocation::UserLocation(QString id, QString name, QString location) : +UserLocation::UserLocation(const QString& id, const QString& name, const QString& address) : _id(id), _name(name), - _location(location), + _address(address), _previousName(name), _updating(false) { } @@ -35,10 +34,15 @@ void UserLocation::requestRename(const QString& newName) { _updating = true; JSONCallbackParameters callbackParams(this, "handleRenameResponse", this, "handleRenameError"); + QJsonObject jsonNameObject; - jsonNameObject.insert("name", QJsonValue(newName)); + jsonNameObject.insert("name", newName); + + QJsonObject locationObject; + locationObject.insert("location", jsonNameObject); + QJsonDocument jsonDocument(jsonNameObject); - AccountManager::getInstance().authenticatedRequest(PLACES_UPDATE.arg(_id), + AccountManager::getInstance().authenticatedRequest(LOCATION_UPDATE_OR_DELETE.arg(_id), QNetworkAccessManager::PutOperation, callbackParams, jsonDocument.toJson()); @@ -54,7 +58,9 @@ void UserLocation::handleRenameResponse(const QJsonObject& responseData) { QJsonValue status = responseData["status"]; if (!status.isUndefined() && status.toString() == "success") { - QString updatedName = responseData["data"].toObject()["name"].toString(); + qDebug() << responseData; + QString updatedName = responseData["data"].toObject()["location"].toObject()["name"].toString(); + qDebug() << "The updated name is" << updatedName; _name = updatedName; } else { _name = _previousName; @@ -90,7 +96,7 @@ void UserLocation::requestDelete() { _updating = true; JSONCallbackParameters callbackParams(this, "handleDeleteResponse", this, "handleDeleteError"); - AccountManager::getInstance().authenticatedRequest(PLACES_DELETE.arg(_id), + AccountManager::getInstance().authenticatedRequest(LOCATION_UPDATE_OR_DELETE.arg(_id), QNetworkAccessManager::DeleteOperation, callbackParams); } @@ -153,7 +159,7 @@ void UserLocationsModel::refresh() { endResetModel(); JSONCallbackParameters callbackParams(this, "handleLocationsResponse"); - AccountManager::getInstance().authenticatedRequest(PLACES_GET, + AccountManager::getInstance().authenticatedRequest(LOCATIONS_GET, QNetworkAccessManager::GetOperation, callbackParams); } @@ -165,14 +171,13 @@ void UserLocationsModel::handleLocationsResponse(const QJsonObject& responseData QJsonValue status = responseData["status"]; if (!status.isUndefined() && status.toString() == "success") { beginResetModel(); - QJsonArray locations = responseData["data"].toObject()["places"].toArray(); + QJsonArray locations = responseData["data"].toObject()["locations"].toArray(); for (QJsonArray::const_iterator it = locations.constBegin(); it != locations.constEnd(); it++) { QJsonObject location = (*it).toObject(); - QJsonObject address = location["address"].toObject(); + QString locationAddress = "hifi://" + location["domain"].toObject()["name"].toString() + + location["path"].toString(); UserLocation* userLocation = new UserLocation(location["id"].toString(), location["name"].toString(), - "hifi://" + address["domain"].toString() - + "/" + address["position"].toString() - + "/" + address["orientation"].toString()); + locationAddress); _locations.append(userLocation); connect(userLocation, &UserLocation::deleted, this, &UserLocationsModel::removeLocation); connect(userLocation, &UserLocation::updated, this, &UserLocationsModel::update); @@ -214,8 +219,8 @@ QVariant UserLocationsModel::data(const QModelIndex& index, int role) const { return QVariant(); } else if (index.column() == NameColumn) { return _locations[index.row()]->name(); - } else if (index.column() == LocationColumn) { - return QVariant(_locations[index.row()]->location()); + } else if (index.column() == AddressColumn) { + return QVariant(_locations[index.row()]->address()); } } @@ -226,7 +231,7 @@ QVariant UserLocationsModel::headerData(int section, Qt::Orientation orientation if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { switch (section) { case NameColumn: return "Name"; - case LocationColumn: return "Location"; + case AddressColumn: return "Address"; default: return QVariant(); } } diff --git a/interface/src/UserLocationsModel.h b/interface/src/UserLocationsModel.h index 4a1eb9fd0a..54518d72e1 100644 --- a/interface/src/UserLocationsModel.h +++ b/interface/src/UserLocationsModel.h @@ -20,14 +20,14 @@ class UserLocation : public QObject { Q_OBJECT public: - UserLocation(QString id, QString name, QString location); + UserLocation(const QString& id, const QString& name, const QString& address); bool isUpdating() { return _updating; } void requestRename(const QString& newName); void requestDelete(); - QString id() { return _id; } - QString name() { return _name; } - QString location() { return _location; } + const QString& id() { return _id; } + const QString& name() { return _name; } + const QString& address() { return _address; } public slots: void handleRenameResponse(const QJsonObject& responseData); @@ -42,7 +42,7 @@ signals: private: QString _id; QString _name; - QString _location; + QString _address; QString _previousName; bool _updating; @@ -65,7 +65,7 @@ public: enum Columns { NameColumn = 0, - LocationColumn + AddressColumn }; public slots: diff --git a/interface/src/ui/UserLocationsDialog.cpp b/interface/src/ui/UserLocationsDialog.cpp index ca1a9b5ad6..5aed0c3df4 100644 --- a/interface/src/ui/UserLocationsDialog.cpp +++ b/interface/src/ui/UserLocationsDialog.cpp @@ -51,7 +51,7 @@ void UserLocationsDialog::updateEnabled() { } void UserLocationsDialog::goToModelIndex(const QModelIndex& index) { - QVariant location = _proxyModel.data(index.sibling(index.row(), UserLocationsModel::LocationColumn)); + QVariant location = _proxyModel.data(index.sibling(index.row(), UserLocationsModel::AddressColumn)); // Menu::getInstance()->goToURL(location.toString()); } From 7896119228c6405bace9511f7cfe582bd755cc9c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 12 Sep 2014 09:56:40 -0700 Subject: [PATCH 36/46] remap two goToUrl calls to AddressManager --- interface/src/Application.cpp | 2 +- interface/src/ui/UserLocationsDialog.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 39c8f1a82f..350f0fe1b9 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -813,7 +813,7 @@ bool Application::event(QEvent* event) { QFileOpenEvent* fileEvent = static_cast(event); bool isHifiSchemeURL = !fileEvent->url().isEmpty() && fileEvent->url().toLocalFile().startsWith(HIFI_URL_SCHEME); if (isHifiSchemeURL) { -// Menu::getInstance()->goToURL(fileEvent->url().toLocalFile()); + AddressManager::getInstance().handleLookupString(fileEvent->url().toLocalFile()); } return false; } diff --git a/interface/src/ui/UserLocationsDialog.cpp b/interface/src/ui/UserLocationsDialog.cpp index 5aed0c3df4..31f388d045 100644 --- a/interface/src/ui/UserLocationsDialog.cpp +++ b/interface/src/ui/UserLocationsDialog.cpp @@ -13,6 +13,8 @@ #include #include +#include + #include "Menu.h" #include "UserLocationsDialog.h" @@ -51,8 +53,8 @@ void UserLocationsDialog::updateEnabled() { } void UserLocationsDialog::goToModelIndex(const QModelIndex& index) { - QVariant location = _proxyModel.data(index.sibling(index.row(), UserLocationsModel::AddressColumn)); -// Menu::getInstance()->goToURL(location.toString()); + QVariant address = _proxyModel.data(index.sibling(index.row(), UserLocationsModel::AddressColumn)); + AddressManager::getInstance().handleLookupString(address.toString()); } void UserLocationsDialog::deleteSelection() { From 1f2020d1690e3c2691c23adaee147c22ccc1eaa8 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 12 Sep 2014 10:13:33 -0700 Subject: [PATCH 37/46] some url handling repairs, move existing error reply handlers to new format --- interface/src/Application.cpp | 66 ++++--------------- interface/src/Application.h | 3 +- interface/src/ModelUploader.cpp | 4 +- interface/src/ModelUploader.h | 2 +- interface/src/ui/ChatMessageArea.cpp | 4 +- libraries/networking/src/AddressManager.cpp | 14 +++- libraries/networking/src/AddressManager.h | 3 +- .../networking/src/UserActivityLogger.cpp | 4 +- libraries/networking/src/UserActivityLogger.h | 2 +- 9 files changed, 37 insertions(+), 65 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 350f0fe1b9..13a94ebebf 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -358,9 +358,6 @@ 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 @@ -405,13 +402,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : connect(_window, &MainWindow::windowGeometryChanged, _runningScriptsWidget, &RunningScriptsWidget::setBoundary); + + AddressManager& addressManager = AddressManager::getInstance(); // connect to the domainChangeRequired signal on AddressManager - connect(&AddressManager::getInstance(), &AddressManager::possibleDomainChangeRequired, + connect(&addressManager, &AddressManager::possibleDomainChangeRequired, this, &Application::changeDomainHostname); - //When -url in command line, teleport to location - urlGoTo(argc, constArgv); + // when -url in command line, teleport to location + addressManager.handleUrl(QUrl(getCmdOption(argc, constArgv, "-url"))); // call the OAuthWebviewHandler static getter so that its instance lives in our thread OAuthWebViewHandler::getInstance(); @@ -1066,10 +1065,6 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_Equal: _myAvatar->resetSize(); break; - - case Qt::Key_At: -// Menu::getInstance()->goTo(); - break; default: event->ignore(); break; @@ -1323,7 +1318,7 @@ void Application::dropEvent(QDropEvent *event) { SnapshotMetaData* snapshotData = Snapshot::parseSnapshotData(snapshotPath); if (snapshotData) { if (!snapshotData->getDomain().isEmpty()) { -// Menu::getInstance()->goToDomain(snapshotData->getDomain()); + changeDomainHostname(snapshotData->getDomain()); } _myAvatar->setPosition(snapshotData->getLocation()); @@ -3797,14 +3792,6 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser scriptEngine->registerGlobalObject("Overlays", &_overlays); - QScriptValue windowValue = scriptEngine->registerGlobalObject("Window", WindowScriptingInterface::getInstance()); -// scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter, -// LocationScriptingInterface::locationSetter, windowValue); -// -// // register `location` on the global object. -// scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter, -// LocationScriptingInterface::locationSetter); - scriptEngine->registerGlobalObject("Menu", MenuScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("Settings", SettingsScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("AudioDevice", AudioDeviceScriptingInterface::getInstance()); @@ -3932,6 +3919,13 @@ void Application::uploadAttachment() { uploadModel(ATTACHMENT_MODEL); } +void Application::openUrl(const QUrl& url) { + if (!AddressManager::getInstance().handleUrl(url)) { + // address manager did not handle - ask QDesktopServices to handle + QDesktopServices::openUrl(url); + } +} + void Application::domainSettingsReceived(const QJsonObject& domainSettingsObject) { // from the domain-handler, figure out the satoshi cost per voxel and per meter cubed @@ -4120,37 +4114,3 @@ void Application::takeSnapshot() { } _snapshotShareDialog->show(); } - -void Application::urlGoTo(int argc, const char * constArgv[]) { - //Gets the url (hifi://domain/destination/orientation) - QString customUrl = getCmdOption(argc, constArgv, "-url"); - if(customUrl.startsWith(HIFI_URL_SCHEME + "//")) { - QStringList urlParts = customUrl.remove(0, HIFI_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); - } - } - } -} diff --git a/interface/src/Application.h b/interface/src/Application.h index ef08cf4ec5..0c50aca4b9 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -152,7 +152,6 @@ public: void initializeGL(); void paintGL(); void resizeGL(int width, int height); - void urlGoTo(int argc, const char * constArgv[]); void keyPressEvent(QKeyEvent* event); void keyReleaseEvent(QKeyEvent* event); @@ -352,6 +351,8 @@ public slots: void uploadHead(); void uploadSkeleton(); void uploadAttachment(); + + void openUrl(const QUrl& url); void bumpSettings() { ++_numChangedSettings; } diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index 12a4b145cc..d120f74991 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -381,11 +381,11 @@ void ModelUploader::uploadSuccess(const QJsonObject& jsonResponse) { checkS3(); } -void ModelUploader::uploadFailed(QNetworkReply::NetworkError errorCode, const QString& errorString) { +void ModelUploader::uploadFailed(QNetworkReply& errorReply) { if (_progressDialog) { _progressDialog->reject(); } - qDebug() << "Model upload failed (" << errorCode << "): " << errorString; + qDebug() << "Model upload failed (" << errorReply.error() << "): " << errorReply.errorString(); QMessageBox::warning(NULL, QString("ModelUploader::uploadFailed()"), QString("There was a problem with your upload, please try again later."), diff --git a/interface/src/ModelUploader.h b/interface/src/ModelUploader.h index 2596120751..a1c7a27393 100644 --- a/interface/src/ModelUploader.h +++ b/interface/src/ModelUploader.h @@ -43,7 +43,7 @@ private slots: void checkJSON(const QJsonObject& jsonResponse); void uploadUpdate(qint64 bytesSent, qint64 bytesTotal); void uploadSuccess(const QJsonObject& jsonResponse); - void uploadFailed(QNetworkReply::NetworkError errorCode, const QString& errorString); + void uploadFailed(QNetworkReply& errorReply); void checkS3(); void processCheck(); diff --git a/interface/src/ui/ChatMessageArea.cpp b/interface/src/ui/ChatMessageArea.cpp index ab93c7abe9..1dc38e9c94 100644 --- a/interface/src/ui/ChatMessageArea.cpp +++ b/interface/src/ui/ChatMessageArea.cpp @@ -19,8 +19,8 @@ ChatMessageArea::ChatMessageArea(bool useFixedHeight) : QTextBrowser(), _useFixe connect(document()->documentLayout(), &QAbstractTextDocumentLayout::documentSizeChanged, this, &ChatMessageArea::updateLayout); -// connect(this, &QTextBrowser::anchorClicked, -// Menu::getInstance(), &Menu::openUrl); + + connect(this, &QTextBrowser::anchorClicked, Application::getInstance(), &Application::openUrl); } void ChatMessageArea::setHtml(const QString& html) { diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 5e3c7f22be..591a7a3ef6 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -49,6 +49,16 @@ const JSONCallbackParameters& AddressManager::apiCallbackParameters() { return callbackParams; } +bool AddressManager::handleUrl(const QUrl& lookupUrl) { + if (lookupUrl.scheme() == HIFI_URL_SCHEME) { + // we've verified that this is a valid hifi URL - hand it off to handleLookupString + handleLookupString(lookupUrl.toString()); + return true; + } + + return false; +} + void AddressManager::handleLookupString(const QString& lookupString) { // there are 4 possible lookup strings @@ -113,8 +123,8 @@ void AddressManager::handleAPIResponse(const QJsonObject &jsonObject) { } } -void AddressManager::handleAPIError(QNetworkReply::NetworkError error, const QString& message) { - qDebug() << "AddressManager API error -" << error << "-" << message; +void AddressManager::handleAPIError(QNetworkReply& errorReply) { + qDebug() << "AddressManager API error -" << errorReply.error() << "-" << errorReply.errorString(); } const QString GET_PLACE = "/api/v1/places/%1"; diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index f1960b73f7..8ccffe39fa 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -31,11 +31,12 @@ public: static QString pathForPositionAndOrientation(const glm::vec3& position, bool hasOrientation = false, const glm::quat& orientation = EMPTY_QUAT); + bool handleUrl(const QUrl& lookupUrl); void handleLookupString(const QString& lookupString); void attemptPlaceNameLookup(const QString& lookupString); public slots: void handleAPIResponse(const QJsonObject& jsonObject); - void handleAPIError(QNetworkReply::NetworkError error, const QString& message); + void handleAPIError(QNetworkReply& errorReply); signals: void lookupResultIsOffline(); void possibleDomainChangeRequired(const QString& newHostname); diff --git a/libraries/networking/src/UserActivityLogger.cpp b/libraries/networking/src/UserActivityLogger.cpp index e2d3434867..549f02ae3c 100644 --- a/libraries/networking/src/UserActivityLogger.cpp +++ b/libraries/networking/src/UserActivityLogger.cpp @@ -73,8 +73,8 @@ void UserActivityLogger::requestFinished(const QJsonObject& object) { // qDebug() << object; } -void UserActivityLogger::requestError(QNetworkReply::NetworkError error,const QString& string) { - qDebug() << error << ": " << string; +void UserActivityLogger::requestError(QNetworkReply& errorReply) { + qDebug() << errorReply.error() << "-" << errorReply.errorString(); } void UserActivityLogger::launch(QString applicationVersion) { diff --git a/libraries/networking/src/UserActivityLogger.h b/libraries/networking/src/UserActivityLogger.h index 7e8abe9fb2..1bd966d632 100644 --- a/libraries/networking/src/UserActivityLogger.h +++ b/libraries/networking/src/UserActivityLogger.h @@ -40,7 +40,7 @@ public slots: private slots: void requestFinished(const QJsonObject& object); - void requestError(QNetworkReply::NetworkError error,const QString& string); + void requestError(QNetworkReply& errorReply); private: UserActivityLogger(); From b77a3f4904cd57dd4cb59b3940e86d21a26d75a6 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 12 Sep 2014 10:15:51 -0700 Subject: [PATCH 38/46] cleanup application file event handler --- interface/src/Application.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 13a94ebebf..9963706d97 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -810,10 +810,7 @@ bool Application::event(QEvent* event) { // handle custom URL if (event->type() == QEvent::FileOpen) { QFileOpenEvent* fileEvent = static_cast(event); - bool isHifiSchemeURL = !fileEvent->url().isEmpty() && fileEvent->url().toLocalFile().startsWith(HIFI_URL_SCHEME); - if (isHifiSchemeURL) { - AddressManager::getInstance().handleLookupString(fileEvent->url().toLocalFile()); - } + AddressManager::getInstance().handleLookupString(fileEvent->url().toLocalFile()); return false; } return QApplication::event(event); From ab7df8679dbbbaebf7a2261783b88632e1226b28 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 12 Sep 2014 11:19:22 -0700 Subject: [PATCH 39/46] fix broken hifi linking --- interface/src/Application.cpp | 8 ++- interface/src/Menu.cpp | 2 +- libraries/networking/src/AddressManager.cpp | 75 +++++++++++++-------- libraries/networking/src/AddressManager.h | 9 +-- 4 files changed, 60 insertions(+), 34 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9963706d97..15aacc7f8d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -410,6 +410,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : this, &Application::changeDomainHostname); // when -url in command line, teleport to location + qDebug() << getCmdOption(argc, constArgv, "-url"); addressManager.handleUrl(QUrl(getCmdOption(argc, constArgv, "-url"))); // call the OAuthWebviewHandler static getter so that its instance lives in our thread @@ -810,9 +811,14 @@ bool Application::event(QEvent* event) { // handle custom URL if (event->type() == QEvent::FileOpen) { QFileOpenEvent* fileEvent = static_cast(event); - AddressManager::getInstance().handleLookupString(fileEvent->url().toLocalFile()); + + if (!fileEvent->url().isEmpty()) { + AddressManager::getInstance().handleLookupString(fileEvent->url().toLocalFile()); + } + return false; } + return QApplication::event(event); } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 98f2986b9a..bd6a82f3df 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -1140,7 +1140,7 @@ void Menu::toggleAddressBar() { QInputDialog addressBarDialog(Application::getInstance()->getWindow()); addressBarDialog.setWindowTitle("Address Bar"); addressBarDialog.setWindowFlags(Qt::Sheet); - addressBarDialog.setLabelText("place, domain, @user, example.com, position/orientation"); + addressBarDialog.setLabelText("place, domain, @user, example.com, /position/orientation"); addressBarDialog.resize(addressBarDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, addressBarDialog.size().height()); diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 591a7a3ef6..59d00c496b 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -51,8 +51,34 @@ const JSONCallbackParameters& AddressManager::apiCallbackParameters() { bool AddressManager::handleUrl(const QUrl& lookupUrl) { if (lookupUrl.scheme() == HIFI_URL_SCHEME) { - // we've verified that this is a valid hifi URL - hand it off to handleLookupString - handleLookupString(lookupUrl.toString()); + + // there are 4 possible lookup strings + + // 1. global place name (name of domain or place) - example: sanfrancisco + // 2. user name (prepended with @) - example: @philip + // 3. location string (posX,posY,posZ/eulerX,eulerY,eulerZ) + // 4. domain network address (IP or dns resolvable hostname) + + qDebug() << lookupUrl; + + if (lookupUrl.isRelative()) { + // if this is a relative path then handle it as a relative viewpoint + handleRelativeViewpoint(lookupUrl.path()); + } else { + // use our regex'ed helpers to figure out what we're supposed to do with this + if (!handleUsername(lookupUrl.authority())) { + // we're assuming this is either a network address or global place name + // check if it is a network address first + if (!handleNetworkAddress(lookupUrl.host())) { + // wasn't an address - lookup the place name + attemptPlaceNameLookup(lookupUrl.host()); + } + + // we may have a path that defines a relative viewpoint - if so we should jump to that now + handleRelativeViewpoint(lookupUrl.path()); + } + } + return true; } @@ -60,22 +86,12 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl) { } void AddressManager::handleLookupString(const QString& lookupString) { - // there are 4 possible lookup strings + // we've verified that this is a valid hifi URL - hand it off to handleLookupString + QString sanitizedString = lookupString; + const QRegExp HIFI_SCHEME_REGEX = QRegExp(HIFI_URL_SCHEME + ":\\/{1,2}", Qt::CaseInsensitive); + sanitizedString = sanitizedString.remove(HIFI_SCHEME_REGEX); - // 1. global place name (name of domain or place) - example: sanfrancisco - // 2. user name (prepended with @) - example: @philip - // 3. location string (posX,posY,posZ/eulerX,eulerY,eulerZ) - // 4. domain network address (IP or dns resolvable hostname) - - QString sanitizedLookupString = lookupString.trimmed().remove(HIFI_URL_SCHEME + "//"); - - - // use our regex'ed helpers to figure out what we're supposed to do with this - if (!isLookupHandledAsUsername(sanitizedLookupString) && - !isLookupHandledAsNetworkAddress(sanitizedLookupString) && - !isLookupHandledAsViewpoint(sanitizedLookupString)) { - attemptPlaceNameLookup(sanitizedLookupString); - } + handleUrl(QUrl(HIFI_URL_SCHEME + "://" + sanitizedString)); } void AddressManager::handleAPIResponse(const QJsonObject &jsonObject) { @@ -108,7 +124,7 @@ void AddressManager::handleAPIResponse(const QJsonObject &jsonObject) { if (!returnedPath.isEmpty()) { // try to parse this returned path as a viewpoint, that's the only thing it could be for now - if (!isLookupHandledAsViewpoint(returnedPath)) { + if (!handleRelativeViewpoint(returnedPath)) { qDebug() << "Received a location path that was could not be handled as a viewpoint -" << returnedPath; } } @@ -137,7 +153,7 @@ void AddressManager::attemptPlaceNameLookup(const QString& lookupString) { apiCallbackParameters()); } -bool AddressManager::isLookupHandledAsNetworkAddress(const QString& lookupString) { +bool AddressManager::handleNetworkAddress(const QString& lookupString) { const QString IP_ADDRESS_REGEX_STRING = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}" "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(:\\d{1,5})?$"; @@ -161,7 +177,7 @@ bool AddressManager::isLookupHandledAsNetworkAddress(const QString& lookupString return false; } -bool AddressManager::isLookupHandledAsViewpoint(const QString& lookupString) { +bool AddressManager::handleRelativeViewpoint(const QString& lookupString) { const QString FLOAT_REGEX_STRING = "([-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?)"; const QString TRIPLE_FLOAT_REGEX_STRING = QString("\\/") + FLOAT_REGEX_STRING + "\\s*,\\s*" + FLOAT_REGEX_STRING + "\\s*,\\s*" + FLOAT_REGEX_STRING + "\\s*(?:$|\\/)"; @@ -206,20 +222,23 @@ bool AddressManager::isLookupHandledAsViewpoint(const QString& lookupString) { const QString GET_USER_LOCATION = "/api/v1/users/%1/location"; -bool AddressManager::isLookupHandledAsUsername(const QString& lookupString) { - const QString USERNAME_REGEX_STRING = "^@(\\S+)$"; +bool AddressManager::handleUsername(const QString& lookupString) { + const QString USERNAME_REGEX_STRING = "^@(\\S+)"; QRegExp usernameRegex(USERNAME_REGEX_STRING); if (usernameRegex.indexIn(lookupString) != -1) { - QString username = QUrl::toPercentEncoding(usernameRegex.cap(1)); - // this is a username - pull the captured name and lookup that user's location - AccountManager::getInstance().authenticatedRequest(GET_USER_LOCATION.arg(username), - QNetworkAccessManager::GetOperation, - apiCallbackParameters()); - + lookupUserViaAPI(usernameRegex.cap(1)); return true; } return false; } + +void AddressManager::lookupUserViaAPI(const QString& username) { + QString formattedUsername = QUrl::toPercentEncoding(username); + // this is a username - pull the captured name and lookup that user's location + AccountManager::getInstance().authenticatedRequest(GET_USER_LOCATION.arg(formattedUsername), + QNetworkAccessManager::GetOperation, + apiCallbackParameters()); +} diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 8ccffe39fa..1afdf00e7d 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -19,7 +19,7 @@ #include "AccountManager.h" -static const QString HIFI_URL_SCHEME = "hifi:"; +static const QString HIFI_URL_SCHEME = "hifi"; const glm::quat EMPTY_QUAT = glm::quat(); @@ -37,6 +37,7 @@ public: public slots: void handleAPIResponse(const QJsonObject& jsonObject); void handleAPIError(QNetworkReply& errorReply); + void lookupUserViaAPI(const QString& username); signals: void lookupResultIsOffline(); void possibleDomainChangeRequired(const QString& newHostname); @@ -44,9 +45,9 @@ signals: private: const JSONCallbackParameters& apiCallbackParameters(); - bool isLookupHandledAsNetworkAddress(const QString& lookupString); - bool isLookupHandledAsViewpoint(const QString& lookupString); - bool isLookupHandledAsUsername(const QString& lookupString); + bool handleNetworkAddress(const QString& lookupString); + bool handleRelativeViewpoint(const QString& pathSubsection); + bool handleUsername(const QString& lookupString); }; #endif // hifi_AddressManager_h \ No newline at end of file From 93ff34baaa03d1b374f460ab8587071c05b408e2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 12 Sep 2014 11:21:38 -0700 Subject: [PATCH 40/46] force address bar lookup through handleLookupString --- interface/src/Application.cpp | 7 ++++--- libraries/networking/src/AddressManager.h | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 15aacc7f8d..89c3dcebd5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -410,8 +410,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : this, &Application::changeDomainHostname); // when -url in command line, teleport to location - qDebug() << getCmdOption(argc, constArgv, "-url"); - addressManager.handleUrl(QUrl(getCmdOption(argc, constArgv, "-url"))); + addressManager.handleLookupString(getCmdOption(argc, constArgv, "-url")); // call the OAuthWebviewHandler static getter so that its instance lives in our thread OAuthWebViewHandler::getInstance(); @@ -3923,7 +3922,9 @@ void Application::uploadAttachment() { } void Application::openUrl(const QUrl& url) { - if (!AddressManager::getInstance().handleUrl(url)) { + if (url.scheme() == HIFI_URL_SCHEME) { + AddressManager::getInstance().handleLookupString(url.toString()); + } else { // address manager did not handle - ask QDesktopServices to handle QDesktopServices::openUrl(url); } diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 1afdf00e7d..dd5e5ad0a3 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -31,7 +31,6 @@ public: static QString pathForPositionAndOrientation(const glm::vec3& position, bool hasOrientation = false, const glm::quat& orientation = EMPTY_QUAT); - bool handleUrl(const QUrl& lookupUrl); void handleLookupString(const QString& lookupString); void attemptPlaceNameLookup(const QString& lookupString); public slots: @@ -45,6 +44,8 @@ signals: private: const JSONCallbackParameters& apiCallbackParameters(); + bool handleUrl(const QUrl& lookupUrl); + bool handleNetworkAddress(const QString& lookupString); bool handleRelativeViewpoint(const QString& pathSubsection); bool handleUsername(const QString& lookupString); From 1084483dd503270a2ee699093668a7f69fcd4fac Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 12 Sep 2014 11:22:34 -0700 Subject: [PATCH 41/46] fix for default param of default constructed quat --- libraries/networking/src/AddressManager.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index dd5e5ad0a3..2365f8b4c1 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -21,15 +21,13 @@ static const QString HIFI_URL_SCHEME = "hifi"; -const glm::quat EMPTY_QUAT = glm::quat(); - class AddressManager : public QObject { Q_OBJECT public: static AddressManager& getInstance(); static QString pathForPositionAndOrientation(const glm::vec3& position, bool hasOrientation = false, - const glm::quat& orientation = EMPTY_QUAT); + const glm::quat& orientation = glm::quat()); void handleLookupString(const QString& lookupString); void attemptPlaceNameLookup(const QString& lookupString); From 88a75a35855e4b65e7c862e3d036630b0b18534c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 12 Sep 2014 11:27:54 -0700 Subject: [PATCH 42/46] fix for goToUser from ChatWindow --- interface/src/ui/ChatWindow.cpp | 3 ++- libraries/networking/src/AddressManager.cpp | 4 ++-- libraries/networking/src/AddressManager.h | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index cf62b75215..5add09a9a6 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include "Application.h" @@ -170,7 +171,7 @@ bool ChatWindow::eventFilter(QObject* sender, QEvent* event) { } else if (event->type() == QEvent::MouseButtonRelease) { QVariant userVar = sender->property("user"); if (userVar.isValid()) { -// Menu::getInstance()->goToUser("@" + userVar.toString()); + AddressManager::getInstance().goToUser(userVar.toString()); return true; } } diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 59d00c496b..e41dbe0e3a 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -228,14 +228,14 @@ bool AddressManager::handleUsername(const QString& lookupString) { QRegExp usernameRegex(USERNAME_REGEX_STRING); if (usernameRegex.indexIn(lookupString) != -1) { - lookupUserViaAPI(usernameRegex.cap(1)); + goToUser(usernameRegex.cap(1)); return true; } return false; } -void AddressManager::lookupUserViaAPI(const QString& username) { +void AddressManager::goToUser(const QString& username) { QString formattedUsername = QUrl::toPercentEncoding(username); // this is a username - pull the captured name and lookup that user's location AccountManager::getInstance().authenticatedRequest(GET_USER_LOCATION.arg(formattedUsername), diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 2365f8b4c1..987e435981 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -34,7 +34,7 @@ public: public slots: void handleAPIResponse(const QJsonObject& jsonObject); void handleAPIError(QNetworkReply& errorReply); - void lookupUserViaAPI(const QString& username); + void goToUser(const QString& username); signals: void lookupResultIsOffline(); void possibleDomainChangeRequired(const QString& newHostname); From 892e0e7cbfcb573140461c641ec7afd216497cb0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 12 Sep 2014 11:43:50 -0700 Subject: [PATCH 43/46] fix node auth url, NAN break on windows --- libraries/networking/src/AddressManager.cpp | 4 ++-- libraries/networking/src/LimitedNodeList.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index e41dbe0e3a..f2e9ce64ab 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -190,7 +190,7 @@ bool AddressManager::handleRelativeViewpoint(const QString& lookupString) { tripleFloatRegex.cap(2).toFloat(), tripleFloatRegex.cap(3).toFloat()); - if (newPosition.x != NAN && newPosition.y != NAN && newPosition.z != NAN) { + if (!isNaN(newPosition.x) && !isNaN(newPosition.y) && !isNaN(newPosition.z)) { glm::vec3 newOrientation; // we may also have an orientation if (lookupString[tripleFloatRegex.matchedLength() - 1] == QChar('/') @@ -200,7 +200,7 @@ bool AddressManager::handleRelativeViewpoint(const QString& lookupString) { tripleFloatRegex.cap(2).toFloat(), tripleFloatRegex.cap(3).toFloat()); - if (newOrientation.x != NAN && newOrientation.y != NAN && newOrientation.z != NAN) { + if (!isNaN(newOrientation.x) && !isNaN(newOrientation.y) && !isNaN(newOrientation.z)) { emit locationChangeRequired(newPosition, true, newOrientation); return true; } else { diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 604f8c7434..f50f7493fb 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -33,7 +33,7 @@ const char SOLO_NODE_TYPES[2] = { NodeType::AudioMixer }; -const QUrl DEFAULT_NODE_AUTH_URL = QUrl("http://localhost:3000"); +const QUrl DEFAULT_NODE_AUTH_URL = QUrl("https://data.highfidelity.io"); LimitedNodeList* LimitedNodeList::_sharedInstance = NULL; From f0ead98a2a2e62029f806fbf51c0559be8748509 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 12 Sep 2014 13:27:01 -0700 Subject: [PATCH 44/46] put back LocationScriptingInterface so it works prior to replacement --- interface/src/Application.cpp | 8 +++ .../scripting/LocationScriptingInterface.cpp | 52 +++++++++++++++++++ .../scripting/LocationScriptingInterface.h | 50 ++++++++++++++++++ libraries/networking/src/AddressManager.h | 3 +- 4 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 interface/src/scripting/LocationScriptingInterface.cpp create mode 100644 interface/src/scripting/LocationScriptingInterface.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3208347728..18b39b30ef 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -81,6 +81,7 @@ #include "scripting/AccountScriptingInterface.h" #include "scripting/AudioDeviceScriptingInterface.h" #include "scripting/ClipboardScriptingInterface.h" +#include "scripting/LocationScriptingInterface.h" #include "scripting/MenuScriptingInterface.h" #include "scripting/SettingsScriptingInterface.h" #include "scripting/WindowScriptingInterface.h" @@ -3811,6 +3812,13 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser scriptEngine->registerGlobalObject("Overlays", &_overlays); + QScriptValue windowValue = scriptEngine->registerGlobalObject("Window", WindowScriptingInterface::getInstance()); + scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter, + LocationScriptingInterface::locationSetter, windowValue); + // register `location` on the global object. + scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter, + LocationScriptingInterface::locationSetter); + scriptEngine->registerGlobalObject("Menu", MenuScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("Settings", SettingsScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("AudioDevice", AudioDeviceScriptingInterface::getInstance()); diff --git a/interface/src/scripting/LocationScriptingInterface.cpp b/interface/src/scripting/LocationScriptingInterface.cpp new file mode 100644 index 0000000000..bead12117d --- /dev/null +++ b/interface/src/scripting/LocationScriptingInterface.cpp @@ -0,0 +1,52 @@ +// +// LocationScriptingInterface.cpp +// interface/src/scripting +// +// Created by Ryan Huffman on 4/29/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 "NodeList.h" + +#include "LocationScriptingInterface.h" + +LocationScriptingInterface* LocationScriptingInterface::getInstance() { + static LocationScriptingInterface sharedInstance; + return &sharedInstance; +} + +bool LocationScriptingInterface::isConnected() { + return NodeList::getInstance()->getDomainHandler().isConnected(); +} + +QString LocationScriptingInterface::getHref() { + return getProtocol() + "//" + getHostname() + getPathname(); +} + +QString LocationScriptingInterface::getPathname() { + MyAvatar* applicationAvatar = Application::getInstance()->getAvatar(); + return AddressManager::pathForPositionAndOrientation(applicationAvatar->getPosition(), + true, applicationAvatar->getOrientation()); +} + +QString LocationScriptingInterface::getHostname() { + return NodeList::getInstance()->getDomainHandler().getHostname(); +} + +void LocationScriptingInterface::assign(const QString& url) { + QMetaObject::invokeMethod(&AddressManager::getInstance(), "handleLookupString", Q_ARG(const QString&, url)); +} + +QScriptValue LocationScriptingInterface::locationGetter(QScriptContext* context, QScriptEngine* engine) { + return engine->newQObject(getInstance()); +} + +QScriptValue LocationScriptingInterface::locationSetter(QScriptContext* context, QScriptEngine* engine) { + LocationScriptingInterface::getInstance()->assign(context->argument(0).toString()); + return QScriptValue::UndefinedValue; +} diff --git a/interface/src/scripting/LocationScriptingInterface.h b/interface/src/scripting/LocationScriptingInterface.h new file mode 100644 index 0000000000..3d725776fd --- /dev/null +++ b/interface/src/scripting/LocationScriptingInterface.h @@ -0,0 +1,50 @@ +// +// LocationScriptingInterface.h +// interface/src/scripting +// +// Created by Ryan Huffman on 4/29/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_LocationScriptingInterface_h +#define hifi_LocationScriptingInterface_h + +#include +#include +#include +#include +#include + +#include + +#include "Application.h" + +class LocationScriptingInterface : public QObject { + Q_OBJECT + Q_PROPERTY(bool isConnected READ isConnected) + Q_PROPERTY(QString href READ getHref) + Q_PROPERTY(QString protocol READ getProtocol) + Q_PROPERTY(QString hostname READ getHostname) + Q_PROPERTY(QString pathname READ getPathname) + LocationScriptingInterface() { }; +public: + static LocationScriptingInterface* getInstance(); + + bool isConnected(); + QString getHref(); + QString getProtocol() { return HIFI_URL_SCHEME; }; + QString getPathname(); + QString getHostname(); + + static QScriptValue locationGetter(QScriptContext* context, QScriptEngine* engine); + static QScriptValue locationSetter(QScriptContext* context, QScriptEngine* engine); + +public slots: + void assign(const QString& url); + +}; + +#endif // hifi_LocationScriptingInterface_h diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 987e435981..f27fb475c2 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -29,9 +29,10 @@ public: static QString pathForPositionAndOrientation(const glm::vec3& position, bool hasOrientation = false, const glm::quat& orientation = glm::quat()); - void handleLookupString(const QString& lookupString); void attemptPlaceNameLookup(const QString& lookupString); public slots: + void handleLookupString(const QString& lookupString); + void handleAPIResponse(const QJsonObject& jsonObject); void handleAPIError(QNetworkReply& errorReply); void goToUser(const QString& username); From 113e9cf43b9d18d68e01dd3894c856798e662515 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 12 Sep 2014 13:31:07 -0700 Subject: [PATCH 45/46] Remove use of Quat::rotate --- examples/gracefulControls.js | 2 +- libraries/script-engine/src/Quat.cpp | 4 ---- libraries/script-engine/src/Quat.h | 1 - 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/examples/gracefulControls.js b/examples/gracefulControls.js index 4d9e3e2f96..e2b603c5d7 100644 --- a/examples/gracefulControls.js +++ b/examples/gracefulControls.js @@ -150,7 +150,7 @@ function update(dt) { var maxSpeed = movementParameters.MAX_SPEED; velocity.x = Math.max(-maxSpeed, Math.min(maxSpeed, velocity.x)); velocity.z = Math.max(-maxSpeed, Math.min(maxSpeed, velocity.z)); - var v = Quat.rotate(MyAvatar.headOrientation, velocity); + var v = Vec3.multiplyQbyV(MyAvatar.headOrientation, velocity); if (targetVelocityVertical == 0) { targetVelocityVertical -= (velocityVertical * movementParameters.DRAG_COEFFICIENT * dt); diff --git a/libraries/script-engine/src/Quat.cpp b/libraries/script-engine/src/Quat.cpp index 4a0e4f8317..5985858026 100644 --- a/libraries/script-engine/src/Quat.cpp +++ b/libraries/script-engine/src/Quat.cpp @@ -42,10 +42,6 @@ glm::quat Quat::inverse(const glm::quat& q) { return glm::inverse(q); } -glm::vec3 Quat::rotate(const glm::quat& q, const glm::vec3& v) { - return glm::rotate(q, v); -} - glm::vec3 Quat::getFront(const glm::quat& orientation) { return orientation * IDENTITY_FRONT; } diff --git a/libraries/script-engine/src/Quat.h b/libraries/script-engine/src/Quat.h index 74e80a825b..faae636f02 100644 --- a/libraries/script-engine/src/Quat.h +++ b/libraries/script-engine/src/Quat.h @@ -30,7 +30,6 @@ public slots: glm::quat fromPitchYawRollDegrees(float pitch, float yaw, float roll); // degrees glm::quat fromPitchYawRollRadians(float pitch, float yaw, float roll); // radians glm::quat inverse(const glm::quat& q); - glm::vec3 rotate(const glm::quat& q, const glm::vec3& v); glm::vec3 getFront(const glm::quat& orientation); glm::vec3 getRight(const glm::quat& orientation); glm::vec3 getUp(const glm::quat& orientation); From b0593bcdc0f862b49c4d426fc37eb75f6a37007a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 12 Sep 2014 13:31:27 -0700 Subject: [PATCH 46/46] fix a double space --- interface/src/location/LocationManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/location/LocationManager.cpp b/interface/src/location/LocationManager.cpp index 029657996b..92e8616478 100644 --- a/interface/src/location/LocationManager.cpp +++ b/interface/src/location/LocationManager.cpp @@ -32,7 +32,7 @@ void LocationManager::namedLocationDataReceived(const QJsonObject& data) { if (data.contains("status") && data["status"].toString() == "success") { emit creationCompleted(QString()); } else { - emit creationCompleted(UNKNOWN_ERROR_MESSAGE); + emit creationCompleted(UNKNOWN_ERROR_MESSAGE); } }