Showing the changes to interface/src/Application.cpp (1 of 665 files). Show all
Unified · Split
| @@ -78,6 +78,7 @@ · 77 unmodified lines | ||
| 78 | 78 | #include <InfoView.h> |
| 79 | 79 | #include <input-plugins/InputPlugin.h> |
| 80 | 80 | #include <controllers/UserInputMapper.h> |
| 81 | +#include <controllers/InputRecorder.h> | |
| 81 | 82 | #include <controllers/ScriptingInterface.h> |
| 82 | 83 | #include <controllers/StateController.h> |
| 83 | 84 | #include <UserActivityLoggerScriptingInterface.h> |
| @@ -127,20 +128,19 @@ · 43 unmodified lines | ||
| 127 | 128 | #include <QmlWebWindowClass.h> |
| 128 | 129 | #include <Preferences.h> |
| 129 | 130 | #include <display-plugins/CompositorHelper.h> |
| 130 | − | |
| 131 | +#include <trackers/EyeTracker.h> | |
| 132 | +#include <avatars-renderer/ScriptAvatar.h> | |
| 131 | 133 | |
| 132 | 134 | #include "AudioClient.h" |
| 133 | 135 | #include "audio/AudioScope.h" |
| 134 | 136 | #include "avatar/AvatarManager.h" |
| 135 | −#include "avatar/ScriptAvatar.h" | |
| 137 | +#include "avatar/MyHead.h" | |
| 136 | 138 | #include "CrashHandler.h" |
| 137 | 139 | #include "devices/DdeFaceTracker.h" |
| 138 | −#include "devices/EyeTracker.h" | |
| 139 | −#include "devices/Faceshift.h" | |
| 140 | 140 | #include "devices/Leapmotion.h" |
| 141 | 141 | #include "DiscoverabilityManager.h" |
| 142 | 142 | #include "GLCanvas.h" |
| 143 | −#include "InterfaceActionFactory.h" | |
| 143 | +#include "InterfaceDynamicFactory.h" | |
| 144 | 144 | #include "InterfaceLogging.h" |
| 145 | 145 | #include "LODManager.h" |
| 146 | 146 | #include "ModelPackager.h" |
| @@ -462,7 +462,7 @@ bool setupEssentials(int& argc, char** argv) { · 315 unmodified lines | ||
| 462 | 462 | |
| 463 | 463 | DependencyManager::registerInheritance<LimitedNodeList, NodeList>(); |
| 464 | 464 | DependencyManager::registerInheritance<AvatarHashMap, AvatarManager>(); |
| 465 | − DependencyManager::registerInheritance<EntityActionFactoryInterface, InterfaceActionFactory>(); | |
| 465 | + DependencyManager::registerInheritance<EntityDynamicFactoryInterface, InterfaceDynamicFactory>(); | |
| 466 | 466 | DependencyManager::registerInheritance<SpatialParentFinder, InterfaceParentFinder>(); |
| 467 | 467 | |
| 468 | 468 | // Set dependencies |
| @@ -479,7 +479,6 @@ bool setupEssentials(int& argc, char** argv) { · 10 unmodified lines | ||
| 479 | 479 | DependencyManager::set<ModelCache>(); |
| 480 | 480 | DependencyManager::set<ScriptCache>(); |
| 481 | 481 | DependencyManager::set<SoundCache>(); |
| 482 | − DependencyManager::set<Faceshift>(); | |
| 483 | 482 | DependencyManager::set<DdeFaceTracker>(); |
| 484 | 483 | DependencyManager::set<EyeTracker>(); |
| 485 | 484 | DependencyManager::set<AudioClient>(); |
| @@ -516,7 +515,7 @@ bool setupEssentials(int& argc, char** argv) { · 30 unmodified lines | ||
| 516 | 515 | DependencyManager::set<OffscreenUi>(); |
| 517 | 516 | DependencyManager::set<AutoUpdater>(); |
| 518 | 517 | DependencyManager::set<PathUtils>(); |
| 519 | − DependencyManager::set<InterfaceActionFactory>(); | |
| 518 | + DependencyManager::set<InterfaceDynamicFactory>(); | |
| 520 | 519 | DependencyManager::set<AudioInjectorManager>(); |
| 521 | 520 | DependencyManager::set<MessagesClient>(); |
| 522 | 521 | controller::StateController::setStateVariables({ { STATE_IN_HMD, STATE_CAMERA_FULL_SCREEN_MIRROR, |
| @@ -534,6 +533,7 @@ bool setupEssentials(int& argc, char** argv) { · 11 unmodified lines | ||
| 534 | 533 | DependencyManager::set<OctreeStatsProvider>(nullptr, qApp->getOcteeSceneStats()); |
| 535 | 534 | DependencyManager::set<AvatarBookmarks>(); |
| 536 | 535 | DependencyManager::set<LocationBookmarks>(); |
| 536 | + DependencyManager::set<Snapshot>(); | |
| 537 | 537 | |
| 538 | 538 | return previousSessionCrashed; |
| 539 | 539 | } |
| @@ -796,7 +796,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 256 unmodified lines | ||
| 796 | 796 | connect(&domainHandler, SIGNAL(resetting()), SLOT(resettingDomain())); |
| 797 | 797 | connect(&domainHandler, SIGNAL(connectedToDomain(const QString&)), SLOT(updateWindowTitle())); |
| 798 | 798 | connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(updateWindowTitle())); |
| 799 | − connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(clearDomainOctreeDetails())); | |
| 799 | + connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, &Application::clearDomainAvatars); | |
| 800 | 800 | connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, [this]() { |
| 801 | 801 | getOverlays().deleteOverlay(getTabletScreenID()); |
| 802 | 802 | getOverlays().deleteOverlay(getTabletHomeButtonID()); |
| @@ -1208,10 +1208,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 405 unmodified lines | ||
| 1208 | 1208 | |
| 1209 | 1209 | this->installEventFilter(this); |
| 1210 | 1210 | |
| 1211 | − // initialize our face trackers after loading the menu settings | |
| 1212 | − auto faceshiftTracker = DependencyManager::get<Faceshift>(); | |
| 1213 | − faceshiftTracker->init(); | |
| 1214 | − connect(faceshiftTracker.data(), &FaceTracker::muteToggled, this, &Application::faceTrackerMuteToggled); | |
| 1215 | 1211 | #ifdef HAVE_DDE |
| 1216 | 1212 | auto ddeTracker = DependencyManager::get<DdeFaceTracker>(); |
| 1217 | 1213 | ddeTracker->init(); |
| @@ -1445,8 +1441,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 227 unmodified lines | ||
| 1445 | 1441 | QString skyboxUrl { PathUtils::resourcesPath() + "images/Default-Sky-9-cubemap.jpg" }; |
| 1446 | 1442 | QString skyboxAmbientUrl { PathUtils::resourcesPath() + "images/Default-Sky-9-ambient.jpg" }; |
| 1447 | 1443 | |
| 1448 | − _defaultSkyboxTexture = textureCache->getImageTexture(skyboxUrl, NetworkTexture::CUBE_TEXTURE, { { "generateIrradiance", false } }); | |
| 1449 | − _defaultSkyboxAmbientTexture = textureCache->getImageTexture(skyboxAmbientUrl, NetworkTexture::CUBE_TEXTURE, { { "generateIrradiance", true } }); | |
| 1444 | + _defaultSkyboxTexture = textureCache->getImageTexture(skyboxUrl, image::TextureUsage::CUBE_TEXTURE, { { "generateIrradiance", false } }); | |
| 1445 | + _defaultSkyboxAmbientTexture = textureCache->getImageTexture(skyboxAmbientUrl, image::TextureUsage::CUBE_TEXTURE, { { "generateIrradiance", true } }); | |
| 1450 | 1446 | |
| 1451 | 1447 | _defaultSkybox->setCubemap(_defaultSkyboxTexture); |
| 1452 | 1448 | |
| @@ -1465,46 +1461,53 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 12 unmodified lines | ||
| 1465 | 1461 | const auto testScript = property(hifi::properties::TEST).toUrl(); |
| 1466 | 1462 | scriptEngines->loadScript(testScript, false); |
| 1467 | 1463 | } else { |
| 1468 | − // Get sandbox content set version, if available | |
| 1464 | + enum HandControllerType { | |
| 1465 | + Vive, | |
| 1466 | + Oculus | |
| 1467 | + }; | |
| 1468 | + static const std::map<HandControllerType, int> MIN_CONTENT_VERSION = { | |
| 1469 | + { Vive, 1 }, | |
| 1470 | + { Oculus, 27 } | |
| 1471 | + }; | |
| 1472 | + | |
| 1473 | + // Get sandbox content set version | |
| 1469 | 1474 | auto acDirPath = PathUtils::getAppDataPath() + "../../" + BuildInfo::MODIFIED_ORGANIZATION + "/assignment-client/"; |
| 1470 | 1475 | auto contentVersionPath = acDirPath + "content-version.txt"; |
| 1471 | 1476 | qCDebug(interfaceapp) << "Checking " << contentVersionPath << " for content version"; |
| 1472 | − auto contentVersion = 0; | |
| 1477 | + int contentVersion = 0; | |
| 1473 | 1478 | QFile contentVersionFile(contentVersionPath); |
| 1474 | 1479 | if (contentVersionFile.open(QIODevice::ReadOnly | QIODevice::Text)) { |
| 1475 | 1480 | QString line = contentVersionFile.readAll(); |
| 1476 | − // toInt() returns 0 if the conversion fails, so we don't need to specifically check for failure | |
| 1477 | − contentVersion = line.toInt(); | |
| 1481 | + contentVersion = line.toInt(); // returns 0 if conversion fails | |
| 1478 | 1482 | } |
| 1479 | − qCDebug(interfaceapp) << "Server content version: " << contentVersion; | |
| 1480 | − | |
| 1481 | − static const int MIN_VIVE_CONTENT_VERSION = 1; | |
| 1482 | − static const int MIN_OCULUS_TOUCH_CONTENT_VERSION = 27; | |
| 1483 | 1483 | |
| 1484 | − bool hasSufficientTutorialContent = false; | |
| 1484 | + // Get controller availability | |
| 1485 | 1485 | bool hasHandControllers = false; |
| 1486 | − | |
| 1487 | − // Only specific hand controllers are currently supported, so only send users to the tutorial | |
| 1488 | − // if they have one of those hand controllers. | |
| 1486 | + HandControllerType handControllerType = Vive; | |
| 1489 | 1487 | if (PluginUtils::isViveControllerAvailable()) { |
| 1490 | 1488 | hasHandControllers = true; |
| 1491 | − hasSufficientTutorialContent = contentVersion >= MIN_VIVE_CONTENT_VERSION; | |
| 1489 | + handControllerType = Vive; | |
| 1492 | 1490 | } else if (PluginUtils::isOculusTouchControllerAvailable()) { |
| 1493 | 1491 | hasHandControllers = true; |
| 1494 | − hasSufficientTutorialContent = contentVersion >= MIN_OCULUS_TOUCH_CONTENT_VERSION; | |
| 1492 | + handControllerType = Oculus; | |
| 1495 | 1493 | } |
| 1496 | 1494 | |
| 1497 | − Setting::Handle<bool> firstRun { Settings::firstRun, true }; | |
| 1495 | + // Check tutorial content versioning | |
| 1496 | + bool hasTutorialContent = contentVersion >= MIN_CONTENT_VERSION.at(handControllerType); | |
| 1497 | + | |
| 1498 | + // Check HMD use (may be technically available without being in use) | |
| 1499 | + bool hasHMD = PluginUtils::isHMDAvailable(); | |
| 1500 | + bool isUsingHMD = hasHMD && hasHandControllers && _displayPlugin->isHmd(); | |
| 1498 | 1501 | |
| 1499 | − bool hasHMDAndHandControllers = PluginUtils::isHMDAvailable() && hasHandControllers; | |
| 1500 | 1502 | Setting::Handle<bool> tutorialComplete { "tutorialComplete", false }; |
| 1503 | + Setting::Handle<bool> firstRun { Settings::firstRun, true }; | |
| 1501 | 1504 | |
| 1502 | − bool shouldGoToTutorial = hasHMDAndHandControllers && hasSufficientTutorialContent && !tutorialComplete.get(); | |
| 1505 | + bool isTutorialComplete = tutorialComplete.get(); | |
| 1506 | + bool shouldGoToTutorial = isUsingHMD && hasTutorialContent && !isTutorialComplete; | |
| 1503 | 1507 | |
| 1504 | − qCDebug(interfaceapp) << "Has HMD + Hand Controllers: " << hasHMDAndHandControllers << ", current plugin: " << _displayPlugin->getName(); | |
| 1505 | − qCDebug(interfaceapp) << "Has sufficient tutorial content (" << contentVersion << ") : " << hasSufficientTutorialContent; | |
| 1506 | − qCDebug(interfaceapp) << "Tutorial complete: " << tutorialComplete.get(); | |
| 1507 | − qCDebug(interfaceapp) << "Should go to tutorial: " << shouldGoToTutorial; | |
| 1508 | + qCDebug(interfaceapp) << "HMD:" << hasHMD << ", Hand Controllers: " << hasHandControllers << ", Using HMD: " << isUsingHMD; | |
| 1509 | + qCDebug(interfaceapp) << "Tutorial version:" << contentVersion << ", sufficient:" << hasTutorialContent << | |
| 1510 | + ", complete:" << isTutorialComplete << ", should go:" << shouldGoToTutorial; | |
| 1508 | 1511 | |
| 1509 | 1512 | // when --url in command line, teleport to location |
| 1510 | 1513 | const QString HIFI_URL_COMMAND_LINE_KEY = "--url"; |
| @@ -1541,7 +1544,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 30 unmodified lines | ||
| 1541 | 1544 | |
| 1542 | 1545 | // If this is a first run we short-circuit the address passed in |
| 1543 | 1546 | if (isFirstRun) { |
| 1544 | − if (hasHMDAndHandControllers) { | |
| 1547 | + if (isUsingHMD) { | |
| 1545 | 1548 | if (sandboxIsRunning) { |
| 1546 | 1549 | qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home."; |
| 1547 | 1550 | DependencyManager::get<AddressManager>()->goToLocalSandbox(); |
| @@ -1583,6 +1586,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 35 unmodified lines | ||
| 1583 | 1586 | connect(&domainHandler, &DomainHandler::hostnameChanged, this, &Application::addAssetToWorldMessageClose); |
| 1584 | 1587 | |
| 1585 | 1588 | updateSystemTabletMode(); |
| 1589 | + | |
| 1590 | + connect(&_myCamera, &Camera::modeUpdated, this, &Application::cameraModeChanged); | |
| 1586 | 1591 | } |
| 1587 | 1592 | |
| 1588 | 1593 | void Application::domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo) { |
| @@ -2042,6 +2047,7 @@ void Application::initializeUi() { · 453 unmodified lines | ||
| 2042 | 2047 | rootContext->setContextProperty("Scene", DependencyManager::get<SceneScriptingInterface>().data()); |
| 2043 | 2048 | rootContext->setContextProperty("Render", _renderEngine->getConfiguration().get()); |
| 2044 | 2049 | rootContext->setContextProperty("Reticle", getApplicationCompositor().getReticleInterface()); |
| 2050 | + rootContext->setContextProperty("Snapshot", DependencyManager::get<Snapshot>().data()); | |
| 2045 | 2051 | |
| 2046 | 2052 | rootContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor()); |
| 2047 | 2053 | |
| @@ -2185,7 +2191,7 @@ void Application::paintGL() { · 137 unmodified lines | ||
| 2185 | 2191 | _myCamera.setOrientation(glm::quat_cast(camMat)); |
| 2186 | 2192 | } else { |
| 2187 | 2193 | _myCamera.setPosition(myAvatar->getDefaultEyePosition()); |
| 2188 | − _myCamera.setOrientation(myAvatar->getHead()->getCameraOrientation()); | |
| 2194 | + _myCamera.setOrientation(myAvatar->getMyHead()->getCameraOrientation()); | |
| 2189 | 2195 | } |
| 2190 | 2196 | } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { |
| 2191 | 2197 | if (isHMDMode()) { |
| @@ -2520,6 +2526,11 @@ bool Application::event(QEvent* event) { · 328 unmodified lines | ||
| 2520 | 2526 | |
| 2521 | 2527 | isPaintingThrottled = false; |
| 2522 | 2528 | |
| 2529 | + return true; | |
| 2530 | + } else if ((int)event->type() == (int)Idle) { | |
| 2531 | + float nsecsElapsed = (float)_lastTimeUpdated.nsecsElapsed(); | |
| 2532 | + idle(nsecsElapsed); | |
| 2533 | + | |
| 2523 | 2534 | return true; |
| 2524 | 2535 | } |
| 2525 | 2536 | |
| @@ -2744,6 +2755,9 @@ void Application::keyPressEvent(QKeyEvent* event) { · 218 unmodified lines | ||
| 2744 | 2755 | if (isMeta) { |
| 2745 | 2756 | auto offscreenUi = DependencyManager::get<OffscreenUi>(); |
| 2746 | 2757 | offscreenUi->load("Browser.qml"); |
| 2758 | + } else if (isOption) { | |
| 2759 | + controller::InputRecorder* inputRecorder = controller::InputRecorder::getInstance(); | |
| 2760 | + inputRecorder->stopPlayback(); | |
| 2747 | 2761 | } |
| 2748 | 2762 | break; |
| 2749 | 2763 | |
| @@ -3611,20 +3625,13 @@ ivec2 Application::getMouse() const { · 861 unmodified lines | ||
| 3611 | 3625 | } |
| 3612 | 3626 | |
| 3613 | 3627 | FaceTracker* Application::getActiveFaceTracker() { |
| 3614 | − auto faceshift = DependencyManager::get<Faceshift>(); | |
| 3615 | 3628 | auto dde = DependencyManager::get<DdeFaceTracker>(); |
| 3616 | 3629 | |
| 3617 | − return (dde->isActive() ? static_cast<FaceTracker*>(dde.data()) : | |
| 3618 | − (faceshift->isActive() ? static_cast<FaceTracker*>(faceshift.data()) : nullptr)); | |
| 3630 | + return dde->isActive() ? static_cast<FaceTracker*>(dde.data()) : nullptr; | |
| 3619 | 3631 | } |
| 3620 | 3632 | |
| 3621 | 3633 | FaceTracker* Application::getSelectedFaceTracker() { |
| 3622 | 3634 | FaceTracker* faceTracker = nullptr; |
| 3623 | −#ifdef HAVE_FACESHIFT | |
| 3624 | − if (Menu::getInstance()->isOptionChecked(MenuOption::Faceshift)) { | |
| 3625 | − faceTracker = DependencyManager::get<Faceshift>().data(); | |
| 3626 | − } | |
| 3627 | −#endif | |
| 3628 | 3635 | #ifdef HAVE_DDE |
| 3629 | 3636 | if (Menu::getInstance()->isOptionChecked(MenuOption::UseCamera)) { |
| 3630 | 3637 | faceTracker = DependencyManager::get<DdeFaceTracker>().data(); |
| @@ -3634,15 +3641,8 @@ FaceTracker* Application::getSelectedFaceTracker() { · 3 unmodified lines | ||
| 3634 | 3641 | } |
| 3635 | 3642 | |
| 3636 | 3643 | void Application::setActiveFaceTracker() const { |
| 3637 | −#if defined(HAVE_FACESHIFT) || defined(HAVE_DDE) | |
| 3638 | − bool isMuted = Menu::getInstance()->isOptionChecked(MenuOption::MuteFaceTracking); | |
| 3639 | −#endif | |
| 3640 | −#ifdef HAVE_FACESHIFT | |
| 3641 | − auto faceshiftTracker = DependencyManager::get<Faceshift>(); | |
| 3642 | − faceshiftTracker->setIsMuted(isMuted); | |
| 3643 | − faceshiftTracker->setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift) && !isMuted); | |
| 3644 | −#endif | |
| 3645 | 3644 | #ifdef HAVE_DDE |
| 3645 | + bool isMuted = Menu::getInstance()->isOptionChecked(MenuOption::MuteFaceTracking); | |
| 3646 | 3646 | bool isUsingDDE = Menu::getInstance()->isOptionChecked(MenuOption::UseCamera); |
| 3647 | 3647 | Menu::getInstance()->getActionForOption(MenuOption::BinaryEyelidControl)->setVisible(isUsingDDE); |
| 3648 | 3648 | Menu::getInstance()->getActionForOption(MenuOption::CoupleEyelids)->setVisible(isUsingDDE); |
| @@ -4087,6 +4087,30 @@ void Application::cycleCamera() { · 438 unmodified lines | ||
| 4087 | 4087 | cameraMenuChanged(); // handle the menu change |
| 4088 | 4088 | } |
| 4089 | 4089 | |
| 4090 | +void Application::cameraModeChanged() { | |
| 4091 | + switch (_myCamera.getMode()) { | |
| 4092 | + case CAMERA_MODE_FIRST_PERSON: | |
| 4093 | + Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, true); | |
| 4094 | + break; | |
| 4095 | + case CAMERA_MODE_THIRD_PERSON: | |
| 4096 | + Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, true); | |
| 4097 | + break; | |
| 4098 | + case CAMERA_MODE_MIRROR: | |
| 4099 | + Menu::getInstance()->setIsOptionChecked(MenuOption::FullscreenMirror, true); | |
| 4100 | + break; | |
| 4101 | + case CAMERA_MODE_INDEPENDENT: | |
| 4102 | + Menu::getInstance()->setIsOptionChecked(MenuOption::IndependentMode, true); | |
| 4103 | + break; | |
| 4104 | + case CAMERA_MODE_ENTITY: | |
| 4105 | + Menu::getInstance()->setIsOptionChecked(MenuOption::CameraEntityMode, true); | |
| 4106 | + break; | |
| 4107 | + default: | |
| 4108 | + break; | |
| 4109 | + } | |
| 4110 | + cameraMenuChanged(); | |
| 4111 | +} | |
| 4112 | + | |
| 4113 | + | |
| 4090 | 4114 | void Application::cameraMenuChanged() { |
| 4091 | 4115 | if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { |
| 4092 | 4116 | if (_myCamera.getMode() != CAMERA_MODE_MIRROR) { |
| @@ -4360,7 +4384,13 @@ void Application::update(float deltaTime) { · 267 unmodified lines | ||
| 4360 | 4384 | controller::InputCalibrationData calibrationData = { |
| 4361 | 4385 | myAvatar->getSensorToWorldMatrix(), |
| 4362 | 4386 | createMatFromQuatAndPos(myAvatar->getOrientation(), myAvatar->getPosition()), |
| 4363 | − myAvatar->getHMDSensorMatrix() | |
| 4387 | + myAvatar->getHMDSensorMatrix(), | |
| 4388 | + myAvatar->getCenterEyeCalibrationMat(), | |
| 4389 | + myAvatar->getHeadCalibrationMat(), | |
| 4390 | + myAvatar->getSpine2CalibrationMat(), | |
| 4391 | + myAvatar->getHipsCalibrationMat(), | |
| 4392 | + myAvatar->getLeftFootCalibrationMat(), | |
| 4393 | + myAvatar->getRightFootCalibrationMat() | |
| 4364 | 4394 | }; |
| 4365 | 4395 | |
| 4366 | 4396 | InputPluginPointer keyboardMousePlugin; |
| @@ -4408,6 +4438,13 @@ void Application::update(float deltaTime) { · 41 unmodified lines | ||
| 4408 | 4438 | controller::Pose rightFootPose = userInputMapper->getPoseState(controller::Action::RIGHT_FOOT); |
| 4409 | 4439 | myAvatar->setFootControllerPosesInSensorFrame(leftFootPose.transform(avatarToSensorMatrix), rightFootPose.transform(avatarToSensorMatrix)); |
| 4410 | 4440 | |
| 4441 | + controller::Pose hipsPose = userInputMapper->getPoseState(controller::Action::HIPS); | |
| 4442 | + controller::Pose spine2Pose = userInputMapper->getPoseState(controller::Action::SPINE2); | |
| 4443 | + myAvatar->setSpineControllerPosesInSensorFrame(hipsPose.transform(avatarToSensorMatrix), spine2Pose.transform(avatarToSensorMatrix)); | |
| 4444 | + | |
| 4445 | + controller::Pose headPose = userInputMapper->getPoseState(controller::Action::HEAD); | |
| 4446 | + myAvatar->setHeadControllerPoseInSensorFrame(headPose.transform(avatarToSensorMatrix)); | |
| 4447 | + | |
| 4411 | 4448 | updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process... |
| 4412 | 4449 | updateDialogs(deltaTime); // update various stats dialogs if present |
| 4413 | 4450 | |
| @@ -4438,7 +4475,7 @@ void Application::update(float deltaTime) { · 24 unmodified lines | ||
| 4438 | 4475 | _entitySimulation->setObjectsToChange(stillNeedChange); |
| 4439 | 4476 | }); |
| 4440 | 4477 | |
| 4441 | − _entitySimulation->applyActionChanges(); | |
| 4478 | + _entitySimulation->applyDynamicChanges(); | |
| 4442 | 4479 | |
| 4443 | 4480 | avatarManager->getObjectsToRemoveFromPhysics(motionStates); |
| 4444 | 4481 | _physicsEngine->removeObjects(motionStates); |
| @@ -4448,8 +4485,8 @@ void Application::update(float deltaTime) { · 3 unmodified lines | ||
| 4448 | 4485 | _physicsEngine->changeObjects(motionStates); |
| 4449 | 4486 | |
| 4450 | 4487 | myAvatar->prepareForPhysicsSimulation(); |
| 4451 | − _physicsEngine->forEachAction([&](EntityActionPointer action) { | |
| 4452 | − action->prepareForPhysicsSimulation(); | |
| 4488 | + _physicsEngine->forEachDynamic([&](EntityDynamicPointer dynamic) { | |
| 4489 | + dynamic->prepareForPhysicsSimulation(); | |
| 4453 | 4490 | }); |
| 4454 | 4491 | } |
| 4455 | 4492 | { |
| @@ -5118,7 +5155,6 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se · 662 unmodified lines | ||
| 5118 | 5155 | } |
| 5119 | 5156 | |
| 5120 | 5157 | void Application::resetSensors(bool andReload) { |
| 5121 | − DependencyManager::get<Faceshift>()->reset(); | |
| 5122 | 5158 | DependencyManager::get<DdeFaceTracker>()->reset(); |
| 5123 | 5159 | DependencyManager::get<EyeTracker>()->reset(); |
| 5124 | 5160 | getActiveDisplayPlugin()->resetSensors(); |
| @@ -5164,7 +5200,6 @@ void Application::clearDomainOctreeDetails() { · 39 unmodified lines | ||
| 5164 | 5200 | qCDebug(interfaceapp) << "Clearing domain octree details..."; |
| 5165 | 5201 | |
| 5166 | 5202 | resetPhysicsReadyInformation(); |
| 5167 | − getMyAvatar()->setAvatarEntityDataChanged(true); // to recreate worn entities | |
| 5168 | 5203 | |
| 5169 | 5204 | // reset our node to stats and node to jurisdiction maps... since these must be changing... |
| 5170 | 5205 | _entityServerJurisdictions.withWriteLock([&] { |
| @@ -5183,14 +5218,18 @@ void Application::clearDomainOctreeDetails() { · 12 unmodified lines | ||
| 5183 | 5218 | skyStage->setBackgroundMode(model::SunSkyStage::SKY_DEFAULT); |
| 5184 | 5219 | |
| 5185 | 5220 | _recentlyClearedDomain = true; |
| 5186 | − | |
| 5187 | − DependencyManager::get<AvatarManager>()->clearOtherAvatars(); | |
| 5221 | + | |
| 5188 | 5222 | DependencyManager::get<AnimationCache>()->clearUnusedResources(); |
| 5189 | 5223 | DependencyManager::get<ModelCache>()->clearUnusedResources(); |
| 5190 | 5224 | DependencyManager::get<SoundCache>()->clearUnusedResources(); |
| 5191 | 5225 | DependencyManager::get<TextureCache>()->clearUnusedResources(); |
| 5192 | 5226 | } |
| 5193 | 5227 | |
| 5228 | +void Application::clearDomainAvatars() { | |
| 5229 | + getMyAvatar()->setAvatarEntityDataChanged(true); // to recreate worn entities | |
| 5230 | + DependencyManager::get<AvatarManager>()->clearOtherAvatars(); | |
| 5231 | +} | |
| 5232 | + | |
| 5194 | 5233 | void Application::domainChanged(const QString& domainHostname) { |
| 5195 | 5234 | updateWindowTitle(); |
| 5196 | 5235 | // disable physics until we have enough information about our new location to not cause craziness. |
| @@ -5203,11 +5242,7 @@ void Application::resettingDomain() { · 6 unmodified lines | ||
| 5203 | 5242 | } |
| 5204 | 5243 | |
| 5205 | 5244 | void Application::nodeAdded(SharedNodePointer node) const { |
| 5206 | − if (node->getType() == NodeType::AvatarMixer) { | |
| 5207 | − // new avatar mixer, send off our identity packet right away | |
| 5208 | − getMyAvatar()->sendIdentityPacket(); | |
| 5209 | − getMyAvatar()->resetLastSent(); | |
| 5210 | − } | |
| 5245 | + // nothing to do here | |
| 5211 | 5246 | } |
| 5212 | 5247 | |
| 5213 | 5248 | void Application::nodeActivated(SharedNodePointer node) { |
| @@ -5243,6 +5278,13 @@ void Application::nodeActivated(SharedNodePointer node) { · 29 unmodified lines | ||
| 5243 | 5278 | if (node->getType() == NodeType::AudioMixer) { |
| 5244 | 5279 | DependencyManager::get<AudioClient>()->negotiateAudioFormat(); |
| 5245 | 5280 | } |
| 5281 | + | |
| 5282 | + if (node->getType() == NodeType::AvatarMixer) { | |
| 5283 | + // new avatar mixer, send off our identity packet right away | |
| 5284 | + getMyAvatar()->markIdentityDataChanged(); | |
| 5285 | + getMyAvatar()->sendIdentityPacket(); | |
| 5286 | + getMyAvatar()->resetLastSent(); | |
| 5287 | + } | |
| 5246 | 5288 | } |
| 5247 | 5289 | |
| 5248 | 5290 | void Application::nodeKilled(SharedNodePointer node) { |
| @@ -5257,33 +5299,8 @@ void Application::nodeKilled(SharedNodePointer node) { · 8 unmodified lines | ||
| 5257 | 5299 | if (node->getType() == NodeType::AudioMixer) { |
| 5258 | 5300 | QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(), "audioMixerKilled"); |
| 5259 | 5301 | } else if (node->getType() == NodeType::EntityServer) { |
| 5260 | − QUuid nodeUUID = node->getUUID(); | |
| 5261 | − // see if this is the first we've heard of this node... | |
| 5262 | − _entityServerJurisdictions.withReadLock([&] { | |
| 5263 | − if (_entityServerJurisdictions.find(nodeUUID) == _entityServerJurisdictions.end()) { | |
| 5264 | − return; | |
| 5265 | − } | |
| 5266 | − | |
| 5267 | − auto rootCode = _entityServerJurisdictions[nodeUUID].getRootOctalCode(); | |
| 5268 | − VoxelPositionSize rootDetails; | |
| 5269 | − voxelDetailsForCode(rootCode.get(), rootDetails); | |
| 5270 | − | |
| 5271 | − qCDebug(interfaceapp, "model server going away...... v[%f, %f, %f, %f]", | |
| 5272 | − (double)rootDetails.x, (double)rootDetails.y, (double)rootDetails.z, (double)rootDetails.s); | |
| 5273 | − | |
| 5274 | − }); | |
| 5275 | − | |
| 5276 | − // If the model server is going away, remove it from our jurisdiction map so we don't send voxels to a dead server | |
| 5277 | − _entityServerJurisdictions.withWriteLock([&] { | |
| 5278 | − _entityServerJurisdictions.erase(_entityServerJurisdictions.find(nodeUUID)); | |
| 5279 | − }); | |
| 5280 | − | |
| 5281 | − // also clean up scene stats for that server | |
| 5282 | − _octreeServerSceneStats.withWriteLock([&] { | |
| 5283 | − if (_octreeServerSceneStats.find(nodeUUID) != _octreeServerSceneStats.end()) { | |
| 5284 | − _octreeServerSceneStats.erase(nodeUUID); | |
| 5285 | − } | |
| 5286 | − }); | |
| 5302 | + // we lost an entity server, clear all of the domain octree details | |
| 5303 | + clearDomainOctreeDetails(); | |
| 5287 | 5304 | } else if (node->getType() == NodeType::AvatarMixer) { |
| 5288 | 5305 | // our avatar mixer has gone away - clear the hash of avatars |
| 5289 | 5306 | DependencyManager::get<AvatarManager>()->clearOtherAvatars(); |
| @@ -5435,9 +5452,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri · 145 unmodified lines | ||
| 5435 | 5452 | entityScriptingInterface->setPacketSender(&_entityEditSender); |
| 5436 | 5453 | entityScriptingInterface->setEntityTree(getEntities()->getTree()); |
| 5437 | 5454 | |
| 5438 | − // AvatarManager has some custom types | |
| 5439 | − AvatarManager::registerMetaTypes(scriptEngine); | |
| 5440 | − | |
| 5441 | 5455 | // give the script engine to the RecordingScriptingInterface for its callbacks |
| 5442 | 5456 | DependencyManager::get<RecordingScriptingInterface>()->setScriptEngine(scriptEngine); |
| 5443 | 5457 | |
| @@ -5488,6 +5502,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri · 44 unmodified lines | ||
| 5488 | 5502 | scriptEngine->registerGlobalObject("Menu", MenuScriptingInterface::getInstance()); |
| 5489 | 5503 | scriptEngine->registerGlobalObject("Stats", Stats::getInstance()); |
| 5490 | 5504 | scriptEngine->registerGlobalObject("Settings", SettingsScriptingInterface::getInstance()); |
| 5505 | + scriptEngine->registerGlobalObject("Snapshot", DependencyManager::get<Snapshot>().data()); | |
| 5491 | 5506 | scriptEngine->registerGlobalObject("AudioDevice", AudioDeviceScriptingInterface::getInstance()); |
| 5492 | 5507 | scriptEngine->registerGlobalObject("AudioStats", DependencyManager::get<AudioClient>()->getStats().data()); |
| 5493 | 5508 | scriptEngine->registerGlobalObject("AudioScope", DependencyManager::get<AudioScope>().data()); |
| @@ -6432,7 +6447,7 @@ void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRa · 938 unmodified lines | ||
| 6432 | 6447 | // Get a screenshot and save it |
| 6433 | 6448 | QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio)); |
| 6434 | 6449 | // If we're not doing an animated snapshot as well... |
| 6435 | − if (!includeAnimated || !(SnapshotAnimated::alsoTakeAnimatedSnapshot.get())) { | |
| 6450 | + if (!includeAnimated) { | |
| 6436 | 6451 | // Tell the dependency manager that the capture of the still snapshot has taken place. |
| 6437 | 6452 | emit DependencyManager::get<WindowScriptingInterface>()->stillSnapshotTaken(path, notify); |
| 6438 | 6453 | } else { |
| @@ -6505,10 +6520,22 @@ void Application::activeChanged(Qt::ApplicationState state) { · 66 unmodified lines | ||
| 6505 | 6520 | } |
| 6506 | 6521 | |
| 6507 | 6522 | void Application::windowMinimizedChanged(bool minimized) { |
| 6523 | + // initialize the _minimizedWindowTimer | |
| 6524 | + static std::once_flag once; | |
| 6525 | + std::call_once(once, [&] { | |
| 6526 | + connect(&_minimizedWindowTimer, &QTimer::timeout, this, [] { | |
| 6527 | + QCoreApplication::postEvent(QCoreApplication::instance(), new QEvent(static_cast<QEvent::Type>(Idle)), Qt::HighEventPriority); | |
| 6528 | + }); | |
| 6529 | + }); | |
| 6530 | + | |
| 6531 | + // avoid rendering to the display plugin but continue posting Idle events, | |
| 6532 | + // so that physics continues to simulate and the deadlock watchdog knows we're alive | |
| 6508 | 6533 | if (!minimized && !getActiveDisplayPlugin()->isActive()) { |
| 6534 | + _minimizedWindowTimer.stop(); | |
| 6509 | 6535 | getActiveDisplayPlugin()->activate(); |
| 6510 | 6536 | } else if (minimized && getActiveDisplayPlugin()->isActive()) { |
| 6511 | 6537 | getActiveDisplayPlugin()->deactivate(); |
| 6538 | + _minimizedWindowTimer.start(THROTTLED_SIM_FRAME_PERIOD_MS); | |
| 6512 | 6539 | } |
| 6513 | 6540 | } |
| 6514 | 6541 | |
| @@ -6757,11 +6784,6 @@ void Application::updateDisplayMode() { · 242 unmodified lines | ||
| 6757 | 6784 | return; |
| 6758 | 6785 | } |
| 6759 | 6786 | |
| 6760 | − UserActivityLogger::getInstance().logAction("changed_display_mode", { | |
| 6761 | − { "previous_display_mode", _displayPlugin ? _displayPlugin->getName() : "" }, | |
| 6762 | − { "display_mode", newDisplayPlugin ? newDisplayPlugin->getName() : "" } | |
| 6763 | − }); | |
| 6764 | − | |
| 6765 | 6787 | auto offscreenUi = DependencyManager::get<OffscreenUi>(); |
| 6766 | 6788 | |
| 6767 | 6789 | // Make the switch atomic from the perspective of other threads |
| @@ -6816,13 +6838,16 @@ void Application::updateDisplayMode() { · 48 unmodified lines | ||
| 6816 | 6838 | offscreenUi->getDesktop()->setProperty("repositionLocked", wasRepositionLocked); |
| 6817 | 6839 | } |
| 6818 | 6840 | |
| 6841 | + bool isHmd = _displayPlugin->isHmd(); | |
| 6842 | + qCDebug(interfaceapp) << "Entering into" << (isHmd ? "HMD" : "Desktop") << "Mode"; | |
| 6843 | + | |
| 6844 | + // Only log/emit after a successful change | |
| 6845 | + UserActivityLogger::getInstance().logAction("changed_display_mode", { | |
| 6846 | + { "previous_display_mode", _displayPlugin ? _displayPlugin->getName() : "" }, | |
| 6847 | + { "display_mode", newDisplayPlugin ? newDisplayPlugin->getName() : "" }, | |
| 6848 | + { "hmd", isHmd } | |
| 6849 | + }); | |
| 6819 | 6850 | emit activeDisplayPluginChanged(); |
| 6820 | − | |
| 6821 | − if (_displayPlugin->isHmd()) { | |
| 6822 | − qCDebug(interfaceapp) << "Entering into HMD Mode"; | |
| 6823 | − } else { | |
| 6824 | − qCDebug(interfaceapp) << "Entering into Desktop Mode"; | |
| 6825 | − } | |
| 6826 | 6851 | |
| 6827 | 6852 | // reset the avatar, to set head and hand palms back to a reasonable default pose. |
| 6828 | 6853 | getMyAvatar()->reset(false); |