diff --git a/cmake/modules/FindGLEW.cmake b/cmake/modules/FindGLEW.cmake index 68e3248850..b621756885 100644 --- a/cmake/modules/FindGLEW.cmake +++ b/cmake/modules/FindGLEW.cmake @@ -26,7 +26,7 @@ else () find_path(GLEW_INCLUDE_DIRS GL/glew.h PATH_SUFFIXES include HINTS ${WIN_GLEW_SEARCH_DIRS}) - find_library(GLEW_LIBRARY glew32s PATH_SUFFIXES "lib/Release/Win32" HINTS ${WIN_GLEW_SEARCH_DIRS}) + find_library(GLEW_LIBRARY glew32s PATH_SUFFIXES "lib/Release/Win32" "lib" HINTS ${WIN_GLEW_SEARCH_DIRS}) endif () include(FindPackageHandleStandardArgs) diff --git a/interface/resources/images/audio-box.svg b/interface/resources/images/audio-box.svg new file mode 100644 index 0000000000..0c0db4f51f --- /dev/null +++ b/interface/resources/images/audio-box.svg @@ -0,0 +1,12 @@ + + + Slice 1 + Created with Sketch (http://www.bohemiancoding.com/sketch) + + + + + + + + \ No newline at end of file diff --git a/interface/resources/images/body.png b/interface/resources/images/body.png deleted file mode 100644 index dda65bad07..0000000000 Binary files a/interface/resources/images/body.png and /dev/null differ diff --git a/interface/resources/images/close.png b/interface/resources/images/close.png deleted file mode 100644 index 8090e3d3d0..0000000000 Binary files a/interface/resources/images/close.png and /dev/null differ diff --git a/interface/resources/images/close.svg b/interface/resources/images/close.svg index 8fe4bf4bdb..0cae08c590 100644 --- a/interface/resources/images/close.svg +++ b/interface/resources/images/close.svg @@ -1,14 +1,12 @@ - - - - - - - - - - + + + Slice 1 + Created with Sketch (http://www.bohemiancoding.com/sketch) + + + + + + + + \ No newline at end of file diff --git a/interface/resources/images/head.png b/interface/resources/images/head.png deleted file mode 100644 index d21b453bee..0000000000 Binary files a/interface/resources/images/head.png and /dev/null differ diff --git a/interface/resources/images/mic-mute.svg b/interface/resources/images/mic-mute.svg new file mode 100644 index 0000000000..39dd811df4 --- /dev/null +++ b/interface/resources/images/mic-mute.svg @@ -0,0 +1,115 @@ + + + +image/svg+xml + + + + + + + + Mic + Created with Sketch (http://www.bohemiancoding.com/sketch) + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/interface/resources/images/mic.svg b/interface/resources/images/mic.svg index a6dee50740..3329f19647 100644 --- a/interface/resources/images/mic.svg +++ b/interface/resources/images/mic.svg @@ -1,20 +1,105 @@ - - Mic - Created with Sketch (http://www.bohemiancoding.com/sketch) - - - - - - - - - - - - - - - + + +image/svg+xml + + + + + + + + Mic + Created with Sketch (http://www.bohemiancoding.com/sketch) + + + + + + + + + + + + + + \ No newline at end of file diff --git a/interface/resources/images/minus.svg b/interface/resources/images/minus.svg new file mode 100644 index 0000000000..463b24aa4c --- /dev/null +++ b/interface/resources/images/minus.svg @@ -0,0 +1,11 @@ + + + Slice 1 + Created with Sketch (http://www.bohemiancoding.com/sketch) + + + + + + + \ No newline at end of file diff --git a/interface/resources/images/mute.svg b/interface/resources/images/mute.svg deleted file mode 100644 index 1f1b238463..0000000000 --- a/interface/resources/images/mute.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - mute - Created with Sketch (http://www.bohemiancoding.com/sketch) - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/interface/resources/images/plus.svg b/interface/resources/images/plus.svg new file mode 100644 index 0000000000..6efaa31abc --- /dev/null +++ b/interface/resources/images/plus.svg @@ -0,0 +1,12 @@ + + + Slice 1 + Created with Sketch (http://www.bohemiancoding.com/sketch) + + + + + + + + \ No newline at end of file diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1faf1d4f0d..6005ae085e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -236,6 +236,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : connect(nodeList, SIGNAL(nodeAdded(SharedNodePointer)), &_voxels, SLOT(nodeAdded(SharedNodePointer))); connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), &_voxels, SLOT(nodeKilled(SharedNodePointer))); connect(nodeList, &NodeList::uuidChanged, this, &Application::updateWindowTitle); + connect(nodeList, SIGNAL(uuidChanged(const QUuid&)), _myAvatar, SLOT(setSessionUUID(const QUuid&))); connect(nodeList, &NodeList::limitOfSilentDomainCheckInsReached, nodeList, &NodeList::reset); // connect to appropriate slots on AccountManager @@ -1220,8 +1221,6 @@ void Application::timer() { // ask the node list to check in with the domain server NodeList::getInstance()->sendDomainServerCheckIn(); - - } void Application::idle() { @@ -2522,20 +2521,19 @@ void Application::displayOverlay() { // Audio VU Meter and Mute Icon const int MUTE_ICON_SIZE = 24; const int AUDIO_METER_INSET = 2; - const int AUDIO_METER_WIDTH = MIRROR_VIEW_WIDTH - MUTE_ICON_SIZE - AUDIO_METER_INSET; + const int MUTE_ICON_PADDING = 10; + const int AUDIO_METER_WIDTH = MIRROR_VIEW_WIDTH - MUTE_ICON_SIZE - AUDIO_METER_INSET - MUTE_ICON_PADDING; const int AUDIO_METER_SCALE_WIDTH = AUDIO_METER_WIDTH - 2 * AUDIO_METER_INSET; const int AUDIO_METER_HEIGHT = 8; - const int AUDIO_METER_Y_GAP = 8; - const int AUDIO_METER_X = MIRROR_VIEW_LEFT_PADDING + MUTE_ICON_SIZE + AUDIO_METER_INSET; + const int AUDIO_METER_GAP = 5; + const int AUDIO_METER_X = MIRROR_VIEW_LEFT_PADDING + MUTE_ICON_SIZE + AUDIO_METER_INSET + AUDIO_METER_GAP; int audioMeterY; if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { - audioMeterY = MIRROR_VIEW_HEIGHT + AUDIO_METER_Y_GAP; + audioMeterY = MIRROR_VIEW_HEIGHT + AUDIO_METER_GAP + MUTE_ICON_PADDING; } else { - audioMeterY = AUDIO_METER_Y_GAP; + audioMeterY = AUDIO_METER_GAP + MUTE_ICON_PADDING; } - _audio.renderMuteIcon(MIRROR_VIEW_LEFT_PADDING, audioMeterY); - const float AUDIO_METER_BLUE[] = {0.0, 0.0, 1.0}; const float AUDIO_METER_GREEN[] = {0.0, 1.0, 0.0}; @@ -2564,18 +2562,27 @@ void Application::displayOverlay() { bool isClipping = ((_audio.getTimeSinceLastClip() > 0.f) && (_audio.getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME)); + _audio.renderToolBox(MIRROR_VIEW_LEFT_PADDING + AUDIO_METER_GAP, + audioMeterY, + Menu::getInstance()->isOptionChecked(MenuOption::Mirror)); + glBegin(GL_QUADS); if (isClipping) { glColor3f(1, 0, 0); } else { - glColor3f(0, 0, 0); + glColor3f(0.475f, 0.475f, 0.475f); } + + audioMeterY += AUDIO_METER_HEIGHT; + + glColor3f(0, 0, 0); // Draw audio meter background Quad glVertex2i(AUDIO_METER_X, audioMeterY); glVertex2i(AUDIO_METER_X + AUDIO_METER_WIDTH, audioMeterY); glVertex2i(AUDIO_METER_X + AUDIO_METER_WIDTH, audioMeterY + AUDIO_METER_HEIGHT); glVertex2i(AUDIO_METER_X, audioMeterY + AUDIO_METER_HEIGHT); + if (audioLevel > AUDIO_RED_START) { if (!isClipping) { glColor3fv(AUDIO_METER_RED); @@ -2615,6 +2622,7 @@ void Application::displayOverlay() { glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET, audioMeterY + AUDIO_METER_HEIGHT - AUDIO_METER_INSET); glEnd(); + if (Menu::getInstance()->isOptionChecked(MenuOption::HeadMouse)) { _myAvatar->renderHeadMouse(); } diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 108a785e95..a98d276acc 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -1050,4 +1050,4 @@ float Audio::calculateDeviceToNetworkInputRatio(int numBytes) { int Audio::calculateNumberOfFrameSamples(int numBytes) { int frameSamples = (int)(numBytes * CALLBACK_ACCELERATOR_RATIO + 0.5f) / sizeof(int16_t); return frameSamples; -} \ No newline at end of file +} diff --git a/interface/src/Audio.h b/interface/src/Audio.h index 84ab6c69cf..c529fc2651 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -72,7 +72,7 @@ public: void init(QGLWidget *parent = 0); bool mousePressEvent(int x, int y); - void renderMuteIcon(int x, int y); + void renderToolBox(int x, int y, bool boxed); int getNetworkSampleRate() { return SAMPLE_RATE; } int getNetworkBufferLengthSamplesPerChannel() { return NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; } @@ -164,6 +164,7 @@ private: bool _localEcho; GLuint _micTextureId; GLuint _muteTextureId; + GLuint _boxTextureId; QRect _iconBounds; // Audio callback in class context. diff --git a/libraries/shared/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp similarity index 80% rename from libraries/shared/src/ModelUploader.cpp rename to interface/src/ModelUploader.cpp index da809283d8..9a0c305bf7 100644 --- a/libraries/shared/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -20,7 +20,9 @@ #include #include -#include "AccountManager.h" +#include + +#include "renderer/FBXReader.h" #include "ModelUploader.h" @@ -61,11 +63,14 @@ bool ModelUploader::zip() { "Select your .fst file ...", QStandardPaths::writableLocation(QStandardPaths::HomeLocation), "*.fst"); - qDebug() << QStandardPaths::writableLocation(QStandardPaths::HomeLocation); if (filename == "") { // If the user canceled we return. return false; } + bool _nameIsPresent = false; + QString texDir; + QString fbxFile; + // First we check the FST file QFile fst(filename); @@ -101,23 +106,26 @@ bool ModelUploader::zip() { textPart.setBody(line[1].toUtf8()); _dataMultiPart->append(textPart); _url = S3_URL + ((_isHead)? "/models/heads/" : "/models/skeletons/") + line[1].toUtf8() + ".fst"; + _nameIsPresent = true; } else if (line[0] == FILENAME_FIELD) { - QFileInfo fbx(QFileInfo(fst).path() + "/" + line[1]); - if (!fbx.exists() || !fbx.isFile()) { // Check existence + fbxFile = QFileInfo(fst).path() + "/" + line[1]; + QFileInfo fbxInfo(fbxFile); + if (!fbxInfo.exists() || !fbxInfo.isFile()) { // Check existence QMessageBox::warning(NULL, QString("ModelUploader::zip()"), - QString("FBX file %1 could not be found.").arg(fbx.fileName()), + QString("FBX file %1 could not be found.").arg(fbxInfo.fileName()), QMessageBox::Ok); - qDebug() << "[Warning] " << QString("FBX file %1 could not be found.").arg(fbx.fileName()); + qDebug() << "[Warning] " << QString("FBX file %1 could not be found.").arg(fbxInfo.fileName()); return false; } // Compress and copy - if (!addPart(fbx.filePath(), "fbx")) { + if (!addPart(fbxInfo.filePath(), "fbx")) { return false; } } else if (line[0] == TEXDIR_FIELD) { // Check existence - QFileInfo texdir(QFileInfo(fst).path() + "/" + line[1]); - if (!texdir.exists() || !texdir.isDir()) { + texDir = QFileInfo(fst).path() + "/" + line[1]; + QFileInfo texInfo(texDir); + if (!texInfo.exists() || !texInfo.isDir()) { QMessageBox::warning(NULL, QString("ModelUploader::zip()"), QString("Texture directory could not be found."), @@ -125,18 +133,14 @@ bool ModelUploader::zip() { qDebug() << "[Warning] " << QString("Texture directory could not be found."); return false; } - if (!addTextures(texdir)) { // Recursive compress and copy - return false; - } } else if (line[0] == LOD_FIELD) { QFileInfo lod(QFileInfo(fst).path() + "/" + line[1]); if (!lod.exists() || !lod.isFile()) { // Check existence QMessageBox::warning(NULL, QString("ModelUploader::zip()"), - QString("FBX file %1 could not be found.").arg(lod.fileName()), + QString("LOD file %1 could not be found.").arg(lod.fileName()), QMessageBox::Ok); qDebug() << "[Warning] " << QString("FBX file %1 could not be found.").arg(lod.fileName()); - return false; } // Compress and copy if (!addPart(lod.filePath(), QString("lod%1").arg(++_lodCount))) { @@ -145,6 +149,10 @@ bool ModelUploader::zip() { } } + if (!addTextures(texDir, fbxFile)) { + return false; + } + QHttpPart textPart; textPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data;" " name=\"model_category\""); @@ -155,12 +163,22 @@ bool ModelUploader::zip() { } _dataMultiPart->append(textPart); + if (!_nameIsPresent) { + QMessageBox::warning(NULL, + QString("ModelUploader::zip()"), + QString("Model name is missing in the .fst file."), + QMessageBox::Ok); + qDebug() << "[Warning] " << QString("Model name is missing in the .fst file."); + return false; + } + _readyToSend = true; return true; } void ModelUploader::send() { if (!zip()) { + deleteLater(); return; } @@ -204,7 +222,7 @@ void ModelUploader::uploadSuccess(const QJsonObject& jsonResponse) { } QMessageBox::information(NULL, QString("ModelUploader::uploadSuccess()"), - QString("Your model is being processed by the system."), + QString("We are reading your model information."), QMessageBox::Ok); qDebug() << "Model sent with success"; checkS3(); @@ -216,7 +234,7 @@ void ModelUploader::uploadFailed(QNetworkReply::NetworkError errorCode, const QS } QMessageBox::warning(NULL, QString("ModelUploader::uploadFailed()"), - QString("Model could not be sent to the data server."), + QString("There was a problem with your upload, please try again later."), QMessageBox::Ok); qDebug() << "Model upload failed (" << errorCode << "): " << errorString; deleteLater(); @@ -249,7 +267,8 @@ void ModelUploader::processCheck() { default: QMessageBox::warning(NULL, QString("ModelUploader::processCheck()"), - QString("Could not verify that the model is present on the server."), + QString("We could not verify that your model was sent sucessfully\n" + "but it may have. If you do not see it in the model browser, try to upload again."), QMessageBox::Ok); deleteLater(); break; @@ -258,24 +277,29 @@ void ModelUploader::processCheck() { delete reply; } -bool ModelUploader::addTextures(const QFileInfo& texdir) { - QStringList filter; - filter << "*.png" << "*.tif" << "*.jpg" << "*.jpeg"; +bool ModelUploader::addTextures(const QString& texdir, const QString fbxFile) { + QFile fbx(fbxFile); + if (!fbx.open(QIODevice::ReadOnly)) { + return false; + } - QFileInfoList list = QDir(texdir.filePath()).entryInfoList(filter, - QDir::Files | - QDir::AllDirs | - QDir::NoDotAndDotDot | - QDir::NoSymLinks); - foreach (QFileInfo info, list) { - if (info.isFile()) { - // Compress and copy - if (!addPart(info.filePath(), QString("texture%1").arg(++_texturesCount))) { - return false; + QByteArray buffer = fbx.readAll(); + QVariantHash variantHash = readMapping(buffer); + FBXGeometry geometry = readFBX(buffer, variantHash); + + foreach (FBXMesh mesh, geometry.meshes) { + foreach (FBXMeshPart part, mesh.parts) { + if (!part.diffuseFilename.isEmpty()) { + if (!addPart(QFileInfo(fbxFile).path() + "/" + part.diffuseFilename, + QString("texture%1").arg(++_texturesCount))) { + return false; + } } - } else if (info.isDir()) { - if (!addTextures(info)) { - return false; + if (!part.normalFilename.isEmpty()) { + if (!addPart(QFileInfo(fbxFile).path() + "/" + part.normalFilename, + QString("texture%1").arg(++_texturesCount))) { + return false; + } } } } diff --git a/libraries/shared/src/ModelUploader.h b/interface/src/ModelUploader.h similarity index 95% rename from libraries/shared/src/ModelUploader.h rename to interface/src/ModelUploader.h index 26c34d4eb7..bec75903af 100644 --- a/libraries/shared/src/ModelUploader.h +++ b/interface/src/ModelUploader.h @@ -19,8 +19,6 @@ class QFileInfo; class QHttpMultiPart; class QProgressBar; -class TemporaryDir; - class ModelUploader : public QObject { Q_OBJECT @@ -57,7 +55,7 @@ private: bool zip(); - bool addTextures(const QFileInfo& texdir); + bool addTextures(const QString& texdir, const QString fbxFile); bool addPart(const QString& path, const QString& name); }; diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 38163ef326..5798f33d0f 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -127,8 +127,8 @@ void AvatarManager::renderAvatarFades(const glm::vec3& cameraPosition, Avatar::R } } -AvatarSharedPointer AvatarManager::matchingOrNewAvatar(const QUuid& nodeUUID, const QWeakPointer& mixerWeakPointer) { - AvatarSharedPointer matchingAvatar = _avatarHash.value(nodeUUID); +AvatarSharedPointer AvatarManager::matchingOrNewAvatar(const QUuid& sessionUUID, const QWeakPointer& mixerWeakPointer) { + AvatarSharedPointer matchingAvatar = _avatarHash.value(sessionUUID); if (!matchingAvatar) { // construct a new Avatar for this node @@ -137,9 +137,9 @@ AvatarSharedPointer AvatarManager::matchingOrNewAvatar(const QUuid& nodeUUID, co // insert the new avatar into our hash matchingAvatar = AvatarSharedPointer(avatar); - _avatarHash.insert(nodeUUID, matchingAvatar); + _avatarHash.insert(sessionUUID, matchingAvatar); - qDebug() << "Adding avatar with UUID" << nodeUUID << "to AvatarManager hash."; + qDebug() << "Adding avatar with sessionUUID " << sessionUUID << "to AvatarManager hash."; } return matchingAvatar; @@ -170,10 +170,10 @@ void AvatarManager::processAvatarDataPacket(const QByteArray &datagram, const QW // enumerate over all of the avatars in this packet // only add them if mixerWeakPointer points to something (meaning that mixer is still around) while (bytesRead < datagram.size() && mixerWeakPointer.data()) { - QUuid nodeUUID = QUuid::fromRfc4122(datagram.mid(bytesRead, NUM_BYTES_RFC4122_UUID)); + QUuid sessionUUID = QUuid::fromRfc4122(datagram.mid(bytesRead, NUM_BYTES_RFC4122_UUID)); bytesRead += NUM_BYTES_RFC4122_UUID; - AvatarSharedPointer matchingAvatarData = matchingOrNewAvatar(nodeUUID, mixerWeakPointer); + AvatarSharedPointer matchingAvatarData = matchingOrNewAvatar(sessionUUID, mixerWeakPointer); // have the matching (or new) avatar parse the data from the packet bytesRead += matchingAvatarData->parseDataAtOffset(datagram, bytesRead); @@ -192,16 +192,16 @@ void AvatarManager::processAvatarIdentityPacket(const QByteArray &packet, const QDataStream identityStream(packet); identityStream.skipRawData(numBytesForPacketHeader(packet)); - QUuid nodeUUID; + QUuid sessionUUID; while (!identityStream.atEnd()) { QUrl faceMeshURL, skeletonURL; QString displayName; - identityStream >> nodeUUID >> faceMeshURL >> skeletonURL >> displayName; + identityStream >> sessionUUID >> faceMeshURL >> skeletonURL >> displayName; // mesh URL for a UUID, find avatar in our list - AvatarSharedPointer matchingAvatar = matchingOrNewAvatar(nodeUUID, mixerWeakPointer); + AvatarSharedPointer matchingAvatar = matchingOrNewAvatar(sessionUUID, mixerWeakPointer); if (matchingAvatar) { Avatar* avatar = static_cast(matchingAvatar.data()); @@ -222,9 +222,9 @@ void AvatarManager::processAvatarIdentityPacket(const QByteArray &packet, const void AvatarManager::processAvatarBillboardPacket(const QByteArray& packet, const QWeakPointer& mixerWeakPointer) { int headerSize = numBytesForPacketHeader(packet); - QUuid nodeUUID = QUuid::fromRfc4122(QByteArray::fromRawData(packet.constData() + headerSize, NUM_BYTES_RFC4122_UUID)); + QUuid sessionUUID = QUuid::fromRfc4122(QByteArray::fromRawData(packet.constData() + headerSize, NUM_BYTES_RFC4122_UUID)); - AvatarSharedPointer matchingAvatar = matchingOrNewAvatar(nodeUUID, mixerWeakPointer); + AvatarSharedPointer matchingAvatar = matchingOrNewAvatar(sessionUUID, mixerWeakPointer); if (matchingAvatar) { Avatar* avatar = static_cast(matchingAvatar.data()); QByteArray billboard = packet.mid(headerSize + NUM_BYTES_RFC4122_UUID); @@ -236,10 +236,10 @@ void AvatarManager::processAvatarBillboardPacket(const QByteArray& packet, const void AvatarManager::processKillAvatar(const QByteArray& datagram) { // read the node id - QUuid nodeUUID = QUuid::fromRfc4122(datagram.mid(numBytesForPacketHeader(datagram), NUM_BYTES_RFC4122_UUID)); + QUuid sessionUUID = QUuid::fromRfc4122(datagram.mid(numBytesForPacketHeader(datagram), NUM_BYTES_RFC4122_UUID)); // remove the avatar with that UUID from our hash, if it exists - AvatarHash::iterator matchedAvatar = _avatarHash.find(nodeUUID); + AvatarHash::iterator matchedAvatar = _avatarHash.find(sessionUUID); if (matchedAvatar != _avatarHash.end()) { erase(matchedAvatar); } diff --git a/interface/src/ui/RearMirrorTools.cpp b/interface/src/ui/RearMirrorTools.cpp index d416805e6f..9620469a22 100644 --- a/interface/src/ui/RearMirrorTools.cpp +++ b/interface/src/ui/RearMirrorTools.cpp @@ -22,9 +22,8 @@ const char SETTINGS_GROUP_NAME[] = "Rear View Tools"; const char ZOOM_LEVEL_SETTINGS[] = "ZoomLevel"; -const int ICON_SIZE = 20; +const int ICON_SIZE = 24; const int ICON_PADDING = 5; -const int MID_ICON_PADDING = 70; RearMirrorTools::RearMirrorTools(QGLWidget* parent, QRect& bounds, QSettings* settings) : _parent(parent), @@ -33,16 +32,19 @@ RearMirrorTools::RearMirrorTools(QGLWidget* parent, QRect& bounds, QSettings* se _fullScreen(false) { _zoomLevel = HEAD; - _closeTextureId = _parent->bindTexture(QImage(Application::resourcesPath() + "images/close.png")); - _resetTextureId = _parent->bindTexture(QImage(Application::resourcesPath() + "images/reset.png")); - _zoomHeadTextureId = _parent->bindTexture(QImage(Application::resourcesPath() + "images/head.png")); - _zoomBodyTextureId = _parent->bindTexture(QImage(Application::resourcesPath() + "images/body.png")); + _closeTextureId = _parent->bindTexture(QImage(Application::resourcesPath() + "images/close.svg")); + + // Disabled for now https://worklist.net/19548 + // _resetTextureId = _parent->bindTexture(QImage(Application::resourcesPath() + "images/reset.png")); + + _zoomHeadTextureId = _parent->bindTexture(QImage(Application::resourcesPath() + "images/plus.svg")); + _zoomBodyTextureId = _parent->bindTexture(QImage(Application::resourcesPath() + "images/minus.svg")); _shrinkIconRect = QRect(ICON_PADDING, ICON_PADDING, ICON_SIZE, ICON_SIZE); _closeIconRect = QRect(_bounds.left() + ICON_PADDING, _bounds.top() + ICON_PADDING, ICON_SIZE, ICON_SIZE); _resetIconRect = QRect(_bounds.width() - ICON_SIZE - ICON_PADDING, _bounds.top() + ICON_PADDING, ICON_SIZE, ICON_SIZE); - _bodyZoomIconRect = QRect(_bounds.width() - MID_ICON_PADDING - ICON_SIZE, _bounds.bottom() - ICON_PADDING - ICON_SIZE, ICON_SIZE, ICON_SIZE); - _headZoomIconRect = QRect(_bounds.left() + MID_ICON_PADDING, _bounds.bottom() - ICON_PADDING - ICON_SIZE, ICON_SIZE, ICON_SIZE); + _bodyZoomIconRect = QRect(_bounds.width() - ICON_SIZE - ICON_PADDING, _bounds.bottom() - ICON_PADDING - ICON_SIZE, ICON_SIZE, ICON_SIZE); + _headZoomIconRect = QRect(_bounds.left() + ICON_PADDING, _bounds.bottom() - ICON_PADDING - ICON_SIZE, ICON_SIZE, ICON_SIZE); settings->beginGroup(SETTINGS_GROUP_NAME); _zoomLevel = loadSetting(settings, ZOOM_LEVEL_SETTINGS, 0) == HEAD ? HEAD : BODY; @@ -59,7 +61,10 @@ void RearMirrorTools::render(bool fullScreen) { _windowed = _bounds.contains(mousePosition.x(), mousePosition.y()); if (_windowed) { displayIcon(_bounds, _closeIconRect, _closeTextureId); - displayIcon(_bounds, _resetIconRect, _resetTextureId); + + // Disabled for now https://worklist.net/19548 + // displayIcon(_bounds, _resetIconRect, _resetTextureId); + displayIcon(_bounds, _headZoomIconRect, _zoomHeadTextureId, _zoomLevel == HEAD); displayIcon(_bounds, _bodyZoomIconRect, _zoomBodyTextureId, _zoomLevel == BODY); } @@ -73,11 +78,13 @@ bool RearMirrorTools::mousePressEvent(int x, int y) { emit closeView(); return true; } - + + /* Disabled for now https://worklist.net/19548 if (_resetIconRect.contains(x, y)) { emit resetView(); return true; } + */ if (_headZoomIconRect.contains(x, y)) { _zoomLevel = HEAD; @@ -88,7 +95,7 @@ bool RearMirrorTools::mousePressEvent(int x, int y) { _zoomLevel = BODY; return true; } - + if (_bounds.contains(x, y)) { _windowed = false; emit restoreView(); @@ -124,7 +131,7 @@ void RearMirrorTools::displayIcon(QRect bounds, QRect iconBounds, GLuint texture glEnable(GL_TEXTURE_2D); if (selected) { - glColor3f(1, 1, 0); + glColor3f(.5f, .5f, .5f); } else { glColor3f(1, 1, 1); } diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 606df649a4..2f412b5e9a 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -35,6 +35,7 @@ using namespace std; QNetworkAccessManager* AvatarData::networkAccessManager = NULL; AvatarData::AvatarData() : + _sessionUUID(), _handPosition(0,0,0), _bodyYaw(-90.f), _bodyPitch(0.0f), diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 24910034b3..0ac12649cf 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -40,6 +40,7 @@ typedef unsigned long long quint64; #include #include #include +#include #include #include @@ -97,10 +98,14 @@ class AvatarData : public QObject { Q_PROPERTY(QString faceModelURL READ getFaceModelURLFromScript WRITE setFaceModelURLFromScript) Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript WRITE setSkeletonModelURLFromScript) Q_PROPERTY(QString billboardURL READ getBillboardURL WRITE setBillboardFromURL) + + Q_PROPERTY(QUuid sessionUUID READ getSessionUUID); public: AvatarData(); virtual ~AvatarData(); + const QUuid& getSessionUUID() { return _sessionUUID; } + const glm::vec3& getPosition() const { return _position; } void setPosition(const glm::vec3 position) { _position = position; } @@ -222,7 +227,9 @@ public slots: void sendBillboardPacket(); void setBillboardFromNetworkReply(); void setJointMappingsFromNetworkReply(); + void setSessionUUID(const QUuid& id) { _sessionUUID = id; } protected: + QUuid _sessionUUID; glm::vec3 _position; glm::vec3 _handPosition; diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index 27dc1bf0bb..1c2cd4bf92 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -18,6 +18,7 @@ AvatarHashMap::AvatarHashMap() : void AvatarHashMap::insert(const QUuid& id, AvatarSharedPointer avatar) { _avatarHash.insert(id, avatar); + avatar->setSessionUUID(id); } AvatarHash::iterator AvatarHashMap::erase(const AvatarHash::iterator& iterator) { diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 9c459518ae..3e63b26b0a 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -63,7 +63,8 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam _scriptName(), _fileNameString(fileNameString), _quatLibrary(), - _vec3Library() + _vec3Library(), + _uuidLibrary() { } @@ -86,7 +87,8 @@ ScriptEngine::ScriptEngine(const QUrl& scriptURL, _scriptName(), _fileNameString(), _quatLibrary(), - _vec3Library() + _vec3Library(), + _uuidLibrary() { QString scriptURLString = scriptURL.toString(); _fileNameString = scriptURLString; @@ -200,6 +202,7 @@ void ScriptEngine::init() { registerGlobalObject("Particles", &_particlesScriptingInterface); registerGlobalObject("Quat", &_quatLibrary); registerGlobalObject("Vec3", &_vec3Library); + registerGlobalObject("Uuid", &_uuidLibrary); registerGlobalObject("Voxels", &_voxelsScriptingInterface); diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 0796aa4f50..b90075e6a9 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -25,6 +25,7 @@ #include "AbstractControllerScriptingInterface.h" #include "Quat.h" +#include "ScriptUUID.h" #include "Vec3.h" class ParticlesScriptingInterface; @@ -124,6 +125,7 @@ private: QString _fileNameString; Quat _quatLibrary; Vec3 _vec3Library; + ScriptUUID _uuidLibrary; }; #endif // hifi_ScriptEngine_h diff --git a/libraries/script-engine/src/ScriptUUID.cpp b/libraries/script-engine/src/ScriptUUID.cpp new file mode 100644 index 0000000000..9e00f9c095 --- /dev/null +++ b/libraries/script-engine/src/ScriptUUID.cpp @@ -0,0 +1,40 @@ +// +// ScriptUUID.cpp +// libraries/script-engine/src/ +// +// Created by Andrew Meadows on 2014-04-07 +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// +// Scriptable interface for a UUID helper class object. Used exclusively in the JavaScript API +// +// 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 "ScriptUUID.h" + +QUuid ScriptUUID::fromString(const QString& s) { + return QUuid(s); +} + +QString ScriptUUID::toString(const QUuid& id) { + return id.toString(); +} + +QUuid ScriptUUID::generate() { + return QUuid::createUuid(); +} + +bool ScriptUUID::isEqual(const QUuid& idA, const QUuid& idB) { + return idA == idB; +} + +bool ScriptUUID::isNull(const QUuid& id) { + return id.isNull(); +} + +void ScriptUUID::print(const QString& lable, const QUuid& id) { + qDebug() << qPrintable(lable) << id.toString(); +} diff --git a/libraries/script-engine/src/ScriptUUID.h b/libraries/script-engine/src/ScriptUUID.h new file mode 100644 index 0000000000..db94b5082b --- /dev/null +++ b/libraries/script-engine/src/ScriptUUID.h @@ -0,0 +1,32 @@ +// +// ScriptUUID.h +// libraries/script-engine/src/ +// +// Created by Andrew Meadows on 2014-04-07 +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// +// Scriptable interface for a UUID helper class object. Used exclusively in the JavaScript API +// +// 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_ScriptUUID_h +#define hifi_ScriptUUID_h + +#include + +/// Scriptable interface for a UUID helper class object. Used exclusively in the JavaScript API +class ScriptUUID : public QObject { + Q_OBJECT + +public slots: + QUuid fromString(const QString& string); + QString toString(const QUuid& id); + QUuid generate(); + bool isEqual(const QUuid& idA, const QUuid& idB); + bool isNull(const QUuid& id); + void print(const QString& lable, const QUuid& id); +}; + +#endif // hifi_ScriptUUID_h