diff --git a/cmake/modules/FindGLEW.cmake b/cmake/modules/FindGLEW.cmake index 684acca762..dbb366390a 100644 --- a/cmake/modules/FindGLEW.cmake +++ b/cmake/modules/FindGLEW.cmake @@ -20,7 +20,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 0d0ec96ce5..327b81296d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -232,6 +232,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 @@ -1216,8 +1217,6 @@ void Application::timer() { // ask the node list to check in with the domain server NodeList::getInstance()->sendDomainServerCheckIn(); - - } void Application::idle() { @@ -2517,20 +2516,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}; @@ -2559,18 +2557,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); @@ -2610,6 +2617,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 63c683dbb0..6274fd7c13 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -15,6 +15,15 @@ #include #endif +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#endif + #include #include #include @@ -86,7 +95,8 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples, QObject* p void Audio::init(QGLWidget *parent) { _micTextureId = parent->bindTexture(QImage(Application::resourcesPath() + "images/mic.svg")); - _muteTextureId = parent->bindTexture(QImage(Application::resourcesPath() + "images/mute.svg")); + _muteTextureId = parent->bindTexture(QImage(Application::resourcesPath() + "images/mic-mute.svg")); + _boxTextureId = parent->bindTexture(QImage(Application::resourcesPath() + "images/audio-box.svg")); } void Audio::reset() { @@ -147,24 +157,56 @@ QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) { #endif #ifdef WIN32 QString deviceName; - if (mode == QAudio::AudioInput) { - WAVEINCAPS wic; - // first use WAVE_MAPPER to get the default devices manufacturer ID - waveInGetDevCaps(WAVE_MAPPER, &wic, sizeof(wic)); - //Use the received manufacturer id to get the device's real name - waveInGetDevCaps(wic.wMid, &wic, sizeof(wic)); - qDebug() << "input device:" << wic.szPname; - deviceName = wic.szPname; + //Check for Windows Vista or higher, IMMDeviceEnumerator doesn't work below that. + OSVERSIONINFO osvi; + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); + const DWORD VISTA_MAJOR_VERSION = 6; + if (osvi.dwMajorVersion < VISTA_MAJOR_VERSION) {// lower then vista + if (mode == QAudio::AudioInput) { + WAVEINCAPS wic; + // first use WAVE_MAPPER to get the default devices manufacturer ID + waveInGetDevCaps(WAVE_MAPPER, &wic, sizeof(wic)); + //Use the received manufacturer id to get the device's real name + waveInGetDevCaps(wic.wMid, &wic, sizeof(wic)); + qDebug() << "input device:" << wic.szPname; + deviceName = wic.szPname; + } else { + WAVEOUTCAPS woc; + // first use WAVE_MAPPER to get the default devices manufacturer ID + waveOutGetDevCaps(WAVE_MAPPER, &woc, sizeof(woc)); + //Use the received manufacturer id to get the device's real name + waveOutGetDevCaps(woc.wMid, &woc, sizeof(woc)); + qDebug() << "output device:" << woc.szPname; + deviceName = woc.szPname; + } } else { - WAVEOUTCAPS woc; - // first use WAVE_MAPPER to get the default devices manufacturer ID - waveOutGetDevCaps(WAVE_MAPPER, &woc, sizeof(woc)); - //Use the received manufacturer id to get the device's real name - waveOutGetDevCaps(woc.wMid, &woc, sizeof(woc)); - qDebug() << "output device:" << woc.szPname; - deviceName = woc.szPname; + HRESULT hr = S_OK; + CoInitialize(NULL); + IMMDeviceEnumerator* pMMDeviceEnumerator = NULL; + CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pMMDeviceEnumerator); + IMMDevice* pEndpoint; + pMMDeviceEnumerator->GetDefaultAudioEndpoint(mode == QAudio::AudioOutput ? eRender : eCapture, eMultimedia, &pEndpoint); + IPropertyStore* pPropertyStore; + pEndpoint->OpenPropertyStore(STGM_READ, &pPropertyStore); + pEndpoint->Release(); + pEndpoint = NULL; + PROPVARIANT pv; + PropVariantInit(&pv); + hr = pPropertyStore->GetValue(PKEY_Device_FriendlyName, &pv); + pPropertyStore->Release(); + pPropertyStore = NULL; + //QAudio devices seems to only take the 31 first characters of the Friendly Device Name. + const DWORD QT_WIN_MAX_AUDIO_DEVICENAME_LEN = 31; + deviceName = QString::fromWCharArray((wchar_t*)pv.pwszVal).left(QT_WIN_MAX_AUDIO_DEVICENAME_LEN); + qDebug() << (mode == QAudio::AudioOutput ? "output" : "input") << " device:" << deviceName; + PropVariantClear(&pv); + pMMDeviceEnumerator->Release(); + pMMDeviceEnumerator = NULL; + CoUninitialize(); } - qDebug() << "DEBUG [" << deviceName << "] [" << getNamedAudioDeviceForMode(mode, deviceName).deviceName() << "]"; + qDebug() << "DEBUG [" << deviceName << "] [" << getNamedAudioDeviceForMode(mode, deviceName).deviceName() << "]"; return getNamedAudioDeviceForMode(mode, deviceName); #endif @@ -817,13 +859,52 @@ void Audio::handleAudioByteArray(const QByteArray& audioByteArray) { // or send to the mixer and use delayed loopback } -void Audio::renderMuteIcon(int x, int y) { +void Audio::renderToolBox(int x, int y, bool boxed) { - _iconBounds = QRect(x, y, MUTE_ICON_SIZE, MUTE_ICON_SIZE); glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, _micTextureId); - glColor3f(.93f, .93f, .93f); + if (boxed) { + + bool isClipping = ((getTimeSinceLastClip() > 0.f) && (getTimeSinceLastClip() < 1.f)); + const int BOX_LEFT_PADDING = 5; + const int BOX_TOP_PADDING = 10; + const int BOX_WIDTH = 266; + const int BOX_HEIGHT = 44; + + QRect boxBounds = QRect(x - BOX_LEFT_PADDING, y - BOX_TOP_PADDING, BOX_WIDTH, BOX_HEIGHT); + + glBindTexture(GL_TEXTURE_2D, _boxTextureId); + + if (isClipping) { + glColor3f(1.f,0.f,0.f); + } else { + glColor3f(.41f,.41f,.41f); + } + glBegin(GL_QUADS); + + glTexCoord2f(1, 1); + glVertex2f(boxBounds.left(), boxBounds.top()); + + glTexCoord2f(0, 1); + glVertex2f(boxBounds.right(), boxBounds.top()); + + glTexCoord2f(0, 0); + glVertex2f(boxBounds.right(), boxBounds.bottom()); + + glTexCoord2f(1, 0); + glVertex2f(boxBounds.left(), boxBounds.bottom()); + + glEnd(); + } + + _iconBounds = QRect(x, y, MUTE_ICON_SIZE, MUTE_ICON_SIZE); + if (!_muted) { + glBindTexture(GL_TEXTURE_2D, _micTextureId); + } else { + glBindTexture(GL_TEXTURE_2D, _muteTextureId); + } + + glColor3f(1,1,1); glBegin(GL_QUADS); glTexCoord2f(1, 1); @@ -840,25 +921,6 @@ void Audio::renderMuteIcon(int x, int y) { glEnd(); - if (_muted) { - glBindTexture(GL_TEXTURE_2D, _muteTextureId); - glBegin(GL_QUADS); - - glTexCoord2f(1, 1); - glVertex2f(_iconBounds.left(), _iconBounds.top()); - - glTexCoord2f(0, 1); - glVertex2f(_iconBounds.right(), _iconBounds.top()); - - glTexCoord2f(0, 0); - glVertex2f(_iconBounds.right(), _iconBounds.bottom()); - - glTexCoord2f(1, 0); - glVertex2f(_iconBounds.left(), _iconBounds.bottom()); - - glEnd(); - } - glDisable(GL_TEXTURE_2D); } diff --git a/interface/src/Audio.h b/interface/src/Audio.h index 88488922f3..c6a3619865 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -69,7 +69,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; } @@ -161,6 +161,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 4386704559..3f496c9890 100644 --- a/libraries/shared/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -18,7 +18,9 @@ #include #include -#include "AccountManager.h" +#include + +#include "renderer/FBXReader.h" #include "ModelUploader.h" @@ -59,11 +61,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); @@ -99,23 +104,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."), @@ -123,18 +131,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))) { @@ -143,6 +147,10 @@ bool ModelUploader::zip() { } } + if (!addTextures(texDir, fbxFile)) { + return false; + } + QHttpPart textPart; textPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data;" " name=\"model_category\""); @@ -153,12 +161,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; } @@ -202,7 +220,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(); @@ -214,7 +232,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(); @@ -247,7 +265,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; @@ -256,24 +275,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 94% rename from libraries/shared/src/ModelUploader.h rename to interface/src/ModelUploader.h index 0e62ab8705..0d18ef9022 100644 --- a/libraries/shared/src/ModelUploader.h +++ b/interface/src/ModelUploader.h @@ -17,8 +17,6 @@ class QFileInfo; class QHttpMultiPart; class QProgressBar; -class TemporaryDir; - class ModelUploader : public QObject { Q_OBJECT @@ -55,7 +53,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 c2ba28ac7b..fbbaad4e84 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -123,8 +123,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 @@ -133,9 +133,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; @@ -166,10 +166,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); @@ -188,16 +188,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()); @@ -218,9 +218,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); @@ -232,10 +232,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 314fd7157b..07503c8cb2 100644 --- a/interface/src/ui/RearMirrorTools.cpp +++ b/interface/src/ui/RearMirrorTools.cpp @@ -18,9 +18,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), @@ -29,16 +28,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; @@ -55,7 +57,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); } @@ -69,11 +74,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; @@ -84,7 +91,7 @@ bool RearMirrorTools::mousePressEvent(int x, int y) { _zoomLevel = BODY; return true; } - + if (_bounds.contains(x, y)) { _windowed = false; emit restoreView(); @@ -120,7 +127,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 e84636b5a4..7d8f4d988b 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -32,6 +32,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 cf645855e8..2b8dfe8861 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -37,6 +37,7 @@ typedef unsigned long long quint64; #include #include #include +#include #include #include @@ -94,10 +95,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; } @@ -219,7 +224,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 82485691c5..3dd5c9991f 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -15,6 +15,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 7572638a30..7d3dd650ae 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -60,7 +60,8 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam _scriptName(), _fileNameString(fileNameString), _quatLibrary(), - _vec3Library() + _vec3Library(), + _uuidLibrary() { } @@ -83,7 +84,8 @@ ScriptEngine::ScriptEngine(const QUrl& scriptURL, _scriptName(), _fileNameString(), _quatLibrary(), - _vec3Library() + _vec3Library(), + _uuidLibrary() { QString scriptURLString = scriptURL.toString(); _fileNameString = scriptURLString; @@ -197,6 +199,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 964f64a005..2b98549d66 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -22,6 +22,7 @@ #include "AbstractControllerScriptingInterface.h" #include "Quat.h" +#include "ScriptUUID.h" #include "Vec3.h" class ParticlesScriptingInterface; @@ -121,6 +122,7 @@ private: QString _fileNameString; Quat _quatLibrary; Vec3 _vec3Library; + ScriptUUID _uuidLibrary; }; #endif /* defined(__hifi__ScriptEngine__) */ 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