diff --git a/cmake/macros/IncludeGLM.cmake b/cmake/macros/IncludeGLM.cmake index c5530bf8c9..ba47c3d28e 100644 --- a/cmake/macros/IncludeGLM.cmake +++ b/cmake/macros/IncludeGLM.cmake @@ -2,4 +2,5 @@ MACRO(INCLUDE_GLM TARGET ROOT_DIR) set(GLM_ROOT_DIR ${ROOT_DIR}/externals) find_package(GLM REQUIRED) include_directories(${GLM_INCLUDE_DIRS}) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${GLM_INCLUDE_DIRS}") ENDMACRO(INCLUDE_GLM _target _root_dir) \ No newline at end of file diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 17967c5f42..2adc7e6643 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -45,6 +45,12 @@ endforeach(SUBDIR) # project subdirectories add_subdirectory(src/starfield) +find_package(Qt5Core REQUIRED) +find_package(Qt5Gui REQUIRED) +find_package(Qt5Network REQUIRED) +find_package(Qt5OpenGL REQUIRED) +find_package(Qt5Svg REQUIRED) + if (APPLE) # set how the icon shows up in the Info.plist file SET(MACOSX_BUNDLE_ICON_FILE interface.icns) @@ -64,15 +70,8 @@ if (APPLE) SET(INTERFACE_SRCS ${INTERFACE_SRCS} ${DIR_CONTENTS}) endif() endforeach() - endif (APPLE) -find_package(Qt5Core REQUIRED) -find_package(Qt5Gui REQUIRED) -find_package(Qt5Network REQUIRED) -find_package(Qt5OpenGL REQUIRED) -find_package(Qt5Svg REQUIRED) - set(QUAZIP_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/quazip) add_subdirectory(external/fervor/) include_directories(external/fervor/) @@ -101,12 +100,12 @@ find_package(UVCCameraControl) find_package(ZLIB) # let the source know that we have OpenNI/NITE for Kinect -if (OPENNI_FOUND) +if (OPENNI_FOUND AND NOT DISABLE_OPENNI) add_definitions(-DHAVE_OPENNI) include_directories(SYSTEM ${OPENNI_INCLUDE_DIRS}) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${OPENNI_INCLUDE_DIRS}") target_link_libraries(${TARGET_NAME} ${OPENNI_LIBRARIES}) -endif (OPENNI_FOUND) +endif (OPENNI_FOUND AND NOT DISABLE_OPENNI) qt5_use_modules(${TARGET_NAME} Core Gui Network OpenGL Svg) diff --git a/interface/external/fervor/fvupdater.cpp b/interface/external/fervor/fvupdater.cpp index 66bdc29163..b720b0a024 100755 --- a/interface/external/fervor/fvupdater.cpp +++ b/interface/external/fervor/fvupdater.cpp @@ -9,7 +9,7 @@ #include "quazip.h" #include "quazipfile.h" -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC #include "CoreFoundation/CoreFoundation.h" #endif @@ -228,7 +228,7 @@ void FvUpdater::httpUpdateDownloadFinished() { if (reply->isReadable()) { -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC CFURLRef appURLRef = CFBundleCopyBundleURL(CFBundleGetMainBundle()); char path[PATH_MAX]; if (!CFURLGetFileSystemRepresentation(appURLRef, TRUE, (UInt8 *)path, PATH_MAX)) { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a701fde1f2..1e5023c8e3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -26,17 +26,11 @@ #include "InterfaceConfig.h" #include -#include #include -#include #include -#include #include -#include -#include #include #include -#include #include #include #include @@ -64,6 +58,7 @@ #include "Application.h" #include "LogDisplay.h" #include "LeapManager.h" +#include "Menu.h" #include "OculusManager.h" #include "Util.h" #include "renderer/ProgramObject.h" @@ -79,11 +74,6 @@ static char STAR_CACHE_FILE[] = "cachedStars.txt"; static const int BANDWIDTH_METER_CLICK_MAX_DRAG_LENGTH = 6; // farther dragged clicks are ignored -// Where one's own Avatar begins in the world (will be overwritten if avatar data file is found) -// this is basically in the center of the ground plane. Slightly adjusted. This was asked for by -// Grayson as he's building a street around here for demo dinner 2 -const glm::vec3 START_LOCATION(0.485f * TREE_SCALE, 0.f, 0.5f * TREE_SCALE); - const int IDLE_SIMULATE_MSECS = 16; // How often should call simulate and other stuff // in the idle loop? (60 FPS is default) static QTimer* idleTimer = NULL; @@ -92,87 +82,6 @@ const int STARTUP_JITTER_SAMPLES = PACKET_LENGTH_SAMPLES_PER_CHANNEL / 2; // Startup optimistically with small jitter buffer that // will start playback on the second received audio packet. -// customized canvas that simply forwards requests/events to the singleton application -class GLCanvas : public QGLWidget { -public: - GLCanvas(); -protected: - - virtual void initializeGL(); - virtual void paintGL(); - virtual void resizeGL(int width, int height); - - virtual void keyPressEvent(QKeyEvent* event); - virtual void keyReleaseEvent(QKeyEvent* event); - - virtual void mouseMoveEvent(QMouseEvent* event); - virtual void mousePressEvent(QMouseEvent* event); - virtual void mouseReleaseEvent(QMouseEvent* event); - - virtual bool event(QEvent* event); - - virtual void wheelEvent(QWheelEvent* event); -}; - -GLCanvas::GLCanvas() : QGLWidget(QGLFormat(QGL::NoDepthBuffer, QGL::NoStencilBuffer)) { -} - -void GLCanvas::initializeGL() { - Application::getInstance()->initializeGL(); - setAttribute(Qt::WA_AcceptTouchEvents); -} - -void GLCanvas::paintGL() { - Application::getInstance()->paintGL(); -} - -void GLCanvas::resizeGL(int width, int height) { - Application::getInstance()->resizeGL(width, height); -} - -void GLCanvas::keyPressEvent(QKeyEvent* event) { - Application::getInstance()->keyPressEvent(event); -} - -void GLCanvas::keyReleaseEvent(QKeyEvent* event) { - Application::getInstance()->keyReleaseEvent(event); -} - -void GLCanvas::mouseMoveEvent(QMouseEvent* event) { - Application::getInstance()->mouseMoveEvent(event); -} - -void GLCanvas::mousePressEvent(QMouseEvent* event) { - Application::getInstance()->mousePressEvent(event); -} - -void GLCanvas::mouseReleaseEvent(QMouseEvent* event) { - Application::getInstance()->mouseReleaseEvent(event); -} - -int updateTime = 0; -bool GLCanvas::event(QEvent* event) { - switch (event->type()) { - case QEvent::TouchBegin: - Application::getInstance()->touchBeginEvent(static_cast(event)); - event->accept(); - return true; - case QEvent::TouchEnd: - Application::getInstance()->touchEndEvent(static_cast(event)); - return true; - case QEvent::TouchUpdate: - Application::getInstance()->touchUpdateEvent(static_cast(event)); - return true; - default: - break; - } - return QGLWidget::event(event); -} - -void GLCanvas::wheelEvent(QWheelEvent* event) { - Application::getInstance()->wheelEvent(event); -} - void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message) { fprintf(stdout, "%s", message.toLocal8Bit().constData()); LogDisplay::instance.addMessage(message.toLocal8Bit().constData()); @@ -182,21 +91,11 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : QApplication(argc, argv), _window(new QMainWindow(desktop())), _glWidget(new GLCanvas()), - _bandwidthDialog(NULL), - _voxelStatsDialog(NULL), _displayLevels(false), _frameCount(0), _fps(120.0f), _justStarted(true), - _particleSystemInitialized(false), - _coolDemoParticleEmitter(-1), _wantToKillLocalVoxels(false), - _frustumDrawingMode(FRUSTUM_DRAW_MODE_ALL), - _viewFrustumOffsetYaw(-135.0), - _viewFrustumOffsetPitch(0.0), - _viewFrustumOffsetRoll(0.0), - _viewFrustumOffsetDistance(25.0), - _viewFrustumOffsetUp(0.0), _audioScope(256, 200, true), _mouseX(0), _mouseY(0), @@ -254,7 +153,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : } // setup QSettings -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC QString resourcesPath = QCoreApplication::applicationDirPath() + "/../Resources"; #else QString resourcesPath = QCoreApplication::applicationDirPath() + "/resources"; @@ -311,13 +210,16 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _window->setCentralWidget(_glWidget); -#if defined(Q_WS_MAC) && defined(QT_NO_DEBUG) +#if defined(Q_OS_MAC) && defined(QT_NO_DEBUG) // if this is a release OS X build use fervor to check for an update FvUpdater::sharedUpdater()->SetFeedURL("https://s3-us-west-1.amazonaws.com/highfidelity/appcast.xml"); FvUpdater::sharedUpdater()->CheckForUpdatesSilent(); #endif - initMenu(); + // call Menu getInstance static method to set up the menur + Menu::getInstance(); + + _networkAccessManager = new QNetworkAccessManager(this); QRect available = desktop()->availableGeometry(); _window->resize(available.size()); @@ -453,14 +355,16 @@ void Application::paintGL() { // myCamera is. But we also want to do meaningful camera transforms on OpenGL for the offset camera Camera whichCamera = _myCamera; - if (_frustumOn->isChecked()) { + if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayFrustum)) { + + ViewFrustumOffset viewFrustumOffset = Menu::getInstance()->getViewFrustumOffset(); // set the camera to third-person view but offset so we can see the frustum _viewFrustumOffsetCamera.setTargetPosition(_myCamera.getTargetPosition()); _viewFrustumOffsetCamera.setTargetRotation(_myCamera.getTargetRotation() * glm::quat(glm::radians(glm::vec3( - _viewFrustumOffsetPitch, _viewFrustumOffsetYaw, _viewFrustumOffsetRoll)))); - _viewFrustumOffsetCamera.setUpShift (_viewFrustumOffsetUp ); - _viewFrustumOffsetCamera.setDistance (_viewFrustumOffsetDistance); + viewFrustumOffset.pitch, viewFrustumOffset.yaw, viewFrustumOffset.roll)))); + _viewFrustumOffsetCamera.setUpShift(viewFrustumOffset.up); + _viewFrustumOffsetCamera.setDistance(viewFrustumOffset.distance); _viewFrustumOffsetCamera.initialize(); // force immediate snap to ideal position and orientation _viewFrustumOffsetCamera.update(1.f/_fps); whichCamera = _viewFrustumOffsetCamera; @@ -490,7 +394,7 @@ void Application::resetCamerasOnResizeGL(Camera& camera, int width, int height) camera.setFieldOfView(2 * atan((0.0468 * _oculusDistortionScale) / 0.041) * (180 / PIf)); } else { camera.setAspectRatio(aspectRatio); - camera.setFieldOfView(_fieldOfView); + camera.setFieldOfView(Menu::getInstance()->getFieldOfView()); } } @@ -520,7 +424,7 @@ void Application::resizeGL(int width, int height) { // If we're in Display Frustum mode, then we want to use the slightly adjust near/far clip values of the // _viewFrustumOffsetCamera, so that we can see more of the application content in the application's frustum - if (_frustumOn->isChecked()) { + if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayFrustum)) { nearVal = _viewFrustumOffsetCamera.getNearClip(); farVal = _viewFrustumOffsetCamera.getFarClip(); } @@ -536,7 +440,7 @@ void Application::controlledBroadcastToNodes(unsigned char* broadcastData, size_ for (int i = 0; i < numNodeTypes; ++i) { // Intercept data to voxel server when voxels are disabled - if (nodeTypes[i] == NODE_TYPE_VOXEL_SERVER && ! self->_renderVoxels->isChecked()) { + if (nodeTypes[i] == NODE_TYPE_VOXEL_SERVER && !Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) { continue; } @@ -578,53 +482,25 @@ void Application::keyPressEvent(QKeyEvent* event) { } //this is for switching between modes for the leap rave glove test - if (_simulateLeapHand->isChecked() || _testRaveGlove->isChecked()) { + if (Menu::getInstance()->isOptionChecked(MenuOption::SimulateLeapHand) + || Menu::getInstance()->isOptionChecked(MenuOption::TestRaveGlove)) { _myAvatar.getHand().setRaveGloveEffectsMode((QKeyEvent*)event); } - bool isMeta = event->modifiers().testFlag(Qt::MetaModifier); bool isShifted = event->modifiers().testFlag(Qt::ShiftModifier); switch (event->key()) { case Qt::Key_BracketLeft: - _viewFrustumOffsetYaw -= 0.5; - break; - case Qt::Key_BracketRight: - _viewFrustumOffsetYaw += 0.5; - break; - case Qt::Key_BraceLeft: - _viewFrustumOffsetPitch -= 0.5; - break; - case Qt::Key_BraceRight: - _viewFrustumOffsetPitch += 0.5; - break; - case Qt::Key_ParenLeft: - _viewFrustumOffsetRoll -= 0.5; - break; - case Qt::Key_ParenRight: - _viewFrustumOffsetRoll += 0.5; - break; - case Qt::Key_Less: - _viewFrustumOffsetDistance -= 0.5; - break; - case Qt::Key_Greater: - _viewFrustumOffsetDistance += 0.5; - break; - case Qt::Key_Comma: - _viewFrustumOffsetUp -= 0.05; - break; - case Qt::Key_Period: - _viewFrustumOffsetUp += 0.05; + Menu::getInstance()->handleViewFrustumOffsetKeyModifier(event->key()); break; - case Qt::Key_Semicolon: _audio.ping(); break; @@ -644,9 +520,7 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_C: if (isShifted) { - _occlusionCulling->trigger(); - } else if (isMeta) { - chooseVoxelPaintColor(); + Menu::getInstance()->triggerOption(MenuOption::OcclusionCulling); } else { _myAvatar.setDriveKeys(DOWN, 1); } @@ -658,7 +532,7 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_S: if (isShifted) { - doTreeStats(); + _voxels.collectStatsForTreesAndVBOs(); } else { _myAvatar.setDriveKeys(BACK, 1); } @@ -671,15 +545,15 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_G: if (isShifted) { - _gravityUse->trigger(); + Menu::getInstance()->triggerOption(MenuOption::Gravity); } else { - _eyedropperMode->trigger(); + Menu::getInstance()->triggerOption(MenuOption::VoxelGetColorMode); } break; case Qt::Key_A: if (isShifted) { - _renderAtmosphereOn->trigger(); + Menu::getInstance()->triggerOption(MenuOption::Atmosphere); } else { _myAvatar.setDriveKeys(ROT_LEFT, 1); } @@ -772,56 +646,53 @@ void Application::keyPressEvent(QKeyEvent* event) { } resizeGL(_glWidget->width(), _glWidget->height()); break; - case Qt::Key_N: - _noise->trigger(); - break; case Qt::Key_H: - _lookingInMirror->trigger(); + Menu::getInstance()->triggerOption(MenuOption::Mirror); break; case Qt::Key_F: if (isShifted) { - _frustumOn->trigger(); + Menu::getInstance()->triggerOption(MenuOption::DisplayFrustum); } else { - _fullScreenMode->trigger(); + Menu::getInstance()->triggerOption(MenuOption::Fullscreen); } break; case Qt::Key_V: if (isShifted) { - _renderVoxels->trigger(); + Menu::getInstance()->triggerOption(MenuOption::Voxels); } else { - _addVoxelMode->trigger(); + Menu::getInstance()->triggerOption(MenuOption::VoxelAddMode); } break; case Qt::Key_P: - _manualFirstPerson->trigger(); + Menu::getInstance()->triggerOption(MenuOption::FirstPerson); break; case Qt::Key_R: if (isShifted) { - _frustumRenderModeAction->trigger(); + Menu::getInstance()->triggerOption(MenuOption::FrustumRenderMode); } else { - _deleteVoxelMode->trigger(); + Menu::getInstance()->triggerOption(MenuOption::VoxelDeleteMode); } break; case Qt::Key_B: - _colorVoxelMode->trigger(); + Menu::getInstance()->triggerOption(MenuOption::VoxelColorMode); break; case Qt::Key_O: - _selectVoxelMode->trigger(); + Menu::getInstance()->triggerOption(MenuOption::VoxelSelectMode); break; case Qt::Key_Slash: - _renderStatsOn->trigger(); + Menu::getInstance()->triggerOption(MenuOption::Stats); break; case Qt::Key_Backspace: case Qt::Key_Delete: - if (_selectVoxelMode->isChecked()) { + if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelDeleteMode)) { deleteVoxelUnderCursor(); } break; case Qt::Key_Plus: - increaseAvatarSize(); + _myAvatar.increaseSize(); break; case Qt::Key_Minus: - decreaseAvatarSize(); + _myAvatar.decreaseSize(); break; case Qt::Key_1: @@ -832,7 +703,7 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_6: case Qt::Key_7: case Qt::Key_8: - _swatch.handleEvent(event->key(), _eyedropperMode->isChecked()); + _swatch.handleEvent(event->key(), Menu::getInstance()->isOptionChecked(MenuOption::VoxelGetColorMode)); break; default: event->ignore(); @@ -911,7 +782,7 @@ void Application::mouseMoveEvent(QMouseEvent* event) { if (event->buttons().testFlag(Qt::LeftButton)) { maybeEditVoxelUnderCursor(); - } else if (event->buttons().testFlag(Qt::RightButton) && checkedVoxelModeAction() != 0) { + } else if (event->buttons().testFlag(Qt::RightButton) && Menu::getInstance()->isVoxelModeActionChecked()) { deleteVoxelUnderCursor(); } } @@ -959,7 +830,7 @@ void Application::mousePressEvent(QMouseEvent* event) { _isHoverVoxelSounding = true; } - } else if (event->button() == Qt::RightButton && checkedVoxelModeAction() != 0) { + } else if (event->button() == Qt::RightButton && Menu::getInstance()->isVoxelModeActionChecked()) { deleteVoxelUnderCursor(); } } @@ -1018,7 +889,7 @@ const bool USE_MOUSEWHEEL = false; void Application::wheelEvent(QWheelEvent* event) { // Wheel Events disabled for now because they are also activated by touch look pitch up/down. if (USE_MOUSEWHEEL && (activeWindow() == _window)) { - if (checkedVoxelModeAction() == 0) { + if (!Menu::getInstance()->isVoxelModeActionChecked()) { event->ignore(); return; } @@ -1078,7 +949,7 @@ void Application::sendAvatarFaceVideoMessage(int frameCount, const QByteArray& d void Application::timer() { gettimeofday(&_timerEnd, NULL); - if (_testPing->isChecked()) { + if (Menu::getInstance()->isOptionChecked(MenuOption::TestPing)) { sendPingPackets(); } @@ -1154,8 +1025,8 @@ void Application::terminate() { LeapManager::terminate(); - if (_settingsAutosave->isChecked()) { - saveSettings(); + if (Menu::getInstance()->isOptionChecked(MenuOption::SettingsAutosave)) { + Menu::getInstance()->saveSettings(); _settings->sync(); } @@ -1168,24 +1039,6 @@ void Application::terminate() { _voxelEditSender.terminate(); } -void Application::sendAvatarVoxelURLMessage(const QUrl& url) { - uint16_t ownerID = NodeList::getInstance()->getOwnerID(); - - if (ownerID == UNKNOWN_NODE_ID) { - return; // we don't yet know who we are - } - QByteArray message; - - char packetHeader[MAX_PACKET_HEADER_BYTES]; - int numBytesPacketHeader = populateTypeAndVersion((unsigned char*) packetHeader, PACKET_TYPE_AVATAR_VOXEL_URL); - - message.append(packetHeader, numBytesPacketHeader); - message.append((const char*)&ownerID, sizeof(ownerID)); - message.append(url.toEncoded()); - - controlledBroadcastToNodes((unsigned char*)message.data(), message.size(), & NODE_TYPE_AVATAR_MIXER, 1); -} - static Avatar* processAvatarMessageHeader(unsigned char*& packetData, size_t& dataBytes) { // record the packet for stats-tracking Application::getInstance()->getBandwidthMeter()->inputStream(BandwidthMeter::AVATARS).updateValue(dataBytes); @@ -1235,207 +1088,22 @@ void Application::processAvatarFaceVideoMessage(unsigned char* packetData, size_ void Application::checkBandwidthMeterClick() { // ... to be called upon button release - if (_bandwidthDisplayOn->isChecked() && + if (Menu::getInstance()->isOptionChecked(MenuOption::Bandwidth) && glm::compMax(glm::abs(glm::ivec2(_mouseX - _mouseDragStartedX, _mouseY - _mouseDragStartedY))) <= BANDWIDTH_METER_CLICK_MAX_DRAG_LENGTH && _bandwidthMeter.isWithinArea(_mouseX, _mouseY, _glWidget->width(), _glWidget->height())) { // The bandwidth meter is visible, the click didn't get dragged too far and // we actually hit the bandwidth meter - bandwidthDetails(); + Menu::getInstance()->bandwidthDetails(); } } -void Application::bandwidthDetails() { - - if (! _bandwidthDialog) { - _bandwidthDialog = new BandwidthDialog(_glWidget, getBandwidthMeter()); - connect(_bandwidthDialog, SIGNAL(closed()), SLOT(bandwidthDetailsClosed())); - - _bandwidthDialog->show(); - } - _bandwidthDialog->raise(); -} - -void Application::bandwidthDetailsClosed() { - - QDialog* dlg = _bandwidthDialog; - _bandwidthDialog = NULL; - delete dlg; -} - -void Application::voxelStatsDetails() { - if (!_voxelStatsDialog) { - _voxelStatsDialog = new VoxelStatsDialog(_glWidget, &_voxelSceneStats); - connect(_voxelStatsDialog, SIGNAL(closed()), SLOT(voxelStatsDetailsClosed())); - _voxelStatsDialog->show(); - } - _voxelStatsDialog->raise(); -} - -void Application::voxelStatsDetailsClosed() { - QDialog* dlg = _voxelStatsDialog; - _voxelStatsDialog = NULL; - delete dlg; -} - -void Application::editPreferences() { - QDialog dialog(_glWidget); - dialog.setWindowTitle("Interface Preferences"); - QBoxLayout* layout = new QBoxLayout(QBoxLayout::TopToBottom); - dialog.setLayout(layout); - - QFormLayout* form = new QFormLayout(); - layout->addLayout(form, 1); - - const int QLINE_MINIMUM_WIDTH = 400; - - QLineEdit* domainServerHostname = new QLineEdit(QString(NodeList::getInstance()->getDomainHostname())); - domainServerHostname->setMinimumWidth(QLINE_MINIMUM_WIDTH); - form->addRow("Domain server:", domainServerHostname); - - QLineEdit* avatarURL = new QLineEdit(_myAvatar.getVoxels()->getVoxelURL().toString()); - avatarURL->setMinimumWidth(QLINE_MINIMUM_WIDTH); - form->addRow("Avatar URL:", avatarURL); - - QSpinBox* fieldOfView = new QSpinBox(); - fieldOfView->setMaximum(180); - fieldOfView->setMinimum(1); - fieldOfView->setValue(_fieldOfView); - form->addRow("Vertical Field of View (Degrees):", fieldOfView); - - QDoubleSpinBox* gyroCameraSensitivity = new QDoubleSpinBox(); - gyroCameraSensitivity->setValue(_gyroCameraSensitivity); - form->addRow("Gyro Camera Sensitivity (0 - 1):", gyroCameraSensitivity); - - QDoubleSpinBox* leanScale = new QDoubleSpinBox(); - leanScale->setValue(_myAvatar.getLeanScale()); - form->addRow("Lean Scale:", leanScale); - - QSpinBox* audioJitterBufferSamples = new QSpinBox(); - audioJitterBufferSamples->setMaximum(10000); - audioJitterBufferSamples->setMinimum(-10000); - audioJitterBufferSamples->setValue(_audioJitterBufferSamples); - form->addRow("Audio Jitter Buffer Samples (0 for automatic):", audioJitterBufferSamples); - - QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - dialog.connect(buttons, SIGNAL(accepted()), SLOT(accept())); - dialog.connect(buttons, SIGNAL(rejected()), SLOT(reject())); - layout->addWidget(buttons); - - if (dialog.exec() != QDialog::Accepted) { - return; - } - - QByteArray newHostname; - - if (domainServerHostname->text().size() > 0) { - // the user input a new hostname, use that - newHostname = domainServerHostname->text().toLocal8Bit(); - } else { - // the user left the field blank, use the default hostname - newHostname = QByteArray(DEFAULT_DOMAIN_HOSTNAME); - } - - // check if the domain server hostname is new - if (memcmp(NodeList::getInstance()->getDomainHostname(), newHostname.constData(), newHostname.size()) != 0) { - - NodeList::getInstance()->clear(); - - // kill the local voxels - _voxels.killLocalVoxels(); - - // reset the environment to default - _environment.resetToDefault(); - - // set the new hostname - NodeList::getInstance()->setDomainHostname(newHostname.constData()); - } - - QUrl url(avatarURL->text()); - _myAvatar.getVoxels()->setVoxelURL(url); - sendAvatarVoxelURLMessage(url); - - _gyroCameraSensitivity = gyroCameraSensitivity->value(); - _myAvatar.setLeanScale(leanScale->value()); - _audioJitterBufferSamples = audioJitterBufferSamples->value(); - if (!shouldDynamicallySetJitterBuffer()) { - _audio.setJitterBufferSamples(_audioJitterBufferSamples); - } - _fieldOfView = fieldOfView->value(); - resizeGL(_glWidget->width(), _glWidget->height()); - -} - -void Application::pair() { - PairingHandler::sendPairRequest(); -} - -void Application::setRenderMirrored(bool mirrored) { - if (mirrored) { - _manualFirstPerson->setChecked(false); - _manualThirdPerson->setChecked(false); - } -} - -void Application::setNoise(bool noise) { - _myAvatar.setNoise(noise); -} - void Application::setFullscreen(bool fullscreen) { _window->setWindowState(fullscreen ? (_window->windowState() | Qt::WindowFullScreen) : (_window->windowState() & ~Qt::WindowFullScreen)); updateCursor(); } -void Application::setRenderFirstPerson(bool firstPerson) { - if (firstPerson) { - _lookingInMirror->setChecked(false); - _manualThirdPerson->setChecked(false); - } else { - _manualThirdPerson->trigger(); - } -} - -void Application::setRenderThirdPerson(bool thirdPerson) { - if (thirdPerson) { - _lookingInMirror->setChecked(false); - _manualFirstPerson->setChecked(false); - } -} - -void Application::increaseAvatarSize() { - if ((1.f + SCALING_RATIO) * _myAvatar.getNewScale() < MAX_SCALE) { - _myAvatar.setNewScale((1.f + SCALING_RATIO) * _myAvatar.getNewScale()); - qDebug("Changed scale to %f\n", _myAvatar.getNewScale()); - } -} - -void Application::decreaseAvatarSize() { - if (MIN_SCALE < (1.f - SCALING_RATIO) * _myAvatar.getNewScale()) { - _myAvatar.setNewScale((1.f - SCALING_RATIO) * _myAvatar.getNewScale()); - qDebug("Changed scale to %f\n", _myAvatar.getNewScale()); - } -} - -void Application::resetAvatarSize() { - _myAvatar.setNewScale(1.f); - qDebug("Reseted scale to %f\n", _myAvatar.getNewScale()); -} - -void Application::setFrustumOffset(bool frustumOffset) { - // reshape so that OpenGL will get the right lens details for the camera of choice - resizeGL(_glWidget->width(), _glWidget->height()); -} - -void Application::cycleFrustumRenderMode() { - _frustumDrawingMode = (FrustumDrawMode)((_frustumDrawingMode + 1) % FRUSTUM_DRAW_MODE_COUNT); - updateFrustumRenderModeAction(); -} - -void Application::setRenderWarnings(bool renderWarnings) { - _voxels.setRenderPipelineWarnings(renderWarnings); -} - void Application::setRenderVoxels(bool voxelRender) { if (!voxelRender) { doKillLocalVoxels(); @@ -1446,75 +1114,6 @@ void Application::doKillLocalVoxels() { _wantToKillLocalVoxels = true; } -void Application::doRandomizeVoxelColors() { - _voxels.randomizeVoxelColors(); -} - -void Application::doFalseRandomizeVoxelColors() { - _voxels.falseColorizeRandom(); -} - -void Application::doFalseRandomizeEveryOtherVoxelColors() { - _voxels.falseColorizeRandomEveryOther(); -} - -void Application::doFalseColorizeByDistance() { - loadViewFrustum(_myCamera, _viewFrustum); - _voxels.falseColorizeDistanceFromView(&_viewFrustum); -} - -void Application::doFalseColorizeInView() { - loadViewFrustum(_myCamera, _viewFrustum); - // we probably want to make sure the viewFrustum is initialized first - _voxels.falseColorizeInView(&_viewFrustum); -} - -void Application::doFalseColorizeOccluded() { - CoverageMap::wantDebugging = true; - _voxels.falseColorizeOccluded(); -} - -void Application::doFalseColorizeOccludedV2() { - _voxels.falseColorizeOccludedV2(); -} - -void Application::doFalseColorizeBySource() { - _voxels.falseColorizeBySource(); -} - -void Application::doTrueVoxelColors() { - _voxels.trueColorize(); -} - -void Application::doTreeStats() { - _voxels.collectStatsForTreesAndVBOs(); -} - -void Application::disableLowResMoving(bool disableLowResMoving) { - _myAvatar.setWantLowResMoving(!disableLowResMoving); -} - -void Application::setWantsMonochrome(bool wantsMonochrome) { - _myAvatar.setWantColor(!wantsMonochrome); -} - -void Application::disableDeltaSending(bool disableDeltaSending) { - _myAvatar.setWantDelta(!disableDeltaSending); -} - -void Application::disableOcclusionCulling(bool disableOcclusionCulling) { - _myAvatar.setWantOcclusionCulling(!disableOcclusionCulling); -} - -void Application::updateVoxelModeActions() { - // only the sender can be checked - foreach (QAction* action, _voxelModeActions->actions()) { - if (action->isChecked() && action != sender()) { - action->setChecked(false); - } - } -} - const glm::vec3 Application::getMouseVoxelWorldCoordinates(const VoxelDetail _mouseVoxel) { return glm::vec3((_mouseVoxel.x + _mouseVoxel.s / 2.f) * TREE_SCALE, (_mouseVoxel.y + _mouseVoxel.s / 2.f) * TREE_SCALE, @@ -1529,27 +1128,6 @@ void Application::increaseVoxelSize() { _mouseVoxelScale *= 2; } -void Application::resetSwatchColors() { - _swatch.reset(); -} - -static QIcon createSwatchIcon(const QColor& color) { - QPixmap map(16, 16); - map.fill(color); - return QIcon(map); -} - -void Application::chooseVoxelPaintColor() { - QColor selected = QColorDialog::getColor(_voxelPaintColor->data().value(), _glWidget, "Voxel Paint Color"); - if (selected.isValid()) { - _voxelPaintColor->setData(selected); - _voxelPaintColor->setIcon(createSwatchIcon(selected)); - } - - // restore the main window's active state - _window->activateWindow(); -} - const int MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE = 1500; struct SendVoxelsOperationArgs { unsigned char* newBaseOctCode; @@ -1835,197 +1413,6 @@ void Application::pasteVoxels() { } } -void Application::initMenu() { - QMenuBar* menuBar = new QMenuBar(); - _window->setMenuBar(menuBar); - - QMenu* fileMenu = menuBar->addMenu("File"); - QAction* quitAction = fileMenu->addAction("Quit", this, SLOT(quit()), Qt::CTRL | Qt::Key_Q); - quitAction->setMenuRole(QAction::QuitRole); - - QMenu* editMenu = menuBar->addMenu("Edit"); - QAction* preferencesAction = editMenu->addAction("Preferences...", this, SLOT(editPreferences()), Qt::CTRL | Qt::Key_Comma); - preferencesAction->setMenuRole(QAction::PreferencesRole); - - QMenu* pairMenu = menuBar->addMenu("Pair"); - pairMenu->addAction("Pair", this, SLOT(pair())); - - QMenu* optionsMenu = menuBar->addMenu("Options"); - (_lookingInMirror = optionsMenu->addAction("Mirror", this, SLOT(setRenderMirrored(bool)), Qt::Key_H))->setCheckable(true); - - - (_noise = optionsMenu->addAction("Noise", this, SLOT(setNoise(bool)), Qt::Key_N))->setCheckable(true); - (_gyroLook = optionsMenu->addAction("Smooth Gyro Look"))->setCheckable(true); - _gyroLook->setChecked(true); - (_showHeadMouse = optionsMenu->addAction("Head Mouse"))->setCheckable(true); - _showHeadMouse->setChecked(false); - (_transmitterDrives = optionsMenu->addAction("Transmitter Drive"))->setCheckable(true); - _transmitterDrives->setChecked(true); - (_gravityUse = optionsMenu->addAction("Use Gravity"))->setCheckable(true); - _gravityUse->setChecked(true); - _gravityUse->setShortcut(Qt::SHIFT | Qt::Key_G); - (_testPing = optionsMenu->addAction("Test Ping"))->setCheckable(true); - _testPing->setChecked(true); - (_fullScreenMode = optionsMenu->addAction("Fullscreen", this, SLOT(setFullscreen(bool)), Qt::Key_F))->setCheckable(true); - optionsMenu->addAction("Webcam", &_webcam, SLOT(setEnabled(bool)))->setCheckable(true); - optionsMenu->addAction("Skeleton Tracking", &_webcam, SLOT(setSkeletonTrackingOn(bool)))->setCheckable(true); - (_wantCollisionsOn = optionsMenu->addAction("Turn collisions On", this, SLOT(toggleWantCollisionsOn())))->setCheckable(true); - _wantCollisionsOn->setChecked(true); - optionsMenu->addAction("Cycle Webcam Send Mode", _webcam.getGrabber(), SLOT(cycleVideoSendMode())); - optionsMenu->addAction("Webcam Texture", _webcam.getGrabber(), SLOT(setDepthOnly(bool)))->setCheckable(true); - optionsMenu->addAction("Go Home", this, SLOT(goHome()), Qt::CTRL | Qt::Key_G); - - QMenu* audioMenu = menuBar->addMenu("Audio"); - (_echoAudioMode = audioMenu->addAction("Echo Audio"))->setCheckable(true); - _rawAudioMicrophoneMix = audioMenu->addAction("Mix RAW Song", this, SLOT(toggleMixedSong())); - - QMenu* renderMenu = menuBar->addMenu("Render"); - (_renderVoxels = renderMenu->addAction("Voxels", this, SLOT(setRenderVoxels(bool)), Qt::SHIFT | Qt::Key_V))->setCheckable(true); - _renderVoxels->setChecked(true); - (_renderVoxelTextures = renderMenu->addAction("Voxel Textures"))->setCheckable(true); - (_renderStarsOn = renderMenu->addAction("Stars"))->setCheckable(true); - _renderStarsOn->setChecked(true); - _renderStarsOn->setShortcut(Qt::Key_Asterisk); - (_renderAtmosphereOn = renderMenu->addAction("Atmosphere"))->setCheckable(true); - _renderAtmosphereOn->setChecked(true); - _renderAtmosphereOn->setShortcut(Qt::SHIFT | Qt::Key_A); - (_renderGroundPlaneOn = renderMenu->addAction("Ground Plane"))->setCheckable(true); - _renderGroundPlaneOn->setChecked(true); - (_renderAvatarsOn = renderMenu->addAction("Avatars"))->setCheckable(true); - _renderAvatarsOn->setChecked(true); - (_renderAvatarBalls = renderMenu->addAction("Avatar as Balls"))->setCheckable(true); - _renderAvatarBalls->setChecked(false); - renderMenu->addAction("Cycle Voxel Mode", _myAvatar.getVoxels(), SLOT(cycleMode())); - renderMenu->addAction("Cycle Face Mode", &_myAvatar.getHead().getFace(), SLOT(cycleRenderMode())); - renderMenu->addAction("Cycle Glow Mode", &_glowEffect, SLOT(cycleRenderMode())); - (_renderFrameTimerOn = renderMenu->addAction("Show Timer"))->setCheckable(true); - _renderFrameTimerOn->setChecked(false); - (_renderLookatOn = renderMenu->addAction("Lookat Vectors"))->setCheckable(true); - _renderLookatOn->setChecked(false); - (_renderLookatIndicatorOn = renderMenu->addAction("Lookat Indicator"))->setCheckable(true); - _renderLookatIndicatorOn->setChecked(true); - (_renderParticleSystemOn = renderMenu->addAction("Particle System"))->setCheckable(true); - (_manualFirstPerson = renderMenu->addAction( - "First Person", this, SLOT(setRenderFirstPerson(bool)), Qt::Key_P))->setCheckable(true); - (_manualThirdPerson = renderMenu->addAction( - "Third Person", this, SLOT(setRenderThirdPerson(bool))))->setCheckable(true); - renderMenu->addAction("Increase Avatar Size", this, SLOT(increaseAvatarSize()), Qt::Key_Plus); - renderMenu->addAction("Decrease Avatar Size", this, SLOT(decreaseAvatarSize()), Qt::Key_Minus); - renderMenu->addAction("Reset Avatar Size", this, SLOT(resetAvatarSize())); - - - QMenu* toolsMenu = menuBar->addMenu("Tools"); - (_renderStatsOn = toolsMenu->addAction("Stats"))->setCheckable(true); - _renderStatsOn->setShortcut(Qt::Key_Slash); - (_logOn = toolsMenu->addAction("Log"))->setCheckable(true); - _logOn->setChecked(false); - _logOn->setShortcut(Qt::CTRL | Qt::Key_L); - (_oscilloscopeOn = toolsMenu->addAction("Audio Oscilloscope"))->setCheckable(true); - _oscilloscopeOn->setChecked(true); - (_bandwidthDisplayOn = toolsMenu->addAction("Bandwidth Display"))->setCheckable(true); - _bandwidthDisplayOn->setChecked(true); - toolsMenu->addAction("Bandwidth Details", this, SLOT(bandwidthDetails())); - toolsMenu->addAction("Voxel Stats Details", this, SLOT(voxelStatsDetails())); - - - QMenu* voxelMenu = menuBar->addMenu("Voxels"); - _voxelModeActions = new QActionGroup(this); - _voxelModeActions->setExclusive(false); // exclusivity implies one is always checked - - (_addVoxelMode = voxelMenu->addAction( - "Add Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::Key_V))->setCheckable(true); - _voxelModeActions->addAction(_addVoxelMode); - (_deleteVoxelMode = voxelMenu->addAction( - "Delete Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::Key_R))->setCheckable(true); - _voxelModeActions->addAction(_deleteVoxelMode); - (_colorVoxelMode = voxelMenu->addAction( - "Color Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::Key_B))->setCheckable(true); - _voxelModeActions->addAction(_colorVoxelMode); - (_selectVoxelMode = voxelMenu->addAction( - "Select Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::Key_O))->setCheckable(true); - _voxelModeActions->addAction(_selectVoxelMode); - (_eyedropperMode = voxelMenu->addAction( - "Get Color Mode", this, SLOT(updateVoxelModeActions()), Qt::Key_G))->setCheckable(true); - _voxelModeActions->addAction(_eyedropperMode); - - voxelMenu->addAction("Decrease Voxel Size", this, SLOT(decreaseVoxelSize()), QKeySequence::ZoomOut); - voxelMenu->addAction("Increase Voxel Size", this, SLOT(increaseVoxelSize()), QKeySequence::ZoomIn); - voxelMenu->addAction("Reset Swatch Colors", this, SLOT(resetSwatchColors())); - - _voxelPaintColor = voxelMenu->addAction("Voxel Paint Color", this, - SLOT(chooseVoxelPaintColor()), Qt::META | Qt::Key_C); - _swatch.setAction(_voxelPaintColor); - - QColor paintColor(128, 128, 128); - _voxelPaintColor->setData(paintColor); - _voxelPaintColor->setIcon(createSwatchIcon(paintColor)); - (_destructiveAddVoxel = voxelMenu->addAction("Create Voxel is Destructive"))->setCheckable(true); - - voxelMenu->addAction("Export Voxels", this, SLOT(exportVoxels()), Qt::CTRL | Qt::Key_E); - voxelMenu->addAction("Import Voxels", this, SLOT(importVoxels()), Qt::CTRL | Qt::Key_I); - voxelMenu->addAction("Import Voxels to Clipboard", this, SLOT(importVoxelsToClipboard()), Qt::SHIFT | Qt::CTRL | Qt::Key_I); - voxelMenu->addAction("Cut Voxels", this, SLOT(cutVoxels()), Qt::CTRL | Qt::Key_X); - voxelMenu->addAction("Copy Voxels", this, SLOT(copyVoxels()), Qt::CTRL | Qt::Key_C); - voxelMenu->addAction("Paste Voxels", this, SLOT(pasteVoxels()), Qt::CTRL | Qt::Key_V); - - QMenu* debugMenu = menuBar->addMenu("Debug"); - - QMenu* frustumMenu = debugMenu->addMenu("View Frustum Debugging Tools"); - (_frustumOn = frustumMenu->addAction("Display Frustum"))->setCheckable(true); - _frustumOn->setShortcut(Qt::SHIFT | Qt::Key_F); - _frustumRenderModeAction = frustumMenu->addAction( - "Render Mode", this, SLOT(cycleFrustumRenderMode()), Qt::SHIFT | Qt::Key_R); - updateFrustumRenderModeAction(); - - debugMenu->addAction("Run Timing Tests", this, SLOT(runTests())); - debugMenu->addAction("Calculate Tree Stats", this, SLOT(doTreeStats()), Qt::SHIFT | Qt::Key_S); - - QMenu* renderDebugMenu = debugMenu->addMenu("Render Debugging Tools"); - (_renderPipelineWarnings = renderDebugMenu->addAction("Show Render Pipeline Warnings", - this, SLOT(setRenderWarnings(bool))))->setCheckable(true); - renderDebugMenu->addAction("Kill Local Voxels", this, SLOT(doKillLocalVoxels()), Qt::CTRL | Qt::Key_K); - renderDebugMenu->addAction("Randomize Voxel TRUE Colors", this, SLOT(doRandomizeVoxelColors()), Qt::CTRL | Qt::Key_R); - renderDebugMenu->addAction("FALSE Color Voxels Randomly", this, SLOT(doFalseRandomizeVoxelColors())); - renderDebugMenu->addAction("FALSE Color Voxel Every Other Randomly", this, SLOT(doFalseRandomizeEveryOtherVoxelColors())); - renderDebugMenu->addAction("FALSE Color Voxels by Distance", this, SLOT(doFalseColorizeByDistance())); - renderDebugMenu->addAction("FALSE Color Voxel Out of View", this, SLOT(doFalseColorizeInView())); - renderDebugMenu->addAction("FALSE Color Occluded Voxels", this, SLOT(doFalseColorizeOccluded()), Qt::CTRL | Qt::Key_O); - renderDebugMenu->addAction("FALSE Color Occluded V2 Voxels", this, SLOT(doFalseColorizeOccludedV2()), Qt::CTRL | Qt::Key_P); - renderDebugMenu->addAction("FALSE Color By Source", this, SLOT(doFalseColorizeBySource()), Qt::CTRL | Qt::SHIFT | Qt::Key_S); - renderDebugMenu->addAction("Show TRUE Colors", this, SLOT(doTrueVoxelColors()), Qt::CTRL | Qt::Key_T); - - (_shouldLowPassFilter = debugMenu->addAction("Test: LowPass filter"))->setCheckable(true); - - debugMenu->addAction("Wants Monochrome", this, SLOT(setWantsMonochrome(bool)))->setCheckable(true); - debugMenu->addAction("Disable Lower Resolution While Moving", this, SLOT(disableLowResMoving(bool)))->setCheckable(true); - debugMenu->addAction("Disable Delta Sending", this, SLOT(disableDeltaSending(bool)))->setCheckable(true); - (_occlusionCulling = debugMenu->addAction("Disable Occlusion Culling", this, SLOT(disableOcclusionCulling(bool)), - Qt::SHIFT | Qt::Key_C))->setCheckable(true); - - (_renderCoverageMap = debugMenu->addAction("Render Coverage Map"))->setCheckable(true); - _renderCoverageMap->setShortcut(Qt::SHIFT | Qt::CTRL | Qt::Key_O); - (_renderCoverageMapV2 = debugMenu->addAction("Render Coverage Map V2"))->setCheckable(true); - _renderCoverageMapV2->setShortcut(Qt::SHIFT | Qt::CTRL | Qt::Key_P); - - (_simulateLeapHand = debugMenu->addAction("Simulate Leap Hand"))->setCheckable(true); - (_testRaveGlove = debugMenu->addAction("Test RaveGlove"))->setCheckable(true); - - QMenu* audioDebugMenu = debugMenu->addMenu("Audio Debugging Tools"); - audioDebugMenu->addAction("Listen Mode Normal", this, SLOT(setListenModeNormal()), Qt::CTRL | Qt::Key_1); - audioDebugMenu->addAction("Listen Mode Point/Radius", this, SLOT(setListenModePoint()), Qt::CTRL | Qt::Key_2); - audioDebugMenu->addAction("Listen Mode Single Source", this, SLOT(setListenModeSingleSource()), Qt::CTRL | Qt::Key_3); - - QMenu* settingsMenu = menuBar->addMenu("Settings"); - (_settingsAutosave = settingsMenu->addAction("Autosave"))->setCheckable(true); - _settingsAutosave->setChecked(true); - settingsMenu->addAction("Load settings", this, SLOT(loadSettings())); - settingsMenu->addAction("Save settings", this, SLOT(saveSettings())); - settingsMenu->addAction("Import settings", this, SLOT(importSettings())); - settingsMenu->addAction("Export settings", this, SLOT(exportSettings())); - - _networkAccessManager = new QNetworkAccessManager(this); -} - void Application::setListenModeNormal() { _audio.setListenMode(AudioRingBuffer::NORMAL); } @@ -2049,63 +1436,6 @@ void Application::setListenModeSingleSource() { } } -void Application::toggleMixedSong() { - if (_audio.getSongFileBytes() == 0) { - QString filename = QFileDialog::getOpenFileName(_glWidget, - tr("Choose RAW Audio file"), - QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), - tr("RAW Audio file (*.raw)")); - - QByteArray filenameArray = filename.toLocal8Bit(); - _audio.importSongToMixWithMicrophone(filenameArray.data()); - resetSongMixMenuItem(); - } else { - _audio.stopMixingSongWithMicrophone(); - resetSongMixMenuItem(); - } -} - -void Application::toggleWantCollisionsOn() { - _myAvatar.setWantCollisionsOn(_wantCollisionsOn->isChecked()); -} - -void Application::resetSongMixMenuItem() { - if (_audio.getSongFileBytes() == 0) { - _rawAudioMicrophoneMix->setText("Mix RAW Song"); - } else { - _rawAudioMicrophoneMix->setText("Stop Mixing Song"); - } - -} - -void Application::updateFrustumRenderModeAction() { - switch (_frustumDrawingMode) { - default: - case FRUSTUM_DRAW_MODE_ALL: - _frustumRenderModeAction->setText("Render Mode - All"); - break; - case FRUSTUM_DRAW_MODE_VECTORS: - _frustumRenderModeAction->setText("Render Mode - Vectors"); - break; - case FRUSTUM_DRAW_MODE_PLANES: - _frustumRenderModeAction->setText("Render Mode - Planes"); - break; - case FRUSTUM_DRAW_MODE_NEAR_PLANE: - _frustumRenderModeAction->setText("Render Mode - Near"); - break; - case FRUSTUM_DRAW_MODE_FAR_PLANE: - _frustumRenderModeAction->setText("Render Mode - Far"); - break; - case FRUSTUM_DRAW_MODE_KEYHOLE: - _frustumRenderModeAction->setText("Render Mode - Keyhole"); - break; - } -} - -void Application::runTests() { - runTimingTests(); -} - void Application::initDisplay() { glEnable(GL_BLEND); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); @@ -2138,7 +1468,9 @@ void Application::init() { OculusManager::connect(); if (OculusManager::isConnected()) { - QMetaObject::invokeMethod(_fullScreenMode, "trigger", Qt::QueuedConnection); + QMetaObject::invokeMethod(Menu::getInstance()->getActionForOption(MenuOption::Fullscreen), + "trigger", + Qt::QueuedConnection); } LeapManager::initialize(); @@ -2146,22 +1478,22 @@ void Application::init() { gettimeofday(&_timerStart, NULL); gettimeofday(&_lastTimeUpdated, NULL); - loadSettings(); - if (!shouldDynamicallySetJitterBuffer()) { - _audio.setJitterBufferSamples(_audioJitterBufferSamples); + Menu::getInstance()->loadSettings(); + if (Menu::getInstance()->getAudioJitterBufferSamples() != 0) { + _audio.setJitterBufferSamples(Menu::getInstance()->getAudioJitterBufferSamples()); } qDebug("Loaded settings.\n"); - sendAvatarVoxelURLMessage(_myAvatar.getVoxels()->getVoxelURL()); + Avatar::sendAvatarVoxelURLMessage(_myAvatar.getVoxels()->getVoxelURL()); _palette.init(_glWidget->width(), _glWidget->height()); - _palette.addAction(_addVoxelMode, 0, 0); - _palette.addAction(_deleteVoxelMode, 0, 1); + _palette.addAction(Menu::getInstance()->getActionForOption(MenuOption::VoxelAddMode), 0, 0); + _palette.addAction(Menu::getInstance()->getActionForOption(MenuOption::VoxelDeleteMode), 0, 1); _palette.addTool(&_swatch); - _palette.addAction(_colorVoxelMode, 0, 2); - _palette.addAction(_eyedropperMode, 0, 3); - _palette.addAction(_selectVoxelMode, 0, 4); + _palette.addAction(Menu::getInstance()->getActionForOption(MenuOption::VoxelColorMode), 0, 2); + _palette.addAction(Menu::getInstance()->getActionForOption(MenuOption::VoxelGetColorMode), 0, 3); + _palette.addAction(Menu::getInstance()->getActionForOption(MenuOption::VoxelSelectMode), 0, 4); _pieMenu.init("./resources/images/hifi-interface-tools-v2-pie.svg", _glWidget->width(), @@ -2388,7 +1720,7 @@ void Application::update(float deltaTime) { } _mouseVoxel.s = 0.0f; - if (checkedVoxelModeAction() != 0 && + if (Menu::getInstance()->isVoxelModeActionChecked() && (fabs(_myAvatar.getVelocity().x) + fabs(_myAvatar.getVelocity().y) + fabs(_myAvatar.getVelocity().z)) / 3 < MAX_AVATAR_EDIT_VELOCITY) { @@ -2413,7 +1745,7 @@ void Application::update(float deltaTime) { _mouseVoxel.z = _mouseVoxelScale * floorf(pt.z / _mouseVoxelScale); _mouseVoxel.s = _mouseVoxelScale; } - if (_addVoxelMode->isChecked()) { + if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelAddMode)) { // use the face to determine the side on which to create a neighbor _mouseVoxel.x += faceVector.x * _mouseVoxel.s; _mouseVoxel.y += faceVector.y * _mouseVoxel.s; @@ -2423,7 +1755,8 @@ void Application::update(float deltaTime) { } else { _mouseVoxel.s = 0.0f; } - } else if (_addVoxelMode->isChecked() || _selectVoxelMode->isChecked()) { + } else if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelAddMode) + || Menu::getInstance()->isOptionChecked(MenuOption::VoxelSelectMode)) { // place the voxel a fixed distance away float worldMouseVoxelScale = _mouseVoxelScale * TREE_SCALE; glm::vec3 pt = mouseRayOrigin + mouseRayDirection * (2.0f + worldMouseVoxelScale * 0.5f); @@ -2433,16 +1766,16 @@ void Application::update(float deltaTime) { _mouseVoxel.s = _mouseVoxelScale; } - if (_deleteVoxelMode->isChecked()) { + if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelDeleteMode)) { // red indicates deletion _mouseVoxel.red = 255; _mouseVoxel.green = _mouseVoxel.blue = 0; - } else if (_selectVoxelMode->isChecked()) { + } else if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelSelectMode)) { // yellow indicates deletion _mouseVoxel.red = _mouseVoxel.green = 255; _mouseVoxel.blue = 0; } else { // _addVoxelMode->isChecked() || _colorVoxelMode->isChecked() - QColor paintColor = _voxelPaintColor->data().value(); + QColor paintColor = Menu::getInstance()->getActionForOption(MenuOption::VoxelPaintColor)->data().value(); _mouseVoxel.red = paintColor.red(); _mouseVoxel.green = paintColor.green(); _mouseVoxel.blue = paintColor.blue(); @@ -2472,8 +1805,8 @@ void Application::update(float deltaTime) { } // Leap finger-sensing device - LeapManager::enableFakeFingers(_simulateLeapHand->isChecked()); - _myAvatar.getHand().setRaveGloveActive(_testRaveGlove->isChecked()); + LeapManager::enableFakeFingers(Menu::getInstance()->isOptionChecked(MenuOption::SimulateLeapHand)); + _myAvatar.getHand().setRaveGloveActive(Menu::getInstance()->isOptionChecked(MenuOption::TestRaveGlove)); LeapManager::nextFrame(_myAvatar); // Read serial port interface devices @@ -2513,60 +1846,47 @@ void Application::update(float deltaTime) { } // Simulate myself - if (_gravityUse->isChecked()) { + if (Menu::getInstance()->isOptionChecked(MenuOption::Gravity)) { _myAvatar.setGravity(_environment.getGravity(_myAvatar.getPosition())); } else { _myAvatar.setGravity(glm::vec3(0.0f, 0.0f, 0.0f)); } - if (_transmitterDrives->isChecked() && _myTransmitter.isConnected()) { - _myAvatar.simulate(deltaTime, &_myTransmitter, _gyroCameraSensitivity); + if (Menu::getInstance()->isOptionChecked(MenuOption::TransmitterDrive) && _myTransmitter.isConnected()) { + _myAvatar.simulate(deltaTime, &_myTransmitter, Menu::getInstance()->getGyroCameraSensitivity()); } else { - _myAvatar.simulate(deltaTime, NULL, _gyroCameraSensitivity); + _myAvatar.simulate(deltaTime, NULL, Menu::getInstance()->getGyroCameraSensitivity()); } if (!OculusManager::isConnected()) { - if (_lookingInMirror->isChecked()) { + if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { if (_myCamera.getMode() != CAMERA_MODE_MIRROR) { _myCamera.setMode(CAMERA_MODE_MIRROR); _myCamera.setModeShiftRate(100.0f); } - } else if (_manualFirstPerson->isChecked()) { + } else if (Menu::getInstance()->isOptionChecked(MenuOption::FirstPerson)) { if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON) { _myCamera.setMode(CAMERA_MODE_FIRST_PERSON); _myCamera.setModeShiftRate(1.0f); } - } else if (_manualThirdPerson->isChecked()) { + } else { if (_myCamera.getMode() != CAMERA_MODE_THIRD_PERSON) { _myCamera.setMode(CAMERA_MODE_THIRD_PERSON); _myCamera.setModeShiftRate(1.0f); } - } else { - const float THIRD_PERSON_SHIFT_VELOCITY = 1000.0f; - const float TIME_BEFORE_SHIFT_INTO_FIRST_PERSON = 0.75f; - const float TIME_BEFORE_SHIFT_INTO_THIRD_PERSON = 0.1f; - - if ((_myAvatar.getElapsedTimeStopped() > TIME_BEFORE_SHIFT_INTO_FIRST_PERSON) - && (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON)) { - _myCamera.setMode(CAMERA_MODE_FIRST_PERSON); - _myCamera.setModeShiftRate(1.0f); - } - if ((_myAvatar.getSpeed() > THIRD_PERSON_SHIFT_VELOCITY) - && (_myAvatar.getElapsedTimeMoving() > TIME_BEFORE_SHIFT_INTO_THIRD_PERSON) - && (_myCamera.getMode() != CAMERA_MODE_THIRD_PERSON)) { - _myCamera.setMode(CAMERA_MODE_THIRD_PERSON); - _myCamera.setModeShiftRate(1000.0f); - } } } // Update bandwidth dialog, if any - if (_bandwidthDialog) { - _bandwidthDialog->update(); + BandwidthDialog* bandwidthDialog = Menu::getInstance()->getBandwidthDialog(); + if (bandwidthDialog) { + bandwidthDialog->update(); } - if (_voxelStatsDialog) { - _voxelStatsDialog->update(); + + VoxelStatsDialog* voxelStatsDialog = Menu::getInstance()->getVoxelStatsDialog(); + if (voxelStatsDialog) { + voxelStatsDialog->update(); } // Update audio stats for procedural sounds @@ -2575,10 +1895,6 @@ void Application::update(float deltaTime) { _audio.setLastVelocity(_myAvatar.getVelocity()); _audio.eventuallyAnalyzePing(); #endif - - if (_renderParticleSystemOn->isChecked()) { - updateParticleSystem(deltaTime); - } } void Application::updateAvatar(float deltaTime) { @@ -2589,7 +1905,7 @@ void Application::updateAvatar(float deltaTime) { _yawFromTouch = 0.f; // Update my avatar's state from gyros and/or webcam - _myAvatar.updateFromGyrosAndOrWebcam(_gyroLook->isChecked(), + _myAvatar.updateFromGyrosAndOrWebcam(Menu::getInstance()->isOptionChecked(MenuOption::GyroLook), _pitchFromTouch); if (_serialHeadSensor.isActive()) { @@ -2613,17 +1929,20 @@ void Application::updateAvatar(float deltaTime) { _headMouseY = min(_headMouseY, _glWidget->height()); const float MIDPOINT_OF_SCREEN = 0.5; - - // Set lookAtPosition if an avatar is at the center of the screen - glm::vec3 screenCenterRayOrigin, screenCenterRayDirection; - _viewFrustum.computePickRay(MIDPOINT_OF_SCREEN, MIDPOINT_OF_SCREEN, screenCenterRayOrigin, screenCenterRayDirection); - - glm::vec3 eyePosition; - _isLookingAtOtherAvatar = isLookingAtOtherAvatar(screenCenterRayOrigin, screenCenterRayDirection, eyePosition); - if (_isLookingAtOtherAvatar) { - glm::vec3 myLookAtFromMouse(eyePosition); - _myAvatar.getHead().setLookAtPosition(myLookAtFromMouse); + // Only use gyro to set lookAt if mouse hasn't selected an avatar + if (!_isLookingAtOtherAvatar) { + + // Set lookAtPosition if an avatar is at the center of the screen + glm::vec3 screenCenterRayOrigin, screenCenterRayDirection; + _viewFrustum.computePickRay(MIDPOINT_OF_SCREEN, MIDPOINT_OF_SCREEN, screenCenterRayOrigin, screenCenterRayDirection); + + glm::vec3 eyePosition; + _isLookingAtOtherAvatar = isLookingAtOtherAvatar(screenCenterRayOrigin, screenCenterRayDirection, eyePosition); + if (_isLookingAtOtherAvatar) { + glm::vec3 myLookAtFromMouse(eyePosition); + _myAvatar.getHead().setLookAtPosition(myLookAtFromMouse); + } } } @@ -2675,7 +1994,7 @@ void Application::updateAvatar(float deltaTime) { // once in a while, send my voxel url const float AVATAR_VOXEL_URL_SEND_INTERVAL = 1.0f; // seconds if (shouldDo(AVATAR_VOXEL_URL_SEND_INTERVAL, deltaTime)) { - sendAvatarVoxelURLMessage(_myAvatar.getVoxels()->getVoxelURL()); + Avatar::sendAvatarVoxelURLMessage(_myAvatar.getVoxels()->getVoxelURL()); } } } @@ -2885,7 +2204,7 @@ void Application::displaySide(Camera& whichCamera) { // transform by eye offset // flip x if in mirror mode (also requires reversing winding order for backface culling) - if (_lookingInMirror->isChecked()) { + if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { glScalef(-1.0f, 1.0f, 1.0f); glFrontFace(GL_CW); @@ -2915,7 +2234,7 @@ void Application::displaySide(Camera& whichCamera) { // prepare the glow effect _glowEffect.prepare(); - if (_renderStarsOn->isChecked()) { + if (Menu::getInstance()->isOptionChecked(MenuOption::Stars)) { if (!_stars.getFileLoaded()) { _stars.readInput(STAR_FILE, STAR_CACHE_FILE, 0); } @@ -2923,7 +2242,7 @@ void Application::displaySide(Camera& whichCamera) { // compute starfield alpha based on distance from atmosphere float alpha = 1.0f; - if (_renderAtmosphereOn->isChecked()) { + if (Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) { const EnvironmentData& closestData = _environment.getClosestData(whichCamera.getPosition()); float height = glm::distance(whichCamera.getPosition(), closestData.getAtmosphereCenter()); if (height < closestData.getAtmosphereInnerRadius()) { @@ -2940,7 +2259,7 @@ void Application::displaySide(Camera& whichCamera) { } // draw the sky dome - if (_renderAtmosphereOn->isChecked()) { + if (Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) { _environment.renderAtmospheres(whichCamera); } @@ -2962,7 +2281,7 @@ void Application::displaySide(Camera& whichCamera) { glMaterialfv(GL_FRONT, GL_SPECULAR, NO_SPECULAR_COLOR); //draw a grid ground plane.... - if (_renderGroundPlaneOn->isChecked()) { + if (Menu::getInstance()->isOptionChecked(MenuOption::GroundPlane)) { // draw grass plane with fog glEnable(GL_FOG); glEnable(GL_NORMALIZE); @@ -2985,8 +2304,8 @@ void Application::displaySide(Camera& whichCamera) { //renderGroundPlaneGrid(EDGE_SIZE_GROUND_PLANE, _audio.getCollisionSoundMagnitude()); } // Draw voxels - if (_renderVoxels->isChecked()) { - _voxels.render(_renderVoxelTextures->isChecked()); + if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) { + _voxels.render(Menu::getInstance()->isOptionChecked(MenuOption::VoxelTextures)); } // restore default, white specular @@ -2998,7 +2317,7 @@ void Application::displaySide(Camera& whichCamera) { glPushMatrix(); glScalef(TREE_SCALE, TREE_SCALE, TREE_SCALE); renderMouseVoxelGrid(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); - if (_addVoxelMode->isChecked()) { + if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelAddMode)) { // use a contrasting color so that we can see what we're doing glColor3ub(_mouseVoxel.red + 128, _mouseVoxel.green + 128, _mouseVoxel.blue + 128); } else { @@ -3016,7 +2335,7 @@ void Application::displaySide(Camera& whichCamera) { _myAvatar.renderScreenTint(SCREEN_TINT_BEFORE_AVATARS, whichCamera); - if (_renderAvatarsOn->isChecked()) { + if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) { // Render avatars of other nodes NodeList* nodeList = NodeList::getInstance(); @@ -3028,11 +2347,12 @@ void Application::displaySide(Camera& whichCamera) { if (!avatar->isInitialized()) { avatar->init(); } + // Set lookAt to myCamera on client side if other avatars are looking at client if (isLookingAtMyAvatar(avatar)) { avatar->getHead().setLookAtPosition(_myCamera.getPosition()); } - avatar->render(false, _renderAvatarBalls->isChecked()); - avatar->setDisplayingLookatVectors(_renderLookatOn->isChecked()); + avatar->render(false, Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls)); + avatar->setDisplayingLookatVectors(Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors)); } node->unlock(); @@ -3042,30 +2362,28 @@ void Application::displaySide(Camera& whichCamera) { if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { _myAvatar.getHead().setLookAtPosition(_myCamera.getPosition()); } - _myAvatar.render(_lookingInMirror->isChecked(), _renderAvatarBalls->isChecked()); - - _myAvatar.setDisplayingLookatVectors(_renderLookatOn->isChecked()); + _myAvatar.render(Menu::getInstance()->isOptionChecked(MenuOption::Mirror), + Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls)); + _myAvatar.setDisplayingLookatVectors(Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors)); - if (_renderLookatIndicatorOn->isChecked() && _isLookingAtOtherAvatar) { + if (Menu::getInstance()->isOptionChecked(MenuOption::LookAtIndicator) && _isLookingAtOtherAvatar) { renderLookatIndicator(_lookatOtherPosition, whichCamera); } } _myAvatar.renderScreenTint(SCREEN_TINT_AFTER_AVATARS, whichCamera); - if (_renderParticleSystemOn->isChecked()) { - if (_particleSystemInitialized) { - _particleSystem.render(); - } - } - // Render the world box - if (!_lookingInMirror->isChecked() && _renderStatsOn->isChecked()) { renderWorldBox(); } + if (!Menu::getInstance()->isOptionChecked(MenuOption::Mirror) && Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { + renderWorldBox(); + } _ambientOcclusionEffect.render(); // brad's frustum for debugging - if (_frustumOn->isChecked()) renderViewFrustum(_viewFrustum); + if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayFrustum)) { + renderViewFrustum(_viewFrustum); + } // render voxel fades if they exist if (_voxelFades.size() > 0) { @@ -3103,14 +2421,16 @@ void Application::displayOverlay() { #ifndef _WIN32 _audio.render(_glWidget->width(), _glWidget->height()); - if (_oscilloscopeOn->isChecked()) { + if (Menu::getInstance()->isOptionChecked(MenuOption::Oscilloscope)) { _audioScope.render(20, _glWidget->height() - 200); } #endif //noiseTest(_glWidget->width(), _glWidget->height()); - if (_showHeadMouse->isChecked() && !_lookingInMirror->isChecked() && USING_INVENSENSE_MPU9150) { + if (Menu::getInstance()->isOptionChecked(MenuOption::HeadMouse) + && !Menu::getInstance()->isOptionChecked(MenuOption::Mirror) + && USING_INVENSENSE_MPU9150) { // Display small target box at center or head mouse target that can also be used to measure LOD glColor3f(1.0, 1.0, 1.0); glDisable(GL_LINE_SMOOTH); @@ -3136,14 +2456,26 @@ void Application::displayOverlay() { glLineWidth(1.0f); glPointSize(1.0f); - if (_renderStatsOn->isChecked()) { displayStats(); } + if (Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { + displayStats(); + } // testing rendering coverage map - if (_renderCoverageMapV2->isChecked()) { renderCoverageMapV2(); } - if (_renderCoverageMap->isChecked()) { renderCoverageMap(); } - if (_bandwidthDisplayOn->isChecked()) { _bandwidthMeter.render(_glWidget->width(), _glWidget->height()); } + if (Menu::getInstance()->isOptionChecked(MenuOption::CoverageMapV2)) { + renderCoverageMapV2(); + } + + if (Menu::getInstance()->isOptionChecked(MenuOption::CoverageMap)) { + renderCoverageMap(); + } + + if (Menu::getInstance()->isOptionChecked(MenuOption::Bandwidth)) { + _bandwidthMeter.render(_glWidget->width(), _glWidget->height()); + } - if (_logOn->isChecked()) { LogDisplay::instance.render(_glWidget->width(), _glWidget->height()); } + if (Menu::getInstance()->isOptionChecked(MenuOption::Log)) { + LogDisplay::instance.render(_glWidget->width(), _glWidget->height()); + } // Show chat entry field if (_chatEntryOn) { @@ -3151,7 +2483,7 @@ void Application::displayOverlay() { } // Show on-screen msec timer - if (_renderFrameTimerOn->isChecked()) { + if (Menu::getInstance()->isOptionChecked(MenuOption::FrameTimer)) { char frameTimer[10]; uint64_t mSecsNow = floor(usecTimestampNow() / 1000.0 + 0.5); sprintf(frameTimer, "%d\n", (int)(mSecsNow % 1000)); @@ -3159,7 +2491,6 @@ void Application::displayOverlay() { drawtext(_glWidget->width() - 102, _glWidget->height() - 22, 0.30, 0, 1.0, 0, frameTimer, 1, 1, 1); } - // Stats at upper right of screen about who domain server is telling us about glPointSize(1.0f); char nodes[100]; @@ -3179,8 +2510,11 @@ void Application::displayOverlay() { _palette.render(_glWidget->width(), _glWidget->height()); - if (_eyedropperMode->isChecked() && _voxelPaintColor->data().value() != _swatch.getColor()) { - QColor color = _voxelPaintColor->data().value(); + QAction* paintColorAction = NULL; + if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelGetColorMode) + && (paintColorAction = Menu::getInstance()->getActionForOption(MenuOption::VoxelPaintColor))->data().value() + != _swatch.getColor()) { + QColor color = paintColorAction->data().value(); TextRenderer textRenderer(SANS_FONT_FAMILY, 11, 50); const char line1[] = "Assign this color to a swatch"; const char line2[] = "by choosing a key from 1 to 8."; @@ -3237,7 +2571,7 @@ void Application::displayStats() { _fps, _packetsPerSecond, (float)_bytesPerSecond * 8.f / 1000000.f); drawtext(10, statsVerticalOffset + 15, 0.10f, 0, 1.0, 0, stats); - if (_testPing->isChecked()) { + if (Menu::getInstance()->isOptionChecked(MenuOption::TestPing)) { int pingAudio = 0, pingAvatar = 0, pingVoxel = 0, pingVoxelMax = 0; NodeList* nodeList = NodeList::getInstance(); @@ -3531,7 +2865,8 @@ void Application::renderViewFrustum(ViewFrustum& viewFrustum) { glLineWidth(1.0); glBegin(GL_LINES); - if (_frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || _frustumDrawingMode == FRUSTUM_DRAW_MODE_VECTORS) { + if (Menu::getInstance()->getFrustumDrawMode() == FRUSTUM_DRAW_MODE_ALL + || Menu::getInstance()->getFrustumDrawMode() == FRUSTUM_DRAW_MODE_VECTORS) { // Calculate the origin direction vectors glm::vec3 lookingAt = position + (direction * 0.2f); glm::vec3 lookingAtUp = position + (up * 0.2f); @@ -3553,8 +2888,9 @@ void Application::renderViewFrustum(ViewFrustum& viewFrustum) { glVertex3f(lookingAtRight.x, lookingAtRight.y, lookingAtRight.z); } - if (_frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || _frustumDrawingMode == FRUSTUM_DRAW_MODE_PLANES - || _frustumDrawingMode == FRUSTUM_DRAW_MODE_NEAR_PLANE) { + if (Menu::getInstance()->getFrustumDrawMode() == FRUSTUM_DRAW_MODE_ALL + || Menu::getInstance()->getFrustumDrawMode() == FRUSTUM_DRAW_MODE_PLANES + || Menu::getInstance()->getFrustumDrawMode() == FRUSTUM_DRAW_MODE_NEAR_PLANE) { // Drawing the bounds of the frustum // viewFrustum.getNear plane - bottom edge glColor3f(1,0,0); @@ -3574,8 +2910,9 @@ void Application::renderViewFrustum(ViewFrustum& viewFrustum) { glVertex3f(viewFrustum.getNearTopLeft().x, viewFrustum.getNearTopLeft().y, viewFrustum.getNearTopLeft().z); } - if (_frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || _frustumDrawingMode == FRUSTUM_DRAW_MODE_PLANES - || _frustumDrawingMode == FRUSTUM_DRAW_MODE_FAR_PLANE) { + if (Menu::getInstance()->getFrustumDrawMode() == FRUSTUM_DRAW_MODE_ALL + || Menu::getInstance()->getFrustumDrawMode() == FRUSTUM_DRAW_MODE_PLANES + || Menu::getInstance()->getFrustumDrawMode() == FRUSTUM_DRAW_MODE_FAR_PLANE) { // viewFrustum.getFar plane - bottom edge glColor3f(0,1,0); // GREEN!!! glVertex3f(viewFrustum.getFarBottomLeft().x, viewFrustum.getFarBottomLeft().y, viewFrustum.getFarBottomLeft().z); @@ -3594,7 +2931,8 @@ void Application::renderViewFrustum(ViewFrustum& viewFrustum) { glVertex3f(viewFrustum.getFarTopLeft().x, viewFrustum.getFarTopLeft().y, viewFrustum.getFarTopLeft().z); } - if (_frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || _frustumDrawingMode == FRUSTUM_DRAW_MODE_PLANES) { + if (Menu::getInstance()->getFrustumDrawMode() == FRUSTUM_DRAW_MODE_ALL + || Menu::getInstance()->getFrustumDrawMode() == FRUSTUM_DRAW_MODE_PLANES) { // RIGHT PLANE IS CYAN // right plane - bottom edge - viewFrustum.getNear to distant glColor3f(0,1,1); @@ -3618,7 +2956,8 @@ void Application::renderViewFrustum(ViewFrustum& viewFrustum) { glEnd(); glEnable(GL_LIGHTING); - if (_frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || _frustumDrawingMode == FRUSTUM_DRAW_MODE_KEYHOLE) { + if (Menu::getInstance()->getFrustumDrawMode() == FRUSTUM_DRAW_MODE_ALL + || Menu::getInstance()->getFrustumDrawMode() == FRUSTUM_DRAW_MODE_KEYHOLE) { // Draw the keyhole float keyholeRadius = viewFrustum.getKeyholeRadius(); if (keyholeRadius > 0.0f) { @@ -3688,15 +3027,18 @@ void Application::injectVoxelAddedSoundEffect() { } bool Application::maybeEditVoxelUnderCursor() { - if (_addVoxelMode->isChecked() || _colorVoxelMode->isChecked()) { + if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelAddMode) + || Menu::getInstance()->isOptionChecked(MenuOption::VoxelColorMode)) { if (_mouseVoxel.s != 0) { - PACKET_TYPE message = (_destructiveAddVoxel->isChecked() ? - PACKET_TYPE_SET_VOXEL_DESTRUCTIVE : PACKET_TYPE_SET_VOXEL); + PACKET_TYPE message = Menu::getInstance()->isOptionChecked(MenuOption::DestructiveAddVoxel) + ? PACKET_TYPE_SET_VOXEL_DESTRUCTIVE + : PACKET_TYPE_SET_VOXEL; _voxelEditSender.sendVoxelEditMessage(message, _mouseVoxel); // create the voxel locally so it appears immediately _voxels.createVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s, - _mouseVoxel.red, _mouseVoxel.green, _mouseVoxel.blue, _destructiveAddVoxel->isChecked()); + _mouseVoxel.red, _mouseVoxel.green, _mouseVoxel.blue, + Menu::getInstance()->isOptionChecked(MenuOption::DestructiveAddVoxel)); // Implement voxel fade effect VoxelFade fade(VoxelFade::FADE_OUT, 1.0f, 1.0f, 1.0f); @@ -3715,7 +3057,7 @@ bool Application::maybeEditVoxelUnderCursor() { _justEditedVoxel = true; } - } else if (_deleteVoxelMode->isChecked()) { + } else if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelDeleteMode)) { deleteVoxelUnderCursor(); VoxelFade fade(VoxelFade::FADE_OUT, 1.0f, 1.0f, 1.0f); const float VOXEL_BOUNDS_ADJUST = 0.01f; @@ -3726,7 +3068,7 @@ bool Application::maybeEditVoxelUnderCursor() { fade.voxelDetails.s = _mouseVoxel.s + slightlyBigger + slightlyBigger; _voxelFades.push_back(fade); - } else if (_eyedropperMode->isChecked()) { + } else if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelGetColorMode)) { eyedropperVoxelUnderCursor(); } else { return false; @@ -3767,18 +3109,13 @@ void Application::eyedropperVoxelUnderCursor() { selectedNode->getColor()[BLUE_INDEX]); if (selectedColor.isValid()) { - _voxelPaintColor->setData(selectedColor); - _voxelPaintColor->setIcon(createSwatchIcon(selectedColor)); + QAction* voxelPaintColorAction = Menu::getInstance()->getActionForOption(MenuOption::VoxelPaintColor); + voxelPaintColorAction->setData(selectedColor); + voxelPaintColorAction->setIcon(Swatch::createIcon(selectedColor)); } } } -void Application::goHome() { - qDebug("Going Home!\n"); - _myAvatar.setPosition(START_LOCATION); -} - - void Application::toggleFollowMode() { glm::vec3 mouseRayOrigin, mouseRayDirection; _viewFrustum.computePickRay(_pieMenu.getX() / (float)_glWidget->width(), @@ -3833,17 +3170,6 @@ void Application::updateCursor() { Qt::BlankCursor : Qt::ArrowCursor); } -// when QActionGroup is set to non-exclusive, it doesn't return anything as checked; -// hence, we must check ourselves -QAction* Application::checkedVoxelModeAction() const { - foreach (QAction* action, _voxelModeActions->actions()) { - if (action->isChecked()) { - return action; - } - } - return 0; -} - void Application::attachNewHeadToNode(Node* newNode) { if (newNode->getLinkedData() == NULL) { newNode->setLinkedData(new Avatar(newNode)); @@ -3974,190 +3300,3 @@ void* Application::networkReceive(void* args) { } return NULL; } - -void Application::scanMenuBar(settingsAction modifySetting, QSettings* set) { - if (!_window->menuBar()) { - return; - } - - QList menus = _window->menuBar()->findChildren(); - - for (QList::const_iterator it = menus.begin(); menus.end() != it; ++it) { - scanMenu(*it, modifySetting, set); - } -} - -void Application::scanMenu(QMenu* menu, settingsAction modifySetting, QSettings* set) { - QList actions = menu->actions(); - - set->beginGroup(menu->title()); - for (QList::const_iterator it = actions.begin(); actions.end() != it; ++it) { - if ((*it)->menu()) { - scanMenu((*it)->menu(), modifySetting, set); - } - if ((*it)->isCheckable()) { - modifySetting(set, *it); - } - } - set->endGroup(); -} - -void Application::loadAction(QSettings* set, QAction* action) { - if (action->isChecked() != set->value(action->text(), action->isChecked()).toBool()) { - action->trigger(); - } -} - -void Application::saveAction(QSettings* set, QAction* action) { - set->setValue(action->text(), action->isChecked()); -} - -void Application::loadSettings(QSettings* settings) { - if (!settings) { - settings = getSettings(); - } - - _gyroCameraSensitivity = loadSetting(settings, "gyroCameraSensitivity", 0.5f); - _audioJitterBufferSamples = loadSetting(settings, "audioJitterBufferSamples", 0); - _fieldOfView = loadSetting(settings, "fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES); - - settings->beginGroup("View Frustum Offset Camera"); - // in case settings is corrupt or missing loadSetting() will check for NaN - _viewFrustumOffsetYaw = loadSetting(settings, "viewFrustumOffsetYaw" , 0.0f); - _viewFrustumOffsetPitch = loadSetting(settings, "viewFrustumOffsetPitch" , 0.0f); - _viewFrustumOffsetRoll = loadSetting(settings, "viewFrustumOffsetRoll" , 0.0f); - _viewFrustumOffsetDistance = loadSetting(settings, "viewFrustumOffsetDistance", 0.0f); - _viewFrustumOffsetUp = loadSetting(settings, "viewFrustumOffsetUp" , 0.0f); - settings->endGroup(); - - scanMenuBar(&Application::loadAction, settings); - getAvatar()->loadData(settings); - _swatch.loadData(settings); -} - - -void Application::saveSettings(QSettings* settings) { - if (!settings) { - settings = getSettings(); - } - - settings->setValue("gyroCameraSensitivity", _gyroCameraSensitivity); - settings->setValue("audioJitterBufferSamples", _audioJitterBufferSamples); - settings->setValue("fieldOfView", _fieldOfView); - settings->beginGroup("View Frustum Offset Camera"); - settings->setValue("viewFrustumOffsetYaw", _viewFrustumOffsetYaw); - settings->setValue("viewFrustumOffsetPitch", _viewFrustumOffsetPitch); - settings->setValue("viewFrustumOffsetRoll", _viewFrustumOffsetRoll); - settings->setValue("viewFrustumOffsetDistance", _viewFrustumOffsetDistance); - settings->setValue("viewFrustumOffsetUp", _viewFrustumOffsetUp); - settings->endGroup(); - - scanMenuBar(&Application::saveAction, settings); - getAvatar()->saveData(settings); - _swatch.saveData(settings); - - // ask the NodeList to save its data - NodeList::getInstance()->saveData(settings); -} - -void Application::importSettings() { - QString locationDir(QStandardPaths::displayName(QStandardPaths::DesktopLocation)); - QString fileName = QFileDialog::getOpenFileName(_window, - tr("Open .ini config file"), - locationDir, - tr("Text files (*.ini)")); - if (fileName != "") { - QSettings tmp(fileName, QSettings::IniFormat); - loadSettings(&tmp); - } -} - -void Application::exportSettings() { - QString locationDir(QStandardPaths::displayName(QStandardPaths::DesktopLocation)); - QString fileName = QFileDialog::getSaveFileName(_window, - tr("Save .ini config file"), - locationDir, - tr("Text files (*.ini)")); - if (fileName != "") { - QSettings tmp(fileName, QSettings::IniFormat); - saveSettings(&tmp); - tmp.sync(); - } -} - - -void Application::updateParticleSystem(float deltaTime) { - - if (!_particleSystemInitialized) { - - const int LIFESPAN_IN_SECONDS = 100000.0f; - const float EMIT_RATE_IN_SECONDS = 10000.0; - // create a stable test emitter and spit out a bunch of particles - _coolDemoParticleEmitter = _particleSystem.addEmitter(); - - if (_coolDemoParticleEmitter != -1) { - - _particleSystem.setShowingEmitter(_coolDemoParticleEmitter, true); - glm::vec3 particleEmitterPosition = glm::vec3(5.0f, 1.0f, 5.0f); - - _particleSystem.setEmitterPosition (_coolDemoParticleEmitter, particleEmitterPosition); - _particleSystem.setEmitterParticleLifespan(_coolDemoParticleEmitter, LIFESPAN_IN_SECONDS); - _particleSystem.setEmitterThrust (_coolDemoParticleEmitter, 0.0f); - _particleSystem.setEmitterRate (_coolDemoParticleEmitter, EMIT_RATE_IN_SECONDS); // to emit a pile o particles now - } - - // signal that the particle system has been initialized - _particleSystemInitialized = true; - } else { - // update the particle system - - static bool emitting = true; - static float effectsTimer = 0.0f; - effectsTimer += deltaTime; - - if (_coolDemoParticleEmitter != -1) { - - _particleSystem.setEmitterDirection(_coolDemoParticleEmitter, glm::vec3(0.0f, 1.0f, 0.0f)); - - ParticleSystem::ParticleAttributes attributes; - - attributes.radius = 0.01f; - attributes.color = glm::vec4( 1.0f, 1.0f, 1.0f, 1.0f); - attributes.gravity = 0.0f + 0.05f * sinf( effectsTimer * 0.52f ); - attributes.airFriction = 2.5 + 2.0f * sinf( effectsTimer * 0.32f ); - attributes.jitter = 0.05f + 0.05f * sinf( effectsTimer * 0.42f ); - attributes.emitterAttraction = 0.015f + 0.015f * cosf( effectsTimer * 0.6f ); - attributes.tornadoForce = 0.0f + 0.03f * sinf( effectsTimer * 0.7f ); - attributes.neighborAttraction = 0.1f + 0.1f * cosf( effectsTimer * 0.8f ); - attributes.neighborRepulsion = 0.2f + 0.2f * sinf( effectsTimer * 0.4f ); - attributes.bounce = 1.0f; - attributes.usingCollisionSphere = true; - attributes.collisionSpherePosition = glm::vec3( 5.0f, 0.5f, 5.0f ); - attributes.collisionSphereRadius = 0.5f; - attributes.usingCollisionPlane = true; - attributes.collisionPlanePosition = glm::vec3( 5.0f, 0.0f, 5.0f ); - attributes.collisionPlaneNormal = glm::vec3( 0.0f, 1.0f, 0.0f ); - - if (attributes.gravity < 0.0f) { - attributes.gravity = 0.0f; - } - - _particleSystem.setParticleAttributes(_coolDemoParticleEmitter, attributes); - } - - _particleSystem.setUpDirection(glm::vec3(0.0f, 1.0f, 0.0f)); - _particleSystem.simulate(deltaTime); - - const float EMIT_RATE_IN_SECONDS = 0.0; - - if (_coolDemoParticleEmitter != -1) { - if (emitting) { - _particleSystem.setEmitterRate(_coolDemoParticleEmitter, EMIT_RATE_IN_SECONDS); // stop emitter - emitting = false; - } - } - } -} - - - diff --git a/interface/src/Application.h b/interface/src/Application.h index d298790327..51606ce75a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -30,8 +30,8 @@ #include "BandwidthMeter.h" #include "Camera.h" #include "Environment.h" +#include "GLCanvas.h" #include "PacketHeaders.h" -#include "ParticleSystem.h" #include "PieMenu.h" #include "SerialInterface.h" #include "Stars.h" @@ -112,101 +112,56 @@ public: Camera* getCamera() { return &_myCamera; } ViewFrustum* getViewFrustum() { return &_viewFrustum; } VoxelSystem* getVoxels() { return &_voxels; } - QSettings* getSettings() { return _settings; } Environment* getEnvironment() { return &_environment; } SerialInterface* getSerialHeadSensor() { return &_serialHeadSensor; } Webcam* getWebcam() { return &_webcam; } BandwidthMeter* getBandwidthMeter() { return &_bandwidthMeter; } - bool shouldEchoAudio() { return _echoAudioMode->isChecked(); } - bool shouldLowPassFilter() { return _shouldLowPassFilter->isChecked(); } - - bool shouldDynamicallySetJitterBuffer() { return _audioJitterBufferSamples == 0; } + QSettings* getSettings() { return _settings; } + Swatch* getSwatch() { return &_swatch; } + QMainWindow* getWindow() { return _window; } + VoxelSceneStats* getVoxelSceneStats() { return &_voxelSceneStats; } QNetworkAccessManager* getNetworkAccessManager() { return _networkAccessManager; } GeometryCache* getGeometryCache() { return &_geometryCache; } TextureCache* getTextureCache() { return &_textureCache; } GlowEffect* getGlowEffect() { return &_glowEffect; } - void resetSongMixMenuItem(); + static void controlledBroadcastToNodes(unsigned char* broadcastData, size_t dataBytes, + const char* nodeTypes, int numNodeTypes); + void setupWorldLight(Camera& whichCamera); virtual void nodeAdded(Node* node); virtual void nodeKilled(Node* node); public slots: - void sendAvatarFaceVideoMessage(int frameCount, const QByteArray& data); - -private slots: - - void timer(); - void idle(); - void terminate(); - - void bandwidthDetails(); - void editPreferences(); - void bandwidthDetailsClosed(); - - void voxelStatsDetails(); - void voxelStatsDetailsClosed(); - - void pair(); - - void setRenderMirrored(bool mirrored); - void setNoise(bool noise); - void setFullscreen(bool fullscreen); - - void setRenderFirstPerson(bool firstPerson); - void setRenderThirdPerson(bool thirdPerson); - void increaseAvatarSize(); - void decreaseAvatarSize(); - void resetAvatarSize(); - - void renderThrustAtVoxel(const glm::vec3& thrust); - void renderLineToTouchedVoxel(); - - void setFrustumOffset(bool frustumOffset); - void cycleFrustumRenderMode(); - - void setRenderWarnings(bool renderWarnings); - void setRenderVoxels(bool renderVoxels); - void doKillLocalVoxels(); - void doRandomizeVoxelColors(); - void doFalseRandomizeVoxelColors(); - void doFalseRandomizeEveryOtherVoxelColors(); - void doFalseColorizeByDistance(); - void doFalseColorizeOccluded(); - void doFalseColorizeOccludedV2(); - void doFalseColorizeBySource(); - void doFalseColorizeInView(); - void doTrueVoxelColors(); - void doTreeStats(); - void setWantsMonochrome(bool wantsMonochrome); - void disableLowResMoving(bool disableLowResMoving); - void disableDeltaSending(bool disableDeltaSending); - void disableOcclusionCulling(bool disableOcclusionCulling); - void updateVoxelModeActions(); - void decreaseVoxelSize(); - void increaseVoxelSize(); - void resetSwatchColors(); - void chooseVoxelPaintColor(); - void loadSettings(QSettings* set = NULL); - void saveSettings(QSettings* set = NULL); - void importSettings(); - void exportSettings(); + void sendAvatarFaceVideoMessage(int frameCount, const QByteArray& data); void exportVoxels(); void importVoxels(); void importVoxelsToClipboard(); void cutVoxels(); void copyVoxels(); void pasteVoxels(); - void runTests(); + + void setRenderVoxels(bool renderVoxels); + void doKillLocalVoxels(); + void decreaseVoxelSize(); + void increaseVoxelSize(); void setListenModeNormal(); void setListenModePoint(); void setListenModeSingleSource(); - void toggleMixedSong(); - void toggleWantCollisionsOn(); - - + +private slots: + + void timer(); + void idle(); + void terminate(); + + void setFullscreen(bool fullscreen); + + void renderThrustAtVoxel(const glm::vec3& thrust); + void renderLineToTouchedVoxel(); + void renderCoverageMap(); void renderCoverageMapsRecursively(CoverageMap* map); @@ -214,24 +169,17 @@ private slots: void renderCoverageMapsV2Recursively(CoverageMapV2* map); glm::vec2 getScaledScreenPoint(glm::vec2 projectedPoint); - void goHome(); void toggleFollowMode(); private: void resetCamerasOnResizeGL(Camera& camera, int width, int height); - static void controlledBroadcastToNodes(unsigned char* broadcastData, size_t dataBytes, - const char* nodeTypes, int numNodeTypes); - static bool sendVoxelsOperation(VoxelNode* node, void* extraData); - static void sendAvatarVoxelURLMessage(const QUrl& url); static void processAvatarVoxelURLMessage(unsigned char* packetData, size_t dataBytes); static void processAvatarFaceVideoMessage(unsigned char* packetData, size_t dataBytes); static void sendPingPackets(); - void initMenu(); - void updateFrustumRenderModeAction(); void initDisplay(); void init(); @@ -263,75 +211,15 @@ private: void updateCursor(); - QAction* checkedVoxelModeAction() const; - static void attachNewHeadToNode(Node *newNode); - static void* networkReceive(void* args); // network receive thread - - // methodes handling menu settings - typedef void(*settingsAction)(QSettings*, QAction*); - static void loadAction(QSettings* set, QAction* action); - static void saveAction(QSettings* set, QAction* action); - void scanMenuBar(settingsAction modifySetting, QSettings* set); - void scanMenu(QMenu* menu, settingsAction modifySetting, QSettings* set); + static void* networkReceive(void* args); // network receive thread QMainWindow* _window; QGLWidget* _glWidget; - QAction* _lookingInMirror; // Are we currently rendering one's own head as if in mirror? - QAction* _echoAudioMode; // Are we asking the mixer to echo back our audio? - QAction* _shouldLowPassFilter; // Use test lowpass filter - QAction* _gyroLook; // Whether to allow the gyro data from head to move your view - QAction* _renderAvatarBalls; // Switch between voxels and joints/balls for avatar render - QAction* _showHeadMouse; // Whether the have the mouse near edge of screen move your view - QAction* _transmitterDrives; // Whether to have Transmitter data move/steer the Avatar - QAction* _gravityUse; // Whether gravity is on or not - QAction* _testPing; // Whether to display ping or not - QAction* _renderVoxels; // Whether to render voxels - QAction* _renderVoxelTextures; // Whether to render noise textures on voxels - QAction* _renderStarsOn; // Whether to display the stars - QAction* _renderAtmosphereOn; // Whether to display the atmosphere - QAction* _renderGroundPlaneOn; // Whether to display the ground plane - QAction* _renderAvatarsOn; // Whether to render avatars - QAction* _renderStatsOn; // Whether to show onscreen text overlay with stats - QAction* _renderFrameTimerOn; // Whether to show onscreen text overlay with stats - QAction* _renderLookatOn; // Whether to show lookat vectors from avatar eyes if looking at something - QAction* _renderLookatIndicatorOn; - QAction* _renderParticleSystemOn; - QAction* _manualFirstPerson; // Whether to force first-person mode - QAction* _manualThirdPerson; // Whether to force third-person mode - QAction* _logOn; // Whether to show on-screen log - QAction* _oscilloscopeOn; // Whether to show the oscilloscope - QAction* _bandwidthDisplayOn; // Whether to show on-screen bandwidth bars - QActionGroup* _voxelModeActions; // The group of voxel edit mode actions - QAction* _addVoxelMode; // Whether add voxel mode is enabled - QAction* _deleteVoxelMode; // Whether delete voxel mode is enabled - QAction* _colorVoxelMode; // Whether color voxel mode is enabled - QAction* _selectVoxelMode; // Whether select voxel mode is enabled - QAction* _eyedropperMode; // Whether voxel color eyedropper mode is enabled - QAction* _voxelPaintColor; // The color with which to paint voxels - QAction* _destructiveAddVoxel; // when doing voxel editing do we want them to be destructive - QAction* _frustumOn; // Whether or not to display the debug view frustum - QAction* _fullScreenMode; // whether we are in full screen mode - QAction* _frustumRenderModeAction; - QAction* _settingsAutosave; // Whether settings are saved automatically - QAction* _rawAudioMicrophoneMix; // Mixing of a RAW audio file with microphone stream for rave gloves - QAction* _noise; - QAction* _occlusionCulling; - QAction* _wantCollisionsOn; - QAction* _renderPipelineWarnings; - - QAction* _renderCoverageMapV2; - QAction* _renderCoverageMap; - - QAction* _simulateLeapHand; // When there's no Leap, use this to pretend there is one and feed fake hand data - QAction* _testRaveGlove; // Test fancy sparkle-rave-glove mode - QAction* _followMode; BandwidthMeter _bandwidthMeter; - BandwidthDialog* _bandwidthDialog; - VoxelStatsDialog* _voxelStatsDialog; SerialInterface _serialHeadSensor; QNetworkAccessManager* _networkAccessManager; @@ -347,8 +235,6 @@ private: timeval _timerStart, _timerEnd; timeval _lastTimeUpdated; bool _justStarted; - bool _particleSystemInitialized; - int _coolDemoParticleEmitter; Stars _stars; @@ -359,16 +245,6 @@ private: bool _wantToKillLocalVoxels; ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc. - - enum FrustumDrawMode { FRUSTUM_DRAW_MODE_ALL, FRUSTUM_DRAW_MODE_VECTORS, FRUSTUM_DRAW_MODE_PLANES, - FRUSTUM_DRAW_MODE_NEAR_PLANE, FRUSTUM_DRAW_MODE_FAR_PLANE, FRUSTUM_DRAW_MODE_KEYHOLE, FRUSTUM_DRAW_MODE_COUNT }; - FrustumDrawMode _frustumDrawingMode; - - float _viewFrustumOffsetYaw; // the following variables control yaw, pitch, roll and distance form regular - float _viewFrustumOffsetPitch; // camera to the offset camera - float _viewFrustumOffsetRoll; - float _viewFrustumOffsetDistance; - float _viewFrustumOffsetUp; Oscilloscope _audioScope; @@ -384,11 +260,6 @@ private: Environment _environment; int _headMouseX, _headMouseY; - float _gyroCameraSensitivity; - - int _audioJitterBufferSamples; // Number of extra samples to wait before starting audio playback - - float _fieldOfView; // In Degrees, doesn't apply to HMD like Oculus HandControl _handControl; @@ -443,7 +314,6 @@ private: GeometryCache _geometryCache; TextureCache _textureCache; - ParticleSystem _particleSystem; GlowEffect _glowEffect; AmbientOcclusionEffect _ambientOcclusionEffect; diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index add56df80c..449ec55a16 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -23,6 +23,7 @@ #include "Application.h" #include "Audio.h" +#include "Menu.h" #include "Util.h" // Uncomment the following definition to test audio device latency by copying output to input @@ -112,7 +113,7 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o // + 12 for 3 floats for position + float for bearing + 1 attenuation byte unsigned char dataPacket[MAX_PACKET_SIZE]; - PACKET_TYPE packetType = (Application::getInstance()->shouldEchoAudio()) + PACKET_TYPE packetType = Menu::getInstance()->isOptionChecked(MenuOption::EchoAudio) ? PACKET_TYPE_MICROPHONE_AUDIO_WITH_ECHO : PACKET_TYPE_MICROPHONE_AUDIO_NO_ECHO; @@ -153,38 +154,6 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o memcpy(currentPacketPtr, &headOrientation, sizeof(headOrientation)); currentPacketPtr += sizeof(headOrientation); - // check if we have a song to add to our audio - if (_songFileBytes > 0 && _songFileStream->tellg() != -1) { - // iterate over BUFFER_LENGTH_SAMPLES_PER_CHANNEL from the song file and add that to our audio - for (int i = 0; i < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) { - int16_t songSample = 0; - - _songFileStream->read((char*) &songSample, sizeof(songSample)); - - // attenuate the song samples since they will be loud - const float SONG_SAMPLE_ATTENUATION = 0.25; - songSample *= SONG_SAMPLE_ATTENUATION; - - // add the song sample to the output and input buffersg - inputLeft[i] = inputLeft[i] + songSample; - outputLeft[i] = outputLeft[i] + songSample; - outputRight[i] = outputLeft[i] + songSample; - } - } else if (_songFileStream) { - // close the stream - _songFileStream->close(); - - // delete the _songFileStream - delete _songFileStream; - _songFileStream = NULL; - - // reset the _songFileBytes back to zero - _songFileBytes = 0; - - // call Application stopMixingSong method to fix menu item - Application::getInstance()->resetSongMixMenuItem(); - } - // copy the audio data to the last BUFFER_LENGTH_BYTES bytes of the data packet memcpy(currentPacketPtr, inputLeft, BUFFER_LENGTH_BYTES_PER_CHANNEL); @@ -415,8 +384,6 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples) : _collisionSoundDuration(0.0f), _proceduralEffectSample(0), _heartbeatMagnitude(0.0f), - _songFileStream(NULL), - _songFileBytes(0), _listenMode(AudioRingBuffer::NORMAL), _listenRadius(0.0f) { @@ -489,24 +456,6 @@ Audio::~Audio() { delete[] _echoSamplesLeft; } - -void Audio::importSongToMixWithMicrophone(const char* filename) { - _songFileStream = new std::ifstream(filename); - - long begin = _songFileStream->tellg(); - _songFileStream->seekg(0, std::ios::end); - long end = _songFileStream->tellg(); - - // go back to the beginning - _songFileStream->seekg(0); - - _songFileBytes = end - begin; -} - -void Audio::stopMixingSongWithMicrophone() { - _songFileBytes = 0; -} - void Audio::addReceivedAudioToBuffer(unsigned char* receivedData, int receivedBytes) { const int NUM_INITIAL_PACKETS_DISCARD = 3; const int STANDARD_DEVIATION_SAMPLE_COUNT = 500; @@ -528,7 +477,7 @@ void Audio::addReceivedAudioToBuffer(unsigned char* receivedData, int receivedBy // Set jitter buffer to be a multiple of the measured standard deviation const int MAX_JITTER_BUFFER_SAMPLES = RING_BUFFER_LENGTH_SAMPLES / 2; const float NUM_STANDARD_DEVIATIONS = 3.f; - if (Application::getInstance()->shouldDynamicallySetJitterBuffer()) { + if (Menu::getInstance()->getAudioJitterBufferSamples() == 0) { float newJitterBufferSamples = (NUM_STANDARD_DEVIATIONS * _measuredJitter) / 1000.f * SAMPLE_RATE; @@ -646,7 +595,7 @@ void Audio::render(int screenWidth, int screenHeight) { sprintf(out, "%.0f\n", getJitterBufferSamples() / SAMPLE_RATE * 1000.f); drawtext(startX + jitterBufferPels - 5, topY - 9, 0.10, 0, 1, 0, out, 1, 0, 0); sprintf(out, "j %.1f\n", _measuredJitter); - if (Application::getInstance()->shouldDynamicallySetJitterBuffer()) { + if (Menu::getInstance()->getAudioJitterBufferSamples() == 0) { drawtext(startX + jitterBufferPels - 5, bottomY + 12, 0.10, 0, 1, 0, out, 1, 0, 0); } else { drawtext(startX, bottomY + 12, 0.10, 0, 1, 0, out, 1, 0, 0); diff --git a/interface/src/Audio.h b/interface/src/Audio.h index e60e33d613..8d6371a6f9 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -54,8 +54,6 @@ public: float getCollisionSoundMagnitude() { return _collisionSoundMagnitude; }; - int getSongFileBytes() { return _songFileBytes; } - void ping(); // Call periodically to eventually perform round trip time analysis, @@ -68,11 +66,6 @@ public: void addListenSource(int sourceID); void removeListenSource(int sourceID); void clearListenSources(); - - void importSongToMixWithMicrophone(const char* filename); - -public slots: - void stopMixingSongWithMicrophone(); private: PaStream* _stream; @@ -109,9 +102,7 @@ private: float _collisionSoundDuration; int _proceduralEffectSample; float _heartbeatMagnitude; - std::ifstream* _songFileStream; - int _songFileBytes; - + AudioRingBuffer::ListenMode _listenMode; float _listenRadius; std::vector _listenSources; diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp new file mode 100644 index 0000000000..cd6f49383e --- /dev/null +++ b/interface/src/GLCanvas.cpp @@ -0,0 +1,70 @@ +// +// GLCanvas.cpp +// hifi +// +// Created by Stephen Birarda on 8/14/13. +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// + +#include "Application.h" + +#include "GLCanvas.h" + +GLCanvas::GLCanvas() : QGLWidget(QGLFormat(QGL::NoDepthBuffer, QGL::NoStencilBuffer)) { +} + +void GLCanvas::initializeGL() { + Application::getInstance()->initializeGL(); + setAttribute(Qt::WA_AcceptTouchEvents); +} + +void GLCanvas::paintGL() { + Application::getInstance()->paintGL(); +} + +void GLCanvas::resizeGL(int width, int height) { + Application::getInstance()->resizeGL(width, height); +} + +void GLCanvas::keyPressEvent(QKeyEvent* event) { + Application::getInstance()->keyPressEvent(event); +} + +void GLCanvas::keyReleaseEvent(QKeyEvent* event) { + Application::getInstance()->keyReleaseEvent(event); +} + +void GLCanvas::mouseMoveEvent(QMouseEvent* event) { + Application::getInstance()->mouseMoveEvent(event); +} + +void GLCanvas::mousePressEvent(QMouseEvent* event) { + Application::getInstance()->mousePressEvent(event); +} + +void GLCanvas::mouseReleaseEvent(QMouseEvent* event) { + Application::getInstance()->mouseReleaseEvent(event); +} + +int updateTime = 0; +bool GLCanvas::event(QEvent* event) { + switch (event->type()) { + case QEvent::TouchBegin: + Application::getInstance()->touchBeginEvent(static_cast(event)); + event->accept(); + return true; + case QEvent::TouchEnd: + Application::getInstance()->touchEndEvent(static_cast(event)); + return true; + case QEvent::TouchUpdate: + Application::getInstance()->touchUpdateEvent(static_cast(event)); + return true; + default: + break; + } + return QGLWidget::event(event); +} + +void GLCanvas::wheelEvent(QWheelEvent* event) { + Application::getInstance()->wheelEvent(event); +} \ No newline at end of file diff --git a/interface/src/GLCanvas.h b/interface/src/GLCanvas.h new file mode 100644 index 0000000000..ad181f4456 --- /dev/null +++ b/interface/src/GLCanvas.h @@ -0,0 +1,36 @@ +// +// GLCanvas.h +// hifi +// +// Created by Stephen Birarda on 8/14/13. +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// + +#ifndef __hifi__GLCanvas__ +#define __hifi__GLCanvas__ + +#include + +/// customized canvas that simply forwards requests/events to the singleton application +class GLCanvas : public QGLWidget { +public: + GLCanvas(); +protected: + + virtual void initializeGL(); + virtual void paintGL(); + virtual void resizeGL(int width, int height); + + virtual void keyPressEvent(QKeyEvent* event); + virtual void keyReleaseEvent(QKeyEvent* event); + + virtual void mouseMoveEvent(QMouseEvent* event); + virtual void mousePressEvent(QMouseEvent* event); + virtual void mouseReleaseEvent(QMouseEvent* event); + + virtual bool event(QEvent* event); + + virtual void wheelEvent(QWheelEvent* event); +}; + +#endif /* defined(__hifi__GLCanvas__) */ diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp new file mode 100644 index 0000000000..ee4cd36b16 --- /dev/null +++ b/interface/src/Menu.cpp @@ -0,0 +1,779 @@ +// +// Menu.cpp +// hifi +// +// Created by Stephen Birarda on 8/12/13. +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Application.h" +#include "PairingHandler.h" +#include "Menu.h" +#include "Util.h" + +Menu* Menu::_instance = NULL; + +Menu* Menu::getInstance() { + if (!_instance) { + qDebug("First call to Menu::getInstance() - initing menu.\n"); + + _instance = new Menu(); + } + + return _instance; +} + +const ViewFrustumOffset DEFAULT_FRUSTUM_OFFSET = {-135.0f, 0.0f, 0.0f, 25.0f, 0.0f}; + +Menu::Menu() : + _actionHash(), + _audioJitterBufferSamples(0), + _bandwidthDialog(NULL), + _fieldOfView(DEFAULT_FIELD_OF_VIEW_DEGREES), + _frustumDrawMode(FRUSTUM_DRAW_MODE_ALL), + _viewFrustumOffset(DEFAULT_FRUSTUM_OFFSET), + _voxelModeActionsGroup(NULL), + _voxelStatsDialog(NULL) +{ + Application *appInstance = Application::getInstance(); + + QMenu* fileMenu = addMenu("File"); + (addActionToQMenuAndActionHash(fileMenu, + MenuOption::Quit, + Qt::CTRL | Qt::Key_Q, + appInstance, + SLOT(quit())))->setMenuRole(QAction::QuitRole); + + (addActionToQMenuAndActionHash(fileMenu, + MenuOption::Preferences, + Qt::CTRL | Qt::Key_Comma, + this, + SLOT(editPreferences())))->setMenuRole(QAction::PreferencesRole); + + QMenu* pairMenu = addMenu("Pair"); + addActionToQMenuAndActionHash(pairMenu, MenuOption::Pair, 0, PairingHandler::getInstance(), SLOT(sendPairRequest())); + + + QMenu* optionsMenu = addMenu("Options"); + + addCheckableActionToQMenuAndActionHash(optionsMenu, MenuOption::Mirror, Qt::Key_H); + addCheckableActionToQMenuAndActionHash(optionsMenu, MenuOption::GyroLook, 0, true); + addCheckableActionToQMenuAndActionHash(optionsMenu, MenuOption::HeadMouse); + addCheckableActionToQMenuAndActionHash(optionsMenu, MenuOption::TransmitterDrive, 0, true); + addCheckableActionToQMenuAndActionHash(optionsMenu, MenuOption::Gravity, Qt::SHIFT | Qt::Key_G, true); + addCheckableActionToQMenuAndActionHash(optionsMenu, MenuOption::TestPing, 0, true); + + addCheckableActionToQMenuAndActionHash(optionsMenu, + MenuOption::Fullscreen, + Qt::Key_F, + false, + appInstance, + SLOT(setFullscreen(bool))); + + addCheckableActionToQMenuAndActionHash(optionsMenu, + MenuOption::Webcam, + 0, + false, + appInstance->getWebcam(), + SLOT(setEnabled(bool))); + + addCheckableActionToQMenuAndActionHash(optionsMenu, + MenuOption::SkeletonTracking, + 0, + false, + appInstance->getWebcam(), + SLOT(setSkeletonTrackingOn(bool))); + + addCheckableActionToQMenuAndActionHash(optionsMenu, + MenuOption::Collisions, + 0, + true, + appInstance->getAvatar(), + SLOT(setWantCollisionsOn(bool))); + + addActionToQMenuAndActionHash(optionsMenu, + MenuOption::WebcamMode, + 0, + appInstance->getWebcam()->getGrabber(), + SLOT(cycleVideoSendMode())); + addCheckableActionToQMenuAndActionHash(optionsMenu, + MenuOption::WebcamTexture, + 0, + false, + appInstance->getWebcam()->getGrabber(), + SLOT(setDepthOnly(bool))); + + addActionToQMenuAndActionHash(optionsMenu, + MenuOption::GoHome, + Qt::CTRL | Qt::Key_G, + appInstance->getAvatar(), + SLOT(goHome())); + + QMenu* audioMenu = addMenu("Audio"); + addCheckableActionToQMenuAndActionHash(audioMenu, MenuOption::EchoAudio); + + QMenu* renderMenu = addMenu("Render"); + addCheckableActionToQMenuAndActionHash(renderMenu, + MenuOption::Voxels, + Qt::SHIFT | Qt::Key_V, + true, + appInstance, + SLOT(setRenderVoxels(bool))); + addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::VoxelTextures); + addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::Stars, 0, true); + addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::Atmosphere, Qt::SHIFT | Qt::Key_A, true); + addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::GroundPlane, 0, true); + addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::Avatars, 0, true); + addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::AvatarAsBalls); + + addActionToQMenuAndActionHash(renderMenu, + MenuOption::VoxelMode, + 0, + appInstance->getAvatar()->getVoxels(), + SLOT(cycleMode())); + + addActionToQMenuAndActionHash(renderMenu, + MenuOption::FaceMode, + 0, + &appInstance->getAvatar()->getHead().getFace(), + SLOT(cycleRenderMode())); + + addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::FrameTimer); + addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::LookAtVectors); + addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::LookAtIndicator, 0, true); + addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::FirstPerson, Qt::Key_P, true); + + addActionToQMenuAndActionHash(renderMenu, + MenuOption::IncreaseAvatarSize, + Qt::Key_Plus, + appInstance->getAvatar(), + SLOT(increaseSize())); + addActionToQMenuAndActionHash(renderMenu, + MenuOption::DecreaseAvatarSize, + Qt::Key_Minus, + appInstance->getAvatar(), + SLOT(decreaseSize())); + addActionToQMenuAndActionHash(renderMenu, + MenuOption::ResetAvatarSize, + 0, + appInstance->getAvatar(), + SLOT(resetSize())); + + QMenu* toolsMenu = addMenu("Tools"); + addCheckableActionToQMenuAndActionHash(toolsMenu, MenuOption::Stats, Qt::Key_Slash); + addCheckableActionToQMenuAndActionHash(toolsMenu, MenuOption::Log, Qt::CTRL | Qt::Key_L); + addCheckableActionToQMenuAndActionHash(toolsMenu, MenuOption::Oscilloscope, 0, true); + addCheckableActionToQMenuAndActionHash(toolsMenu, MenuOption::Bandwidth, 0, true); + addActionToQMenuAndActionHash(toolsMenu, MenuOption::BandwidthDetails, 0, this, SLOT(bandwidthDetails())); + addActionToQMenuAndActionHash(toolsMenu, MenuOption::VoxelStats, 0, this, SLOT(voxelStatsDetails())); + + + QMenu* voxelMenu = addMenu("Voxels"); + _voxelModeActionsGroup = new QActionGroup(this); + _voxelModeActionsGroup->setExclusive(false); + + QAction* addVoxelMode = addCheckableActionToQMenuAndActionHash(voxelMenu, MenuOption::VoxelAddMode, Qt::Key_V); + _voxelModeActionsGroup->addAction(addVoxelMode); + + QAction* deleteVoxelMode = addCheckableActionToQMenuAndActionHash(voxelMenu, MenuOption::VoxelDeleteMode, Qt::Key_R); + _voxelModeActionsGroup->addAction(deleteVoxelMode); + + QAction* colorVoxelMode = addCheckableActionToQMenuAndActionHash(voxelMenu, MenuOption::VoxelColorMode, Qt::Key_B); + _voxelModeActionsGroup->addAction(colorVoxelMode); + + QAction* selectVoxelMode = addCheckableActionToQMenuAndActionHash(voxelMenu, MenuOption::VoxelSelectMode, Qt::Key_O); + _voxelModeActionsGroup->addAction(selectVoxelMode); + + QAction* getColorMode = addCheckableActionToQMenuAndActionHash(voxelMenu, MenuOption::VoxelGetColorMode, Qt::Key_G); + _voxelModeActionsGroup->addAction(getColorMode); + + // connect each of the voxel mode actions to the updateVoxelModeActionsSlot + foreach (QAction* action, _voxelModeActionsGroup->actions()) { + connect(action, SIGNAL(triggered()), this, SLOT(updateVoxelModeActions())); + } + + QAction* voxelPaintColor = addActionToQMenuAndActionHash(voxelMenu, + MenuOption::VoxelPaintColor, + Qt::META | Qt::Key_C, + this, + SLOT(chooseVoxelPaintColor())); + + Application::getInstance()->getSwatch()->setAction(voxelPaintColor); + + QColor paintColor(128, 128, 128); + voxelPaintColor->setData(paintColor); + voxelPaintColor->setIcon(Swatch::createIcon(paintColor)); + + addActionToQMenuAndActionHash(voxelMenu, + MenuOption::DecreaseVoxelSize, + QKeySequence::ZoomOut, + appInstance, + SLOT(decreaseVoxelSize())); + addActionToQMenuAndActionHash(voxelMenu, + MenuOption::IncreaseVoxelSize, + QKeySequence::ZoomIn, + appInstance, + SLOT(increaseVoxelSize())); + addActionToQMenuAndActionHash(voxelMenu, MenuOption::ResetSwatchColors, 0, this, SLOT(resetSwatchColors())); + + addCheckableActionToQMenuAndActionHash(voxelMenu, MenuOption::DestructiveAddVoxel); + + addActionToQMenuAndActionHash(voxelMenu, MenuOption::ExportVoxels, Qt::CTRL | Qt::Key_E, appInstance, SLOT(exportVoxels())); + addActionToQMenuAndActionHash(voxelMenu, MenuOption::ImportVoxels, Qt::CTRL | Qt::Key_I, appInstance, SLOT(importVoxels())); + addActionToQMenuAndActionHash(voxelMenu, + MenuOption::ImportVoxelsClipboard, + Qt::SHIFT | Qt::CTRL | Qt::Key_I, + appInstance, + SLOT(importVoxelsToClipboard())); + addActionToQMenuAndActionHash(voxelMenu, MenuOption::CutVoxels, Qt::CTRL | Qt::Key_X, appInstance, SLOT(cutVoxels())); + addActionToQMenuAndActionHash(voxelMenu, MenuOption::CopyVoxels, Qt::CTRL | Qt::Key_C, appInstance, SLOT(copyVoxels())); + addActionToQMenuAndActionHash(voxelMenu, MenuOption::PasteVoxels, Qt::CTRL | Qt::Key_V, appInstance, SLOT(pasteVoxels())); + + QMenu* debugMenu = addMenu("Debug"); + + QMenu* frustumMenu = debugMenu->addMenu("View Frustum Debugging Tools"); + addCheckableActionToQMenuAndActionHash(frustumMenu, MenuOption::DisplayFrustum, Qt::SHIFT | Qt::Key_F); + + addActionToQMenuAndActionHash(frustumMenu, + MenuOption::FrustumRenderMode, + Qt::SHIFT | Qt::Key_R, + this, + SLOT(cycleFrustumRenderMode())); + updateFrustumRenderModeAction(); + + addActionToQMenuAndActionHash(debugMenu, MenuOption::RunTimingTests, 0, this, SLOT(runTests())); + addActionToQMenuAndActionHash(debugMenu, + MenuOption::TreeStats, + Qt::SHIFT | Qt::Key_S, + appInstance->getVoxels(), + SLOT(collectStatsForTreesAndVBOs())); + + QMenu* renderDebugMenu = debugMenu->addMenu("Render Debugging Tools"); + addCheckableActionToQMenuAndActionHash(renderDebugMenu, MenuOption::PipelineWarnings); + + addActionToQMenuAndActionHash(renderDebugMenu, + MenuOption::KillLocalVoxels, + Qt::CTRL | Qt::Key_K, + appInstance, SLOT(doKillLocalVoxels())); + + addActionToQMenuAndActionHash(renderDebugMenu, + MenuOption::RandomizeVoxelColors, + Qt::CTRL | Qt::Key_R, + appInstance->getVoxels(), + SLOT(randomizeVoxelColors())); + + addActionToQMenuAndActionHash(renderDebugMenu, + MenuOption::FalseColorRandomly, + 0, + appInstance->getVoxels(), + SLOT(falseColorizeRandom())); + + addActionToQMenuAndActionHash(renderDebugMenu, + MenuOption::FalseColorEveryOtherVoxel, + 0, + appInstance->getVoxels(), + SLOT(falseColorizeRandomEveryOther())); + + addActionToQMenuAndActionHash(renderDebugMenu, + MenuOption::FalseColorByDistance, + 0, + appInstance->getVoxels(), + SLOT(falseColorizeDistanceFromView())); + + addActionToQMenuAndActionHash(renderDebugMenu, + MenuOption::FalseColorOutOfView, + 0, + appInstance->getVoxels(), + SLOT(falseColorizeInView())); + + addActionToQMenuAndActionHash(renderDebugMenu, + MenuOption::FalseColorOccluded, + 0, + appInstance->getVoxels(), + SLOT(falseColorizeOccluded())); + + addActionToQMenuAndActionHash(renderDebugMenu, + MenuOption::FalseColorOccludedV2, + 0, + appInstance->getVoxels(), + SLOT(falseColorizeOccludedV2())); + + addActionToQMenuAndActionHash(renderDebugMenu, + MenuOption::FalseColorBySource, + 0, + appInstance->getVoxels(), + SLOT(falseColorizeBySource())); + + addActionToQMenuAndActionHash(renderDebugMenu, + MenuOption::ShowTrueColors, + Qt::CTRL | Qt::Key_T, + appInstance->getVoxels(), + SLOT(trueColorize())); + + addCheckableActionToQMenuAndActionHash(debugMenu, + MenuOption::SendVoxelColors, + 0, + true, + appInstance->getAvatar(), + SLOT(setWantColor(bool))); + + addCheckableActionToQMenuAndActionHash(debugMenu, + MenuOption::LowRes, + 0, + true, + appInstance->getAvatar(), + SLOT(setWantLowResMoving(bool))); + + addCheckableActionToQMenuAndActionHash(debugMenu, + MenuOption::DeltaSending, + 0, + true, + appInstance->getAvatar(), + SLOT(setWantDelta(bool))); + + addCheckableActionToQMenuAndActionHash(debugMenu, + MenuOption::OcclusionCulling, + Qt::SHIFT | Qt::Key_C, + true, + appInstance->getAvatar(), + SLOT(setWantOcclusionCulling(bool))); + + addCheckableActionToQMenuAndActionHash(debugMenu, MenuOption::CoverageMap, Qt::SHIFT | Qt::CTRL | Qt::Key_O); + addCheckableActionToQMenuAndActionHash(debugMenu, MenuOption::CoverageMapV2, Qt::SHIFT | Qt::CTRL | Qt::Key_P); + addCheckableActionToQMenuAndActionHash(debugMenu, MenuOption::SimulateLeapHand); + addCheckableActionToQMenuAndActionHash(debugMenu, MenuOption::TestRaveGlove); + + QMenu* audioDebugMenu = debugMenu->addMenu("Audio Debugging Tools"); + addActionToQMenuAndActionHash(audioDebugMenu, + MenuOption::ListenModeNormal, + Qt::CTRL | Qt::Key_1, + appInstance, + SLOT(setListenModeNormal())); + addActionToQMenuAndActionHash(audioDebugMenu, + MenuOption::ListenModePoint, + Qt::CTRL | Qt::Key_2, + appInstance, + SLOT(setListenModePoint())); + addActionToQMenuAndActionHash(audioDebugMenu, + MenuOption::ListenModeSingleSource, + Qt::CTRL | Qt::Key_3, + appInstance, + SLOT(setListenModeSingleSource())); + + QMenu* settingsMenu = addMenu("Settings"); + addCheckableActionToQMenuAndActionHash(settingsMenu, MenuOption::SettingsAutosave, 0, true); + addActionToQMenuAndActionHash(settingsMenu, MenuOption::SettingsLoad, 0, this, SLOT(loadSettings())); + addActionToQMenuAndActionHash(settingsMenu, MenuOption::SettingsSave, 0, this, SLOT(saveSettings())); + addActionToQMenuAndActionHash(settingsMenu, MenuOption::SettingsImport, 0, this, SLOT(importSettings())); + addActionToQMenuAndActionHash(settingsMenu, MenuOption::SettingsExport, 0, this, SLOT(exportSettings())); +} + +void Menu::loadSettings(QSettings* settings) { + if (!settings) { + settings = Application::getInstance()->getSettings(); + } + + _gyroCameraSensitivity = loadSetting(settings, "gyroCameraSensitivity", 0.5f); + _audioJitterBufferSamples = loadSetting(settings, "audioJitterBufferSamples", 0); + _fieldOfView = loadSetting(settings, "fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES); + + settings->beginGroup("View Frustum Offset Camera"); + // in case settings is corrupt or missing loadSetting() will check for NaN + _viewFrustumOffset.yaw = loadSetting(settings, "viewFrustumOffsetYaw", 0.0f); + _viewFrustumOffset.pitch = loadSetting(settings, "viewFrustumOffsetPitch", 0.0f); + _viewFrustumOffset.roll = loadSetting(settings, "viewFrustumOffsetRoll", 0.0f); + _viewFrustumOffset.distance = loadSetting(settings, "viewFrustumOffsetDistance", 0.0f); + _viewFrustumOffset.up = loadSetting(settings, "viewFrustumOffsetUp", 0.0f); + settings->endGroup(); + + scanMenuBar(&loadAction, settings); + Application::getInstance()->getAvatar()->loadData(settings); + Application::getInstance()->getSwatch()->loadData(settings); +} + +void Menu::saveSettings(QSettings* settings) { + if (!settings) { + settings = Application::getInstance()->getSettings(); + } + + settings->setValue("gyroCameraSensitivity", _gyroCameraSensitivity); + settings->setValue("audioJitterBufferSamples", _audioJitterBufferSamples); + settings->setValue("fieldOfView", _fieldOfView); + settings->beginGroup("View Frustum Offset Camera"); + settings->setValue("viewFrustumOffsetYaw", _viewFrustumOffset.yaw); + settings->setValue("viewFrustumOffsetPitch", _viewFrustumOffset.pitch); + settings->setValue("viewFrustumOffsetRoll", _viewFrustumOffset.roll); + settings->setValue("viewFrustumOffsetDistance", _viewFrustumOffset.distance); + settings->setValue("viewFrustumOffsetUp", _viewFrustumOffset.up); + settings->endGroup(); + + scanMenuBar(&saveAction, settings); + Application::getInstance()->getAvatar()->saveData(settings); + Application::getInstance()->getSwatch()->saveData(settings); + + // ask the NodeList to save its data + NodeList::getInstance()->saveData(settings); +} + +void Menu::importSettings() { + QString locationDir(QStandardPaths::displayName(QStandardPaths::DesktopLocation)); + QString fileName = QFileDialog::getOpenFileName(Application::getInstance()->getWindow(), + tr("Open .ini config file"), + locationDir, + tr("Text files (*.ini)")); + if (fileName != "") { + QSettings tmp(fileName, QSettings::IniFormat); + loadSettings(&tmp); + } +} + +void Menu::exportSettings() { + QString locationDir(QStandardPaths::displayName(QStandardPaths::DesktopLocation)); + QString fileName = QFileDialog::getSaveFileName(Application::getInstance()->getWindow(), + tr("Save .ini config file"), + locationDir, + tr("Text files (*.ini)")); + if (fileName != "") { + QSettings tmp(fileName, QSettings::IniFormat); + saveSettings(&tmp); + tmp.sync(); + } +} + + +void Menu::loadAction(QSettings* set, QAction* action) { + if (action->isChecked() != set->value(action->text(), action->isChecked()).toBool()) { + action->trigger(); + } +} + +void Menu::saveAction(QSettings* set, QAction* action) { + set->setValue(action->text(), action->isChecked()); +} + +void Menu::scanMenuBar(settingsAction modifySetting, QSettings* set) { + QList menus = this->findChildren(); + + for (QList::const_iterator it = menus.begin(); menus.end() != it; ++it) { + scanMenu(*it, modifySetting, set); + } +} + +void Menu::scanMenu(QMenu* menu, settingsAction modifySetting, QSettings* set) { + QList actions = menu->actions(); + + set->beginGroup(menu->title()); + for (QList::const_iterator it = actions.begin(); actions.end() != it; ++it) { + if ((*it)->menu()) { + scanMenu((*it)->menu(), modifySetting, set); + } + if ((*it)->isCheckable()) { + modifySetting(set, *it); + } + } + set->endGroup(); +} + +void Menu::handleViewFrustumOffsetKeyModifier(int key) { + const float VIEW_FRUSTUM_OFFSET_DELTA = 0.5f; + const float VIEW_FRUSTUM_OFFSET_UP_DELTA = 0.05f; + + switch (key) { + case Qt::Key_BracketLeft: + _viewFrustumOffset.yaw -= VIEW_FRUSTUM_OFFSET_DELTA; + break; + + case Qt::Key_BracketRight: + _viewFrustumOffset.yaw += VIEW_FRUSTUM_OFFSET_DELTA; + break; + + case Qt::Key_BraceLeft: + _viewFrustumOffset.pitch -= VIEW_FRUSTUM_OFFSET_DELTA; + break; + + case Qt::Key_BraceRight: + _viewFrustumOffset.pitch += VIEW_FRUSTUM_OFFSET_DELTA; + break; + + case Qt::Key_ParenLeft: + _viewFrustumOffset.roll -= VIEW_FRUSTUM_OFFSET_DELTA; + break; + + case Qt::Key_ParenRight: + _viewFrustumOffset.roll += VIEW_FRUSTUM_OFFSET_DELTA; + break; + + case Qt::Key_Less: + _viewFrustumOffset.distance -= VIEW_FRUSTUM_OFFSET_DELTA; + break; + + case Qt::Key_Greater: + _viewFrustumOffset.distance += VIEW_FRUSTUM_OFFSET_DELTA; + break; + + case Qt::Key_Comma: + _viewFrustumOffset.up -= VIEW_FRUSTUM_OFFSET_UP_DELTA; + break; + + case Qt::Key_Period: + _viewFrustumOffset.up += VIEW_FRUSTUM_OFFSET_UP_DELTA; + break; + + default: + break; + } +} + +QAction* Menu::addActionToQMenuAndActionHash(QMenu* destinationMenu, + const QString actionName, + const QKeySequence& shortcut, + const QObject* receiver, + const char* member) { + QAction* action; + + if (receiver && member) { + action = destinationMenu->addAction(actionName, receiver, member, shortcut); + } else { + action = destinationMenu->addAction(actionName); + action->setShortcut(shortcut); + } + + _actionHash.insert(actionName, action); + + return action; +} + +QAction* Menu::addCheckableActionToQMenuAndActionHash(QMenu* destinationMenu, + const QString actionName, + const QKeySequence& shortcut, + const bool checked, + const QObject* receiver, + const char* member) { + QAction* action = addActionToQMenuAndActionHash(destinationMenu, actionName, shortcut, receiver, member); + action->setCheckable(true); + action->setChecked(checked); + + return action; +} + +bool Menu::isOptionChecked(const QString& menuOption) { + return _actionHash.value(menuOption)->isChecked(); +} + +void Menu::triggerOption(const QString& menuOption) { + _actionHash.value(menuOption)->trigger(); +} + +QAction* Menu::getActionForOption(const QString& menuOption) { + return _actionHash.value(menuOption); +} + +bool Menu::isVoxelModeActionChecked() { + foreach (QAction* action, _voxelModeActionsGroup->actions()) { + if (action->isChecked()) { + return true; + } + } + return false; +} + +void Menu::editPreferences() { + Application *applicationInstance = Application::getInstance(); + QDialog dialog(applicationInstance->getGLWidget()); + dialog.setWindowTitle("Interface Preferences"); + QBoxLayout* layout = new QBoxLayout(QBoxLayout::TopToBottom); + dialog.setLayout(layout); + + QFormLayout* form = new QFormLayout(); + layout->addLayout(form, 1); + + const int QLINE_MINIMUM_WIDTH = 400; + + QLineEdit* domainServerHostname = new QLineEdit(QString(NodeList::getInstance()->getDomainHostname())); + domainServerHostname->setMinimumWidth(QLINE_MINIMUM_WIDTH); + form->addRow("Domain server:", domainServerHostname); + + QLineEdit* avatarURL = new QLineEdit(applicationInstance->getAvatar()->getVoxels()->getVoxelURL().toString()); + avatarURL->setMinimumWidth(QLINE_MINIMUM_WIDTH); + form->addRow("Avatar URL:", avatarURL); + + QSpinBox* fieldOfView = new QSpinBox(); + fieldOfView->setMaximum(180); + fieldOfView->setMinimum(1); + fieldOfView->setValue(_fieldOfView); + form->addRow("Vertical Field of View (Degrees):", fieldOfView); + + QDoubleSpinBox* gyroCameraSensitivity = new QDoubleSpinBox(); + gyroCameraSensitivity->setValue(_gyroCameraSensitivity); + form->addRow("Gyro Camera Sensitivity (0 - 1):", gyroCameraSensitivity); + + QDoubleSpinBox* leanScale = new QDoubleSpinBox(); + leanScale->setValue(applicationInstance->getAvatar()->getLeanScale()); + form->addRow("Lean Scale:", leanScale); + + QSpinBox* audioJitterBufferSamples = new QSpinBox(); + audioJitterBufferSamples->setMaximum(10000); + audioJitterBufferSamples->setMinimum(-10000); + audioJitterBufferSamples->setValue(_audioJitterBufferSamples); + form->addRow("Audio Jitter Buffer Samples (0 for automatic):", audioJitterBufferSamples); + + QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + dialog.connect(buttons, SIGNAL(accepted()), SLOT(accept())); + dialog.connect(buttons, SIGNAL(rejected()), SLOT(reject())); + layout->addWidget(buttons); + + if (dialog.exec() != QDialog::Accepted) { + return; + } + + QByteArray newHostname; + + if (domainServerHostname->text().size() > 0) { + // the user input a new hostname, use that + newHostname = domainServerHostname->text().toLocal8Bit(); + } else { + // the user left the field blank, use the default hostname + newHostname = QByteArray(DEFAULT_DOMAIN_HOSTNAME); + } + + // check if the domain server hostname is new + if (memcmp(NodeList::getInstance()->getDomainHostname(), newHostname.constData(), newHostname.size()) != 0) { + + NodeList::getInstance()->clear(); + + // kill the local voxels + applicationInstance->getVoxels()->killLocalVoxels(); + + // reset the environment to default + applicationInstance->getEnvironment()->resetToDefault(); + + // set the new hostname + NodeList::getInstance()->setDomainHostname(newHostname.constData()); + } + + QUrl url(avatarURL->text()); + applicationInstance->getAvatar()->getVoxels()->setVoxelURL(url); + Avatar::sendAvatarVoxelURLMessage(url); + + _gyroCameraSensitivity = gyroCameraSensitivity->value(); + + applicationInstance->getAvatar()->setLeanScale(leanScale->value()); + + _audioJitterBufferSamples = audioJitterBufferSamples->value(); + + if (_audioJitterBufferSamples != 0) { + applicationInstance->getAudio()->setJitterBufferSamples(_audioJitterBufferSamples); + } + + _fieldOfView = fieldOfView->value(); + applicationInstance->resizeGL(applicationInstance->getGLWidget()->width(), applicationInstance->getGLWidget()->height()); +} + + +void Menu::bandwidthDetails() { + + if (! _bandwidthDialog) { + _bandwidthDialog = new BandwidthDialog(Application::getInstance()->getGLWidget(), + Application::getInstance()->getBandwidthMeter()); + connect(_bandwidthDialog, SIGNAL(closed()), SLOT(bandwidthDetailsClosed())); + + _bandwidthDialog->show(); + } + _bandwidthDialog->raise(); +} + +void Menu::bandwidthDetailsClosed() { + delete _bandwidthDialog; + _bandwidthDialog = NULL; +} + +void Menu::voxelStatsDetails() { + if (!_voxelStatsDialog) { + _voxelStatsDialog = new VoxelStatsDialog(Application::getInstance()->getGLWidget(), + Application::getInstance()->getVoxelSceneStats()); + connect(_voxelStatsDialog, SIGNAL(closed()), SLOT(voxelStatsDetailsClosed())); + _voxelStatsDialog->show(); + } + _voxelStatsDialog->raise(); +} + +void Menu::voxelStatsDetailsClosed() { + delete _voxelStatsDialog; + _voxelStatsDialog = NULL; +} + +void Menu::cycleFrustumRenderMode() { + _frustumDrawMode = (FrustumDrawMode)((_frustumDrawMode + 1) % FRUSTUM_DRAW_MODE_COUNT); + updateFrustumRenderModeAction(); +} + +void Menu::updateVoxelModeActions() { + // only the sender can be checked + foreach (QAction* action, _voxelModeActionsGroup->actions()) { + if (action->isChecked() && action != sender()) { + action->setChecked(false); + } + } +} + +void Menu::chooseVoxelPaintColor() { + Application* appInstance = Application::getInstance(); + QAction* paintColor = _actionHash.value(MenuOption::VoxelPaintColor); + + QColor selected = QColorDialog::getColor(paintColor->data().value(), + appInstance->getGLWidget(), + "Voxel Paint Color"); + if (selected.isValid()) { + paintColor->setData(selected); + paintColor->setIcon(Swatch::createIcon(selected)); + } + + // restore the main window's active state + appInstance->getWindow()->activateWindow(); +} + +void Menu::runTests() { + runTimingTests(); +} + +void Menu::resetSwatchColors() { + Application::getInstance()->getSwatch()->reset(); +} + +void Menu::updateFrustumRenderModeAction() { + QAction* frustumRenderModeAction = _actionHash.value(MenuOption::FrustumRenderMode); + switch (_frustumDrawMode) { + default: + case FRUSTUM_DRAW_MODE_ALL: + frustumRenderModeAction->setText("Render Mode - All"); + break; + case FRUSTUM_DRAW_MODE_VECTORS: + frustumRenderModeAction->setText("Render Mode - Vectors"); + break; + case FRUSTUM_DRAW_MODE_PLANES: + frustumRenderModeAction->setText("Render Mode - Planes"); + break; + case FRUSTUM_DRAW_MODE_NEAR_PLANE: + frustumRenderModeAction->setText("Render Mode - Near"); + break; + case FRUSTUM_DRAW_MODE_FAR_PLANE: + frustumRenderModeAction->setText("Render Mode - Far"); + break; + case FRUSTUM_DRAW_MODE_KEYHOLE: + frustumRenderModeAction->setText("Render Mode - Keyhole"); + break; + } +} \ No newline at end of file diff --git a/interface/src/Menu.h b/interface/src/Menu.h new file mode 100644 index 0000000000..544a6c0faf --- /dev/null +++ b/interface/src/Menu.h @@ -0,0 +1,198 @@ +// +// Menu.h +// hifi +// +// Created by Stephen Birarda on 8/12/13. +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// + +#ifndef __hifi__Menu__ +#define __hifi__Menu__ + +#include +#include +#include + +enum FrustumDrawMode { + FRUSTUM_DRAW_MODE_ALL, + FRUSTUM_DRAW_MODE_VECTORS, + FRUSTUM_DRAW_MODE_PLANES, + FRUSTUM_DRAW_MODE_NEAR_PLANE, + FRUSTUM_DRAW_MODE_FAR_PLANE, + FRUSTUM_DRAW_MODE_KEYHOLE, + FRUSTUM_DRAW_MODE_COUNT +}; + +struct ViewFrustumOffset { + float yaw; + float pitch; + float roll; + float distance; + float up; +}; + +class Menu : public QMenuBar { + Q_OBJECT +public: + static Menu* getInstance(); + + bool isOptionChecked(const QString& menuOption); + void triggerOption(const QString& menuOption); + QAction* getActionForOption(const QString& menuOption); + bool isVoxelModeActionChecked(); + + float getAudioJitterBufferSamples() const { return _audioJitterBufferSamples; } + float getFieldOfView() const { return _fieldOfView; } + float getGyroCameraSensitivity() const { return _gyroCameraSensitivity; } + BandwidthDialog* getBandwidthDialog() const { return _bandwidthDialog; } + FrustumDrawMode getFrustumDrawMode() const { return _frustumDrawMode; } + ViewFrustumOffset getViewFrustumOffset() const { return _viewFrustumOffset; } + VoxelStatsDialog* getVoxelStatsDialog() const { return _voxelStatsDialog; } + + void handleViewFrustumOffsetKeyModifier(int key); + +public slots: + void bandwidthDetails(); + void voxelStatsDetails(); + void loadSettings(QSettings* settings = NULL); + void saveSettings(QSettings* settings = NULL); + void importSettings(); + void exportSettings(); + +private slots: + void editPreferences(); + void bandwidthDetailsClosed(); + void voxelStatsDetailsClosed(); + void cycleFrustumRenderMode(); + void updateVoxelModeActions(); + void chooseVoxelPaintColor(); + void runTests(); + void resetSwatchColors(); + +private: + static Menu* _instance; + + Menu(); + + typedef void(*settingsAction)(QSettings*, QAction*); + static void loadAction(QSettings* set, QAction* action); + static void saveAction(QSettings* set, QAction* action); + void scanMenuBar(settingsAction modifySetting, QSettings* set); + void scanMenu(QMenu* menu, settingsAction modifySetting, QSettings* set); + + QAction* addActionToQMenuAndActionHash(QMenu* destinationMenu, + const QString actionName, + const QKeySequence& shortcut = 0, + const QObject* receiver = NULL, + const char* member = NULL); + QAction* addCheckableActionToQMenuAndActionHash(QMenu* destinationMenu, + const QString actionName, + const QKeySequence& shortcut = 0, + const bool checked = false, + const QObject* receiver = NULL, + const char* member = NULL); + + void updateFrustumRenderModeAction(); + + QHash _actionHash; + int _audioJitterBufferSamples; /// number of extra samples to wait before starting audio playback + BandwidthDialog* _bandwidthDialog; + float _fieldOfView; /// in Degrees, doesn't apply to HMD like Oculus + FrustumDrawMode _frustumDrawMode; + float _gyroCameraSensitivity; + ViewFrustumOffset _viewFrustumOffset; + QActionGroup* _voxelModeActionsGroup; + VoxelStatsDialog* _voxelStatsDialog; +}; + +namespace MenuOption { + + const QString Avatars = "Avatars"; + const QString AvatarAsBalls = "Avatar as Balls"; + const QString Atmosphere = "Atmosphere"; + const QString Bandwidth = "Bandwidth Display"; + const QString BandwidthDetails = "Bandwidth Details"; + const QString Collisions = "Collisions"; + const QString CopyVoxels = "Copy Voxels"; + const QString CoverageMap = "Render Coverage Map"; + const QString CoverageMapV2 = "Render Coverage Map V2"; + const QString CutVoxels = "Cut Voxels"; + const QString DecreaseAvatarSize = "Decrease Avatar Size"; + const QString DecreaseVoxelSize = "Decrease Voxel Size"; + const QString DestructiveAddVoxel = "Create Voxel is Destructive"; + const QString DeltaSending = "Delta Sending"; + const QString DisplayFrustum = "Display Frustum"; + const QString EchoAudio = "Echo Audio"; + const QString ExportVoxels = "Export Voxels"; + const QString HeadMouse = "Head Mouse"; + const QString FaceMode = "Cycle Face Mode"; + const QString FalseColorByDistance = "FALSE Color By Distance"; + const QString FalseColorBySource = "FALSE Color By Source"; + const QString FalseColorEveryOtherVoxel = "FALSE Color Every Other Randomly"; + const QString FalseColorOccluded = "FALSE Color Occluded Voxels"; + const QString FalseColorOccludedV2 = "FALSE Color Occluded V2 Voxels"; + const QString FalseColorOutOfView = "FALSE Color Voxel Out of View"; + const QString FalseColorRandomly = "FALSE Color Voxels Randomly"; + const QString FirstPerson = "First Person"; + const QString FrameTimer = "Show Timer"; + const QString FrustumRenderMode = "Render Mode"; + const QString Fullscreen = "Fullscreen"; + const QString ImportVoxels = "Import Voxels"; + const QString ImportVoxelsClipboard = "Import Voxels to Clipboard"; + const QString IncreaseAvatarSize = "Increase Avatar Size"; + const QString IncreaseVoxelSize = "Increase Voxel Size"; + const QString KillLocalVoxels = "Kill Local Voxels"; + const QString GoHome = "Go Home"; + const QString Gravity = "Use Gravity"; + const QString GroundPlane = "Ground Plane"; + const QString GyroLook = "Smooth Gyro Look"; + const QString ListenModeNormal = "Listen Mode Normal"; + const QString ListenModePoint = "Listen Mode Point"; + const QString ListenModeSingleSource = "Listen Mode Single Source"; + const QString Log = "Log"; + const QString LookAtIndicator = "Look-at Indicator"; + const QString LookAtVectors = "Look-at Vectors"; + const QString LowRes = "Lower Resolution While Moving"; + const QString Mirror = "Mirror"; + const QString OcclusionCulling = "Occlusion Culling"; + const QString Oscilloscope = "Audio Oscilloscope"; + const QString Pair = "Pair"; + const QString PasteVoxels = "Paste Voxels"; + const QString PipelineWarnings = "Show Render Pipeline Warnings"; + const QString Preferences = "Preferences..."; + const QString RandomizeVoxelColors = "Randomize Voxel TRUE Colors"; + const QString ResetAvatarSize = "Reset Avatar Size"; + const QString ResetSwatchColors = "Reset Swatch Colors"; + const QString RunTimingTests = "Run Timing Tests"; + const QString SendVoxelColors = "Colored Voxels"; + const QString SettingsAutosave = "Autosave"; + const QString SettingsLoad = "Load Settings"; + const QString SettingsSave = "Save Settings"; + const QString SettingsImport = "Import Settings"; + const QString SettingsExport = "Export Settings"; + const QString ShowTrueColors = "Show TRUE Colors"; + const QString SimulateLeapHand = "Simulate Leap Hand"; + const QString SkeletonTracking = "Skeleton Tracking"; + const QString Stars = "Stars"; + const QString Stats = "Stats"; + const QString TestPing = "Test Ping"; + const QString TestRaveGlove = "Test Rave Glove"; + const QString TreeStats = "Calculate Tree Stats"; + const QString TransmitterDrive = "Transmitter Drive"; + const QString Quit = "Quit"; + const QString Webcam = "Webcam"; + const QString WebcamMode = "Cycle Webcam Send Mode"; + const QString WebcamTexture = "Webcam Texture"; + const QString Voxels = "Voxels"; + const QString VoxelAddMode = "Add Voxel Mode"; + const QString VoxelColorMode = "Color Voxel Mode"; + const QString VoxelDeleteMode = "Delete Voxel Mode"; + const QString VoxelGetColorMode = "Get Color Mode"; + const QString VoxelMode = "Cycle Voxel Mode"; + const QString VoxelPaintColor = "Voxel Paint Color"; + const QString VoxelSelectMode = "Select Voxel Mode"; + const QString VoxelStats = "Voxel Stats"; + const QString VoxelTextures = "Voxel Textures"; +} + +#endif /* defined(__hifi__Menu__) */ diff --git a/interface/src/PairingHandler.cpp b/interface/src/PairingHandler.cpp index 920f2c519c..c220c5f943 100644 --- a/interface/src/PairingHandler.cpp +++ b/interface/src/PairingHandler.cpp @@ -17,6 +17,16 @@ const char PAIRING_SERVER_HOSTNAME[] = "pairing.highfidelity.io"; const int PAIRING_SERVER_PORT = 7247; +PairingHandler* PairingHandler::getInstance() { + static PairingHandler* instance = NULL; + + if (!instance) { + instance = new PairingHandler(); + } + + return instance; +} + void PairingHandler::sendPairRequest() { // grab the node socket from the NodeList singleton UDPSocket *nodeSocket = NodeList::getInstance()->getNodeSocket(); diff --git a/interface/src/PairingHandler.h b/interface/src/PairingHandler.h index d201465898..68d9f7de5a 100644 --- a/interface/src/PairingHandler.h +++ b/interface/src/PairingHandler.h @@ -9,11 +9,14 @@ #ifndef __hifi__PairingHandler__ #define __hifi__PairingHandler__ -#include +#include -class PairingHandler { +class PairingHandler : public QObject { + Q_OBJECT public: - static void sendPairRequest(); + static PairingHandler* getInstance(); +public slots: + void sendPairRequest(); }; #endif /* defined(__hifi__PairingHandler__) */ diff --git a/interface/src/Swatch.cpp b/interface/src/Swatch.cpp index ea8516e9a8..d3d2a2341b 100644 --- a/interface/src/Swatch.cpp +++ b/interface/src/Swatch.cpp @@ -1,6 +1,20 @@ +// +// Swatch.h +// interface +// +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + #include "Swatch.h" #include +QIcon Swatch::createIcon(const QColor& color) { + QPixmap map(16, 16); + map.fill(color); + return QIcon(map); +} + + Swatch::Swatch(QAction* action) : Tool(action, 0, -1, -1), _textRenderer(MONO_FONT_FAMILY, 10, 100), diff --git a/interface/src/Swatch.h b/interface/src/Swatch.h index e167cd05c4..e1245fb4f3 100644 --- a/interface/src/Swatch.h +++ b/interface/src/Swatch.h @@ -23,6 +23,8 @@ static const int colorBase[8][3] = {{237, 175, 0}, class Swatch : public Tool { public: + static QIcon createIcon(const QColor& color); + Swatch(QAction* action); QColor getColor(); diff --git a/interface/src/VoxelEditPacketSender.cpp b/interface/src/VoxelEditPacketSender.cpp index c663977268..3716e16208 100644 --- a/interface/src/VoxelEditPacketSender.cpp +++ b/interface/src/VoxelEditPacketSender.cpp @@ -11,6 +11,7 @@ #include #include "Application.h" +#include "Menu.h" #include "VoxelEditPacketSender.h" VoxelEditPacketSender::VoxelEditPacketSender(Application* app) : @@ -21,7 +22,7 @@ VoxelEditPacketSender::VoxelEditPacketSender(Application* app) : void VoxelEditPacketSender::sendVoxelEditMessage(PACKET_TYPE type, VoxelDetail& detail) { // if the app has Voxels disabled, we don't do any of this... - if (!_app->_renderVoxels->isChecked()) { + if (!Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) { return; // bail early } diff --git a/interface/src/VoxelPacketProcessor.cpp b/interface/src/VoxelPacketProcessor.cpp index 558037b0bc..40101b9b77 100644 --- a/interface/src/VoxelPacketProcessor.cpp +++ b/interface/src/VoxelPacketProcessor.cpp @@ -11,6 +11,7 @@ #include #include "Application.h" +#include "Menu.h" #include "VoxelPacketProcessor.h" VoxelPacketProcessor::VoxelPacketProcessor(Application* app) : @@ -18,7 +19,8 @@ VoxelPacketProcessor::VoxelPacketProcessor(Application* app) : } void VoxelPacketProcessor::processPacket(sockaddr& senderAddress, unsigned char* packetData, ssize_t packetLength) { - PerformanceWarning warn(_app->_renderPipelineWarnings->isChecked(),"VoxelPacketProcessor::processPacket()"); + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "VoxelPacketProcessor::processPacket()"); ssize_t messageLength = packetLength; // check to see if the UI thread asked us to kill the voxel tree. since we're the only thread allowed to do that @@ -44,7 +46,7 @@ void VoxelPacketProcessor::processPacket(sockaddr& senderAddress, unsigned char* } } // fall through to piggyback message - if (_app->_renderVoxels->isChecked()) { + if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) { Node* voxelServer = NodeList::getInstance()->nodeWithAddress(&senderAddress); if (voxelServer && socketMatch(voxelServer->getActiveSocket(), &senderAddress)) { voxelServer->lock(); diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index becf9f868f..974595216b 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -28,6 +28,7 @@ #include "CoverageMap.h" #include "CoverageMapV2.h" #include "InterfaceConfig.h" +#include "Menu.h" #include "renderer/ProgramObject.h" #include "VoxelConstants.h" #include "VoxelSystem.h" @@ -173,14 +174,16 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { switch(command) { case PACKET_TYPE_VOXEL_DATA: { - PerformanceWarning warn(_renderWarningsOn, "readBitstreamToTree()"); + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "readBitstreamToTree()"); // ask the VoxelTree to read the bitstream into the tree ReadBitstreamToTreeParams args(WANT_COLOR, WANT_EXISTS_BITS, NULL, getDataSourceID()); _tree->readBitstreamToTree(voxelData, numBytes - numBytesPacketHeader, args); } break; case PACKET_TYPE_VOXEL_DATA_MONOCHROME: { - PerformanceWarning warn(_renderWarningsOn, "readBitstreamToTree()"); + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "readBitstreamToTree()"); // ask the VoxelTree to read the MONOCHROME bitstream into the tree ReadBitstreamToTreeParams args(NO_COLOR, WANT_EXISTS_BITS, NULL, getDataSourceID()); _tree->readBitstreamToTree(voxelData, numBytes - numBytesPacketHeader, args); @@ -222,7 +225,8 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { } void VoxelSystem::setupNewVoxelsForDrawing() { - PerformanceWarning warn(_renderWarningsOn, "setupNewVoxelsForDrawing()"); // would like to include _voxelsInArrays, _voxelsUpdated + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "setupNewVoxelsForDrawing()"); // would like to include _voxelsInArrays, _voxelsUpdated uint64_t start = usecTimestampNow(); uint64_t sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished) / 1000; @@ -257,10 +261,10 @@ void VoxelSystem::setupNewVoxelsForDrawing() { bool didWriteFullVBO = _writeRenderFullVBO; if (_tree->isDirty()) { static char buffer[64] = { 0 }; - if (_renderWarningsOn) { + if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) { sprintf(buffer, "newTreeToArrays() _writeRenderFullVBO=%s", debug::valueOf(_writeRenderFullVBO)); }; - PerformanceWarning warn(_renderWarningsOn, buffer); + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), buffer); _callsToTreesToArrays++; if (_writeRenderFullVBO) { _voxelsInWriteArrays = 0; // reset our VBO @@ -299,7 +303,7 @@ void VoxelSystem::setupNewVoxelsForDrawing() { } void VoxelSystem::cleanupRemovedVoxels() { - PerformanceWarning warn(_renderWarningsOn, "cleanupRemovedVoxels()"); + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "cleanupRemovedVoxels()"); // This handles cleanup of voxels that were culled as part of our regular out of view culling operation if (!_removedVoxels.isEmpty()) { while (!_removedVoxels.isEmpty()) { @@ -375,7 +379,8 @@ void VoxelSystem::copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, } void VoxelSystem::copyWrittenDataToReadArrays(bool fullVBOs) { - PerformanceWarning warn(_renderWarningsOn, "copyWrittenDataToReadArrays()"); + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "copyWrittenDataToReadArrays()"); if (_voxelsDirty && _voxelsUpdated) { if (fullVBOs) { copyWrittenDataToReadArraysFullVBOs(); @@ -509,8 +514,6 @@ glm::vec3 VoxelSystem::computeVoxelVertex(const glm::vec3& startVertex, float vo ProgramObject* VoxelSystem::_perlinModulateProgram = 0; void VoxelSystem::init() { - - _renderWarningsOn = false; _callsToTreesToArrays = 0; _setupNewVoxelsForDrawingLastFinished = 0; _setupNewVoxelsForDrawingLastElapsed = 0; @@ -641,10 +644,11 @@ void VoxelSystem::updatePartialVBOs() { void VoxelSystem::updateVBOs() { static char buffer[40] = { 0 }; - if (_renderWarningsOn) { + if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) { sprintf(buffer, "updateVBOs() _readRenderFullVBO=%s", debug::valueOf(_readRenderFullVBO)); }; - PerformanceWarning warn(_renderWarningsOn, buffer); // would like to include _callsToTreesToArrays + // would like to include _callsToTreesToArrays + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), buffer); if (_voxelsDirty) { if (_readRenderFullVBO) { updateFullVBOs(); @@ -672,7 +676,7 @@ void VoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferIndex seg } void VoxelSystem::render(bool texture) { - PerformanceWarning warn(_renderWarningsOn, "render()"); + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "render()"); // get the lock so that the update thread won't change anything pthread_mutex_lock(&_bufferWriteLock); @@ -808,7 +812,9 @@ bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, void* extraData) return true; // keep going! } -void VoxelSystem::falseColorizeInView(ViewFrustum* viewFrustum) { +void VoxelSystem::falseColorizeInView() { + ViewFrustum* viewFrustum = Application::getInstance()->getViewFrustum(); + _nodeCount = 0; _tree->recurseTreeWithOperation(falseColorizeInViewOperation,(void*)viewFrustum); qDebug("setting in view false color for %d nodes\n", _nodeCount); @@ -935,14 +941,16 @@ bool VoxelSystem::getDistanceFromViewRangeOperation(VoxelNode* node, void* extra return true; // keep going! } -void VoxelSystem::falseColorizeDistanceFromView(ViewFrustum* viewFrustum) { +void VoxelSystem::falseColorizeDistanceFromView() { + ViewFrustum* viewFrustum = Application::getInstance()->getViewFrustum(); + _nodeCount = 0; _maxDistance = 0.0; _minDistance = FLT_MAX; - _tree->recurseTreeWithOperation(getDistanceFromViewRangeOperation,(void*)viewFrustum); + _tree->recurseTreeWithOperation(getDistanceFromViewRangeOperation, (void*) viewFrustum); qDebug("determining distance range for %d nodes\n", _nodeCount); _nodeCount = 0; - _tree->recurseTreeWithOperation(falseColorizeDistanceFromViewOperation,(void*)viewFrustum); + _tree->recurseTreeWithOperation(falseColorizeDistanceFromViewOperation, (void*) viewFrustum); qDebug("setting in distance false color for %d nodes\n", _nodeCount); _tree->setDirtyBit(); setupNewVoxelsForDrawing(); @@ -1047,7 +1055,7 @@ bool VoxelSystem::hasViewChanged() { } void VoxelSystem::removeOutOfView() { - PerformanceWarning warn(_renderWarningsOn, "removeOutOfView()"); + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "removeOutOfView()"); removeOutOfViewArgs args(this); _tree->recurseTreeWithOperation(removeOutOfViewOperation,(void*)&args); diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 94e2d42e5e..c55bd552db 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -1,13 +1,13 @@ // -// Cube.h +// VoxelSystem.h // interface // // Created by Philip on 12/31/12. // Copyright (c) 2012 High Fidelity, Inc. All rights reserved. // -#ifndef __interface__Cube__ -#define __interface__Cube__ +#ifndef __interface__VoxelSystem__ +#define __interface__VoxelSystem__ #include "InterfaceConfig.h" #include @@ -29,6 +29,7 @@ class ProgramObject; const int NUM_CHILDREN = 8; class VoxelSystem : public NodeData, public VoxelNodeDeleteHook, public NodeListHook { + Q_OBJECT public: VoxelSystem(float treeScale = TREE_SCALE, int maxVoxels = MAX_VOXELS_PER_SYSTEM); ~VoxelSystem(); @@ -56,21 +57,7 @@ public: float getVoxelsColoredPerSecondAverage(); float getVoxelsBytesReadPerSecondAverage(); - // Methods that recurse tree - void randomizeVoxelColors(); - void falseColorizeRandom(); - void trueColorize(); - void falseColorizeInView(ViewFrustum* viewFrustum); - void falseColorizeDistanceFromView(ViewFrustum* viewFrustum); - void falseColorizeRandomEveryOther(); - void falseColorizeOccluded(); - void falseColorizeOccludedV2(); - void falseColorizeBySource(); - - void killLocalVoxels(); - void setRenderPipelineWarnings(bool on) { _renderWarningsOn = on; }; - bool getRenderPipelineWarnings() const { return _renderWarningsOn; }; virtual void removeOutOfView(); bool hasViewChanged(); @@ -81,8 +68,6 @@ public: bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration); bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration); - - void collectStatsForTreesAndVBOs(); void deleteVoxelAt(float x, float y, float z, float s); VoxelNode* getVoxelAt(float x, float y, float z, float s) const; @@ -101,6 +86,20 @@ public: virtual void nodeDeleted(VoxelNode* node); virtual void nodeAdded(Node* node); virtual void nodeKilled(Node* node); + +public slots: + void collectStatsForTreesAndVBOs(); + + // Methods that recurse tree + void randomizeVoxelColors(); + void falseColorizeRandom(); + void trueColorize(); + void falseColorizeInView(); + void falseColorizeDistanceFromView(); + void falseColorizeRandomEveryOther(); + void falseColorizeOccluded(); + void falseColorizeOccludedV2(); + void falseColorizeBySource(); protected: float _treeScale; @@ -126,7 +125,6 @@ private: int _callsToTreesToArrays; VoxelNodeBag _removedVoxels; - bool _renderWarningsOn; // Operation functions for tree recursion methods static int _nodeCount; static bool randomColorOperation(VoxelNode* node, void* extraData); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index e561720eaf..2879c7ded0 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -63,6 +63,28 @@ bool usingBigSphereCollisionTest = true; float chatMessageScale = 0.0015; float chatMessageHeight = 0.20; +void Avatar::sendAvatarVoxelURLMessage(const QUrl& url) { + uint16_t ownerID = NodeList::getInstance()->getOwnerID(); + + if (ownerID == UNKNOWN_NODE_ID) { + return; // we don't yet know who we are + } + + QByteArray message; + + char packetHeader[MAX_PACKET_HEADER_BYTES]; + int numBytesPacketHeader = populateTypeAndVersion((unsigned char*) packetHeader, PACKET_TYPE_AVATAR_VOXEL_URL); + + message.append(packetHeader, numBytesPacketHeader); + message.append((const char*)&ownerID, sizeof(ownerID)); + message.append(url.toEncoded()); + + Application::controlledBroadcastToNodes((unsigned char*)message.data(), + message.size(), + &NODE_TYPE_AVATAR_MIXER, + 1); +} + Avatar::Avatar(Node* owningNode) : AvatarData(owningNode), _initialized(false), @@ -1632,6 +1654,30 @@ void Avatar::renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, glEnd(); } +void Avatar::goHome() { + qDebug("Going Home!\n"); + setPosition(START_LOCATION); +} + +void Avatar::increaseSize() { + if ((1.f + SCALING_RATIO) * _newScale < MAX_SCALE) { + _newScale *= (1.f + SCALING_RATIO); + qDebug("Changed scale to %f\n", _newScale); + } +} + +void Avatar::decreaseSize() { + if (MIN_SCALE < (1.f - SCALING_RATIO) * _newScale) { + _newScale *= (1.f - SCALING_RATIO); + qDebug("Changed scale to %f\n", _newScale); + } +} + +void Avatar::resetSize() { + _newScale = 1.0f; + qDebug("Reseted scale to %f\n", _newScale); +} + void Avatar::setNewScale(const float scale) { _newScale = scale; } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 29a79047ed..9d77e922ad 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -58,8 +58,7 @@ const float BODY_BALL_RADIUS_RIGHT_KNEE = 0.025; const float BODY_BALL_RADIUS_RIGHT_HEEL = 0.025; const float BODY_BALL_RADIUS_RIGHT_TOES = 0.025; -enum AvatarBodyBallID -{ +enum AvatarBodyBallID { BODY_BALL_NULL = -1, BODY_BALL_PELVIS, BODY_BALL_TORSO, @@ -91,8 +90,7 @@ enum AvatarBodyBallID NUM_AVATAR_BODY_BALLS }; -enum DriveKeys -{ +enum DriveKeys { FWD = 0, BACK, LEFT, @@ -104,16 +102,14 @@ enum DriveKeys MAX_DRIVE_KEYS }; -enum AvatarMode -{ +enum AvatarMode { AVATAR_MODE_STANDING = 0, AVATAR_MODE_WALKING, AVATAR_MODE_INTERACTING, NUM_AVATAR_MODES }; -enum ScreenTintLayer -{ +enum ScreenTintLayer { SCREEN_TINT_BEFORE_LANDSCAPE = 0, SCREEN_TINT_BEFORE_AVATARS, SCREEN_TINT_BEFORE_MY_AVATAR, @@ -121,8 +117,16 @@ enum ScreenTintLayer NUM_SCREEN_TINT_LAYERS }; +// Where one's own Avatar begins in the world (will be overwritten if avatar data file is found) +// this is basically in the center of the ground plane. Slightly adjusted. This was asked for by +// Grayson as he's building a street around here for demo dinner 2 +const glm::vec3 START_LOCATION(0.485f * TREE_SCALE, 0.f, 0.5f * TREE_SCALE); + class Avatar : public AvatarData { + Q_OBJECT public: + static void sendAvatarVoxelURLMessage(const QUrl& url); + Avatar(Node* owningNode = NULL); ~Avatar(); @@ -139,52 +143,51 @@ public: void renderScreenTint(ScreenTintLayer layer, Camera& whichCamera); //setters - void setMousePressed (bool mousePressed ) { _mousePressed = mousePressed;} - void setNoise (float mag ) { _head.noise = mag;} - void setMovedHandOffset (glm::vec3 movedHandOffset ) { _movedHandOffset = movedHandOffset;} - void setThrust (glm::vec3 newThrust ) { _thrust = newThrust; }; - void setDisplayingLookatVectors(bool displayingLookatVectors) { _head.setRenderLookatVectors(displayingLookatVectors);} - void setVelocity (const glm::vec3 velocity ) { _velocity = velocity; }; - void setLeanScale (float scale ) { _leanScale = scale;} - void setGravity (glm::vec3 gravity); - void setMouseRay (const glm::vec3 &origin, const glm::vec3 &direction); - void setOrientation (const glm::quat& orientation); - void setNewScale (const float scale); - void setWantCollisionsOn (bool wantCollisionsOn ) { _isCollisionsOn = wantCollisionsOn; } + void setMousePressed(bool mousePressed) { _mousePressed = mousePressed; } + void setMovedHandOffset(glm::vec3 movedHandOffset) { _movedHandOffset = movedHandOffset;} + void setThrust(glm::vec3 newThrust) { _thrust = newThrust; } + void setDisplayingLookatVectors(bool displayingLookatVectors) { _head.setRenderLookatVectors(displayingLookatVectors); } + void setVelocity(const glm::vec3 velocity) { _velocity = velocity; }; + void setLeanScale(float scale) { _leanScale = scale;} + + void setGravity(glm::vec3 gravity); + void setMouseRay(const glm::vec3 &origin, const glm::vec3 &direction); + void setOrientation(const glm::quat& orientation); + void setNewScale(const float scale); //getters - bool isInitialized () const { return _initialized;} - bool isMyAvatar () const { return _owningNode == NULL; } - const Skeleton& getSkeleton () const { return _skeleton;} - float getHeadYawRate () const { return _head.yawRate;} - float getBodyYaw () const { return _bodyYaw;} - bool getIsNearInteractingOther () const { return _avatarTouch.getAbleToReachOtherAvatar();} - const glm::vec3& getHeadJointPosition () const { return _skeleton.joint[ AVATAR_JOINT_HEAD_BASE ].position;} - const glm::vec3& getBallPosition (AvatarJointID j) const { return _bodyBall[j].position;} - glm::vec3 getBodyRightDirection () const { return getOrientation() * IDENTITY_RIGHT; } - glm::vec3 getBodyUpDirection () const { return getOrientation() * IDENTITY_UP; } - glm::vec3 getBodyFrontDirection () const { return getOrientation() * IDENTITY_FRONT; } - float getScale () const { return _scale;} - float getNewScale () const { return _newScale;} - const glm::vec3& getVelocity () const { return _velocity;} - float getSpeed () const { return _speed;} - float getHeight () const { return _height;} - AvatarMode getMode () const { return _mode;} - float getLeanScale () const { return _leanScale;} - float getElapsedTimeStopped () const { return _elapsedTimeStopped;} - float getElapsedTimeMoving () const { return _elapsedTimeMoving;} - float getElapsedTimeSinceCollision() const { return _elapsedTimeSinceCollision;} - const glm::vec3& getLastCollisionPosition () const { return _lastCollisionPosition;} - float getAbsoluteHeadYaw () const; - float getAbsoluteHeadPitch () const; - Head& getHead () {return _head; } - Hand& getHand () {return _hand; } - glm::quat getOrientation () const; - glm::quat getWorldAlignedOrientation() const; - const glm::vec3& getMouseRayOrigin () const { return _mouseRayOrigin; } - const glm::vec3& getMouseRayDirection () const { return _mouseRayDirection; } - Avatar* getLeadingAvatar () const { return _leadingAvatar; } - glm::vec3 getGravity () const { return _gravity; } + bool isInitialized() const { return _initialized;} + bool isMyAvatar() const { return _owningNode == NULL; } + const Skeleton& getSkeleton() const { return _skeleton;} + float getHeadYawRate() const { return _head.yawRate;} + float getBodyYaw() const { return _bodyYaw;} + bool getIsNearInteractingOther() const { return _avatarTouch.getAbleToReachOtherAvatar();} + const glm::vec3& getHeadJointPosition() const { return _skeleton.joint[ AVATAR_JOINT_HEAD_BASE ].position;} + const glm::vec3& getBallPosition(AvatarJointID j) const { return _bodyBall[j].position;} + glm::vec3 getBodyRightDirection() const { return getOrientation() * IDENTITY_RIGHT; } + glm::vec3 getBodyUpDirection() const { return getOrientation() * IDENTITY_UP; } + glm::vec3 getBodyFrontDirection() const { return getOrientation() * IDENTITY_FRONT; } + float getScale() const { return _scale;} + float getNewScale() const { return _newScale;} + const glm::vec3& getVelocity() const { return _velocity;} + float getSpeed() const { return _speed;} + float getHeight() const { return _height;} + AvatarMode getMode() const { return _mode;} + float getLeanScale() const { return _leanScale;} + float getElapsedTimeStopped() const { return _elapsedTimeStopped;} + float getElapsedTimeMoving() const { return _elapsedTimeMoving;} + float getElapsedTimeSinceCollision() const { return _elapsedTimeSinceCollision;} + const glm::vec3& getLastCollisionPosition() const { return _lastCollisionPosition;} + float getAbsoluteHeadYaw() const; + float getAbsoluteHeadPitch() const; + Head& getHead() {return _head; } + Hand& getHand() {return _hand; } + glm::quat getOrientation() const; + glm::quat getWorldAlignedOrientation() const; + const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; } + const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; } + Avatar* getLeadingAvatar() const { return _leadingAvatar; } + glm::vec3 getGravity() const { return _gravity; } glm::vec3 getUprightHeadPosition() const; glm::vec3 getUprightEyeLevelPosition() const; @@ -209,14 +212,20 @@ public: void getBodyBallTransform(AvatarJointID jointID, glm::vec3& position, glm::quat& rotation) const; static void renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2); + +public slots: + void setWantCollisionsOn(bool wantCollisionsOn) { _isCollisionsOn = wantCollisionsOn; } + void goHome(); + void increaseSize(); + void decreaseSize(); + void resetSize(); private: // privatize copy constructor and assignment operator to avoid copying Avatar(const Avatar&); Avatar& operator= (const Avatar&); - struct AvatarBall - { + struct AvatarBall { AvatarJointID parentJoint; // the skeletal joint that serves as a reference for determining the position glm::vec3 parentOffset; // a 3D vector in the frame of reference of the parent skeletal joint AvatarBodyBallID parentBall; // the ball to which this ball is constrained for spring forces diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index f35b09895e..160510734f 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -384,6 +384,12 @@ void Head::renderMohawk() { if (!_mohawkTriangleFan) { createMohawk(); + + // if we get here and still don't have a mohawk then we don't know who we are + // so return out since we can't render it yet + if (!_mohawkTriangleFan) { + return; + } } if (USING_PHYSICAL_MOHAWK) { diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 31efc21d48..c6fcac0bd7 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -23,8 +23,7 @@ #include "SerialInterface.h" #include "world.h" -enum eyeContactTargets -{ +enum eyeContactTargets { LEFT_EYE, RIGHT_EYE, MOUTH @@ -45,19 +44,18 @@ public: void render(float alpha); void renderMohawk(); - void setScale (float scale ); - void setPosition (glm::vec3 position ) { _position = position; } - void setBodyRotation (glm::vec3 bodyRotation ) { _bodyRotation = bodyRotation; } - void setGravity (glm::vec3 gravity ) { _gravity = gravity; } - void setSkinColor (glm::vec3 skinColor ) { _skinColor = skinColor; } - void setSpringScale (float returnSpringScale ) { _returnSpringScale = returnSpringScale; } - void setAverageLoudness(float averageLoudness ) { _averageLoudness = averageLoudness; } - void setReturnToCenter (bool returnHeadToCenter) { _returnHeadToCenter = returnHeadToCenter; } - void setRenderLookatVectors(bool onOff ) { _renderLookatVectors = onOff; } - + void setScale(float scale); + void setPosition(glm::vec3 position) { _position = position; } + void setBodyRotation(glm::vec3 bodyRotation) { _bodyRotation = bodyRotation; } + void setGravity(glm::vec3 gravity) { _gravity = gravity; } + void setSkinColor(glm::vec3 skinColor) { _skinColor = skinColor; } + void setSpringScale(float returnSpringScale) { _returnSpringScale = returnSpringScale; } + void setAverageLoudness(float averageLoudness) { _averageLoudness = averageLoudness; } + void setReturnToCenter (bool returnHeadToCenter) { _returnHeadToCenter = returnHeadToCenter; } + void setRenderLookatVectors(bool onOff) { _renderLookatVectors = onOff; } void setCameraFollowsHead(bool cameraFollowsHead) { _cameraFollowsHead = cameraFollowsHead; } - float getMousePitch() { return _mousePitch; } + float getMousePitch() const { return _mousePitch; } void setMousePitch(float mousePitch) { _mousePitch = mousePitch; } glm::quat getOrientation() const; @@ -67,7 +65,7 @@ public: glm::vec3 getPosition() const { return _position; } const glm::vec3& getEyePosition() const { return _eyePosition; } glm::vec3 getRightDirection() const { return getOrientation() * IDENTITY_RIGHT; } - glm::vec3 getUpDirection () const { return getOrientation() * IDENTITY_UP; } + glm::vec3 getUpDirection() const { return getOrientation() * IDENTITY_UP; } glm::vec3 getFrontDirection() const { return getOrientation() * IDENTITY_FRONT; } Face& getFace() { return _face; } @@ -77,61 +75,59 @@ public: glm::vec3 calculateAverageEyePosition() { return _leftEyePosition + (_rightEyePosition - _leftEyePosition ) * ONE_HALF; } float yawRate; - float noise; private: // disallow copies of the Head, copy of owning Avatar is disallowed too Head(const Head&); Head& operator= (const Head&); - struct Nose - { + struct Nose { glm::vec3 top; glm::vec3 left; glm::vec3 right; glm::vec3 front; }; - float _renderAlpha; - bool _returnHeadToCenter; - glm::vec3 _skinColor; - glm::vec3 _position; - glm::vec3 _rotation; - glm::vec3 _leftEyePosition; - glm::vec3 _rightEyePosition; - glm::vec3 _eyePosition; - glm::vec3 _leftEyeBrowPosition; - glm::vec3 _rightEyeBrowPosition; - glm::vec3 _leftEarPosition; - glm::vec3 _rightEarPosition; - glm::vec3 _mouthPosition; - Nose _nose; - float _scale; - float _browAudioLift; - glm::vec3 _gravity; - float _lastLoudness; - float _averageLoudness; - float _audioAttack; - float _returnSpringScale; //strength of return springs - glm::vec3 _bodyRotation; - bool _renderLookatVectors; - BendyLine _hairTuft[NUM_HAIR_TUFTS]; - glm::vec3* _mohawkTriangleFan; - glm::vec3* _mohawkColors; - glm::vec3 _saccade; - glm::vec3 _saccadeTarget; - float _leftEyeBlink; - float _rightEyeBlink; - float _leftEyeBlinkVelocity; - float _rightEyeBlinkVelocity; - float _timeWithoutTalking; - float _cameraPitch; // Used to position the camera differently from the head - float _mousePitch; - float _cameraYaw; - bool _isCameraMoving; - bool _cameraFollowsHead; - float _cameraFollowHeadRate; - Face _face; + float _renderAlpha; + bool _returnHeadToCenter; + glm::vec3 _skinColor; + glm::vec3 _position; + glm::vec3 _rotation; + glm::vec3 _leftEyePosition; + glm::vec3 _rightEyePosition; + glm::vec3 _eyePosition; + glm::vec3 _leftEyeBrowPosition; + glm::vec3 _rightEyeBrowPosition; + glm::vec3 _leftEarPosition; + glm::vec3 _rightEarPosition; + glm::vec3 _mouthPosition; + Nose _nose; + float _scale; + float _browAudioLift; + glm::vec3 _gravity; + float _lastLoudness; + float _averageLoudness; + float _audioAttack; + float _returnSpringScale; //strength of return springs + glm::vec3 _bodyRotation; + bool _renderLookatVectors; + BendyLine _hairTuft[NUM_HAIR_TUFTS]; + glm::vec3* _mohawkTriangleFan; + glm::vec3* _mohawkColors; + glm::vec3 _saccade; + glm::vec3 _saccadeTarget; + float _leftEyeBlink; + float _rightEyeBlink; + float _leftEyeBlinkVelocity; + float _rightEyeBlinkVelocity; + float _timeWithoutTalking; + float _cameraPitch; // Used to position the camera differently from the head + float _mousePitch; + float _cameraYaw; + bool _isCameraMoving; + bool _cameraFollowsHead; + float _cameraFollowHeadRate; + Face _face; static ProgramObject* _irisProgram; static GLuint _irisTextureID; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 98ed4fb231..c1d9bd778d 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -18,12 +18,19 @@ #include "Application.h" #include +#include int main(int argc, const char * argv[]) { timeval startup_time; gettimeofday(&startup_time, NULL); + #if defined(Q_OS_MAC) + const QString QT_RELEASE_PLUGIN_PATH = "/usr/local/lib/qt5/plugins"; + QCoreApplication::addLibraryPath(QT_RELEASE_PLUGIN_PATH); + #endif + Application app(argc, const_cast(argv), startup_time); + qDebug( "Created QT Application.\n" ); int exitCode = app.exec(); qDebug("Normal exit.\n"); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index c3def00140..db328053c0 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -56,8 +56,8 @@ public: const glm::vec3& getPosition() const { return _position; } - void setPosition (const glm::vec3 position ) { _position = position; } - void setHandPosition (const glm::vec3 handPosition ) { _handPosition = handPosition; } + void setPosition(const glm::vec3 position) { _position = position; } + void setHandPosition(const glm::vec3 handPosition) { _handPosition = handPosition; } void setPositionFromVariantMap(QVariantMap positionMap); QVariantMap getPositionVariantMap(); @@ -82,22 +82,22 @@ public: char getHandState() const {return _handState; }; // getters for camera details - const glm::vec3& getCameraPosition() const { return _cameraPosition; }; + const glm::vec3& getCameraPosition() const { return _cameraPosition; }; const glm::quat& getCameraOrientation() const { return _cameraOrientation; } - float getCameraFov() const { return _cameraFov; } - float getCameraAspectRatio() const { return _cameraAspectRatio; } - float getCameraNearClip() const { return _cameraNearClip; } - float getCameraFarClip() const { return _cameraFarClip; } + float getCameraFov() const { return _cameraFov; } + float getCameraAspectRatio() const { return _cameraAspectRatio; } + float getCameraNearClip() const { return _cameraNearClip; } + float getCameraFarClip() const { return _cameraFarClip; } glm::vec3 calculateCameraDirection() const; // setters for camera details - void setCameraPosition(const glm::vec3& position) { _cameraPosition = position; } + void setCameraPosition(const glm::vec3& position) { _cameraPosition = position; } void setCameraOrientation(const glm::quat& orientation) { _cameraOrientation = orientation; } - void setCameraFov(float fov) { _cameraFov = fov; } - void setCameraAspectRatio(float aspectRatio) { _cameraAspectRatio = aspectRatio; } - void setCameraNearClip(float nearClip) { _cameraNearClip = nearClip; } - void setCameraFarClip(float farClip) { _cameraFarClip = farClip; } + void setCameraFov(float fov) { _cameraFov = fov; } + void setCameraAspectRatio(float aspectRatio) { _cameraAspectRatio = aspectRatio; } + void setCameraNearClip(float nearClip) { _cameraNearClip = nearClip; } + void setCameraFarClip(float farClip) { _cameraFarClip = farClip; } // key state void setKeyState(KeyState s) { _keyState = s; } @@ -110,22 +110,21 @@ public: QString getQStringChatMessage() { return QString(_chatMessage.data()); } // related to Voxel Sending strategies - bool getWantColor() const { return _wantColor; } - bool getWantDelta() const { return _wantDelta; } - bool getWantLowResMoving() const { return _wantLowResMoving; } + bool getWantColor() const { return _wantColor; } + bool getWantDelta() const { return _wantDelta; } + bool getWantLowResMoving() const { return _wantLowResMoving; } bool getWantOcclusionCulling() const { return _wantOcclusionCulling; } - uint16_t getLeaderID() const { return _leaderID; } - - void setWantColor(bool wantColor) { _wantColor = wantColor; } - void setWantDelta(bool wantDelta) { _wantDelta = wantDelta; } - void setWantLowResMoving(bool wantLowResMoving) { _wantLowResMoving = wantLowResMoving; } - void setWantOcclusionCulling(bool wantOcclusionCulling) { _wantOcclusionCulling = wantOcclusionCulling; } + uint16_t getLeaderID() const { return _leaderID; } void setHeadData(HeadData* headData) { _headData = headData; } void setHandData(HandData* handData) { _handData = handData; } public slots: void sendData(); + void setWantLowResMoving(bool wantLowResMoving) { _wantLowResMoving = wantLowResMoving; } + void setWantColor(bool wantColor) { _wantColor = wantColor; } + void setWantDelta(bool wantDelta) { _wantDelta = wantDelta; } + void setWantOcclusionCulling(bool wantOcclusionCulling) { _wantOcclusionCulling = wantOcclusionCulling; } protected: glm::vec3 _position; diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 23b39df205..8850d34e87 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -63,7 +63,7 @@ NodeList::NodeList(char newOwnerType, unsigned short int newSocketListenPort) : _ownerType(newOwnerType), _nodeTypesOfInterest(NULL), _ownerID(UNKNOWN_NODE_ID), - _lastNodeID(0) + _lastNodeID(UNKNOWN_NODE_ID + 1) { memcpy(_domainHostname, DEFAULT_DOMAIN_HOSTNAME, sizeof(DEFAULT_DOMAIN_HOSTNAME)); memcpy(_domainIP, DEFAULT_DOMAIN_IP, sizeof(DEFAULT_DOMAIN_IP)); diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 84bc4f6151..6f0e6827e9 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -41,7 +41,7 @@ extern const char DEFAULT_DOMAIN_HOSTNAME[MAX_HOSTNAME_BYTES]; extern const char DEFAULT_DOMAIN_IP[INET_ADDRSTRLEN]; // IP Address will be re-set by lookup on startup extern const int DEFAULT_DOMAINSERVER_PORT; -const int UNKNOWN_NODE_ID = -1; +const int UNKNOWN_NODE_ID = 0; class NodeListIterator;