mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 18:23:54 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into actions-over-wire
This commit is contained in:
commit
5ecc39b811
19 changed files with 242 additions and 99 deletions
4
examples/html/jquery-2.1.4.min.js
vendored
Normal file
4
examples/html/jquery-2.1.4.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
@ -18,7 +18,7 @@ Hifi.Tooltip {
|
|||
offsetX = (lastMousePosition.x > surfaceSize.width/2) ? -root.width : 0
|
||||
offsetY = (lastMousePosition.y > surfaceSize.height/2) ? -root.height : 0
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: border
|
||||
color: "#7f000000"
|
||||
|
@ -41,10 +41,10 @@ Hifi.Tooltip {
|
|||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
font.pixelSize: hifi.fonts.pixelSize * 2
|
||||
text: root.text
|
||||
text: root.title
|
||||
wrapMode: Text.WrapAnywhere
|
||||
|
||||
/* Uncomment for debugging to see the extent of the
|
||||
|
||||
/* Uncomment for debugging to see the extent of the
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "#7fff00ff"
|
||||
|
@ -63,7 +63,9 @@ Hifi.Tooltip {
|
|||
|
||||
Image {
|
||||
id: tooltipPic
|
||||
source: "../images/NoPictureProvided.svg"
|
||||
source: root.imageURL
|
||||
height: 180
|
||||
width: 320
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
verticalAlignment: Image.AlignVCenter
|
||||
|
@ -75,10 +77,10 @@ Hifi.Tooltip {
|
|||
width: border.implicitWidth
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text: root.description
|
||||
font.pixelSize: hifi.fonts.pixelSize
|
||||
text: root.text
|
||||
wrapMode: Text.WrapAnywhere
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,14 +13,14 @@
|
|||
|
||||
#include <QScriptEngine>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdouble-promotion"
|
||||
#endif
|
||||
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
|
@ -74,19 +74,19 @@ void AvatarManager::init() {
|
|||
|
||||
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
|
||||
render::PendingChanges pendingChanges;
|
||||
_myAvatar->addToScene(_myAvatar, scene, pendingChanges);
|
||||
_myAvatar->addToScene(_myAvatar, scene, pendingChanges);
|
||||
scene->enqueuePendingChanges(pendingChanges);
|
||||
}
|
||||
|
||||
void AvatarManager::updateMyAvatar(float deltaTime) {
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "AvatarManager::updateMyAvatar()");
|
||||
|
||||
|
||||
_myAvatar->update(deltaTime);
|
||||
|
||||
|
||||
quint64 now = usecTimestampNow();
|
||||
quint64 dt = now - _lastSendAvatarDataTime;
|
||||
|
||||
|
||||
if (dt > MIN_TIME_BETWEEN_MY_AVATAR_DATA_SENDS) {
|
||||
// send head/hand data to the avatar mixer and voxel server
|
||||
PerformanceTimer perfTimer("send");
|
||||
|
@ -103,12 +103,12 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
|||
PerformanceWarning warn(showWarnings, "Application::updateAvatars()");
|
||||
|
||||
PerformanceTimer perfTimer("otherAvatars");
|
||||
|
||||
|
||||
// simulate avatars
|
||||
AvatarHash::iterator avatarIterator = _avatarHash.begin();
|
||||
while (avatarIterator != _avatarHash.end()) {
|
||||
auto avatar = std::dynamic_pointer_cast<Avatar>(avatarIterator.value());
|
||||
|
||||
|
||||
if (avatar == _myAvatar || !avatar->isInitialized()) {
|
||||
// DO NOT update _myAvatar! Its update has already been done earlier in the main loop.
|
||||
// DO NOT update or fade out uninitialized Avatars
|
||||
|
@ -122,17 +122,17 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
|||
++avatarIterator;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// simulate avatar fades
|
||||
simulateAvatarFades(deltaTime);
|
||||
}
|
||||
|
||||
void AvatarManager::simulateAvatarFades(float deltaTime) {
|
||||
QVector<AvatarSharedPointer>::iterator fadingIterator = _avatarFades.begin();
|
||||
|
||||
|
||||
const float SHRINK_RATE = 0.9f;
|
||||
const float MIN_FADE_SCALE = 0.001f;
|
||||
|
||||
|
||||
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
|
||||
render::PendingChanges pendingChanges;
|
||||
while (fadingIterator != _avatarFades.end()) {
|
||||
|
@ -153,12 +153,12 @@ AvatarSharedPointer AvatarManager::newSharedAvatar() {
|
|||
return AvatarSharedPointer(std::make_shared<Avatar>());
|
||||
}
|
||||
|
||||
// virtual
|
||||
// virtual
|
||||
AvatarSharedPointer AvatarManager::addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) {
|
||||
auto avatar = std::dynamic_pointer_cast<Avatar>(AvatarHashMap::addAvatar(sessionUUID, mixerWeakPointer));
|
||||
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
|
||||
render::PendingChanges pendingChanges;
|
||||
avatar->addToScene(avatar, scene, pendingChanges);
|
||||
avatar->addToScene(avatar, scene, pendingChanges);
|
||||
scene->enqueuePendingChanges(pendingChanges);
|
||||
return avatar;
|
||||
}
|
||||
|
@ -177,7 +177,7 @@ void AvatarManager::removeAvatarMotionState(AvatarSharedPointer avatar) {
|
|||
}
|
||||
}
|
||||
|
||||
// virtual
|
||||
// virtual
|
||||
void AvatarManager::removeAvatar(const QUuid& sessionUUID) {
|
||||
AvatarHash::iterator avatarIterator = _avatarHash.find(sessionUUID);
|
||||
if (avatarIterator != _avatarHash.end()) {
|
||||
|
|
|
@ -17,8 +17,9 @@
|
|||
|
||||
#include <avatar/AvatarManager.h>
|
||||
#include <gpu/GLBackend.h>
|
||||
#include <CursorManager.h>
|
||||
#include <Tooltip.h>
|
||||
|
||||
#include "CursorManager.h"
|
||||
#include "Tooltip.h"
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
|
@ -117,7 +118,7 @@ ApplicationCompositor::ApplicationCompositor() {
|
|||
memset(_magSizeMult, 0, sizeof(_magSizeMult));
|
||||
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
|
||||
|
||||
_reticleQuad = geometryCache->allocateID();
|
||||
_magnifierQuad = geometryCache->allocateID();
|
||||
_magnifierBorder = geometryCache->allocateID();
|
||||
|
@ -128,9 +129,22 @@ ApplicationCompositor::ApplicationCompositor() {
|
|||
_hoverItemId = entityItemID;
|
||||
_hoverItemEnterUsecs = usecTimestampNow();
|
||||
auto properties = entityScriptingInterface->getEntityProperties(_hoverItemId);
|
||||
_hoverItemHref = properties.getHref();
|
||||
|
||||
// check the format of this href string before we parse it
|
||||
QString hrefString = properties.getHref();
|
||||
if (!hrefString.startsWith("hifi:")) {
|
||||
hrefString.prepend("hifi://");
|
||||
}
|
||||
|
||||
// parse out a QUrl from the hrefString
|
||||
QUrl href = QUrl(hrefString);
|
||||
|
||||
_hoverItemTitle = href.host();
|
||||
_hoverItemDescription = properties.getDescription();
|
||||
|
||||
auto cursor = Cursor::Manager::instance().getCursor();
|
||||
if (!_hoverItemHref.isEmpty()) {
|
||||
|
||||
if (!href.isEmpty()) {
|
||||
cursor->setIcon(Cursor::Icon::LINK);
|
||||
} else {
|
||||
cursor->setIcon(Cursor::Icon::DEFAULT);
|
||||
|
@ -141,7 +155,10 @@ ApplicationCompositor::ApplicationCompositor() {
|
|||
connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity, [=](const EntityItemID& entityItemID, const MouseEvent& event) {
|
||||
if (_hoverItemId == entityItemID) {
|
||||
_hoverItemId = _noItemId;
|
||||
_hoverItemHref.clear();
|
||||
|
||||
_hoverItemTitle.clear();
|
||||
_hoverItemDescription.clear();
|
||||
|
||||
auto cursor = Cursor::Manager::instance().getCursor();
|
||||
cursor->setIcon(Cursor::Icon::DEFAULT);
|
||||
if (!_tooltipId.isEmpty()) {
|
||||
|
@ -314,7 +331,7 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int
|
|||
batch.setModelTransform(reticleXfm);
|
||||
geometryCache->renderUnitQuad(batch, glm::vec4(1), _reticleQuad);
|
||||
}
|
||||
|
||||
|
||||
renderArgs->_context->render(batch);
|
||||
}
|
||||
|
||||
|
@ -324,7 +341,7 @@ void ApplicationCompositor::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& or
|
|||
const glm::vec2 projection = screenToSpherical(cursorPos);
|
||||
// The overlay space orientation of the mouse coordinates
|
||||
const glm::quat orientation(glm::vec3(-projection.y, projection.x, 0.0f));
|
||||
// FIXME We now have the direction of the ray FROM THE DEFAULT HEAD POSE.
|
||||
// FIXME We now have the direction of the ray FROM THE DEFAULT HEAD POSE.
|
||||
// Now we need to account for the actual camera position relative to the overlay
|
||||
glm::vec3 overlaySpaceDirection = glm::normalize(orientation * IDENTITY_FRONT);
|
||||
|
||||
|
@ -377,7 +394,7 @@ QPoint ApplicationCompositor::getPalmClickLocation(const PalmData *palm) const {
|
|||
//Finds the collision point of a world space ray
|
||||
bool ApplicationCompositor::calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const {
|
||||
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
|
||||
|
||||
glm::quat inverseOrientation = glm::inverse(myAvatar->getOrientation());
|
||||
|
||||
glm::vec3 relativePosition = inverseOrientation * (position - myAvatar->getDefaultEyePosition());
|
||||
|
@ -409,7 +426,7 @@ void ApplicationCompositor::renderPointers(gpu::Batch& batch) {
|
|||
renderControllerPointers(batch);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ApplicationCompositor::renderControllerPointers(gpu::Batch& batch) {
|
||||
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
|
@ -517,7 +534,7 @@ void ApplicationCompositor::renderControllerPointers(gpu::Batch& batch) {
|
|||
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
|
||||
glm::vec4(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], 1.0f));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -527,10 +544,10 @@ void ApplicationCompositor::renderMagnifier(gpu::Batch& batch, const glm::vec2&
|
|||
return;
|
||||
}
|
||||
auto canvasSize = qApp->getCanvasSize();
|
||||
|
||||
|
||||
const int widgetWidth = canvasSize.x;
|
||||
const int widgetHeight = canvasSize.y;
|
||||
|
||||
|
||||
const float halfWidth = (MAGNIFY_WIDTH / _textureAspectRatio) * sizeMult / 2.0f;
|
||||
const float halfHeight = MAGNIFY_HEIGHT * sizeMult / 2.0f;
|
||||
// Magnification Texture Coordinates
|
||||
|
@ -538,7 +555,7 @@ void ApplicationCompositor::renderMagnifier(gpu::Batch& batch, const glm::vec2&
|
|||
const float magnifyURight = (magPos.x + halfWidth) / (float)widgetWidth;
|
||||
const float magnifyVTop = 1.0f - (magPos.y - halfHeight) / (float)widgetHeight;
|
||||
const float magnifyVBottom = 1.0f - (magPos.y + halfHeight) / (float)widgetHeight;
|
||||
|
||||
|
||||
const float newHalfWidth = halfWidth * MAGNIFY_MULT;
|
||||
const float newHalfHeight = halfHeight * MAGNIFY_MULT;
|
||||
//Get yaw / pitch value for the corners
|
||||
|
@ -546,7 +563,7 @@ void ApplicationCompositor::renderMagnifier(gpu::Batch& batch, const glm::vec2&
|
|||
magPos.y - newHalfHeight));
|
||||
const glm::vec2 bottomRightYawPitch = overlayToSpherical(glm::vec2(magPos.x + newHalfWidth,
|
||||
magPos.y + newHalfHeight));
|
||||
|
||||
|
||||
const glm::vec3 bottomLeft = getPoint(topLeftYawPitch.x, bottomRightYawPitch.y);
|
||||
const glm::vec3 bottomRight = getPoint(bottomRightYawPitch.x, bottomRightYawPitch.y);
|
||||
const glm::vec3 topLeft = getPoint(topLeftYawPitch.x, topLeftYawPitch.y);
|
||||
|
@ -569,7 +586,7 @@ void ApplicationCompositor::renderMagnifier(gpu::Batch& batch, const glm::vec2&
|
|||
_previousMagnifierTopLeft = topLeft;
|
||||
_previousMagnifierTopRight = topRight;
|
||||
}
|
||||
|
||||
|
||||
glPushMatrix(); {
|
||||
if (showBorder) {
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
@ -581,12 +598,12 @@ void ApplicationCompositor::renderMagnifier(gpu::Batch& batch, const glm::vec2&
|
|||
glm::vec4 magnifierColor = { 1.0f, 1.0f, 1.0f, _alpha };
|
||||
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(bottomLeft, bottomRight, topRight, topLeft,
|
||||
glm::vec2(magnifyULeft, magnifyVBottom),
|
||||
glm::vec2(magnifyURight, magnifyVBottom),
|
||||
glm::vec2(magnifyURight, magnifyVTop),
|
||||
glm::vec2(magnifyULeft, magnifyVBottom),
|
||||
glm::vec2(magnifyURight, magnifyVBottom),
|
||||
glm::vec2(magnifyURight, magnifyVTop),
|
||||
glm::vec2(magnifyULeft, magnifyVTop),
|
||||
magnifierColor, _magnifierQuad);
|
||||
|
||||
|
||||
} glPopMatrix();
|
||||
}
|
||||
|
||||
|
@ -611,8 +628,8 @@ void ApplicationCompositor::buildHemiVertices(
|
|||
}
|
||||
|
||||
//UV mapping source: http://www.mvps.org/directx/articles/spheremap.htm
|
||||
|
||||
vec3 pos;
|
||||
|
||||
vec3 pos;
|
||||
vec2 uv;
|
||||
// Compute vertices positions and texture UV coordinate
|
||||
// Create and write to buffer
|
||||
|
@ -631,13 +648,13 @@ void ApplicationCompositor::buildHemiVertices(
|
|||
_hemiVertices->append(sizeof(vec4), (gpu::Byte*)&color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Compute number of indices needed
|
||||
static const int VERTEX_PER_TRANGLE = 3;
|
||||
static const int TRIANGLE_PER_RECTANGLE = 2;
|
||||
int numberOfRectangles = (slices - 1) * (stacks - 1);
|
||||
_hemiIndexCount = numberOfRectangles * TRIANGLE_PER_RECTANGLE * VERTEX_PER_TRANGLE;
|
||||
|
||||
|
||||
// Compute indices order
|
||||
std::vector<GLushort> indices;
|
||||
for (int i = 0; i < stacks - 1; i++) {
|
||||
|
@ -694,7 +711,7 @@ glm::vec2 ApplicationCompositor::directionToSpherical(const glm::vec3& direction
|
|||
}
|
||||
// Compute pitch
|
||||
result.y = angleBetween(IDENTITY_UP, direction) - PI_OVER_TWO;
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -710,7 +727,7 @@ glm::vec2 ApplicationCompositor::screenToSpherical(const glm::vec2& screenPos) {
|
|||
result.y = (screenPos.y / screenSize.y - 0.5f);
|
||||
result.x *= MOUSE_YAW_RANGE;
|
||||
result.y *= MOUSE_PITCH_RANGE;
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -720,7 +737,7 @@ glm::vec2 ApplicationCompositor::sphericalToScreen(const glm::vec2& sphericalPos
|
|||
result /= MOUSE_RANGE;
|
||||
result += 0.5f;
|
||||
result *= qApp->getCanvasSize();
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
glm::vec2 ApplicationCompositor::sphericalToOverlay(const glm::vec2& sphericalPos) const {
|
||||
|
@ -737,7 +754,7 @@ glm::vec2 ApplicationCompositor::overlayToSpherical(const glm::vec2& overlayPos
|
|||
glm::vec2 result = overlayPos;
|
||||
result /= qApp->getCanvasSize();
|
||||
result -= 0.5f;
|
||||
result *= _textureFov;
|
||||
result *= _textureFov;
|
||||
result.x *= _textureAspectRatio;
|
||||
result.x *= -1.0f;
|
||||
return result;
|
||||
|
@ -754,10 +771,10 @@ glm::vec2 ApplicationCompositor::overlayToScreen(const glm::vec2& overlayPos) co
|
|||
void ApplicationCompositor::updateTooltips() {
|
||||
if (_hoverItemId != _noItemId) {
|
||||
quint64 hoverDuration = usecTimestampNow() - _hoverItemEnterUsecs;
|
||||
if (_hoverItemEnterUsecs != UINT64_MAX && !_hoverItemHref.isEmpty() && hoverDuration > TOOLTIP_DELAY) {
|
||||
if (_hoverItemEnterUsecs != UINT64_MAX && !_hoverItemTitle.isEmpty() && hoverDuration > TOOLTIP_DELAY) {
|
||||
// TODO Enable and position the tooltip
|
||||
_hoverItemEnterUsecs = UINT64_MAX;
|
||||
_tooltipId = Tooltip::showTip("URL: " + _hoverItemHref);
|
||||
_tooltipId = Tooltip::showTip(_hoverItemTitle, _hoverItemDescription);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ public:
|
|||
|
||||
QPoint getPalmClickLocation(const PalmData *palm) const;
|
||||
bool calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const;
|
||||
|
||||
|
||||
bool hasMagnifier() const { return _magnifier; }
|
||||
void toggleMagnifier() { _magnifier = !_magnifier; }
|
||||
|
||||
|
@ -68,7 +68,7 @@ public:
|
|||
static glm::vec3 sphericalToDirection(const glm::vec2 & sphericalPos);
|
||||
static glm::vec2 screenToSpherical(const glm::vec2 & screenPos);
|
||||
static glm::vec2 sphericalToScreen(const glm::vec2 & sphericalPos);
|
||||
|
||||
|
||||
private:
|
||||
void displayOverlayTextureStereo(RenderArgs* renderArgs, float aspectRatio, float fov);
|
||||
void bindCursorTexture(gpu::Batch& batch, uint8_t cursorId = 0);
|
||||
|
@ -83,9 +83,10 @@ private:
|
|||
|
||||
// Support for hovering and tooltips
|
||||
static EntityItemID _noItemId;
|
||||
EntityItemID _hoverItemId{ _noItemId };
|
||||
QString _hoverItemHref;
|
||||
quint64 _hoverItemEnterUsecs{ 0 };
|
||||
EntityItemID _hoverItemId { _noItemId };
|
||||
QString _hoverItemTitle;
|
||||
QString _hoverItemDescription;
|
||||
quint64 _hoverItemEnterUsecs { 0 };
|
||||
|
||||
float _hmdUIAngularSize = DEFAULT_HMD_UI_ANGULAR_SIZE;
|
||||
float _textureFov{ glm::radians(DEFAULT_HMD_UI_ANGULAR_SIZE) };
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdouble-promotion"
|
||||
#endif
|
||||
|
@ -20,7 +20,7 @@
|
|||
#include <QTextBlock>
|
||||
#include <QtGui>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
#include <QByteArray>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdouble-promotion"
|
||||
#endif
|
||||
|
@ -19,7 +19,7 @@
|
|||
#include <glm/gtx/quaternion.hpp>
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
|
@ -458,7 +458,7 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o
|
|||
const glm::vec3& direction,
|
||||
bool& keepSearching,
|
||||
OctreeElement*& element,
|
||||
float& distance, BoxFace& face,
|
||||
float& distance, BoxFace& face,
|
||||
void** intersectedObject,
|
||||
bool precisionPicking) const
|
||||
{
|
||||
|
|
|
@ -340,8 +340,6 @@ void AddressManager::handleAPIError(QNetworkReply& errorReply) {
|
|||
emit lookupResultsFinished();
|
||||
}
|
||||
|
||||
const QString GET_PLACE = "/api/v1/places/%1";
|
||||
|
||||
void AddressManager::attemptPlaceNameLookup(const QString& lookupString, const QString& overridePath, LookupTrigger trigger) {
|
||||
// assume this is a place name and see if we can get any info on it
|
||||
QString placeName = QUrl::toPercentEncoding(lookupString);
|
||||
|
|
|
@ -26,6 +26,8 @@ const QString HIFI_URL_SCHEME = "hifi";
|
|||
const QString DEFAULT_HIFI_ADDRESS = "hifi://entry";
|
||||
const QString INDEX_PATH = "/";
|
||||
|
||||
const QString GET_PLACE = "/api/v1/places/%1";
|
||||
|
||||
typedef const glm::vec3& (*PositionGetter)();
|
||||
typedef glm::quat (*OrientationGetter)();
|
||||
|
||||
|
|
|
@ -22,14 +22,14 @@ HifiSockAddr::HifiSockAddr() :
|
|||
_address(),
|
||||
_port(0)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
HifiSockAddr::HifiSockAddr(const QHostAddress& address, quint16 port) :
|
||||
_address(address),
|
||||
_port(port)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
HifiSockAddr::HifiSockAddr(const HifiSockAddr& otherSockAddr) :
|
||||
|
@ -37,7 +37,7 @@ HifiSockAddr::HifiSockAddr(const HifiSockAddr& otherSockAddr) :
|
|||
_address(otherSockAddr._address),
|
||||
_port(otherSockAddr._port)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
HifiSockAddr& HifiSockAddr::operator=(const HifiSockAddr& rhsSockAddr) {
|
||||
|
@ -66,7 +66,7 @@ HifiSockAddr::HifiSockAddr(const QString& hostname, quint16 hostOrderPort, bool
|
|||
|
||||
HifiSockAddr::HifiSockAddr(const sockaddr* sockaddr) {
|
||||
_address = QHostAddress(sockaddr);
|
||||
|
||||
|
||||
if (sockaddr->sa_family == AF_INET) {
|
||||
_port = ntohs(reinterpret_cast<const sockaddr_in*>(sockaddr)->sin_port);
|
||||
} else {
|
||||
|
@ -76,7 +76,7 @@ HifiSockAddr::HifiSockAddr(const sockaddr* sockaddr) {
|
|||
|
||||
void HifiSockAddr::swap(HifiSockAddr& otherSockAddr) {
|
||||
using std::swap;
|
||||
|
||||
|
||||
swap(_address, otherSockAddr._address);
|
||||
swap(_port, otherSockAddr._port);
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ void HifiSockAddr::handleLookupResult(const QHostInfo& hostInfo) {
|
|||
qCDebug(networking) << "Lookup failed for" << hostInfo.lookupId() << ":" << hostInfo.errorString();
|
||||
emit lookupFailed();
|
||||
}
|
||||
|
||||
|
||||
foreach(const QHostAddress& address, hostInfo.addresses()) {
|
||||
// just take the first IPv4 address
|
||||
if (address.protocol() == QAbstractSocket::IPv4Protocol) {
|
||||
|
@ -119,9 +119,9 @@ QDataStream& operator>>(QDataStream& dataStream, HifiSockAddr& sockAddr) {
|
|||
}
|
||||
|
||||
QHostAddress getLocalAddress() {
|
||||
|
||||
|
||||
QHostAddress localAddress;
|
||||
|
||||
|
||||
foreach(const QNetworkInterface &networkInterface, QNetworkInterface::allInterfaces()) {
|
||||
if (networkInterface.flags() & QNetworkInterface::IsUp
|
||||
&& networkInterface.flags() & QNetworkInterface::IsRunning
|
||||
|
@ -131,19 +131,19 @@ QHostAddress getLocalAddress() {
|
|||
foreach(const QNetworkAddressEntry &entry, networkInterface.addressEntries()) {
|
||||
// make sure it's an IPv4 address that isn't the loopback
|
||||
if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol && !entry.ip().isLoopback()) {
|
||||
|
||||
|
||||
// set our localAddress and break out
|
||||
localAddress = entry.ip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!localAddress.isNull()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// return the looked up local address
|
||||
return localAddress;
|
||||
}
|
||||
|
|
|
@ -745,6 +745,14 @@ void LimitedNodeList::startSTUNPublicSocketUpdate() {
|
|||
// if we don't know the STUN IP yet we need to have ourselves be called once it is known
|
||||
if (_stunSockAddr.getAddress().isNull()) {
|
||||
connect(&_stunSockAddr, &HifiSockAddr::lookupCompleted, this, &LimitedNodeList::startSTUNPublicSocketUpdate);
|
||||
|
||||
// in case we just completely fail to lookup the stun socket - add a 10s timeout that will trigger the fail case
|
||||
const quint64 STUN_DNS_LOOKUP_TIMEOUT_MSECS = 10 * 1000;
|
||||
|
||||
QTimer* stunLookupFailTimer = new QTimer(this);
|
||||
connect(stunLookupFailTimer, &QTimer::timeout, this, &LimitedNodeList::possiblyTimeoutSTUNAddressLookup);
|
||||
stunLookupFailTimer->start(STUN_DNS_LOOKUP_TIMEOUT_MSECS);
|
||||
|
||||
} else {
|
||||
// setup our initial STUN timer here so we can quickly find out our public IP address
|
||||
_initialSTUNTimer = new QTimer(this);
|
||||
|
@ -760,6 +768,13 @@ void LimitedNodeList::startSTUNPublicSocketUpdate() {
|
|||
}
|
||||
}
|
||||
|
||||
void LimitedNodeList::possiblyTimeoutSTUNAddressLookup() {
|
||||
if (_stunSockAddr.getAddress().isNull()) {
|
||||
// our stun address is still NULL, but we've been waiting for long enough - time to force a fail
|
||||
stopInitialSTUNUpdate(false);
|
||||
}
|
||||
}
|
||||
|
||||
void LimitedNodeList::stopInitialSTUNUpdate(bool success) {
|
||||
_hasCompletedInitialSTUN = true;
|
||||
|
||||
|
@ -779,8 +794,6 @@ void LimitedNodeList::stopInitialSTUNUpdate(bool success) {
|
|||
flagTimeForConnectionStep(ConnectionStep::SetPublicSocketFromSTUN);
|
||||
}
|
||||
|
||||
assert(_initialSTUNTimer);
|
||||
|
||||
// stop our initial fast timer
|
||||
if (_initialSTUNTimer) {
|
||||
_initialSTUNTimer->stop();
|
||||
|
|
|
@ -317,6 +317,7 @@ protected:
|
|||
}
|
||||
private slots:
|
||||
void flagTimeForConnectionStep(ConnectionStep connectionStep, quint64 timestamp);
|
||||
void possiblyTimeoutSTUNAddressLookup();
|
||||
};
|
||||
|
||||
#endif // hifi_LimitedNodeList_h
|
||||
|
|
|
@ -12,14 +12,14 @@
|
|||
#ifndef hifi_ProgramObject_h
|
||||
#define hifi_ProgramObject_h
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdouble-promotion"
|
||||
#endif
|
||||
|
||||
#include <QGLShaderProgram>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ using glm::vec3;
|
|||
using glm::vec4;
|
||||
using glm::quat;
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdouble-promotion"
|
||||
#endif
|
||||
|
@ -37,7 +37,7 @@ using glm::quat;
|
|||
#include <QtGui/QMatrix4x4>
|
||||
#include <QtGui/QColor>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
|
|
|
@ -63,6 +63,10 @@ void vec4FromScriptValue(const QScriptValue& object, glm::vec4& vec4) {
|
|||
|
||||
QScriptValue vec3toScriptValue(QScriptEngine* engine, const glm::vec3 &vec3) {
|
||||
QScriptValue obj = engine->newObject();
|
||||
if (vec3.x != vec3.x || vec3.y != vec3.y || vec3.z != vec3.z) {
|
||||
// if vec3 contains a NaN don't try to convert it
|
||||
return obj;
|
||||
}
|
||||
obj.setProperty("x", vec3.x);
|
||||
obj.setProperty("y", vec3.y);
|
||||
obj.setProperty("z", vec3.z);
|
||||
|
|
|
@ -59,7 +59,7 @@ private:
|
|||
void x::load(std::function<void(QQmlContext*, QObject*)> f) { \
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>(); \
|
||||
offscreenUi->load(QML, f); \
|
||||
}
|
||||
}
|
||||
|
||||
#define HIFI_QML_DEF_LAMBDA(x, f) \
|
||||
const QUrl x::QML = QUrl(#x ".qml"); \
|
||||
|
@ -79,7 +79,7 @@ private:
|
|||
void x::load() { \
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>(); \
|
||||
offscreenUi->load(QML, f); \
|
||||
}
|
||||
}
|
||||
|
||||
class OffscreenUi : public OffscreenQmlSurface, public Dependency {
|
||||
Q_OBJECT
|
||||
|
@ -97,7 +97,7 @@ public:
|
|||
|
||||
static void messageBox(const QString& title, const QString& text,
|
||||
ButtonCallback f,
|
||||
QMessageBox::Icon icon,
|
||||
QMessageBox::Icon icon,
|
||||
QMessageBox::StandardButtons buttons);
|
||||
|
||||
static void information(const QString& title, const QString& text,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
//
|
||||
// Tooltip.cpp
|
||||
// libraries/ui/src
|
||||
//
|
||||
// Created by Bradley Austin Davis on 2015/04/14
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
|
@ -8,24 +9,41 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#include "Tooltip.h"
|
||||
#include <QUuid>
|
||||
|
||||
#include <QtCore/QJsonDocument>
|
||||
#include <QtCore/QUuid>
|
||||
|
||||
#include <AccountManager.h>
|
||||
#include <AddressManager.h>
|
||||
|
||||
HIFI_QML_DEF(Tooltip)
|
||||
|
||||
Tooltip::Tooltip(QQuickItem* parent) : QQuickItem(parent) {
|
||||
connect(this, &Tooltip::titleChanged, this, &Tooltip::requestHyperlinkImage);
|
||||
}
|
||||
|
||||
Tooltip::~Tooltip() {
|
||||
|
||||
}
|
||||
|
||||
QString Tooltip::text() const {
|
||||
return _text;
|
||||
void Tooltip::setTitle(const QString& title) {
|
||||
if (title != _title) {
|
||||
_title = title;
|
||||
emit titleChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Tooltip::setText(const QString& arg) {
|
||||
if (arg != _text) {
|
||||
_text = arg;
|
||||
emit textChanged();
|
||||
void Tooltip::setDescription(const QString& description) {
|
||||
if (description != _description) {
|
||||
_description = description;
|
||||
emit descriptionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Tooltip::setImageURL(const QString& imageURL) {
|
||||
if (imageURL != _imageURL) {
|
||||
_imageURL = imageURL;
|
||||
emit imageURLChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,12 +51,15 @@ void Tooltip::setVisible(bool visible) {
|
|||
QQuickItem::setVisible(visible);
|
||||
}
|
||||
|
||||
QString Tooltip::showTip(const QString& text) {
|
||||
QString Tooltip::showTip(const QString& title, const QString& description) {
|
||||
const QString newTipId = QUuid().createUuid().toString();
|
||||
|
||||
Tooltip::show([&](QQmlContext*, QObject* object) {
|
||||
object->setObjectName(newTipId);
|
||||
object->setProperty("text", text);
|
||||
object->setProperty("title", title);
|
||||
object->setProperty("description", description);
|
||||
});
|
||||
|
||||
return newTipId;
|
||||
}
|
||||
|
||||
|
@ -48,4 +69,65 @@ void Tooltip::closeTip(const QString& tipId) {
|
|||
if (that) {
|
||||
that->deleteLater();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Tooltip::requestHyperlinkImage() {
|
||||
if (!_title.isEmpty()) {
|
||||
// we need to decide if this is a place name - if so we should ask the API for the associated image
|
||||
// and description (if we weren't given one via the entity properties)
|
||||
const QString PLACE_NAME_REGEX_STRING = "^[0-9A-Za-z](([0-9A-Za-z]|-(?!-))*[^\\W_]$|$)";
|
||||
|
||||
QRegExp placeNameRegex(PLACE_NAME_REGEX_STRING);
|
||||
if (placeNameRegex.indexIn(_title) != -1) {
|
||||
// NOTE: I'm currently not 100% sure why the UI library needs networking, but it's linked for now
|
||||
// so I'm leveraging that here to get the place preview. We could also do this from the interface side
|
||||
// should the network link be removed from UI at a later date.
|
||||
|
||||
// we possibly have a valid place name - so ask the API for the associated info
|
||||
AccountManager& accountManager = AccountManager::getInstance();
|
||||
|
||||
JSONCallbackParameters callbackParams;
|
||||
callbackParams.jsonCallbackReceiver = this;
|
||||
callbackParams.jsonCallbackMethod = "handleAPIResponse";
|
||||
|
||||
accountManager.sendRequest(GET_PLACE.arg(_title),
|
||||
AccountManagerAuth::None,
|
||||
QNetworkAccessManager::GetOperation,
|
||||
callbackParams);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Tooltip::handleAPIResponse(QNetworkReply& requestReply) {
|
||||
// did a preview image come back?
|
||||
QJsonObject responseObject = QJsonDocument::fromJson(requestReply.readAll()).object();
|
||||
QJsonObject dataObject = responseObject["data"].toObject();
|
||||
|
||||
const QString PLACE_KEY = "place";
|
||||
|
||||
if (dataObject.contains(PLACE_KEY)) {
|
||||
QJsonObject placeObject = dataObject[PLACE_KEY].toObject();
|
||||
|
||||
const QString PREVIEWS_KEY = "previews";
|
||||
const QString LOBBY_KEY = "lobby";
|
||||
|
||||
if (placeObject.contains(PREVIEWS_KEY) && placeObject[PREVIEWS_KEY].toObject().contains(LOBBY_KEY)) {
|
||||
// we have previews - time to change the image URL
|
||||
setImageURL(placeObject[PREVIEWS_KEY].toObject()[LOBBY_KEY].toString());
|
||||
}
|
||||
|
||||
if (_description.isEmpty()) {
|
||||
const QString DESCRIPTION_KEY = "description";
|
||||
// we have an empty description - did a non-empty desciption come back?
|
||||
if (placeObject.contains(DESCRIPTION_KEY)) {
|
||||
QString placeDescription = placeObject[DESCRIPTION_KEY].toString();
|
||||
|
||||
if (!placeDescription.isEmpty()) {
|
||||
// we got a non-empty description so change our description to that
|
||||
setDescription(placeDescription);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
//
|
||||
// Tooltip.h
|
||||
// libraries/ui/src
|
||||
//
|
||||
// Created by Bradley Austin Davis on 2015/04/14
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
|
@ -12,6 +13,8 @@
|
|||
#ifndef hifi_Tooltip_h
|
||||
#define hifi_Tooltip_h
|
||||
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
|
||||
#include "OffscreenQmlDialog.h"
|
||||
|
||||
class Tooltip : public QQuickItem
|
||||
|
@ -20,26 +23,42 @@ class Tooltip : public QQuickItem
|
|||
HIFI_QML_DECL
|
||||
|
||||
private:
|
||||
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
|
||||
Q_PROPERTY(QString title READ getTitle WRITE setTitle NOTIFY titleChanged)
|
||||
Q_PROPERTY(QString description READ getDescription WRITE setDescription NOTIFY descriptionChanged)
|
||||
Q_PROPERTY(QString imageURL READ getImageURL WRITE setImageURL NOTIFY imageURLChanged)
|
||||
|
||||
public:
|
||||
Tooltip(QQuickItem* parent = 0);
|
||||
virtual ~Tooltip();
|
||||
|
||||
QString text() const;
|
||||
const QString& getTitle() const { return _title; }
|
||||
const QString& getDescription() const { return _description; }
|
||||
const QString& getImageURL() const { return _imageURL; }
|
||||
|
||||
static QString showTip(const QString& text);
|
||||
static QString showTip(const QString& title, const QString& description);
|
||||
static void closeTip(const QString& tipId);
|
||||
|
||||
public slots:
|
||||
virtual void setVisible(bool v);
|
||||
void setText(const QString& arg);
|
||||
|
||||
void setTitle(const QString& title);
|
||||
void setDescription(const QString& description);
|
||||
void setImageURL(const QString& imageURL);
|
||||
|
||||
signals:
|
||||
void textChanged();
|
||||
void titleChanged();
|
||||
void descriptionChanged();
|
||||
void imageURLChanged();
|
||||
|
||||
private slots:
|
||||
void handleAPIResponse(QNetworkReply& requestReply);
|
||||
|
||||
private:
|
||||
QString _text;
|
||||
void requestHyperlinkImage();
|
||||
|
||||
QString _title;
|
||||
QString _description;
|
||||
QString _imageURL { "../images/no-picture-provided.svg" };
|
||||
};
|
||||
|
||||
#endif // hifi_Tooltip_h
|
||||
|
|
Loading…
Reference in a new issue