Merge branch 'master' of github.com:highfidelity/hifi into actions-over-wire

This commit is contained in:
Seth Alves 2015-06-26 20:06:10 -07:00
commit 5ecc39b811
19 changed files with 242 additions and 99 deletions

4
examples/html/jquery-2.1.4.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -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
}
}
}
}
}

View file

@ -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()) {

View file

@ -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);
}
}
}

View file

@ -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) };

View file

@ -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

View file

@ -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
{

View file

@ -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);

View file

@ -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)();

View file

@ -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;
}

View file

@ -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();

View file

@ -317,6 +317,7 @@ protected:
}
private slots:
void flagTimeForConnectionStep(ConnectionStep connectionStep, quint64 timestamp);
void possiblyTimeoutSTUNAddressLookup();
};
#endif // hifi_LimitedNodeList_h

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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,

View file

@ -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);
}
}
}
}
}

View file

@ -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