From 8c9c7248d4a00b3233becfa60c2934e25be9ccf7 Mon Sep 17 00:00:00 2001 From: Alexia Mandeville Date: Mon, 12 Mar 2018 12:52:12 -0700 Subject: [PATCH 001/143] Reorganize of menu action items as well as QML categories --- .../hifi/dialogs/AvatarPreferencesDialog.qml | 2 +- .../hifi/dialogs/GeneralPreferencesDialog.qml | 2 +- .../dialogs/GraphicsPreferencesDialog.qml | 2 +- .../qml/hifi/tablet/ControllerSettings.qml | 19 +- .../hifi/tablet/TabletGraphicsPreferences.qml | 2 +- interface/src/Menu.cpp | 367 +++++++++--------- interface/src/Menu.h | 10 +- interface/src/ui/PreferencesDialog.cpp | 122 +++--- 8 files changed, 268 insertions(+), 258 deletions(-) diff --git a/interface/resources/qml/hifi/dialogs/AvatarPreferencesDialog.qml b/interface/resources/qml/hifi/dialogs/AvatarPreferencesDialog.qml index 86f195612c..01b2690afb 100644 --- a/interface/resources/qml/hifi/dialogs/AvatarPreferencesDialog.qml +++ b/interface/resources/qml/hifi/dialogs/AvatarPreferencesDialog.qml @@ -7,7 +7,7 @@ PreferencesDialog { id: root objectName: "AvatarPreferencesDialog" title: "Avatar Settings" - showCategories: [ "Avatar Basics", "Avatar Tuning", "Avatar Camera" ] + showCategories: [ "Avatar Basics", "Avatar Tuning" ] property var settings: Settings { category: root.objectName property alias x: root.x diff --git a/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml b/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml index 6f5798e2b2..cb4913f999 100644 --- a/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml +++ b/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml @@ -17,7 +17,7 @@ PreferencesDialog { id: root objectName: "GeneralPreferencesDialog" title: "General Settings" - showCategories: ["UI", "Snapshots", "Privacy", "HMD", "Game Controller", "Sixense Controllers", "Perception Neuron", "Kinect", "Leap Motion"] + showCategories: ["User Interface", "HMD", "Snapshots", "Privacy"] property var settings: Settings { category: root.objectName property alias x: root.x diff --git a/interface/resources/qml/hifi/dialogs/GraphicsPreferencesDialog.qml b/interface/resources/qml/hifi/dialogs/GraphicsPreferencesDialog.qml index d95bafd0a9..1388889248 100644 --- a/interface/resources/qml/hifi/dialogs/GraphicsPreferencesDialog.qml +++ b/interface/resources/qml/hifi/dialogs/GraphicsPreferencesDialog.qml @@ -7,7 +7,7 @@ PreferencesDialog { id: root objectName: "GraphicsPreferencesDialog" title: "Graphics Settings" - showCategories: ["Graphics"] + showCategories: ["Graphics Quality"] property var settings: Settings { category: root.objectName property alias x: root.x diff --git a/interface/resources/qml/hifi/tablet/ControllerSettings.qml b/interface/resources/qml/hifi/tablet/ControllerSettings.qml index 4814eaf01c..b71719aa48 100644 --- a/interface/resources/qml/hifi/tablet/ControllerSettings.qml +++ b/interface/resources/qml/hifi/tablet/ControllerSettings.qml @@ -9,10 +9,26 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import QtGraphicalEffects 1.0 +import Qt.labs.settings 1.0 import "../../styles-uit" import "../../controls" import "../../controls-uit" as HifiControls +import "../../dialogs" +PreferencesDialog { + id: root + objectName: "ControlSettings" + title: "Control Settings" + showCategories: ["VR Movement", "Mouse Sensitivity", "Game Controller", "Face Tracking", "Sixense Controllers", "Perception Neuron", "Kinect", "Leap Motion"] + property var settings: Settings { + category: root.objectName + property alias x: root.x + property alias y: root.y + property alias width: root.width + property alias height: root.height + } +} +/* StackView { id: stack initialItem: inputConfiguration @@ -45,7 +61,7 @@ StackView { RalewayRegular { id: header - text: "Controller Settings" + text: "Control Settings" size: 22 color: "white" @@ -226,3 +242,4 @@ StackView { timer.start(); } } +*/ diff --git a/interface/resources/qml/hifi/tablet/TabletGraphicsPreferences.qml b/interface/resources/qml/hifi/tablet/TabletGraphicsPreferences.qml index 25b5be05f2..67794e8f14 100644 --- a/interface/resources/qml/hifi/tablet/TabletGraphicsPreferences.qml +++ b/interface/resources/qml/hifi/tablet/TabletGraphicsPreferences.qml @@ -32,6 +32,6 @@ StackView { TabletPreferencesDialog { id: root objectName: "TabletGraphicsPreferences" - showCategories: ["Graphics"] + showCategories: ["Graphics Quality"] } } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 8c0ac584c5..9e11ad801d 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include @@ -43,12 +45,13 @@ #include "ui/StandAloneJSConsole.h" #include "InterfaceLogging.h" #include "LocationBookmarks.h" +#include "Menu.h" #if defined(Q_OS_MAC) || defined(Q_OS_WIN) #include "SpeechRecognizer.h" #endif -#include "Menu.h" + extern bool DEV_DECIMATE_TEXTURES; @@ -76,9 +79,6 @@ Menu::Menu() { dialogsManager.data(), &DialogsManager::toggleLoginDialog); } - // File > Help - addActionToQMenuAndActionHash(fileMenu, MenuOption::Help, 0, qApp, SLOT(showHelp())); - // File > Quit addActionToQMenuAndActionHash(fileMenu, MenuOption::Quit, Qt::CTRL | Qt::Key_Q, qApp, SLOT(quit()), QAction::QuitRole); @@ -97,6 +97,22 @@ Menu::Menu() { redoAction->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_Z); addActionToQMenuAndActionHash(editMenu, redoAction); + editMenu->addSeparator(); + + // Edit > Cut + addActionToQMenuAndActionHash(editMenu, "Cut", Qt::CTRL | Qt::Key_X); + + // Edit > Copy + addActionToQMenuAndActionHash(editMenu, "Copy", Qt::CTRL | Qt::Key_C); + + // Edit > Paste + addActionToQMenuAndActionHash(editMenu, "Paste", Qt::CTRL | Qt::Key_V); + + // Edit > Delete + addActionToQMenuAndActionHash(editMenu, "Delete", Qt::Key_Delete); + + editMenu->addSeparator(); + // Edit > Running Scripts auto action = addActionToQMenuAndActionHash(editMenu, MenuOption::RunningScripts, Qt::CTRL | Qt::Key_J); connect(action, &QAction::triggered, [] { @@ -106,41 +122,9 @@ Menu::Menu() { qApp->showDialog(widgetUrl, tabletUrl, name); }); - // Edit > Open and Run Script from File... [advanced] - addActionToQMenuAndActionHash(editMenu, MenuOption::LoadScript, Qt::CTRL | Qt::Key_O, - qApp, SLOT(loadDialog()), - QAction::NoRole, UNSPECIFIED_POSITION, "Advanced"); - - // Edit > Open and Run Script from Url... [advanced] - addActionToQMenuAndActionHash(editMenu, MenuOption::LoadScriptURL, - Qt::CTRL | Qt::SHIFT | Qt::Key_O, qApp, SLOT(loadScriptURLDialog()), - QAction::NoRole, UNSPECIFIED_POSITION, "Advanced"); - - auto scriptEngines = DependencyManager::get(); - // Edit > Stop All Scripts... [advanced] - addActionToQMenuAndActionHash(editMenu, MenuOption::StopAllScripts, 0, - scriptEngines.data(), SLOT(stopAllScripts()), - QAction::NoRole, UNSPECIFIED_POSITION, "Advanced"); - - // Edit > Reload All Scripts... [advanced] - action = addActionToQMenuAndActionHash(editMenu, MenuOption::ReloadAllScripts, Qt::CTRL | Qt::Key_R, - nullptr, nullptr, - QAction::NoRole, UNSPECIFIED_POSITION, "Advanced"); - connect(action, &QAction::triggered, [] { - DependencyManager::get()->reloadAllScripts(); - DependencyManager::get()->clearCache(); - }); - - - // Edit > Console... [advanced] - addActionToQMenuAndActionHash(editMenu, MenuOption::Console, Qt::CTRL | Qt::ALT | Qt::Key_J, - DependencyManager::get().data(), - SLOT(toggleConsole()), - QAction::NoRole, UNSPECIFIED_POSITION, "Advanced"); - editMenu->addSeparator(); - // Edit > My Asset Server + // Edit > Asset Browser auto assetServerAction = addActionToQMenuAndActionHash(editMenu, MenuOption::AssetServer, Qt::CTRL | Qt::SHIFT | Qt::Key_A, qApp, SLOT(showAssetServerWidget())); @@ -148,64 +132,16 @@ Menu::Menu() { QObject::connect(nodeList.data(), &NodeList::canWriteAssetsChanged, assetServerAction, &QAction::setEnabled); assetServerAction->setEnabled(nodeList->getThisNodeCanWriteAssets()); - // Edit > Package Model... [advanced] + // Edit > Package Model as .fst... addActionToQMenuAndActionHash(editMenu, MenuOption::PackageModel, 0, - qApp, SLOT(packageModel()), - QAction::NoRole, UNSPECIFIED_POSITION, "Advanced"); + qApp, SLOT(packageModel())); - // Edit > Reload All Content [advanced] - addActionToQMenuAndActionHash(editMenu, MenuOption::ReloadContent, 0, qApp, SLOT(reloadResourceCaches()), - QAction::NoRole, UNSPECIFIED_POSITION, "Advanced"); + // Edit > Reload All Content + addActionToQMenuAndActionHash(editMenu, MenuOption::ReloadContent, 0, qApp, SLOT(reloadResourceCaches())); - // Avatar menu ---------------------------------- - MenuWrapper* avatarMenu = addMenu("Avatar"); auto avatarManager = DependencyManager::get(); auto avatar = avatarManager->getMyAvatar(); - // Avatar > Attachments... - action = addActionToQMenuAndActionHash(avatarMenu, MenuOption::Attachments); - connect(action, &QAction::triggered, [] { - qApp->showDialog(QString("hifi/dialogs/AttachmentsDialog.qml"), - QString("hifi/tablet/TabletAttachmentsDialog.qml"), "AttachmentsDialog"); - }); - - // Avatar > Size - MenuWrapper* avatarSizeMenu = avatarMenu->addMenu("Size"); - - // Avatar > Size > Increase - addActionToQMenuAndActionHash(avatarSizeMenu, - MenuOption::IncreaseAvatarSize, - 0, // QML Qt::Key_Plus, - avatar.get(), SLOT(increaseSize())); - - // Avatar > Size > Decrease - addActionToQMenuAndActionHash(avatarSizeMenu, - MenuOption::DecreaseAvatarSize, - 0, // QML Qt::Key_Minus, - avatar.get(), SLOT(decreaseSize())); - - // Avatar > Size > Reset - addActionToQMenuAndActionHash(avatarSizeMenu, - MenuOption::ResetAvatarSize, - 0, // QML Qt::Key_Equal, - avatar.get(), SLOT(resetSize())); - - // Avatar > Reset Sensors - addActionToQMenuAndActionHash(avatarMenu, - MenuOption::ResetSensors, - 0, // QML Qt::Key_Apostrophe, - qApp, SLOT(resetSensors())); - - addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::EnableAvatarCollisions, 0, true, - avatar.get(), SLOT(updateMotionBehaviorFromMenu())); - - addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::EnableFlying, 0, true, - avatar.get(), SLOT(setFlyingEnabled(bool))); - - // Avatar > AvatarBookmarks related menus -- Note: the AvatarBookmarks class adds its own submenus here. - auto avatarBookmarks = DependencyManager::get(); - avatarBookmarks->setupMenus(this, avatarMenu); - // Display menu ---------------------------------- // FIXME - this is not yet matching Alan's spec because it doesn't have // menus for "2D"/"3D" - we need to add support for detecting the appropriate @@ -225,38 +161,36 @@ Menu::Menu() { // View > First Person auto firstPersonAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash( - viewMenu, MenuOption::FirstPerson, Qt::CTRL | Qt::Key_F, + viewMenu, MenuOption::FirstPerson, Qt::Key_1, true, qApp, SLOT(cameraMenuChanged()))); firstPersonAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup)); // View > Third Person auto thirdPersonAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash( - viewMenu, MenuOption::ThirdPerson, Qt::CTRL | Qt::Key_G, + viewMenu, MenuOption::ThirdPerson, Qt::Key_3, false, qApp, SLOT(cameraMenuChanged()))); thirdPersonAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup)); // View > Mirror auto viewMirrorAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash( - viewMenu, MenuOption::FullscreenMirror, Qt::CTRL | Qt::Key_H, + viewMenu, MenuOption::FullscreenMirror, Qt::Key_2, false, qApp, SLOT(cameraMenuChanged()))); viewMirrorAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup)); - // View > Independent [advanced] + // View > Independent auto viewIndependentAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::IndependentMode, 0, - false, qApp, SLOT(cameraMenuChanged()), - UNSPECIFIED_POSITION, "Advanced")); + false, qApp, SLOT(cameraMenuChanged()))); viewIndependentAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup)); - // View > Entity Camera [advanced] + // View > Entity Camera auto viewEntityCameraAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::CameraEntityMode, 0, - false, qApp, SLOT(cameraMenuChanged()), - UNSPECIFIED_POSITION, "Advanced")); + false, qApp, SLOT(cameraMenuChanged()))); viewEntityCameraAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup)); @@ -264,54 +198,51 @@ Menu::Menu() { // View > Center Player In View addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::CenterPlayerInView, - 0, true, qApp, SLOT(rotationModeChanged()), - UNSPECIFIED_POSITION, "Advanced"); + 0, true, qApp, SLOT(rotationModeChanged())); + //TODO: remove Overlays action, but the action is tied to some other places in code // View > Overlays addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Overlays, 0, true); // View > Enter First Person Mode in HMD addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPersonHMD, 0, true); + //TODO: Remove Navigation menu when these functions are included in GoTo menu // Navigate menu ---------------------------------- MenuWrapper* navigateMenu = addMenu("Navigate"); - // Navigate > Show Address Bar - addActionToQMenuAndActionHash(navigateMenu, MenuOption::AddressBar, Qt::CTRL | Qt::Key_L, - dialogsManager.data(), SLOT(toggleAddressBar())); - // Navigate > LocationBookmarks related menus -- Note: the LocationBookmarks class adds its own submenus here. auto locationBookmarks = DependencyManager::get(); locationBookmarks->setupMenus(this, navigateMenu); - // Navigate > Copy Address [advanced] + // Navigate > Copy Address auto addressManager = DependencyManager::get(); addActionToQMenuAndActionHash(navigateMenu, MenuOption::CopyAddress, 0, - addressManager.data(), SLOT(copyAddress()), - QAction::NoRole, UNSPECIFIED_POSITION, "Advanced"); + addressManager.data(), SLOT(copyAddress())); - // Navigate > Copy Path [advanced] + // Navigate > Copy Path addActionToQMenuAndActionHash(navigateMenu, MenuOption::CopyPath, 0, - addressManager.data(), SLOT(copyPath()), - QAction::NoRole, UNSPECIFIED_POSITION, "Advanced"); + addressManager.data(), SLOT(copyPath())); // Settings menu ---------------------------------- MenuWrapper* settingsMenu = addMenu("Settings"); - // Settings > Advance Menus - addCheckableActionToQMenuAndActionHash(settingsMenu, "Advanced Menus", 0, false, this, SLOT(toggleAdvancedMenus())); - - // Settings > Developer Menus - addCheckableActionToQMenuAndActionHash(settingsMenu, "Developer Menus", 0, false, this, SLOT(toggleDeveloperMenus())); - // Settings > General... - action = addActionToQMenuAndActionHash(settingsMenu, MenuOption::Preferences, Qt::CTRL | Qt::Key_Comma, nullptr, nullptr, QAction::PreferencesRole); + action = addActionToQMenuAndActionHash(settingsMenu, MenuOption::Preferences, Qt::CTRL | Qt::Key_G, nullptr, nullptr, QAction::PreferencesRole); connect(action, &QAction::triggered, [] { qApp->showDialog(QString("hifi/dialogs/GeneralPreferencesDialog.qml"), QString("hifi/tablet/TabletGeneralPreferences.qml"), "GeneralPreferencesDialog"); }); + // Settings > Controls... + action = addActionToQMenuAndActionHash(settingsMenu, "Controls..."); + connect(action, &QAction::triggered, [] { + qApp->showDialog(QString("hifi/tablet/ControllerSettings.qml"), + QString("hifi/tablet/ControllerSettings.qml"), "ControlSettings"); + }); + + // Settings > Audio... action = addActionToQMenuAndActionHash(settingsMenu, "Audio..."); connect(action, &QAction::triggered, [] { static const QUrl widgetUrl("hifi/dialogs/Audio.qml"); @@ -320,6 +251,13 @@ Menu::Menu() { qApp->showDialog(widgetUrl, tabletUrl, name); }); + // Settings > Graphics... + action = addActionToQMenuAndActionHash(settingsMenu, "Graphics..."); + connect(action, &QAction::triggered, [] { + qApp->showDialog(QString("hifi/dialogs/GraphicsPreferencesDialog.qml"), + QString("hifi/tablet/TabletGraphicsPreferences.qml"), "GraphicsPreferencesDialog"); + }); + // Settings > Avatar... action = addActionToQMenuAndActionHash(settingsMenu, "Avatar..."); connect(action, &QAction::triggered, [] { @@ -327,44 +265,83 @@ Menu::Menu() { QString("hifi/tablet/TabletAvatarPreferences.qml"), "AvatarPreferencesDialog"); }); - // Settings > LOD... - action = addActionToQMenuAndActionHash(settingsMenu, "LOD..."); - connect(action, &QAction::triggered, [] { - qApp->showDialog(QString("hifi/dialogs/LodPreferencesDialog.qml"), - QString("hifi/tablet/TabletLodPreferences.qml"), "LodPreferencesDialog"); - }); + // Settings > Notifications + MenuWrapper * notificationsMenu = settingsMenu->addMenu("Notifications"); //This was in notifications.js. The menu needs to be moved here. - action = addActionToQMenuAndActionHash(settingsMenu, "Controller Settings..."); - connect(action, &QAction::triggered, [] { - auto tablet = DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system"); - auto hmd = DependencyManager::get(); - tablet->loadQMLSource("hifi/tablet/ControllerSettings.qml"); + //TODO: Hookup notification actions below. + // Settings > Notifications > Play Notification Sounds + addActionToQMenuAndActionHash(notificationsMenu, "Play Notification Sounds"); - if (!hmd->getShouldShowTablet()) { - hmd->toggleShouldShowTablet(); - } - }); + notificationsMenu->addSeparator(); - // Settings > Control with Speech [advanced] -#if defined(Q_OS_MAC) || defined(Q_OS_WIN) - auto speechRecognizer = DependencyManager::get(); - QAction* speechRecognizerAction = addCheckableActionToQMenuAndActionHash(settingsMenu, MenuOption::ControlWithSpeech, - Qt::CTRL | Qt::SHIFT | Qt::Key_C, - speechRecognizer->getEnabled(), - speechRecognizer.data(), - SLOT(setEnabled(bool)), - UNSPECIFIED_POSITION, "Advanced"); - connect(speechRecognizer.data(), SIGNAL(enabledUpdated(bool)), speechRecognizerAction, SLOT(setChecked(bool))); -#endif + // Settings > Notifications > Play Sounds for: + addDisabledActionAndSeparator(notificationsMenu, "Show notifications for:"); + + // Settings > Notifications > Snapshot + addActionToQMenuAndActionHash(notificationsMenu, "Snapshot"); + + // Settings > Notifications > Level of Detail + addActionToQMenuAndActionHash(notificationsMenu, "Level of Detail"); + + // Settings > Notifications > Connection + addActionToQMenuAndActionHash(notificationsMenu, "Connection"); + + // Settings > Notifications > Connection Refused + addActionToQMenuAndActionHash(notificationsMenu, "Connection Refused"); + + // Settings > Notifications > Edit Error + addActionToQMenuAndActionHash(notificationsMenu, "Edit Error"); + + // Settings > Notifications > Tablet + addActionToQMenuAndActionHash(notificationsMenu, "Tablet"); + + // Settings > Notifications > Wallet + addActionToQMenuAndActionHash(notificationsMenu, "Wallet"); + + // Settings > Developer Menu + addCheckableActionToQMenuAndActionHash(settingsMenu, "Developer Menu", 0, false, this, SLOT(toggleDeveloperMenus())); + + // Settings > Ask to Reset Settings + addCheckableActionToQMenuAndActionHash(settingsMenu, MenuOption::AskToResetSettings, 0, false); // Developer menu ---------------------------------- MenuWrapper* developerMenu = addMenu("Developer", "Developer"); - // Developer > Graphics... - action = addActionToQMenuAndActionHash(developerMenu, "Graphics..."); + // Developer > Console... + addActionToQMenuAndActionHash(developerMenu, MenuOption::Console, Qt::CTRL | Qt::ALT | Qt::Key_J, + DependencyManager::get().data(), + SLOT(toggleConsole()), + QAction::NoRole); + + // Developer > Scripting >>> + MenuWrapper* scriptingOptionsMenu = developerMenu->addMenu("Scripting"); + + // Developer > Scripting > Log... + addActionToQMenuAndActionHash(scriptingOptionsMenu, MenuOption::Log, Qt::CTRL | Qt::SHIFT | Qt::Key_L, + qApp, SLOT(toggleLogDialog())); + + // Developer > Scripting > Entity Script Server Log + auto essLogAction = addActionToQMenuAndActionHash(scriptingOptionsMenu, MenuOption::EntityScriptServerLog, 0, + qApp, SLOT(toggleEntityScriptServerLogDialog())); + + QObject::connect(nodeList.data(), &NodeList::canRezChanged, essLogAction, [essLogAction] { + auto nodeList = DependencyManager::get(); + essLogAction->setEnabled(nodeList->getThisNodeCanRez()); + }); + + essLogAction->setEnabled(nodeList->getThisNodeCanRez()); + + // Developer > Scripting > Script Log (HMD Friendly)... + action = addActionToQMenuAndActionHash(scriptingOptionsMenu, "Script Log (HMD Friendly)...", Qt::NoButton, + qApp, SLOT(showScriptLogs())); + + // Developer > Scripting > API Debugger + action = addActionToQMenuAndActionHash(scriptingOptionsMenu, "API Debugger..."); connect(action, &QAction::triggered, [] { - qApp->showDialog(QString("hifi/dialogs/GraphicsPreferencesDialog.qml"), - QString("hifi/tablet/TabletGraphicsPreferences.qml"), "GraphicsPreferencesDialog"); + auto scriptEngines = DependencyManager::get(); + QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation(); + defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/utilities/tools/currentAPI.js"); + scriptEngines->loadScript(defaultScriptsLoc.toString()); }); // Developer > UI >>> @@ -698,12 +675,6 @@ Menu::Menu() { } addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowHulls, 0, false, qApp->getEntities().data(), SIGNAL(setRenderDebugHulls())); - // Developer > Ask to Reset Settings - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::AskToResetSettings, 0, false); - - // Developer > Display Crash Options - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::DisplayCrashOptions, 0, true); - // Developer > Crash >>> MenuWrapper* crashMenu = developerMenu->addMenu("Crash"); @@ -740,38 +711,23 @@ Menu::Menu() { action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashNewFaultThreaded); connect(action, &QAction::triggered, qApp, []() { std::thread([]() { crash::newFault(); }); }); - // Developer > Log... - addActionToQMenuAndActionHash(developerMenu, MenuOption::Log, Qt::CTRL | Qt::SHIFT | Qt::Key_L, - qApp, SLOT(toggleLogDialog())); - auto essLogAction = addActionToQMenuAndActionHash(developerMenu, MenuOption::EntityScriptServerLog, 0, - qApp, SLOT(toggleEntityScriptServerLogDialog())); - QObject::connect(nodeList.data(), &NodeList::canRezChanged, essLogAction, [essLogAction] { - auto nodeList = DependencyManager::get(); - essLogAction->setEnabled(nodeList->getThisNodeCanRez()); - }); - essLogAction->setEnabled(nodeList->getThisNodeCanRez()); - - action = addActionToQMenuAndActionHash(developerMenu, "Script Log (HMD friendly)...", Qt::NoButton, - qApp, SLOT(showScriptLogs())); + // Developer > Display Crash Options + addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::DisplayCrashOptions, 0, true); // Developer > Stats addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::Stats); - // Developer > Advanced Settings... - action = addActionToQMenuAndActionHash(developerMenu, "Advanced Preferences..."); - connect(action, &QAction::triggered, [] { - qApp->showDialog(QString("hifi/dialogs/AdvancedPreferencesDialog.qml"), - QString("hifi/tablet/AdvancedPreferencesDialog.qml"), "AdvancedPreferencesDialog"); - }); - - // Developer > API Debugger - action = addActionToQMenuAndActionHash(developerMenu, "API Debugger"); - connect(action, &QAction::triggered, [] { - auto scriptEngines = DependencyManager::get(); - QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation(); - defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/utilities/tools/currentAPI.js"); - scriptEngines->loadScript(defaultScriptsLoc.toString()); - }); + // Settings > Enable Speech Control API +#if defined(Q_OS_MAC) || defined(Q_OS_WIN) + auto speechRecognizer = DependencyManager::get(); + QAction* speechRecognizerAction = addCheckableActionToQMenuAndActionHash(settingsMenu, MenuOption::ControlWithSpeech, + Qt::CTRL | Qt::SHIFT | Qt::Key_C, + speechRecognizer->getEnabled(), + speechRecognizer.data(), + SLOT(setEnabled(bool)), + UNSPECIFIED_POSITION, "Advanced"); + connect(speechRecognizer.data(), SIGNAL(enabledUpdated(bool)), speechRecognizerAction, SLOT(setChecked(bool))); +#endif #if 0 /// -------------- REMOVED FOR NOW -------------- addDisabledActionAndSeparator(navigateMenu, "History"); @@ -798,6 +754,55 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::NamesAboveHeads, 0, true, NULL, NULL, UNSPECIFIED_POSITION, "Advanced"); #endif + + // Help/Application menu ---------------------------------- + MenuWrapper * helpMenu = addMenu("Help"); + + // Help > About High Fidelity + //TODO: Add dialog to show about: Logo, Company, Version + addActionToQMenuAndActionHash(helpMenu, "About High Fidelity"); + + helpMenu->addSeparator(); + + // Help > HiFi Docs + action = addActionToQMenuAndActionHash(helpMenu, "Online Documentation"); + connect(action, &QAction::triggered, qApp, [] { + QDesktopServices::openUrl(QUrl("https://docs.highfidelity.com/")); + }); + + // Help > HiFi Forum + action = addActionToQMenuAndActionHash(helpMenu, "Online Forums"); + connect(action, &QAction::triggered, qApp, [] { + QDesktopServices::openUrl(QUrl("https://forums.highfidelity.com/")); + }); + + // Help > Scripting Reference + action = addActionToQMenuAndActionHash(helpMenu, "Online Script Reference"); + connect(action, &QAction::triggered, qApp, [] { + QDesktopServices::openUrl(QUrl("https://docs.highfidelity.com/api-reference")); + }); + + addActionToQMenuAndActionHash(helpMenu, "Controls Reference", 0, qApp, SLOT(showHelp())); + + helpMenu->addSeparator(); + + // Help > Check for Updates + //ToDo: Add check for updates + addActionToQMenuAndActionHash(helpMenu, "Check for Updates"); + + helpMenu->addSeparator(); + + // Help > Release Notes + action = addActionToQMenuAndActionHash(helpMenu, "Release Notes"); + connect(action, &QAction::triggered, qApp, [] { + QDesktopServices::openUrl(QUrl("http://steamcommunity.com/games/390540/announcements/")); + }); + + // Help > Report a Bug! + action = addActionToQMenuAndActionHash(helpMenu, "Report a Bug!"); + connect(action, &QAction::triggered, qApp, [] { + QDesktopServices::openUrl(QUrl("mailto:support@highfidelity.com")); + }); } void Menu::addMenuItem(const MenuItemProperties& properties) { diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 34588535ec..5adde90b0f 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -32,7 +32,7 @@ namespace MenuOption { const QString AnimDebugDrawAnimPose = "Debug Draw Animation"; const QString AnimDebugDrawDefaultPose = "Debug Draw Default Pose"; const QString AnimDebugDrawPosition= "Debug Draw Position"; - const QString AskToResetSettings = "Ask To Reset Settings"; + const QString AskToResetSettings = "Ask To Reset Settings on Start"; const QString AssetMigration = "ATP Asset Migration"; const QString AssetServer = "Asset Browser"; const QString Attachments = "Attachments..."; @@ -59,7 +59,7 @@ namespace MenuOption { const QString Collisions = "Collisions"; const QString Connexion = "Activate 3D Connexion Devices"; const QString Console = "Console..."; - const QString ControlWithSpeech = "Control With Speech"; + const QString ControlWithSpeech = "Enable Speech Control API"; const QString CopyAddress = "Copy Address to Clipboard"; const QString CopyPath = "Copy Path to Clipboard"; const QString CoupleEyelids = "Couple Eyelids"; @@ -121,7 +121,7 @@ namespace MenuOption { const QString LoadScript = "Open and Run Script File..."; const QString LoadScriptURL = "Open and Run Script from URL..."; const QString LodTools = "LOD Tools"; - const QString Login = "Login / Sign Up"; + const QString Login = "Login/Sign Up"; const QString Log = "Log"; const QString LogExtraTimings = "Log Extra Timing Details"; const QString LowVelocityFilter = "Low Velocity Filter"; @@ -137,7 +137,7 @@ namespace MenuOption { const QString OpenVrThreadedSubmit = "OpenVR Threaded Submit"; const QString OutputMenu = "Display"; const QString Overlays = "Overlays"; - const QString PackageModel = "Package Model..."; + const QString PackageModel = "Package Model as .fst..."; const QString Pair = "Pair"; const QString PhysicsShowHulls = "Draw Collision Shapes"; const QString PhysicsShowOwned = "Highlight Simulation Ownership"; @@ -186,7 +186,7 @@ namespace MenuOption { const QString SimulateEyeTracking = "Simulate"; const QString SMIEyeTracking = "SMI Eye Tracking"; const QString SparseTextureManagement = "Enable Sparse Texture Management"; - const QString Stats = "Stats"; + const QString Stats = "Show Statistics"; const QString StopAllScripts = "Stop All Scripts"; const QString SuppressShortTimings = "Suppress Timings Less than 10ms"; const QString ThirdPerson = "Third Person"; diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 48b56c7ced..8860f4dab7 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -56,33 +56,31 @@ void setupPreferences() { preferences->addPreference(preference); } - { - auto getter = [=]()->bool { return myAvatar->getSnapTurn(); }; - auto setter = [=](bool value) { myAvatar->setSnapTurn(value); }; - preferences->addPreference(new CheckPreference(AVATAR_BASICS, "Snap turn when in HMD", getter, setter)); - } - { - auto getter = [=]()->bool { return myAvatar->getClearOverlayWhenMoving(); }; - auto setter = [=](bool value) { myAvatar->setClearOverlayWhenMoving(value); }; - preferences->addPreference(new CheckPreference(AVATAR_BASICS, "Clear overlays when moving", getter, setter)); - } - // UI - static const QString UI_CATEGORY { "UI" }; + static const QString UI_CATEGORY { "User Interface" }; { auto getter = []()->bool { return qApp->getSettingConstrainToolbarPosition(); }; auto setter = [](bool value) { qApp->setSettingConstrainToolbarPosition(value); }; preferences->addPreference(new CheckPreference(UI_CATEGORY, "Constrain Toolbar Position to Horizontal Center", getter, setter)); } + { - auto getter = []()->float { return qApp->getHMDTabletScale(); }; - auto setter = [](float value) { qApp->setHMDTabletScale(value); }; - auto preference = new SpinnerPreference(UI_CATEGORY, "HMD Tablet Scale %", getter, setter); + auto getter = []()->float { return qApp->getDesktopTabletScale(); }; + auto setter = [](float value) { qApp->setDesktopTabletScale(value); }; + auto preference = new SpinnerPreference(UI_CATEGORY, "Desktop Tablet Scale %", getter, setter); preference->setMin(20); preference->setMax(500); preferences->addPreference(preference); } + { + auto getter = []()->float { return qApp->getHMDTabletScale(); }; + auto setter = [](float value) { qApp->setHMDTabletScale(value); }; + auto preference = new SpinnerPreference(UI_CATEGORY, "VR Tablet Scale %", getter, setter); + preference->setMin(20); + preference->setMax(500); + preferences->addPreference(preference); + } { auto getter = []()->bool { return qApp->getPreferStylusOverLaser(); }; @@ -90,19 +88,18 @@ void setupPreferences() { preferences->addPreference(new CheckPreference(UI_CATEGORY, "Prefer Stylus Over Laser", getter, setter)); } - static const QString ADVANCED_UI_CATEGORY { "Advanced UI" }; { - auto getter = []()->float { return qApp->getDesktopTabletScale(); }; - auto setter = [](float value) { qApp->setDesktopTabletScale(value); }; - auto preference = new SpinnerPreference(ADVANCED_UI_CATEGORY, "Desktop Tablet Scale %", getter, setter); - preference->setMin(20); - preference->setMax(500); - preferences->addPreference(preference); + static const QString RETICLE_ICON_NAME = { Cursor::Manager::getIconName(Cursor::Icon::RETICLE) }; + auto getter = []()->bool { return qApp->getPreferredCursor() == RETICLE_ICON_NAME; }; + auto setter = [](bool value) { qApp->setPreferredCursor(value ? RETICLE_ICON_NAME : QString()); }; + preferences->addPreference(new CheckPreference(UI_CATEGORY, "Use reticle cursor instead of arrow", getter, setter)); } + + static const QString VIEW_CATEGORY{ "View" }; { auto getter = [=]()->float { return myAvatar->getRealWorldFieldOfView(); }; auto setter = [=](float value) { myAvatar->setRealWorldFieldOfView(value); }; - auto preference = new SpinnerPreference(ADVANCED_UI_CATEGORY, "Real world vertical field of view (angular size of monitor)", getter, setter); + auto preference = new SpinnerPreference(VIEW_CATEGORY, "Real world vertical field of view (angular size of monitor)", getter, setter); preference->setMin(1); preference->setMax(180); preferences->addPreference(preference); @@ -110,7 +107,7 @@ void setupPreferences() { { auto getter = []()->float { return qApp->getFieldOfView(); }; auto setter = [](float value) { qApp->setFieldOfView(value); }; - auto preference = new SpinnerPreference(ADVANCED_UI_CATEGORY, "Vertical field of view", getter, setter); + auto preference = new SpinnerPreference(VIEW_CATEGORY, "Vertical field of view", getter, setter); preference->setMin(1); preference->setMax(180); preference->setStep(1); @@ -126,12 +123,6 @@ void setupPreferences() { preferences->addPreference(new CheckPreference(UI_CATEGORY, "Prefer Avatar Finger Over Stylus", getter, setter)); } */ - { - static const QString RETICLE_ICON_NAME = { Cursor::Manager::getIconName(Cursor::Icon::RETICLE) }; - auto getter = []()->bool { return qApp->getPreferredCursor() == RETICLE_ICON_NAME; }; - auto setter = [](bool value) { qApp->setPreferredCursor(value ? RETICLE_ICON_NAME : QString()); }; - preferences->addPreference(new CheckPreference(UI_CATEGORY, "Use reticle cursor instead of arrow", getter, setter)); - } // Snapshots static const QString SNAPSHOTS { "Snapshots" }; @@ -160,27 +151,6 @@ void setupPreferences() { "this information you are helping to improve the product. ", getter, setter)); } - static const QString LOD_TUNING("Level of Detail Tuning"); - { - auto getter = []()->float { return DependencyManager::get()->getDesktopLODDecreaseFPS(); }; - auto setter = [](float value) { DependencyManager::get()->setDesktopLODDecreaseFPS(value); }; - auto preference = new SpinnerPreference(LOD_TUNING, "Minimum desktop FPS", getter, setter); - preference->setMin(0); - preference->setMax(120); - preference->setStep(1); - preferences->addPreference(preference); - } - - { - auto getter = []()->float { return DependencyManager::get()->getHMDLODDecreaseFPS(); }; - auto setter = [](float value) { DependencyManager::get()->setHMDLODDecreaseFPS(value); }; - auto preference = new SpinnerPreference(LOD_TUNING, "Minimum HMD FPS", getter, setter); - preference->setMin(0); - preference->setMax(120); - preference->setStep(1); - preferences->addPreference(preference); - } - static const QString AVATAR_TUNING { "Avatar Tuning" }; { auto getter = [=]()->QString { return myAvatar->getDominantHand(); }; @@ -210,16 +180,7 @@ void setupPreferences() { preference->setStep(0.001f); preferences->addPreference(preference); } - { - auto getter = []()->float { return DependencyManager::get()->getEyeClosingThreshold(); }; - auto setter = [](float value) { DependencyManager::get()->setEyeClosingThreshold(value); }; - preferences->addPreference(new SliderPreference(AVATAR_TUNING, "Camera binary eyelid threshold", getter, setter)); - } - { - auto getter = []()->float { return FaceTracker::getEyeDeflection(); }; - auto setter = [](float value) { FaceTracker::setEyeDeflection(value); }; - preferences->addPreference(new SliderPreference(AVATAR_TUNING, "Face tracker eye deflection", getter, setter)); - } + { auto getter = [=]()->QString { return myAvatar->getAnimGraphOverrideUrl().toString(); }; auto setter = [=](const QString& value) { myAvatar->setAnimGraphOverrideUrl(QUrl(value)); }; @@ -228,11 +189,38 @@ void setupPreferences() { preferences->addPreference(preference); } - static const QString AVATAR_CAMERA { "Avatar Camera" }; + static const QString FACE_TRACKING{ "Face Tracking" }; + { + auto getter = []()->float { return DependencyManager::get()->getEyeClosingThreshold(); }; + auto setter = [](float value) { DependencyManager::get()->setEyeClosingThreshold(value); }; + preferences->addPreference(new SliderPreference(FACE_TRACKING, "Eye Closing Threshold", getter, setter)); + } + { + auto getter = []()->float { return FaceTracker::getEyeDeflection(); }; + auto setter = [](float value) { FaceTracker::setEyeDeflection(value); }; + preferences->addPreference(new SliderPreference(FACE_TRACKING, "Eye Deflection", getter, setter)); + } + + static const QString MOVEMENT{ "VR Movement" }; + + { + auto getter = [=]()->bool { return myAvatar->getSnapTurn(); }; + auto setter = [=](bool value) { myAvatar->setSnapTurn(value); }; + preferences->addPreference(new CheckPreference(MOVEMENT, "Snap turn rotation", getter, setter)); + } + + //TODO: Update with advanced movement logic, test that it works + { + auto getter = [=]()->bool { return myAvatar->useAdvancedMovementControls(); }; + auto setter = [=](bool value) { myAvatar->setUseAdvancedMovementControls(value); }; + preferences->addPreference(new CheckPreference(MOVEMENT, "Advanced movement for hand controllers", getter, setter)); + } + + static const QString AVATAR_CAMERA{ "Mouse Sensitivity" }; { auto getter = [=]()->float { return myAvatar->getPitchSpeed(); }; auto setter = [=](float value) { myAvatar->setPitchSpeed(value); }; - auto preference = new SpinnerPreference(AVATAR_CAMERA, "Camera pitch speed (degrees/second)", getter, setter); + auto preference = new SpinnerPreference(AVATAR_CAMERA, "Pitch speed (degrees/second)", getter, setter); preference->setMin(1.0f); preference->setMax(360.0f); preferences->addPreference(preference); @@ -240,7 +228,7 @@ void setupPreferences() { { auto getter = [=]()->float { return myAvatar->getYawSpeed(); }; auto setter = [=](float value) { myAvatar->setYawSpeed(value); }; - auto preference = new SpinnerPreference(AVATAR_CAMERA, "Camera yaw speed (degrees/second)", getter, setter); + auto preference = new SpinnerPreference(AVATAR_CAMERA, "Yaw speed (degrees/second)", getter, setter); preference->setMin(1.0f); preference->setMax(360.0f); preferences->addPreference(preference); @@ -297,14 +285,14 @@ void setupPreferences() { { - static const QString RENDER("Graphics"); + static const QString GRAPHICS_QUALITY("Graphics Quality"); auto renderConfig = qApp->getRenderEngine()->getConfiguration(); if (renderConfig) { auto mainViewAmbientOcclusionConfig = renderConfig->getConfig("RenderMainView.AmbientOcclusion"); if (mainViewAmbientOcclusionConfig) { auto getter = [mainViewAmbientOcclusionConfig]()->QString { return mainViewAmbientOcclusionConfig->getPreset(); }; auto setter = [mainViewAmbientOcclusionConfig](QString preset) { mainViewAmbientOcclusionConfig->setPreset(preset); }; - auto preference = new ComboBoxPreference(RENDER, "Ambient occlusion", getter, setter); + auto preference = new ComboBoxPreference(GRAPHICS_QUALITY, "Ambient occlusion", getter, setter); preference->setItems(mainViewAmbientOcclusionConfig->getPresetList()); preferences->addPreference(preference); } @@ -313,7 +301,7 @@ void setupPreferences() { if (mainViewShadowConfig) { auto getter = [mainViewShadowConfig]()->QString { return mainViewShadowConfig->getPreset(); }; auto setter = [mainViewShadowConfig](QString preset) { mainViewShadowConfig->setPreset(preset); }; - auto preference = new ComboBoxPreference(RENDER, "Shadows", getter, setter); + auto preference = new ComboBoxPreference(GRAPHICS_QUALITY, "Shadows", getter, setter); preference->setItems(mainViewShadowConfig->getPresetList()); preferences->addPreference(preference); } From 61e2814db4dc0455e56aef4acc30cf5861f6cf92 Mon Sep 17 00:00:00 2001 From: Alexia Mandeville Date: Mon, 12 Mar 2018 13:07:21 -0700 Subject: [PATCH 002/143] Removing toolbar apps that are no longer necessary --- scripts/defaultScripts.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/defaultScripts.js b/scripts/defaultScripts.js index 71755e3abb..b0cbf0e246 100644 --- a/scripts/defaultScripts.js +++ b/scripts/defaultScripts.js @@ -19,14 +19,12 @@ var DEFAULT_SCRIPTS_COMBINED = [ "system/menu.js", "system/bubble.js", "system/snapshot.js", - "system/help.js", "system/pal.js", // "system/mod.js", // older UX, if you prefer "system/makeUserConnection.js", "system/tablet-goto.js", "system/marketplaces/marketplaces.js", "system/commerce/wallet.js", "system/edit.js", - "system/notifications.js", "system/dialTone.js", "system/firstPersonHMD.js", "system/tablet-ui/tabletUI.js", From c760c44531e1915671b17be1219301cfb0bcc045 Mon Sep 17 00:00:00 2001 From: Alexia Mandeville Date: Mon, 12 Mar 2018 13:17:23 -0700 Subject: [PATCH 003/143] Revert "Update repo script with marketplace script" This reverts commit 5139f3f50328c0299801906ba435d5e1528c72f8. --- scripts/tutorials/entity_scripts/sit.js | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/scripts/tutorials/entity_scripts/sit.js b/scripts/tutorials/entity_scripts/sit.js index 9de65d7037..70456ea493 100644 --- a/scripts/tutorials/entity_scripts/sit.js +++ b/scripts/tutorials/entity_scripts/sit.js @@ -12,9 +12,9 @@ Script.include("/~/system/libraries/utils.js"); if (!String.prototype.startsWith) { String.prototype.startsWith = function(searchString, position){ - position = position || 0; - return this.substr(position, searchString.length) === searchString; - }; + position = position || 0; + return this.substr(position, searchString.length) === searchString; + }; } var SETTING_KEY = "com.highfidelity.avatar.isSitting"; @@ -122,10 +122,20 @@ this.rolesToOverride = function() { return MyAvatar.getAnimationRoles().filter(function(role) { - return !(role.startsWith("right") || role.startsWith("left")); + return !(role.startsWith("right") || role.startsWith("left")); }); } + // Handler for user changing the avatar model while sitting. There's currently an issue with changing avatar models while override role animations are applied, + // so to avoid that problem, re-apply the role overrides once the model has finished changing. + this.modelURLChangeFinished = function () { + print("Sitter's model has FINISHED changing. Reapply anim role overrides."); + var roles = this.rolesToOverride(); + for (i in roles) { + MyAvatar.overrideRoleAnimation(roles[i], ANIMATION_URL, ANIMATION_FPS, true, ANIMATION_FIRST_FRAME, ANIMATION_LAST_FRAME); + } + } + this.sitDown = function() { if (this.checkSeatForAvatar()) { print("Someone is already sitting in that chair."); @@ -164,12 +174,14 @@ return { headType: 0 }; }, ["headType"]); Script.update.connect(this, this.update); + MyAvatar.onLoadComplete.connect(this, this.modelURLChangeFinished); } this.standUp = function() { print("Standing up (" + this.entityID + ")"); MyAvatar.removeAnimationStateHandler(this.animStateHandlerID); Script.update.disconnect(this, this.update); + MyAvatar.onLoadComplete.disconnect(this, this.modelURLChangeFinished); if (MyAvatar.sessionUUID === this.getSeatUser()) { this.setSeatUser(null); @@ -331,7 +343,7 @@ } this.cleanupOverlay(); } - + this.clickDownOnEntity = function (id, event) { if (isInEditMode()) { return; @@ -340,4 +352,4 @@ this.sitDown(); } } -}); \ No newline at end of file +}); From 6ddb91e5939632fe2a16b8a44768b09d93cb6230 Mon Sep 17 00:00:00 2001 From: Alexia Mandeville Date: Mon, 12 Mar 2018 13:17:48 -0700 Subject: [PATCH 004/143] Revert "Updating default mouse pitch/yaw input to be more stabilized" This reverts commit 2598be16f81734e86e00f2789bc2111bcdf448b8. --- interface/src/avatar/MyAvatar.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 8bbbef041a..53116d81f3 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -67,8 +67,8 @@ using namespace std; const float DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES = 30.0f; -const float YAW_SPEED_DEFAULT = 75.0f; // degrees/sec -const float PITCH_SPEED_DEFAULT = 50.0f; // degrees/sec +const float YAW_SPEED_DEFAULT = 100.0f; // degrees/sec +const float PITCH_SPEED_DEFAULT = 75.0f; // degrees/sec const float MAX_BOOST_SPEED = 0.5f * DEFAULT_AVATAR_MAX_WALKING_SPEED; // action motor gets additive boost below this speed const float MIN_AVATAR_SPEED = 0.05f; From c5b8a2d06ecd933279334ae47858c1a0ef6756c4 Mon Sep 17 00:00:00 2001 From: Alexia Mandeville Date: Mon, 12 Mar 2018 13:18:02 -0700 Subject: [PATCH 005/143] Revert "Increasing speed on mousescroll - zooming in/out of avatar" This reverts commit 748507f1e357b7a03177f847c63362297de9663e. --- interface/src/avatar/MyAvatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 53116d81f3..b6fa3fde96 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2229,7 +2229,7 @@ void MyAvatar::updateActionMotor(float deltaTime) { } float boomChange = getDriveKey(ZOOM); - _boomLength += 4.0f * _boomLength * boomChange + boomChange * boomChange; + _boomLength += 2.0f * _boomLength * boomChange + boomChange * boomChange; _boomLength = glm::clamp(_boomLength, ZOOM_MIN, ZOOM_MAX); } From 31ab39834461afb448bd3a21c55c94bd4cb6a87f Mon Sep 17 00:00:00 2001 From: Alexia Mandeville Date: Thu, 29 Mar 2018 11:20:01 -0700 Subject: [PATCH 006/143] Moving user height and clarifying verbiage --- interface/src/ui/PreferencesDialog.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 8860f4dab7..b309ecd5e3 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -170,16 +170,6 @@ void setupPreferences() { // which can't be changed across domain switches. Having these values loaded up when you load the Dialog each time // is a way around this, therefore they're not specified here but in the QML. } - { - auto getter = [=]()->float { return myAvatar->getUserHeight(); }; - auto setter = [=](float value) { myAvatar->setUserHeight(value); }; - auto preference = new SpinnerPreference(AVATAR_TUNING, "User height (meters)", getter, setter); - preference->setMin(1.0f); - preference->setMax(2.2f); - preference->setDecimals(3); - preference->setStep(0.001f); - preferences->addPreference(preference); - } { auto getter = [=]()->QString { return myAvatar->getAnimGraphOverrideUrl().toString(); }; @@ -216,6 +206,17 @@ void setupPreferences() { preferences->addPreference(new CheckPreference(MOVEMENT, "Advanced movement for hand controllers", getter, setter)); } + { + auto getter = [=]()->float { return myAvatar->getUserHeight(); }; + auto setter = [=](float value) { myAvatar->setUserHeight(value); }; + auto preference = new SpinnerPreference(MOVEMENT, "User real-world height (meters)", getter, setter); + preference->setMin(1.0f); + preference->setMax(2.2f); + preference->setDecimals(3); + preference->setStep(0.001f); + preferences->addPreference(preference); + } + static const QString AVATAR_CAMERA{ "Mouse Sensitivity" }; { auto getter = [=]()->float { return myAvatar->getPitchSpeed(); }; From 8a5d80de312fbe7512a6a1b40fe18c2c32edaf16 Mon Sep 17 00:00:00 2001 From: vladest Date: Tue, 17 Apr 2018 19:51:24 +0200 Subject: [PATCH 007/143] Fix Desktop double windows --- interface/src/Application.cpp | 7 +------ interface/src/ui/PreferencesDialog.cpp | 7 +++++++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index aec31f2de4..a2d117e6ee 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6518,12 +6518,7 @@ void Application::showDialog(const QUrl& widgetUrl, const QUrl& tabletUrl, const if (onTablet) { toggleTabletUI(true); } - } - - if (!onTablet) { - DependencyManager::get()->show(widgetUrl, name); - } - if (tablet->getToolbarMode()) { + } else { DependencyManager::get()->show(widgetUrl, name); } } diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 289166648e..a678a1b94b 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -51,6 +51,13 @@ void setupPreferences() { auto preference = new AvatarPreference(AVATAR_BASICS, "Appearance", getter, setter); preferences->addPreference(preference); } + // UI + static const QString GRAPHICS_QUALITY { "Graphics Quality" }; + { + auto getter = []()->float { return DependencyManager::get()->getLODLevel(); }; + auto setter = [](float value) { FaceTracker::setEyeDeflection(value); }; + preferences->addPreference(new SliderPreference(GRAPHICS_QUALITY, "World Detail", getter, setter)); + } // UI static const QString UI_CATEGORY { "User Interface" }; From c402cb2c19f93b7e4d7b619171996514deaa70aa Mon Sep 17 00:00:00 2001 From: vladest Date: Tue, 17 Apr 2018 19:51:43 +0200 Subject: [PATCH 008/143] Fix Desktop double windows --- .../dialogs/GraphicsPreferencesDialog.qml | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 interface/resources/qml/hifi/dialogs/GraphicsPreferencesDialog.qml diff --git a/interface/resources/qml/hifi/dialogs/GraphicsPreferencesDialog.qml b/interface/resources/qml/hifi/dialogs/GraphicsPreferencesDialog.qml new file mode 100644 index 0000000000..eaab5b8173 --- /dev/null +++ b/interface/resources/qml/hifi/dialogs/GraphicsPreferencesDialog.qml @@ -0,0 +1,29 @@ +// +// AdvancedPreferencesDialog.qml +// +// Created by Brad Hefta-Gaub on 20 Jan 2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 +import Qt.labs.settings 1.0 + +import "../../dialogs" + +PreferencesDialog { + id: root + objectName: "GraphicsPreferencesDialog" + title: "Graphics Settings" + showCategories: ["Graphics Quality" ] + property var settings: Settings { + category: root.objectName + property alias x: root.x + property alias y: root.y + property alias width: root.width + property alias height: root.height + } +} + From ee1738adac9aa0070bd42eb35c802cd5e647d25b Mon Sep 17 00:00:00 2001 From: vladest Date: Tue, 17 Apr 2018 21:58:53 +0200 Subject: [PATCH 009/143] Add stubs for graphics settings. Add avatar collision setting --- interface/src/ui/PreferencesDialog.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index a678a1b94b..ac7a4f0610 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -55,8 +55,11 @@ void setupPreferences() { static const QString GRAPHICS_QUALITY { "Graphics Quality" }; { auto getter = []()->float { return DependencyManager::get()->getLODLevel(); }; - auto setter = [](float value) { FaceTracker::setEyeDeflection(value); }; + auto setter = [](float value) { }; preferences->addPreference(new SliderPreference(GRAPHICS_QUALITY, "World Detail", getter, setter)); + auto getterSQ = []()->float { return 1.0; }; + auto setterSQ = [](float value) { }; + preferences->addPreference(new SliderPreference(GRAPHICS_QUALITY, "Shadow Quality", getterSQ, setterSQ)); } // UI @@ -182,6 +185,13 @@ void setupPreferences() { preferences->addPreference(preference); } + { + auto getter = [=]()->bool { return myAvatar->getCollisionsEnabled(); }; + auto setter = [=](bool value) { myAvatar->setCollisionsEnabled(value); }; + auto preference = new CheckPreference(AVATAR_TUNING, "Enable Avatar collisions", getter, setter); + preferences->addPreference(preference); + } + static const QString FACE_TRACKING{ "Face Tracking" }; { auto getter = []()->float { return DependencyManager::get()->getEyeClosingThreshold(); }; From cacb9359c232b58b2c31a91273783149e1a4289c Mon Sep 17 00:00:00 2001 From: vladest Date: Wed, 18 Apr 2018 20:57:28 +0200 Subject: [PATCH 010/143] Toolbar at bottom --- interface/resources/qml/hifi/Desktop.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/Desktop.qml b/interface/resources/qml/hifi/Desktop.qml index 24111ad935..e3e6d40891 100644 --- a/interface/resources/qml/hifi/Desktop.qml +++ b/interface/resources/qml/hifi/Desktop.qml @@ -36,7 +36,7 @@ OriginalDesktop.Desktop { } } - Component { id: toolbarBuilder; Toolbar { } } + Component { id: toolbarBuilder; Toolbar { y: desktop.y - 50 } } // This used to create sysToolbar dynamically with a call to getToolbar() within onCompleted. // Beginning with QT 5.6, this stopped working, as anything added to toolbars too early got // wiped during startup. @@ -47,7 +47,7 @@ OriginalDesktop.Desktop { anchors.horizontalCenter: settings.constrainToolbarToCenterX ? desktop.horizontalCenter : undefined; // Literal 50 is overwritten by settings from previous session, and sysToolbar.x comes from settings when not constrained. x: sysToolbar.x - y: 50 + y: desktop.height - 50 - height buttonModel: tablet.buttons; shown: tablet.toolbarMode; } From 7b21b36d3cb524edb20bbeb82488ae110d9390a4 Mon Sep 17 00:00:00 2001 From: vladest Date: Wed, 18 Apr 2018 22:19:54 +0200 Subject: [PATCH 011/143] Disable menu button in Toolbar mode --- interface/resources/qml/hifi/Desktop.qml | 4 ++-- interface/resources/qml/hifi/toolbars/Toolbar.qml | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/Desktop.qml b/interface/resources/qml/hifi/Desktop.qml index e3e6d40891..5a0d0e3c05 100644 --- a/interface/resources/qml/hifi/Desktop.qml +++ b/interface/resources/qml/hifi/Desktop.qml @@ -36,7 +36,7 @@ OriginalDesktop.Desktop { } } - Component { id: toolbarBuilder; Toolbar { y: desktop.y - 50 } } + Component { id: toolbarBuilder; Toolbar { } } // This used to create sysToolbar dynamically with a call to getToolbar() within onCompleted. // Beginning with QT 5.6, this stopped working, as anything added to toolbars too early got // wiped during startup. @@ -47,7 +47,7 @@ OriginalDesktop.Desktop { anchors.horizontalCenter: settings.constrainToolbarToCenterX ? desktop.horizontalCenter : undefined; // Literal 50 is overwritten by settings from previous session, and sysToolbar.x comes from settings when not constrained. x: sysToolbar.x - y: desktop.height - 50 - height + y: desktop.height - sysToolbar.height - 50 buttonModel: tablet.buttons; shown: tablet.toolbarMode; } diff --git a/interface/resources/qml/hifi/toolbars/Toolbar.qml b/interface/resources/qml/hifi/toolbars/Toolbar.qml index 49aff06929..79162d9240 100644 --- a/interface/resources/qml/hifi/toolbars/Toolbar.qml +++ b/interface/resources/qml/hifi/toolbars/Toolbar.qml @@ -38,6 +38,8 @@ Window { property var proxy: modelData; onClicked: proxy.clicked() Component.onCompleted: updateProperties() + //menu button should be visible only in VR mode + visible: text !== "MENU" Connections { target: proxy; From fffd4eec419cb689bdbbea6a0edb63060e7995cf Mon Sep 17 00:00:00 2001 From: vladest Date: Thu, 19 Apr 2018 08:46:20 +0200 Subject: [PATCH 012/143] Avatar enable flying added --- interface/src/ui/PreferencesDialog.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index ac7a4f0610..b82f387137 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -229,6 +229,11 @@ void setupPreferences() { preference->setStep(0.001f); preferences->addPreference(preference); } + { + auto getter = [=]()->bool { return myAvatar->getFlyingEnabled(); }; + auto setter = [=](bool value) { myAvatar->setFlyingEnabled(value); }; + preferences->addPreference(new CheckPreference(MOVEMENT, "Enable Flying", getter, setter)); + } static const QString AVATAR_CAMERA{ "Mouse Sensitivity" }; { From 60d53359bbe0faf31a7cc896eaa3ac0c83c2c4b5 Mon Sep 17 00:00:00 2001 From: vladest Date: Thu, 19 Apr 2018 11:39:58 +0200 Subject: [PATCH 013/143] Fix Toolbar vertical position --- interface/resources/qml/hifi/Desktop.qml | 24 ++++++++++++++++++- .../resources/qml/hifi/toolbars/Toolbar.qml | 16 +++++++++++-- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/Desktop.qml b/interface/resources/qml/hifi/Desktop.qml index 5a0d0e3c05..4d342fe775 100644 --- a/interface/resources/qml/hifi/Desktop.qml +++ b/interface/resources/qml/hifi/Desktop.qml @@ -36,6 +36,29 @@ OriginalDesktop.Desktop { } } + onHeightChanged: { + if (height > 100) { + adjustToolbarPosition(); + } + } + + function adjustToolbarPosition() { + var toolbar = getToolbar("com.highfidelity.interface.toolbar.system") + // check if Y position was changed, if toolbar height is assigned etc + // default position is adjusted to border width + var toolbarY = toolbar.settings.y > 6 ? + toolbar.settings.y : + desktop.height - (toolbar.height > 0 ? toolbar.height : 50) - 56 + + if (toolbar.settings.desktopHeight > 100 && desktop.height !== toolbar.settings.desktopHeight) { + toolbarY += desktop.height - toolbar.settings.desktopHeight + } + + toolbar.y = toolbarY + toolbar.settings.y = toolbarY + toolbar.settings.desktopHeight = desktop.height + } + Component { id: toolbarBuilder; Toolbar { } } // This used to create sysToolbar dynamically with a call to getToolbar() within onCompleted. // Beginning with QT 5.6, this stopped working, as anything added to toolbars too early got @@ -47,7 +70,6 @@ OriginalDesktop.Desktop { anchors.horizontalCenter: settings.constrainToolbarToCenterX ? desktop.horizontalCenter : undefined; // Literal 50 is overwritten by settings from previous session, and sysToolbar.x comes from settings when not constrained. x: sysToolbar.x - y: desktop.height - sysToolbar.height - 50 buttonModel: tablet.buttons; shown: tablet.toolbarMode; } diff --git a/interface/resources/qml/hifi/toolbars/Toolbar.qml b/interface/resources/qml/hifi/toolbars/Toolbar.qml index 79162d9240..b31a61e066 100644 --- a/interface/resources/qml/hifi/toolbars/Toolbar.qml +++ b/interface/resources/qml/hifi/toolbars/Toolbar.qml @@ -25,12 +25,24 @@ Window { property bool horizontal: true property real buttonSize: 50; + property alias settings: settings + Settings { + id: settings category: "toolbar/" + window.objectName property alias x: window.x - property alias y: window.y + property real y: 0 + property real desktopHeight: 0 //placeholder for desktop height } - + + onYChanged: { + //check if Y changed not due to Desktop size changed. ie. mouse manipulations + //otherwise it will be save by Desktop + if (desktop.height > 100 && desktop.height === settings.desktopHeight) { + settings.y = window.y + } + } + Component { id: buttonComponent ToolbarButton { From ba4ef74313e58e5e2eecaf122d751f529dbb2083 Mon Sep 17 00:00:00 2001 From: vladest Date: Thu, 19 Apr 2018 12:01:58 +0200 Subject: [PATCH 014/143] Remove View->Overlays menu --- interface/src/Application.cpp | 9 ++------- interface/src/Menu.cpp | 4 ---- interface/src/ui/OverlayConductor.cpp | 2 +- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 420818d931..663902d90f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4819,14 +4819,10 @@ void Application::updateThreads(float deltaTime) { } } -void Application::toggleOverlays() { - auto menu = Menu::getInstance(); - menu->setIsOptionChecked(MenuOption::Overlays, !menu->isOptionChecked(MenuOption::Overlays)); -} +void Application::toggleOverlays() {} void Application::setOverlaysVisible(bool visible) { - auto menu = Menu::getInstance(); - menu->setIsOptionChecked(MenuOption::Overlays, true); + Q_UNUSED(visible) } void Application::centerUI() { @@ -7770,7 +7766,6 @@ void Application::readArgumentsFromLocalSocket() const { } void Application::showDesktop() { - Menu::getInstance()->setIsOptionChecked(MenuOption::Overlays, true); } CompositorHelper& Application::getApplicationCompositor() const { diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 70f32dd216..6b199896f4 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -202,10 +202,6 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::CenterPlayerInView, 0, true, qApp, SLOT(rotationModeChanged())); - //TODO: remove Overlays action, but the action is tied to some other places in code - // View > Overlays - addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Overlays, 0, true); - // View > Enter First Person Mode in HMD addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPersonHMD, 0, true); diff --git a/interface/src/ui/OverlayConductor.cpp b/interface/src/ui/OverlayConductor.cpp index ed8fa53fe2..b265849f62 100644 --- a/interface/src/ui/OverlayConductor.cpp +++ b/interface/src/ui/OverlayConductor.cpp @@ -143,7 +143,7 @@ void OverlayConductor::update(float dt) { } - bool targetVisible = Menu::getInstance()->isOptionChecked(MenuOption::Overlays) && (0 == (_flags & SuppressMask)); + bool targetVisible = (0 == (_flags & SuppressMask)); if (targetVisible != currentVisible) { offscreenUi->setPinned(!targetVisible); } From 3d8d0bfa0741d85148e218a2f52678dec25be455 Mon Sep 17 00:00:00 2001 From: vladest Date: Thu, 19 Apr 2018 12:31:14 +0200 Subject: [PATCH 015/143] Added hot keys enumeration for display menu --- interface/src/Application.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 663902d90f..16dfb70d08 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -7457,7 +7457,7 @@ DisplayPluginPointer Application::getActiveDisplayPlugin() const { static const char* EXCLUSION_GROUP_KEY = "exclusionGroup"; -static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool active = false) { +static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, int index) { auto menu = Menu::getInstance(); QString name = displayPlugin->getName(); auto grouping = displayPlugin->getGrouping(); @@ -7484,12 +7484,12 @@ static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool acti } auto parent = menu->getMenu(MenuOption::OutputMenu); auto action = menu->addActionToQMenuAndActionHash(parent, - name, 0, qApp, + name, QKeySequence(Qt::CTRL + (Qt::Key_0 + index)), qApp, SLOT(updateDisplayMode()), QAction::NoRole, Menu::UNSPECIFIED_POSITION, groupingMenu); action->setCheckable(true); - action->setChecked(active); + action->setChecked(index == 1); displayPluginGroup->addAction(action); action->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(displayPluginGroup)); @@ -7507,8 +7507,6 @@ void Application::updateDisplayMode() { static std::once_flag once; std::call_once(once, [&] { - bool first = true; - // first sort the plugins into groupings: standard, advanced, developer DisplayPluginList standard; DisplayPluginList advanced; @@ -7533,14 +7531,15 @@ void Application::updateDisplayMode() { standard.insert(std::end(standard), std::begin(advanced), std::end(advanced)); standard.insert(std::end(standard), std::begin(developer), std::end(developer)); + int dpIndex = 1; foreach(auto displayPlugin, standard) { - addDisplayPluginToMenu(displayPlugin, first); + addDisplayPluginToMenu(displayPlugin, dpIndex); auto displayPluginName = displayPlugin->getName(); QObject::connect(displayPlugin.get(), &DisplayPlugin::recommendedFramebufferSizeChanged, [this](const QSize & size) { resizeGL(); }); QObject::connect(displayPlugin.get(), &DisplayPlugin::resetSensorsRequested, this, &Application::requestReset); - first = false; + dpIndex++; } // after all plugins have been added to the menu, add a separator to the menu From b191ad866f1cf491d6a53afc90abfdb8e5e84b82 Mon Sep 17 00:00:00 2001 From: vladest Date: Thu, 19 Apr 2018 21:04:11 +0200 Subject: [PATCH 016/143] Merge fixes --- interface/src/Application.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 78beb99e39..78a9f682d9 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -7543,10 +7543,10 @@ void Application::updateDisplayMode() { standard.insert(std::end(standard), std::begin(advanced), std::end(advanced)); standard.insert(std::end(standard), std::begin(developer), std::end(developer)); - int dpIndex = 1; + int dpIndex = 1; foreach(auto displayPlugin, standard) { - addDisplayPluginToMenu(displayPlugin, dpIndex); - dpIndex++; + addDisplayPluginToMenu(displayPlugin, dpIndex); + dpIndex++; } // after all plugins have been added to the menu, add a separator to the menu From d54739cfc29eab6946b7a9302fd6640284acedf0 Mon Sep 17 00:00:00 2001 From: vladest Date: Fri, 20 Apr 2018 18:08:11 +0200 Subject: [PATCH 017/143] Start adding notifications [DNP] --- interface/src/Menu.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6b199896f4..f9cf0bb3c2 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -49,6 +49,7 @@ #include "AmbientOcclusionEffect.h" #include "RenderShadowTask.h" +#include "scripting/SettingsScriptingInterface.h" #if defined(Q_OS_MAC) || defined(Q_OS_WIN) #include "SpeechRecognizer.h" #endif @@ -266,10 +267,15 @@ Menu::Menu() { // Settings > Notifications MenuWrapper * notificationsMenu = settingsMenu->addMenu("Notifications"); //This was in notifications.js. The menu needs to be moved here. - //TODO: Hookup notification actions below. + //TODO: Hookup notification actions below. // Settings > Notifications > Play Notification Sounds + SettingsScriptingInterface* settings = SettingsScriptingInterface::getInstance(); addActionToQMenuAndActionHash(notificationsMenu, "Play Notification Sounds"); - + action = addCheckableActionToQMenuAndActionHash(notificationsMenu, "Play Notification Sounds", 0, + settings->getValue("play_notification_sounds_type_0")); + connect(action, &QAction::triggered, [action] { + qApp->setDesktopTabletBecomesToolbarSetting(action->isChecked()); + }); notificationsMenu->addSeparator(); // Settings > Notifications > Play Sounds for: From e1222ddbc59ce69462c1121c1ad8aafde9f77ed7 Mon Sep 17 00:00:00 2001 From: vladest Date: Mon, 23 Apr 2018 18:54:41 +0200 Subject: [PATCH 018/143] 1st notifications added --- interface/src/Menu.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 99643835a7..1ffcdd73ea 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -270,11 +270,10 @@ Menu::Menu() { //TODO: Hookup notification actions below. // Settings > Notifications > Play Notification Sounds SettingsScriptingInterface* settings = SettingsScriptingInterface::getInstance(); - addActionToQMenuAndActionHash(notificationsMenu, "Play Notification Sounds"); action = addCheckableActionToQMenuAndActionHash(notificationsMenu, "Play Notification Sounds", 0, - settings->getValue("play_notification_sounds_type_0")); - connect(action, &QAction::triggered, [action] { - qApp->setDesktopTabletBecomesToolbarSetting(action->isChecked()); + settings->getValue("play_notification_sounds").toBool()); + connect(action, &QAction::triggered, [action, settings] { + settings->setValue("play_notification_sounds", action->isChecked()); }); notificationsMenu->addSeparator(); @@ -282,11 +281,14 @@ Menu::Menu() { addDisabledActionAndSeparator(notificationsMenu, "Show notifications for:"); // Settings > Notifications > Snapshot - addActionToQMenuAndActionHash(notificationsMenu, "Snapshot"); - + action = addCheckableActionToQMenuAndActionHash(notificationsMenu, "Snapshot", 0, + settings->getValue("play_notification_sounds_type_0").toBool()); + connect(action, &QAction::triggered, [action, settings] { + settings->setValue("play_notification_sounds_type_0", action->isChecked()); + }); // Settings > Notifications > Level of Detail addActionToQMenuAndActionHash(notificationsMenu, "Level of Detail"); - + // Settings > Notifications > Connection addActionToQMenuAndActionHash(notificationsMenu, "Connection"); From deaecc705086c37411a60dc522be9058c39542d5 Mon Sep 17 00:00:00 2001 From: vladest Date: Sun, 29 Apr 2018 11:19:01 +0200 Subject: [PATCH 019/143] Added notifications settings --- interface/src/Menu.cpp | 42 +++++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 74cd1c0ca1..ed8c6910ce 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -287,23 +287,43 @@ Menu::Menu() { settings->setValue("play_notification_sounds_type_0", action->isChecked()); }); // Settings > Notifications > Level of Detail - addActionToQMenuAndActionHash(notificationsMenu, "Level of Detail"); - + action = addCheckableActionToQMenuAndActionHash(notificationsMenu, "Level of Detail", 0, + settings->getValue("play_notification_sounds_type_1").toBool()); + connect(action, &QAction::triggered, [action, settings] { + settings->setValue("play_notification_sounds_type_1", action->isChecked()); + }); // Settings > Notifications > Connection - addActionToQMenuAndActionHash(notificationsMenu, "Connection"); - + action = addCheckableActionToQMenuAndActionHash(notificationsMenu, "Connection", 0, + settings->getValue("play_notification_sounds_type_2").toBool()); + connect(action, &QAction::triggered, [action, settings] { + settings->setValue("play_notification_sounds_type_2", action->isChecked()); + }); // Settings > Notifications > Connection Refused - addActionToQMenuAndActionHash(notificationsMenu, "Connection Refused"); - + action = addCheckableActionToQMenuAndActionHash(notificationsMenu, "Connection Refused", 0, + settings->getValue("play_notification_sounds_type_3").toBool()); + connect(action, &QAction::triggered, [action, settings] { + settings->setValue("play_notification_sounds_type_3", action->isChecked()); + }); // Settings > Notifications > Edit Error - addActionToQMenuAndActionHash(notificationsMenu, "Edit Error"); - + action = addCheckableActionToQMenuAndActionHash(notificationsMenu, "Edit Error", 0, + settings->getValue("play_notification_sounds_type_4").toBool()); + connect(action, &QAction::triggered, [action, settings] { + settings->setValue("play_notification_sounds_type_4", action->isChecked()); + }); // Settings > Notifications > Tablet - addActionToQMenuAndActionHash(notificationsMenu, "Tablet"); - + action = addCheckableActionToQMenuAndActionHash(notificationsMenu, "Tablet", 0, + settings->getValue("play_notification_sounds_type_5").toBool()); + connect(action, &QAction::triggered, [action, settings] { + settings->setValue("play_notification_sounds_type_5", action->isChecked()); + }); // Settings > Notifications > Wallet addActionToQMenuAndActionHash(notificationsMenu, "Wallet"); - + action = addCheckableActionToQMenuAndActionHash(notificationsMenu, "Wallet", 0, + settings->getValue("play_notification_sounds_type_6").toBool()); + connect(action, &QAction::triggered, [action, settings] { + settings->setValue("play_notification_sounds_type_6", action->isChecked()); + }); + // Settings > Developer Menu addCheckableActionToQMenuAndActionHash(settingsMenu, "Developer Menu", 0, false, this, SLOT(toggleDeveloperMenus())); From a16b2c0d20dc8d66b578b52f886bef48e427d6e0 Mon Sep 17 00:00:00 2001 From: vladest Date: Sun, 29 Apr 2018 12:38:37 +0200 Subject: [PATCH 020/143] Restore preferences dialogs buttons spacing --- interface/resources/qml/dialogs/PreferencesDialog.qml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/dialogs/PreferencesDialog.qml b/interface/resources/qml/dialogs/PreferencesDialog.qml index 0a97ab9241..fffd0e2ed9 100644 --- a/interface/resources/qml/dialogs/PreferencesDialog.qml +++ b/interface/resources/qml/dialogs/PreferencesDialog.qml @@ -26,7 +26,7 @@ ScrollingWindow { property var showCategories: [] minSize: Qt.vector2d(400, 500) - //HifiConstants { id: hifi } + HifiConstants { id: hifi } function saveAll() { for (var i = 0; i < sections.length; ++i) { @@ -96,9 +96,9 @@ ScrollingWindow { anchors { top: parent.top right: parent.right - rightMargin: 10//hifi.dimensions.contentMargin.x + rightMargin: hifi.dimensions.contentMargin.x } - spacing: 1//hifi.dimensions.contentSpacing.x + spacing: hifi.dimensions.contentSpacing.x HifiControls.Button { text: "Save changes" From 4adfe94ed5becfb7dcb533c314161c2c7a6a9e8b Mon Sep 17 00:00:00 2001 From: vladest Date: Mon, 30 Apr 2018 20:43:36 +0200 Subject: [PATCH 021/143] Removed check for updates menu item. POC: settings for advanced movements mappings --- interface/src/Menu.cpp | 6 --- interface/src/ui/PreferencesDialog.cpp | 67 +++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 7 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index ed8c6910ce..0f7c0947cf 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -818,12 +818,6 @@ Menu::Menu() { helpMenu->addSeparator(); - // Help > Check for Updates - //ToDo: Add check for updates - addActionToQMenuAndActionHash(helpMenu, "Check for Updates"); - - helpMenu->addSeparator(); - // Help > Release Notes action = addActionToQMenuAndActionHash(helpMenu, "Release Notes"); connect(action, &QAction::triggered, qApp, [] { diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index b82f387137..e9e13721e7 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "Application.h" @@ -24,6 +25,9 @@ #include "SnapshotAnimated.h" #include "UserActivityLogger.h" +#include "controllers/impl/MappingBuilderProxy.h" +#include "controllers/impl/RouteBuilderProxy.h" + void setupPreferences() { auto preferences = DependencyManager::get(); auto nodeList = DependencyManager::get(); @@ -214,8 +218,69 @@ void setupPreferences() { //TODO: Update with advanced movement logic, test that it works { + + using namespace controller; + auto controllerScriptingInterface = DependencyManager::get().data(); + static QString advMovementsMappingName = QString("Hifi-AdvancedMovement-Dev-%1").arg(QRandomGenerator().generateDouble()); + static bool advMovementsIsDisabled = false; + static bool inFlipTurn = false; + + //code need to be revise so it should make correct iteration thru controller interface + /* + if (!advMovementsIsDisabled) { + MappingBuilderProxy* basicMapping = static_cast + (controllerScriptingInterface->newMapping(advMovementsMappingName)); + const auto standard = controllerScriptingInterface->getStandard(); + const auto hardware = controllerScriptingInterface->getHardware(); + qDebug() << "hardware" << hardware; + RouteBuilderProxy* fromMapping = static_cast + (basicMapping->fromQml(QJSValue(standard.value("LY").toFloat()))); + for(QMap::const_iterator i = standard.find("LY"); i != standard.end(); ++i) { + auto stick = controllerScriptingInterface->getValue(standard.value("LS").toInt()); + const float value = i.value().toFloat(); + if(value == 1.0f && hardware.contains("OculusTouch")) { + //rotate180 + myAvatar->setWorldOrientation(Quat().multiply(myAvatar->getWorldOrientation(), + Quat().angleAxis(180.0, glm::vec3(0,1,0)))); + + } else if (hardware.contains("Vive")) { + if (value > 0.75f && inFlipTurn == false) { + inFlipTurn = true; + //rotate180(); + QTimer::singleShot(1000, []() { inFlipTurn = false; } ); + } + } + } + for(QMap::const_iterator i = standard.find("RY"); i != standard.end(); ++i) { + auto stick = controllerScriptingInterface->getValue(standard.value("RS").toInt()); + const float value = i.value().toFloat(); + if(value == 1.0f && hardware.contains("OculusTouch")) { + //rotate180 + myAvatar->setWorldOrientation(Quat().multiply(myAvatar->getWorldOrientation(), + Quat().angleAxis(180.0, glm::vec3(0,1,0)))); + } else if (hardware.contains("Vive")) { + if (value > 0.75f && inFlipTurn == false) { + inFlipTurn = true; + //rotate180 + myAvatar->setWorldOrientation(Quat().multiply(myAvatar->getWorldOrientation(), + Quat().angleAxis(180.0, glm::vec3(0,1,0)))); + + QTimer::singleShot(1000, []() { inFlipTurn = false; } ); + } + } + } + }*/ auto getter = [=]()->bool { return myAvatar->useAdvancedMovementControls(); }; - auto setter = [=](bool value) { myAvatar->setUseAdvancedMovementControls(value); }; + auto setter = [=](bool value) { + auto controllerScriptingInterface = DependencyManager::get().data(); + myAvatar->setUseAdvancedMovementControls(value); + if (value) { + controllerScriptingInterface->enableMapping(advMovementsMappingName); + } else { + controllerScriptingInterface->disableMapping(advMovementsMappingName); + } + + }; preferences->addPreference(new CheckPreference(MOVEMENT, "Advanced movement for hand controllers", getter, setter)); } From 617b49fe1467462d850ba78662d82ee5c6741cf2 Mon Sep 17 00:00:00 2001 From: vladest Date: Tue, 1 May 2018 21:22:48 +0200 Subject: [PATCH 022/143] Added mouse sensivity UI. Reworked advanced movements. TODO: properties interface complitely broken in Tablet mode --- interface/resources/qml/desktop/Desktop.qml | 24 +++--- .../hifi/dialogs/GeneralPreferencesDialog.qml | 2 +- .../hifi/tablet/TabletGeneralPreferences.qml | 2 +- interface/resources/qml/windows/Frame.qml | 2 +- interface/src/ui/PreferencesDialog.cpp | 79 ++++++------------- interface/src/ui/overlays/Web3DOverlay.cpp | 3 + ...oggleAdvancedMovementForHandControllers.js | 40 ++-------- 7 files changed, 49 insertions(+), 103 deletions(-) diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml index 5f924834d9..a59b9d5ac0 100644 --- a/interface/resources/qml/desktop/Desktop.qml +++ b/interface/resources/qml/desktop/Desktop.qml @@ -149,17 +149,17 @@ FocusScope { } function isModalWindow(window) { - return window.modality !== Qt.NonModal; + return true;//window.modality !== (typeof Qt !== 'undefined' ? Qt.NonModal : 0); } function getTopLevelWindows(predicate) { - return findMatchingChildren(desktop, function(child) { - return (isTopLevelWindow(child) && (!predicate || predicate(child))); + return d.findMatchingChildren(desktop, function(child) { + return (d.isTopLevelWindow(child) && (!predicate || predicate(child))); }); } function getDesktopWindow(item) { - return findParentMatching(item, isTopLevelWindow) + return d.findParentMatching(item, d.isTopLevelWindow) } function fixupZOrder(windows, basis, topWindow) { @@ -205,23 +205,23 @@ FocusScope { function raiseWindow(targetWindow) { var predicate; var zBasis; - if (isModalWindow(targetWindow)) { - predicate = isModalWindow; + if (d.isModalWindow(targetWindow)) { + predicate = d.isModalWindow; zBasis = zLevels.modal - } else if (isAlwaysOnTopWindow(targetWindow)) { + } else if (d.isAlwaysOnTopWindow(targetWindow)) { predicate = function(window) { - return (isAlwaysOnTopWindow(window) && !isModalWindow(window)); + return (d.isAlwaysOnTopWindow(window) && !d.isModalWindow(window)); } zBasis = zLevels.top } else { predicate = function(window) { - return (!isAlwaysOnTopWindow(window) && !isModalWindow(window)); + return (!d.isAlwaysOnTopWindow(window) && !d.isModalWindow(window)); } zBasis = zLevels.normal } - var windows = getTopLevelWindows(predicate); - fixupZOrder(windows, zBasis, targetWindow); + var windows = d.getTopLevelWindows(predicate); + d.fixupZOrder(windows, zBasis, targetWindow); } Component.onCompleted: { @@ -264,7 +264,7 @@ FocusScope { } function getRepositionChildren(predicate) { - return findMatchingChildren(desktop, function(child) { + return d.findMatchingChildren(desktop, function(child) { return (child.shouldReposition === true && (!predicate || predicate(child))); }); } diff --git a/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml b/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml index cb4913f999..b6441573d8 100644 --- a/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml +++ b/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml @@ -17,7 +17,7 @@ PreferencesDialog { id: root objectName: "GeneralPreferencesDialog" title: "General Settings" - showCategories: ["User Interface", "HMD", "Snapshots", "Privacy"] + showCategories: ["User Interface", "HMD", "Snapshots", "Privacy", "Mouse Sensivity"] property var settings: Settings { category: root.objectName property alias x: root.x diff --git a/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml b/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml index 810f5bb43f..f754bd4ea5 100644 --- a/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml +++ b/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml @@ -32,6 +32,6 @@ StackView { TabletPreferencesDialog { id: root objectName: "TabletGeneralPreferences" - showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "Game Controller", "Sixense Controllers", "Perception Neuron", "Kinect", "Leap Motion"] + showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "Game Controller", "Sixense Controllers", "Perception Neuron", "Kinect", "Leap Motion", "Mouse Sensivity"] } } diff --git a/interface/resources/qml/windows/Frame.qml b/interface/resources/qml/windows/Frame.qml index 98bfb52c38..271d4f2e07 100644 --- a/interface/resources/qml/windows/Frame.qml +++ b/interface/resources/qml/windows/Frame.qml @@ -43,7 +43,7 @@ Item { Text { id: debugZ - visible: DebugQML + visible: (typeof DebugQML !== 'undefined') ? DebugQML : false color: "red" text: (window ? "Z: " + window.z : "") + " " + qmlFile y: window ? window.height + 4 : 0 diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index e9e13721e7..0ef2aa38a9 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include "Application.h" @@ -55,7 +56,20 @@ void setupPreferences() { auto preference = new AvatarPreference(AVATAR_BASICS, "Appearance", getter, setter); preferences->addPreference(preference); } - // UI + + static const QString MOUSE_SENSIVITY { "Mouse Sensivity" }; + { + auto getterY = []()->float { return 1.0; }; + auto setterY = [](float value) { }; + preferences->addPreference(new SliderPreference(MOUSE_SENSIVITY, "Y Input", getterY, setterY)); + auto getterX = []()->float { return 1.0; }; + auto setterX = [](float value) { }; + preferences->addPreference(new SliderPreference(MOUSE_SENSIVITY, "X Input", getterX, setterX)); + auto getterSW = []()->float { return 1.0; }; + auto setterSW = [](float value) { }; + preferences->addPreference(new SliderPreference(MOUSE_SENSIVITY, "Scroll Wheel", getterSW, setterSW)); + } + // Graphics quality static const QString GRAPHICS_QUALITY { "Graphics Quality" }; { auto getter = []()->float { return DependencyManager::get()->getLODLevel(); }; @@ -219,69 +233,22 @@ void setupPreferences() { //TODO: Update with advanced movement logic, test that it works { - using namespace controller; - auto controllerScriptingInterface = DependencyManager::get().data(); - static QString advMovementsMappingName = QString("Hifi-AdvancedMovement-Dev-%1").arg(QRandomGenerator().generateDouble()); - static bool advMovementsIsDisabled = false; - static bool inFlipTurn = false; - - //code need to be revise so it should make correct iteration thru controller interface - /* - if (!advMovementsIsDisabled) { - MappingBuilderProxy* basicMapping = static_cast - (controllerScriptingInterface->newMapping(advMovementsMappingName)); - const auto standard = controllerScriptingInterface->getStandard(); - const auto hardware = controllerScriptingInterface->getHardware(); - qDebug() << "hardware" << hardware; - RouteBuilderProxy* fromMapping = static_cast - (basicMapping->fromQml(QJSValue(standard.value("LY").toFloat()))); - for(QMap::const_iterator i = standard.find("LY"); i != standard.end(); ++i) { - auto stick = controllerScriptingInterface->getValue(standard.value("LS").toInt()); - const float value = i.value().toFloat(); - if(value == 1.0f && hardware.contains("OculusTouch")) { - //rotate180 - myAvatar->setWorldOrientation(Quat().multiply(myAvatar->getWorldOrientation(), - Quat().angleAxis(180.0, glm::vec3(0,1,0)))); - - } else if (hardware.contains("Vive")) { - if (value > 0.75f && inFlipTurn == false) { - inFlipTurn = true; - //rotate180(); - QTimer::singleShot(1000, []() { inFlipTurn = false; } ); - } - } - } - for(QMap::const_iterator i = standard.find("RY"); i != standard.end(); ++i) { - auto stick = controllerScriptingInterface->getValue(standard.value("RS").toInt()); - const float value = i.value().toFloat(); - if(value == 1.0f && hardware.contains("OculusTouch")) { - //rotate180 - myAvatar->setWorldOrientation(Quat().multiply(myAvatar->getWorldOrientation(), - Quat().angleAxis(180.0, glm::vec3(0,1,0)))); - } else if (hardware.contains("Vive")) { - if (value > 0.75f && inFlipTurn == false) { - inFlipTurn = true; - //rotate180 - myAvatar->setWorldOrientation(Quat().multiply(myAvatar->getWorldOrientation(), - Quat().angleAxis(180.0, glm::vec3(0,1,0)))); - - QTimer::singleShot(1000, []() { inFlipTurn = false; } ); - } - } - } - }*/ + static const QString movementsControlChannel = QStringLiteral("Hifi-Advanced-Movement-Disabler"); auto getter = [=]()->bool { return myAvatar->useAdvancedMovementControls(); }; auto setter = [=](bool value) { - auto controllerScriptingInterface = DependencyManager::get().data(); + auto messagesClient = DependencyManager::get().data(); myAvatar->setUseAdvancedMovementControls(value); + qDebug() << "vladest movement" << value; if (value) { - controllerScriptingInterface->enableMapping(advMovementsMappingName); + messagesClient->sendMessage(movementsControlChannel, QStringLiteral("enable_mappings"), true); } else { - controllerScriptingInterface->disableMapping(advMovementsMappingName); + messagesClient->sendMessage(movementsControlChannel, QStringLiteral("disable_mappings"), true); } }; - preferences->addPreference(new CheckPreference(MOVEMENT, "Advanced movement for hand controllers", getter, setter)); + preferences->addPreference(new CheckPreference(MOVEMENT, + QStringLiteral("Advanced movement for hand controllers"), + getter, setter)); } { diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index fcdac8c00c..a48e5eaf54 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -56,6 +56,7 @@ #include "ui/Snapshot.h" #include "SoundCache.h" #include "raypick/PointerScriptingInterface.h" +#include static int MAX_WINDOW_SIZE = 4096; static const float METERS_TO_INCHES = 39.3701f; @@ -256,6 +257,8 @@ void Web3DOverlay::setupQmlSurface() { _webSurface->getSurfaceContext()->setContextProperty("Pointers", DependencyManager::get().data()); _webSurface->getSurfaceContext()->setContextProperty("Web3DOverlay", this); _webSurface->getSurfaceContext()->setContextProperty("Window", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("Reticle", qApp->getApplicationCompositor().getReticleInterface()); + _webSurface->getSurfaceContext()->setContextProperty("desktop", DependencyManager::get()->getDesktop()); // Override min fps for tablet UI, for silky smooth scrolling setMaxFPS(90); diff --git a/scripts/system/controllers/toggleAdvancedMovementForHandControllers.js b/scripts/system/controllers/toggleAdvancedMovementForHandControllers.js index e6c9b0aee0..40721e7f72 100644 --- a/scripts/system/controllers/toggleAdvancedMovementForHandControllers.js +++ b/scripts/system/controllers/toggleAdvancedMovementForHandControllers.js @@ -16,7 +16,6 @@ var mappingName, basicMapping, isChecked; var TURN_RATE = 1000; -var MENU_ITEM_NAME = "Advanced Movement For Hand Controllers"; var isDisabled = false; var previousSetting = MyAvatar.useAdvancedMovementControls; if (previousSetting === false) { @@ -29,15 +28,6 @@ if (previousSetting === true) { isChecked = true; } -function addAdvancedMovementItemToSettingsMenu() { - Menu.addMenuItem({ - menuName: "Settings", - menuItemName: MENU_ITEM_NAME, - isCheckable: true, - isChecked: previousSetting - }); -} - function rotate180() { var newOrientation = Quat.multiply(MyAvatar.orientation, Quat.angleAxis(180, { x: 0, @@ -100,30 +90,11 @@ function disableMappings() { } function scriptEnding() { - Menu.removeMenuItem("Settings", MENU_ITEM_NAME); disableMappings(); } - -function menuItemEvent(menuItem) { - if (menuItem == MENU_ITEM_NAME) { - isChecked = Menu.isOptionChecked(MENU_ITEM_NAME); - if (isChecked === true) { - MyAvatar.useAdvancedMovementControls = true; - disableMappings(); - } else if (isChecked === false) { - MyAvatar.useAdvancedMovementControls = false; - enableMappings(); - } - } -} - -addAdvancedMovementItemToSettingsMenu(); - Script.scriptEnding.connect(scriptEnding); -Menu.menuItemEvent.connect(menuItemEvent); - registerBasicMapping(); Script.setTimeout(function() { @@ -151,11 +122,16 @@ HMD.displayModeChanged.connect(function(isHMDMode) { var HIFI_ADVANCED_MOVEMENT_DISABLER_CHANNEL = 'Hifi-Advanced-Movement-Disabler'; function handleMessage(channel, message, sender) { - if (channel == HIFI_ADVANCED_MOVEMENT_DISABLER_CHANNEL) { - if (message == 'disable') { + if (channel === HIFI_ADVANCED_MOVEMENT_DISABLER_CHANNEL) { + if (message === 'disable') { isDisabled = true; - } else if (message == 'enable') { + } else if (message === 'enable') { isDisabled = false; + } else if (message === 'enable_mappings') { + print("enable mappings") + enableMappings(); + } else if (message === 'disable_mappings') { + disableMappings(); } } } From ea66e04ab859fbecc0cd714cd46bdfaef26eb913 Mon Sep 17 00:00:00 2001 From: vladest Date: Wed, 2 May 2018 18:58:40 +0200 Subject: [PATCH 023/143] Removed unwanted code --- .../qml/hifi/tablet/ControllerSettings.qml | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/ControllerSettings.qml b/interface/resources/qml/hifi/tablet/ControllerSettings.qml index 0e110517e0..f134e280e6 100644 --- a/interface/resources/qml/hifi/tablet/ControllerSettings.qml +++ b/interface/resources/qml/hifi/tablet/ControllerSettings.qml @@ -15,20 +15,6 @@ import "../../controls" import "../../controls-uit" as HifiControls import "../../dialogs" -PreferencesDialog { - id: root - objectName: "ControlSettings" - title: "Control Settings" - showCategories: ["VR Movement", "Mouse Sensitivity", "Game Controller", "Face Tracking", "Sixense Controllers", "Perception Neuron", "Kinect", "Leap Motion"] - property var settings: Settings { - category: root.objectName - property alias x: root.x - property alias y: root.y - property alias width: root.width - property alias height: root.height - } -} -/* StackView { id: stack initialItem: inputConfiguration @@ -243,4 +229,3 @@ StackView { timer.start(); } } -*/ From 14dfafa815d107aa6800bdd53068482ff06abebd Mon Sep 17 00:00:00 2001 From: vladest Date: Wed, 2 May 2018 19:46:18 +0200 Subject: [PATCH 024/143] Brings logging back --- interface/src/Menu.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 0f7c0947cf..653800a1ab 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -758,6 +758,20 @@ Menu::Menu() { connect(speechRecognizer.data(), SIGNAL(enabledUpdated(bool)), speechRecognizerAction, SLOT(setChecked(bool))); #endif + // Developer > Log... + addActionToQMenuAndActionHash(developerMenu, MenuOption::Log, Qt::CTRL | Qt::SHIFT | Qt::Key_L, + qApp, SLOT(toggleLogDialog())); + auto essLogAction = addActionToQMenuAndActionHash(developerMenu, MenuOption::EntityScriptServerLog, 0, + qApp, SLOT(toggleEntityScriptServerLogDialog())); + QObject::connect(nodeList.data(), &NodeList::canRezChanged, essLogAction, [essLogAction] { + auto nodeList = DependencyManager::get(); + essLogAction->setEnabled(nodeList->getThisNodeCanRez()); + }); + essLogAction->setEnabled(nodeList->getThisNodeCanRez()); + + action = addActionToQMenuAndActionHash(developerMenu, "Script Log (HMD friendly)...", Qt::NoButton, + qApp, SLOT(showScriptLogs())); + addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::VerboseLogging, 0, false, qApp, SLOT(updateVerboseLogging())); From 6d251c4cd3e661242962b7a0ea399eba2c1a62ec Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 3 May 2018 17:46:50 -0700 Subject: [PATCH 025/143] Bringing the work and refinment done in workload branch to master branch --- .../render-utils/src/AmbientOcclusionEffect.h | 2 +- libraries/render-utils/src/LightClusters.h | 2 +- .../render-utils/src/SubsurfaceScattering.h | 2 +- libraries/render/src/render/Item.h | 1 + libraries/task/src/task/Config.h | 35 ++++++++++++--- libraries/task/src/task/Task.h | 45 +++++++++++++++++-- 6 files changed, 74 insertions(+), 13 deletions(-) diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index 3643e608ed..b3a93ab1de 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -181,7 +181,7 @@ class DebugAmbientOcclusionConfig : public render::Job::Config { Q_PROPERTY(bool showCursorPixel MEMBER showCursorPixel NOTIFY dirty) Q_PROPERTY(glm::vec2 debugCursorTexcoord MEMBER debugCursorTexcoord NOTIFY dirty) public: - DebugAmbientOcclusionConfig() : render::Job::Config(true) {} + DebugAmbientOcclusionConfig() : render::Job::Config(false) {} bool showCursorPixel{ false }; glm::vec2 debugCursorTexcoord{ 0.5f, 0.5f }; diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index f495dabebb..fa054c304a 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -195,7 +195,7 @@ class DebugLightClustersConfig : public render::Job::Config { Q_PROPERTY(bool doDrawClusterFromDepth MEMBER doDrawClusterFromDepth NOTIFY dirty) Q_PROPERTY(bool doDrawContent MEMBER doDrawContent NOTIFY dirty) public: - DebugLightClustersConfig() : render::Job::Config(true){} + DebugLightClustersConfig() : render::Job::Config(false){} bool doDrawGrid{ false }; diff --git a/libraries/render-utils/src/SubsurfaceScattering.h b/libraries/render-utils/src/SubsurfaceScattering.h index 30021fae40..780ce34d7f 100644 --- a/libraries/render-utils/src/SubsurfaceScattering.h +++ b/libraries/render-utils/src/SubsurfaceScattering.h @@ -149,7 +149,7 @@ class DebugSubsurfaceScatteringConfig : public render::Job::Config { Q_PROPERTY(bool showCursorPixel MEMBER showCursorPixel NOTIFY dirty) Q_PROPERTY(glm::vec2 debugCursorTexcoord MEMBER debugCursorTexcoord NOTIFY dirty) public: - DebugSubsurfaceScatteringConfig() : render::Job::Config(true) {} + DebugSubsurfaceScatteringConfig() : render::Job::Config(false) {} bool showProfile{ false }; bool showLUT{ false }; diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index e4dcc7ee03..b8a3fbf0f8 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -122,6 +122,7 @@ public: Builder& withDynamic() { _flags.set(DYNAMIC); return (*this); } Builder& withDeformed() { _flags.set(DEFORMED); return (*this); } Builder& withInvisible() { _flags.set(INVISIBLE); return (*this); } + Builder& withVisible() { _flags.reset(INVISIBLE); return (*this); } Builder& withShadowCaster() { _flags.set(SHADOW_CASTER); return (*this); } Builder& withLayered() { _flags.set(LAYERED); return (*this); } Builder& withMetaCullGroup() { _flags.set(META_CULL_GROUP); return (*this); } diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index 36dfb35f25..4ba1934643 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -12,6 +12,8 @@ #ifndef hifi_task_Config_h #define hifi_task_Config_h +#include + #include #include #include @@ -108,11 +110,19 @@ public: Q_INVOKABLE QString toJSON() { return QJsonDocument(toJsonValue(*this).toObject()).toJson(QJsonDocument::Compact); } Q_INVOKABLE void load(const QVariantMap& map) { qObjectFromJsonValue(QJsonObject::fromVariantMap(map), *this); emit loaded(); } + Q_INVOKABLE QObject* getConfig(const QString& name) { return nullptr; } + // Running Time measurement // The new stats signal is emitted once per run time of a job when stats (cpu runtime) are updated - void setCPURunTime(double mstime) { _msCPURunTime = mstime; emit newStats(); } + void setCPURunTime(const std::chrono::nanoseconds& runtime) { _msCPURunTime = std::chrono::duration(runtime).count(); emit newStats(); } double getCPURunTime() const { return _msCPURunTime; } + // Describe the node graph data connections of the associated Job/Task + Q_INVOKABLE virtual bool isTask() const { return false; } + Q_INVOKABLE virtual QObjectList getSubConfigs() const { return QObjectList(); } + Q_INVOKABLE virtual int getNumSubs() const { return 0; } + Q_INVOKABLE virtual QObject* getSubConfig(int i) const { return nullptr; } + public slots: void load(const QJsonObject& val) { qObjectFromJsonValue(val, *this); emit loaded(); } @@ -122,6 +132,8 @@ signals: void dirtyEnabled(); }; +using QConfigPointer = std::shared_ptr; + class TConfigProxy { public: using Config = JobConfig; @@ -134,11 +146,9 @@ public: using Persistent = PersistentConfig; - TaskConfig() = default ; + TaskConfig() = default; TaskConfig(bool enabled) : JobConfig(enabled) {} - - // Get a sub job config through task.getConfig(path) // where path can be: // - search for the first job named job_name traversing the the sub graph of task and jobs (from this task as root) @@ -170,6 +180,21 @@ public: return root->findChild(tokens.front()); } + Q_INVOKABLE bool isTask() const override { return true; } + Q_INVOKABLE QObjectList getSubConfigs() const override { + auto list = findChildren(QRegExp(".*"), Qt::FindDirectChildrenOnly); + QObjectList returned; + for (int i = 0; i < list.size(); i++) { + returned.push_back(list[i]); + } + return returned; + } + Q_INVOKABLE int getNumSubs() const override { return getSubConfigs().size(); } + Q_INVOKABLE QObject* getSubConfig(int i) const override { + auto subs = getSubConfigs(); + return ((i < 0 || i >= subs.size()) ? nullptr : subs[i]); + } + void connectChildConfig(QConfigPointer childConfig, const std::string& name); void transferChildrenConfigs(QConfigPointer source); @@ -179,8 +204,6 @@ public slots: void refresh(); }; -using QConfigPointer = std::shared_ptr; - } #endif // hifi_task_Config_h diff --git a/libraries/task/src/task/Task.h b/libraries/task/src/task/Task.h index 022dd99200..93dfdd85f4 100644 --- a/libraries/task/src/task/Task.h +++ b/libraries/task/src/task/Task.h @@ -80,10 +80,11 @@ public: virtual const Varying getInput() const { return Varying(); } virtual const Varying getOutput() const { return Varying(); } + virtual Varying& editInput() = 0; virtual QConfigPointer& getConfiguration() { return _config; } virtual void applyConfiguration() = 0; - void setCPURunTime(double mstime) { std::static_pointer_cast(_config)->setCPURunTime(mstime); } + void setCPURunTime(const std::chrono::nanoseconds& runtime) { std::static_pointer_cast(_config)->setCPURunTime(runtime); } QConfigPointer _config; protected: @@ -143,6 +144,10 @@ public: const Varying getInput() const override { return _input; } const Varying getOutput() const override { return _output; } + Varying& editInput() override { return _input; } + + template void feedInput(const I& in) { _concept->editInput().template edit() = in; } + template void feedInput(int index, const S& inS) { (_concept->editInput().template editN(index)).template edit() = inS; } template Model(const std::string& name, const Varying& input, QConfigPointer config, A&&... args) : @@ -201,11 +206,12 @@ public: PerformanceTimer perfTimer(getName().c_str()); // NOTE: rather than use the PROFILE_RANGE macro, we create a Duration manually Duration profileRange(jobContext->profileCategory, ("run::" + getName()).c_str()); - auto start = usecTimestampNow(); + + auto startTime = std::chrono::high_resolution_clock::now(); _concept->run(jobContext); - _concept->setCPURunTime((double)(usecTimestampNow() - start) / 1000.0); + _concept->setCPURunTime((std::chrono::high_resolution_clock::now() - startTime)); } protected: @@ -242,6 +248,8 @@ public: const Varying getInput() const override { return _input; } const Varying getOutput() const override { return _output; } + Varying& editInput() override { return _input; } + typename Jobs::iterator editJob(std::string name) { typename Jobs::iterator jobIt; for (jobIt = _jobs.begin(); jobIt != _jobs.end(); ++jobIt) { @@ -370,8 +378,36 @@ public: protected: }; -} +template +class Engine : public Task { +public: + using Context = JC; + using ContextPointer = std::shared_ptr; + using Config = TaskConfig; + using TaskType = Task; + using ConceptPointer = typename TaskType::ConceptPointer; + + Engine(ConceptPointer concept) : TaskType(concept) {} + ~Engine() = default; + + void reset(const ContextPointer& context) { _context = context; } + + void run() { + if (_context) { + run(_context); + } + } + +protected: + void run(const ContextPointer& jobContext) override { + TaskType::run(_context); + } + + ContextPointer _context; +}; + +} #define Task_DeclareTypeAliases(ContextType) \ using JobConfig = task::JobConfig; \ @@ -379,6 +415,7 @@ protected: template using PersistentConfig = task::PersistentConfig; \ using Job = task::Job; \ using Task = task::Task; \ + using _Engine = task::Engine; \ using Varying = task::Varying; \ template < typename T0, typename T1 > using VaryingSet2 = task::VaryingSet2; \ template < typename T0, typename T1, typename T2 > using VaryingSet3 = task::VaryingSet3; \ From e1d063e90880f1e885b29c2612fabb5172a9de70 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 4 May 2018 00:01:48 -0700 Subject: [PATCH 026/143] Adding the scripts for Jet --- scripts/developer/utilities/lib/jet/jet.js | 73 +++++++++++++++++++ .../utilities/lib/jet/qml/TaskList.qml | 48 ++++++++++++ .../developer/utilities/lib/jet/qml/qmldir | 1 + .../render/configSlider/ConfigSlider.qml | 40 ++++++---- .../utilities/render/deferredLighting.qml | 10 +++ 5 files changed, 159 insertions(+), 13 deletions(-) create mode 100644 scripts/developer/utilities/lib/jet/jet.js create mode 100644 scripts/developer/utilities/lib/jet/qml/TaskList.qml create mode 100644 scripts/developer/utilities/lib/jet/qml/qmldir diff --git a/scripts/developer/utilities/lib/jet/jet.js b/scripts/developer/utilities/lib/jet/jet.js new file mode 100644 index 0000000000..39da9b6d90 --- /dev/null +++ b/scripts/developer/utilities/lib/jet/jet.js @@ -0,0 +1,73 @@ +// +// Job Engine & Task... +// jet.js +// +// Created by Sam Gateau, 2018/03/28 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +"use strict"; + + // traverse task tree +function task_traverse(root, functor, depth) { + // if (root.isTask()) { + depth++; + for (var i = 0; i Date: Fri, 4 May 2018 22:01:44 +0200 Subject: [PATCH 027/143] Snapshot notification sound settings --- interface/src/Application.cpp | 15 ++++++++------- interface/src/Menu.cpp | 4 ++-- interface/src/Menu.h | 1 + 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a480af2e0e..83e1f622fd 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3601,13 +3601,14 @@ void Application::keyPressEvent(QKeyEvent* event) { AudioInjectorOptions options; options.localOnly = true; options.stereo = true; - - if (_snapshotSoundInjector) { - _snapshotSoundInjector->setOptions(options); - _snapshotSoundInjector->restart(); - } else { - QByteArray samples = _snapshotSound->getByteArray(); - _snapshotSoundInjector = AudioInjector::playSound(samples, options); + if (SettingsScriptingInterface::getInstance()->getValue(MenuOption::NotificationSoundsSnapshot).toBool()) { + if (_snapshotSoundInjector) { + _snapshotSoundInjector->setOptions(options); + _snapshotSoundInjector->restart(); + } else { + QByteArray samples = _snapshotSound->getByteArray(); + _snapshotSoundInjector = AudioInjector::playSound(samples, options); + } } takeSnapshot(true); break; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 653800a1ab..676e4f25e9 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -282,9 +282,9 @@ Menu::Menu() { // Settings > Notifications > Snapshot action = addCheckableActionToQMenuAndActionHash(notificationsMenu, "Snapshot", 0, - settings->getValue("play_notification_sounds_type_0").toBool()); + settings->getValue(MenuOption::NotificationSoundsSnapshot).toBool()); connect(action, &QAction::triggered, [action, settings] { - settings->setValue("play_notification_sounds_type_0", action->isChecked()); + settings->setValue(MenuOption::NotificationSoundsSnapshot, action->isChecked()); }); // Settings > Notifications > Level of Detail action = addCheckableActionToQMenuAndActionHash(notificationsMenu, "Level of Detail", 0, diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 3a4864cfc6..5917aab38b 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -212,6 +212,7 @@ namespace MenuOption { const QString HMDTabletToToolbar = "HMD Tablet Becomes Toolbar"; const QString Shadows = "Shadows"; const QString AmbientOcclusion = "Ambient Occlusion"; + const QString NotificationSoundsSnapshot = "play_notification_sounds_snapshot"; } #endif // hifi_Menu_h From 6424b91e86798b09525ddd40a288c9899450e6b2 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 4 May 2018 17:58:21 -0700 Subject: [PATCH 028/143] Templatizing the timeProfiler for the task --- libraries/render/src/render/Engine.h | 6 +- libraries/task/src/task/Task.cpp | 4 +- libraries/task/src/task/Task.h | 63 ++++++++++--------- .../utilities/render/deferredLighting.qml | 16 ++--- 4 files changed, 46 insertions(+), 43 deletions(-) diff --git a/libraries/render/src/render/Engine.h b/libraries/render/src/render/Engine.h index 0271c71529..f444416a3f 100644 --- a/libraries/render/src/render/Engine.h +++ b/libraries/render/src/render/Engine.h @@ -25,7 +25,7 @@ namespace render { class RenderContext : public task::JobContext { public: - RenderContext() : task::JobContext(trace_render()) {} + RenderContext() : task::JobContext() {} virtual ~RenderContext() {} RenderArgs* args; @@ -33,7 +33,9 @@ namespace render { }; using RenderContextPointer = std::shared_ptr; - Task_DeclareTypeAliases(RenderContext) + Task_DeclareCategoryTimeProfilerClass(RenderTimeProfiler, trace_render); + + Task_DeclareTypeAliases(RenderContext, RenderTimeProfiler) // Versions of the COnfig integrating a gpu & batch timer class GPUJobConfig : public JobConfig { diff --git a/libraries/task/src/task/Task.cpp b/libraries/task/src/task/Task.cpp index 621d77d7bf..9123ef8b04 100644 --- a/libraries/task/src/task/Task.cpp +++ b/libraries/task/src/task/Task.cpp @@ -12,9 +12,7 @@ using namespace task; -JobContext::JobContext(const QLoggingCategory& category) : - profileCategory(category) { - assert(&category); +JobContext::JobContext() { } JobContext::~JobContext() { diff --git a/libraries/task/src/task/Task.h b/libraries/task/src/task/Task.h index 93dfdd85f4..c9a3285443 100644 --- a/libraries/task/src/task/Task.h +++ b/libraries/task/src/task/Task.h @@ -15,20 +15,15 @@ #include "Config.h" #include "Varying.h" -#include "SettingHandle.h" - -#include -#include - namespace task { class JobConcept; -template class JobT; -template class TaskT; +template class JobT; +template class TaskT; class JobNoIO {}; // Task Flow control class is a simple per value object used to communicate flow control commands trhough the graph of tasks. -// From within the Job::Run function, you can access it from the JobCOntext and issue commands which will be picked up by the Task calling for the Job run. +// From within the Job::Run function, you can access it from the JobContext and issue commands which will be picked up by the Task calling for the Job run. // This is first introduced to provide a way to abort all the work from within a task job. see the "abortTask" call class TaskFlow { public: @@ -55,11 +50,10 @@ protected: // The JobContext can be derived to add more global state to it that Jobs can access class JobContext { public: - JobContext(const QLoggingCategory& category); + JobContext(); virtual ~JobContext(); std::shared_ptr jobConfig { nullptr }; - const QLoggingCategory& profileCategory; // Task flow control TaskFlow taskFlow{}; @@ -115,10 +109,11 @@ template void jobRun(T& data, const JC& jo data.run(jobContext, input, output); } -template +template class Job { public: using Context = JC; + using TimeProfiler = TP; using ContextPointer = std::shared_ptr; using Config = JobConfig; using None = JobNoIO; @@ -165,7 +160,7 @@ public: void applyConfiguration() override { - Duration profileRange(trace_render(), ("configure::" + JobConcept::getName()).c_str()); + TimeProfiler probe(("configure::" + JobConcept::getName())); jobConfigure(_data, *std::static_pointer_cast(Concept::_config)); } @@ -203,14 +198,9 @@ public: } virtual void run(const ContextPointer& jobContext) { - PerformanceTimer perfTimer(getName().c_str()); - // NOTE: rather than use the PROFILE_RANGE macro, we create a Duration manually - Duration profileRange(jobContext->profileCategory, ("run::" + getName()).c_str()); - + TimeProfiler probe(getName()); auto startTime = std::chrono::high_resolution_clock::now(); - _concept->run(jobContext); - _concept->setCPURunTime((std::chrono::high_resolution_clock::now() - startTime)); } @@ -226,13 +216,14 @@ protected: // The build method is where child Jobs can be added internally to the task // where the input of the task can be setup to feed the child jobs // and where the output of the task is defined -template -class Task : public Job { +template +class Task : public Job { public: using Context = JC; + using TimeProfiler = TP; using ContextPointer = std::shared_ptr; using Config = TaskConfig; - using JobType = Job; + using JobType = Job; using None = typename JobType::None; using Concept = typename JobType::Concept; using ConceptPointer = typename JobType::ConceptPointer; @@ -303,7 +294,7 @@ public: auto model = std::make_shared(name, input, std::make_shared()); { - Duration profileRange(trace_render(), ("build::" + model->getName()).c_str()); + TimeProfiler probe("build::" + model->getName()); model->_data.build(*(model), model->_input, model->_output, std::forward(args)...); } // Recreate the Config to use the templated type @@ -338,7 +329,7 @@ public: } void applyConfiguration() override { - Duration profileRange(trace_render(), ("configure::" + JobConcept::getName()).c_str()); + TimeProfiler probe("configure::" + JobConcept::getName()); jobConfigure(_data, *std::static_pointer_cast(Concept::_config)); for (auto& job : TaskConcept::_jobs) { job.applyConfiguration(); @@ -379,13 +370,13 @@ public: protected: }; -template -class Engine : public Task { +template +class Engine : public Task { public: using Context = JC; using ContextPointer = std::shared_ptr; using Config = TaskConfig; - using TaskType = Task; + using TaskType = Task; using ConceptPointer = typename TaskType::ConceptPointer; Engine(ConceptPointer concept) : TaskType(concept) {} @@ -409,13 +400,13 @@ protected: } -#define Task_DeclareTypeAliases(ContextType) \ +#define Task_DeclareTypeAliases(ContextType, TimeProfiler) \ using JobConfig = task::JobConfig; \ using TaskConfig = task::TaskConfig; \ template using PersistentConfig = task::PersistentConfig; \ - using Job = task::Job; \ - using Task = task::Task; \ - using _Engine = task::Engine; \ + using Job = task::Job; \ + using Task = task::Task; \ + using _Engine = task::Engine; \ using Varying = task::Varying; \ template < typename T0, typename T1 > using VaryingSet2 = task::VaryingSet2; \ template < typename T0, typename T1, typename T2 > using VaryingSet3 = task::VaryingSet3; \ @@ -426,4 +417,16 @@ protected: template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7 > using VaryingSet8 = task::VaryingSet8; \ template < class T, int NUM > using VaryingArray = task::VaryingArray; + + +#include +#include + +#define Task_DeclareCategoryTimeProfilerClass(className, category) \ + class className : public PerformanceTimer { \ + public: \ + className(const std::string& label) : PerformanceTimer(label.c_str()), profileRange(category(), label.c_str()) {} \ + Duration profileRange; \ + }; + #endif // hifi_task_Task_h diff --git a/scripts/developer/utilities/render/deferredLighting.qml b/scripts/developer/utilities/render/deferredLighting.qml index 160ec26be0..dc81df48cb 100644 --- a/scripts/developer/utilities/render/deferredLighting.qml +++ b/scripts/developer/utilities/render/deferredLighting.qml @@ -37,9 +37,9 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right - spacing: 20 + spacing: 5 Column { - spacing: 10 + spacing: 5 // padding: 10 Repeater { model: [ @@ -61,7 +61,7 @@ Rectangle { Column { - spacing: 10 + spacing: 5 Repeater { model: [ "Obscurance:LightingModel:enableObscurance", @@ -81,7 +81,7 @@ Rectangle { } Column { - spacing: 10 + spacing: 5 Repeater { model: [ "Ambient:LightingModel:enableAmbientLight", @@ -105,7 +105,7 @@ Rectangle { Column { anchors.left: parent.left anchors.right: parent.right - spacing: 10 + spacing: 5 Repeater { model: [ "Tone Mapping Exposure:ToneMapping:exposure:5.0:-5.0" ] @@ -211,9 +211,9 @@ Rectangle { Separator {} Row { - spacing: 10 + spacing: 5 Column { - spacing: 10 + spacing: 5 HifiControls.CheckBox { boxSize: 20 @@ -254,7 +254,7 @@ Rectangle { } Column { - spacing: 10 + spacing: 5 HifiControls.CheckBox { boxSize: 20 text: "Metas" From ac413c88541c2eb6961c546cc36fb0fda4b72e38 Mon Sep 17 00:00:00 2001 From: vladest Date: Sun, 6 May 2018 09:41:10 +0200 Subject: [PATCH 029/143] Tablet opening notification sound settings added --- interface/src/Menu.cpp | 5 +++-- interface/src/Menu.h | 1 + libraries/ui/src/ui/TabletScriptingInterface.cpp | 5 ++++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index b95a789570..ceef87f97b 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -311,9 +311,10 @@ Menu::Menu() { }); // Settings > Notifications > Tablet action = addCheckableActionToQMenuAndActionHash(notificationsMenu, "Tablet", 0, - settings->getValue("play_notification_sounds_type_5").toBool()); + settings->getValue(MenuOption::NotificationSoundsTablet).toBool()); connect(action, &QAction::triggered, [action, settings] { - settings->setValue("play_notification_sounds_type_5", action->isChecked()); + settings->setValue(MenuOption::NotificationSoundsTablet, action->isChecked()); + qDebug() << "vladest. tablet sound check up" << settings->getValue(MenuOption::NotificationSoundsTablet).toBool(); }); // Settings > Notifications > Wallet addActionToQMenuAndActionHash(notificationsMenu, "Wallet"); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index dc833be173..496368c30b 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -218,6 +218,7 @@ namespace MenuOption { const QString Shadows = "Shadows"; const QString AmbientOcclusion = "Ambient Occlusion"; const QString NotificationSoundsSnapshot = "play_notification_sounds_snapshot"; + const QString NotificationSoundsTablet = "play_notification_sounds_tablet"; } #endif // hifi_Menu_h diff --git a/libraries/ui/src/ui/TabletScriptingInterface.cpp b/libraries/ui/src/ui/TabletScriptingInterface.cpp index a079609bb7..89751b142e 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.cpp +++ b/libraries/ui/src/ui/TabletScriptingInterface.cpp @@ -441,7 +441,10 @@ void TabletProxy::emitWebEvent(const QVariant& msg) { void TabletProxy::onTabletShown() { if (_tabletShown) { - static_cast(parent())->playSound(TabletScriptingInterface::TabletOpen); + Setting::Handle notificationSoundTablet{ "play_notification_sounds_tablet", true}; + if (notificationSoundTablet.get()) { + static_cast(parent())->playSound(TabletScriptingInterface::TabletOpen); + } if (_showRunningScripts) { _showRunningScripts = false; pushOntoStack("hifi/dialogs/TabletRunningScripts.qml"); From 1794113f37b7d2f2799e652acb4b64e16d369a79 Mon Sep 17 00:00:00 2001 From: vladest Date: Sun, 6 May 2018 12:51:59 +0200 Subject: [PATCH 030/143] Check global switch as well --- interface/src/Application.cpp | 4 +++- interface/src/Menu.cpp | 4 ++-- interface/src/Menu.h | 1 + libraries/ui/src/ui/TabletScriptingInterface.cpp | 7 ++++--- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e2010c199e..76e20434b0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3609,7 +3609,9 @@ void Application::keyPressEvent(QKeyEvent* event) { AudioInjectorOptions options; options.localOnly = true; options.stereo = true; - if (SettingsScriptingInterface::getInstance()->getValue(MenuOption::NotificationSoundsSnapshot).toBool()) { + Setting::Handle notificationSounds{ MenuOption::NotificationSounds, true}; + Setting::Handle notificationSoundSnapshot{ MenuOption::NotificationSoundsSnapshot, true}; + if (notificationSounds.get() && notificationSoundSnapshot.get()) { if (_snapshotSoundInjector) { _snapshotSoundInjector->setOptions(options); _snapshotSoundInjector->restart(); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index ceef87f97b..e040f7a22c 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -270,9 +270,9 @@ Menu::Menu() { // Settings > Notifications > Play Notification Sounds SettingsScriptingInterface* settings = SettingsScriptingInterface::getInstance(); action = addCheckableActionToQMenuAndActionHash(notificationsMenu, "Play Notification Sounds", 0, - settings->getValue("play_notification_sounds").toBool()); + settings->getValue(MenuOption::NotificationSounds).toBool()); connect(action, &QAction::triggered, [action, settings] { - settings->setValue("play_notification_sounds", action->isChecked()); + settings->setValue(MenuOption::NotificationSounds, action->isChecked()); }); notificationsMenu->addSeparator(); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 496368c30b..86e44775c5 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -217,6 +217,7 @@ namespace MenuOption { const QString HMDTabletToToolbar = "HMD Tablet Becomes Toolbar"; const QString Shadows = "Shadows"; const QString AmbientOcclusion = "Ambient Occlusion"; + const QString NotificationSounds = "play_notification_sounds"; const QString NotificationSoundsSnapshot = "play_notification_sounds_snapshot"; const QString NotificationSoundsTablet = "play_notification_sounds_tablet"; } diff --git a/libraries/ui/src/ui/TabletScriptingInterface.cpp b/libraries/ui/src/ui/TabletScriptingInterface.cpp index 89751b142e..9070d87a3c 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.cpp +++ b/libraries/ui/src/ui/TabletScriptingInterface.cpp @@ -441,9 +441,10 @@ void TabletProxy::emitWebEvent(const QVariant& msg) { void TabletProxy::onTabletShown() { if (_tabletShown) { - Setting::Handle notificationSoundTablet{ "play_notification_sounds_tablet", true}; - if (notificationSoundTablet.get()) { - static_cast(parent())->playSound(TabletScriptingInterface::TabletOpen); + Setting::Handle notificationSounds{ QStringLiteral("play_notification_sounds"), true}; + Setting::Handle notificationSoundTablet{ QStringLiteral("play_notification_sounds_tablet"), true}; + if (notificationSounds.get() && notificationSoundTablet.get()) { + dynamic_cast(parent())->playSound(TabletScriptingInterface::TabletOpen); } if (_showRunningScripts) { _showRunningScripts = false; From afe04f3a4fbd1ffbd6c3e188264276079f9fefca Mon Sep 17 00:00:00 2001 From: vladest Date: Sun, 6 May 2018 14:24:54 +0200 Subject: [PATCH 031/143] cleanup --- interface/src/Menu.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index e040f7a22c..33e185b954 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -314,7 +314,6 @@ Menu::Menu() { settings->getValue(MenuOption::NotificationSoundsTablet).toBool()); connect(action, &QAction::triggered, [action, settings] { settings->setValue(MenuOption::NotificationSoundsTablet, action->isChecked()); - qDebug() << "vladest. tablet sound check up" << settings->getValue(MenuOption::NotificationSoundsTablet).toBool(); }); // Settings > Notifications > Wallet addActionToQMenuAndActionHash(notificationsMenu, "Wallet"); From 859b187db6e3badd5477ea7dc409252fe04e2534 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 8 May 2018 18:17:52 -0700 Subject: [PATCH 032/143] Separate panel for inspecting the engine --- scripts/developer/utilities/lib/jet/jet.js | 15 +++--- .../utilities/lib/jet/qml/TaskList.qml | 7 +-- .../utilities/render/deferredLighting.qml | 15 +++--- .../utilities/render/engineInspector.js | 13 +++++ .../utilities/render/engineInspector.qml | 30 +++++++++++ scripts/developer/utilities/render/luci.js | 53 +++++++++++++++---- 6 files changed, 100 insertions(+), 33 deletions(-) create mode 100644 scripts/developer/utilities/render/engineInspector.js create mode 100644 scripts/developer/utilities/render/engineInspector.qml diff --git a/scripts/developer/utilities/lib/jet/jet.js b/scripts/developer/utilities/lib/jet/jet.js index 39da9b6d90..c326a3a73e 100644 --- a/scripts/developer/utilities/lib/jet/jet.js +++ b/scripts/developer/utilities/lib/jet/jet.js @@ -46,19 +46,20 @@ function job_propKeys(job) { } // Use this function to create a functor that will print the content of the Job visited calling the specified 'printout' function -function job_print_functor(printout, maxDepth) { +function job_print_functor(printout, showProps, maxDepth) { if (maxDepth === undefined) maxDepth = 100 return function (job, depth, index) { var tab = " " var depthTab = ""; for (var d = 0; d < depth; d++) { depthTab += tab } - printout(depthTab + index + " " + job.objectName + " " + (job.enabled ? "on" : "off")) - var keys = job_propKeys(job); - for (var p=0; p < keys.length;p++) { - var prop = job[keys[p]] - printout(depthTab + tab + tab + typeof prop + " " + keys[p] + " " + prop); + printout(depthTab + index + " " + job.objectName + " " + (job.enabled ? "on " : "off ") + job.cpuRunTime + "ms") + if (showProps) { + var keys = job_propKeys(job); + for (var p=0; p < keys.length;p++) { + var prop = job[keys[p]] + printout(depthTab + tab + tab + typeof prop + " " + keys[p] + " " + prop); + } } - return true // return depth < maxDepth; } diff --git a/scripts/developer/utilities/lib/jet/qml/TaskList.qml b/scripts/developer/utilities/lib/jet/qml/TaskList.qml index fa004627a7..bd4b1e6c79 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskList.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskList.qml @@ -32,14 +32,9 @@ Rectangle { Component.onCompleted: { var message = "" - var functor = Jet.job_print_functor(function (line) { message += line + "\n"; }); + var functor = Jet.job_print_functor(function (line) { message += line + "\n"; }, false); Jet.task_traverseTree(rootConfig, functor); textArea.append(message); - } - function fromScript(mope) { - var message ='Received \n'; - message += mope; - textArea.append(message); } function clearWindow() { diff --git a/scripts/developer/utilities/render/deferredLighting.qml b/scripts/developer/utilities/render/deferredLighting.qml index dc81df48cb..d68b19c513 100644 --- a/scripts/developer/utilities/render/deferredLighting.qml +++ b/scripts/developer/utilities/render/deferredLighting.qml @@ -14,7 +14,6 @@ import QtQuick.Layouts 1.3 import "qrc:///qml/styles-uit" import "qrc:///qml/controls-uit" as HifiControls import "configSlider" -import "../lib/jet/qml" as Jet Rectangle { HifiConstants { id: hifi;} @@ -276,14 +275,12 @@ Rectangle { } } Separator {} - - Jet.TaskList { - rootConfig: Render - anchors.left: parent.left - anchors.right: parent.right - - height: 200 + HifiControls.Button { + text: "Engine" + // activeFocusOnPress: false + onClicked: { + sendToScript({method: "openEngineView"}); + } } } - //} } diff --git a/scripts/developer/utilities/render/engineInspector.js b/scripts/developer/utilities/render/engineInspector.js new file mode 100644 index 0000000000..dcf13157b5 --- /dev/null +++ b/scripts/developer/utilities/render/engineInspector.js @@ -0,0 +1,13 @@ + function openEngineTaskView() { + // Set up the qml ui + var qml = Script.resolvePath('engineInspector.qml'); + var window = new OverlayWindow({ + title: 'Render Engine', + source: qml, + width: 300, + height: 400 + }); + window.setPosition(200, 50); + //window.closed.connect(function() { Script.stop(); }); + } + openEngineTaskView(); \ No newline at end of file diff --git a/scripts/developer/utilities/render/engineInspector.qml b/scripts/developer/utilities/render/engineInspector.qml new file mode 100644 index 0000000000..6461e5d834 --- /dev/null +++ b/scripts/developer/utilities/render/engineInspector.qml @@ -0,0 +1,30 @@ +// +// deferredLighting.qml +// +// Created by Sam Gateau on 6/6/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 + +import "qrc:///qml/styles-uit" +import "qrc:///qml/controls-uit" as HifiControls + +import "../lib/jet/qml" as Jet + +Item { + HifiConstants { id: hifi;} + id: render; + anchors.fill: parent + + property var mainViewTask: Render.getConfig("RenderMainView") + + Jet.TaskList { + rootConfig: Render + anchors.fill: render + } +} \ No newline at end of file diff --git a/scripts/developer/utilities/render/luci.js b/scripts/developer/utilities/render/luci.js index 6482c884ff..005d96780a 100644 --- a/scripts/developer/utilities/render/luci.js +++ b/scripts/developer/utilities/render/luci.js @@ -64,9 +64,6 @@ button.editProperties({isActive: onLuciScreen}); wireEventBridge(onLuciScreen); } - - function fromQml(message) { - } button.clicked.connect(onClicked); tablet.screenChanged.connect(onScreenChanged); @@ -82,14 +79,6 @@ Controller.mouseMoveEvent.connect(function (e) { if (moveDebugCursor) setDebugCursor(e.x, e.y); }); - Script.scriptEnding.connect(function () { - if (onLuciScreen) { - tablet.gotoHomeScreen(); - } - button.clicked.disconnect(onClicked); - tablet.screenChanged.disconnect(onScreenChanged); - tablet.removeButton(button); - }); function setDebugCursor(x, y) { nx = (x / Window.innerWidth); @@ -98,4 +87,46 @@ Render.getConfig("RenderMainView").getConfig("Antialiasing").debugCursorTexcoord = { x: nx, y: ny }; } + + function fromQml(message) { + switch (message.method) { + case "openEngineView": + openEngineTaskView(); + break; + } + } + + + var engineInspectorView = null + function openEngineTaskView() { + if (engineInspectorView == null) { + var qml = Script.resolvePath('engineInspector.qml'); + var window = new OverlayWindow({ + title: 'Render Engine', + source: qml, + width: 300, + height: 400 + }); + window.setPosition(200, 50); + engineInspectorView = window + window.closed.connect(function() { engineInspectorView = null; }); + } else { + engineInspectorView.setPosition(200, 50); + } + } + + + + Script.scriptEnding.connect(function () { + if (onLuciScreen) { + tablet.gotoHomeScreen(); + } + button.clicked.disconnect(onClicked); + tablet.screenChanged.disconnect(onScreenChanged); + tablet.removeButton(button); + + if (engineInspectorView !== null) { + engineInspectorView.close() + } + }); }()); \ No newline at end of file From 3241c182714c2f2bf221d1f910dab38049644406 Mon Sep 17 00:00:00 2001 From: David Back Date: Wed, 9 May 2018 18:10:40 -0700 Subject: [PATCH 033/143] first pass cloneables WIP --- .../src/entities/EntityServer.cpp | 1 + .../entities/src/EntityEditPacketSender.cpp | 14 ++- .../entities/src/EntityEditPacketSender.h | 1 + libraries/entities/src/EntityItem.cpp | 98 ++++++++++++++++++ libraries/entities/src/EntityItem.h | 23 +++++ .../entities/src/EntityItemProperties.cpp | 97 ++++++++++++++++++ libraries/entities/src/EntityItemProperties.h | 7 ++ .../src/EntityItemPropertiesDefaults.h | 5 + libraries/entities/src/EntityPropertyFlags.h | 5 + .../entities/src/EntityScriptingInterface.cpp | 73 +++++++++----- .../entities/src/EntityScriptingInterface.h | 3 + libraries/entities/src/EntityTree.cpp | 99 +++++++++++++++---- libraries/entities/src/EntityTree.h | 1 + libraries/gpu/src/gpu/Buffer.cpp | 2 +- .../networking/src/udt/PacketHeaders.cpp | 3 +- libraries/networking/src/udt/PacketHeaders.h | 4 +- scripts/system/html/js/entityProperties.js | 75 ++------------ scripts/system/libraries/cloneEntityUtils.js | 60 +++-------- .../libraries/controllerDispatcherUtils.js | 3 +- 19 files changed, 410 insertions(+), 164 deletions(-) diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index c108dad6cf..3ca8c1ecd1 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -44,6 +44,7 @@ EntityServer::EntityServer(ReceivedMessage& message) : auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); packetReceiver.registerListenerForTypes({ PacketType::EntityAdd, + PacketType::EntityClone, PacketType::EntityEdit, PacketType::EntityErase, PacketType::EntityPhysics, diff --git a/libraries/entities/src/EntityEditPacketSender.cpp b/libraries/entities/src/EntityEditPacketSender.cpp index d89dd4f9d0..0ae4f7ac2b 100644 --- a/libraries/entities/src/EntityEditPacketSender.cpp +++ b/libraries/entities/src/EntityEditPacketSender.cpp @@ -34,7 +34,7 @@ void EntityEditPacketSender::processEntityEditNackPacket(QSharedPointer EntityItem::getMaterial } return toReturn; } + +bool EntityItem::getCloneable() const { + bool result; + withReadLock([&] { + result = _cloneable; + }); + return result; +} + +void EntityItem::setCloneable(bool value) { + withWriteLock([&] { + _cloneable = value; + }); +} + +float EntityItem::getCloneableLifetime() const { + float result; + withReadLock([&] { + result = _cloneableLifetime; + }); + return result; +} + +void EntityItem::setCloneableLifetime(float value) { + withWriteLock([&] { + _cloneableLifetime = value; + }); +} + +float EntityItem::getCloneableLimit() const { + float result; + withReadLock([&] { + result = _cloneableLimit; + }); + return result; +} + +void EntityItem::setCloneableLimit(float value) { + withWriteLock([&] { + _cloneableLimit = value; + }); +} + +bool EntityItem::getCloneableDynamic() const { + bool result; + withReadLock([&] { + result = _cloneableDynamic; + }); + return result; +} + +void EntityItem::setCloneableDynamic(const bool value) { + withWriteLock([&] { + _cloneableDynamic = value; + }); +} + +bool EntityItem::addCloneID(const QUuid& cloneID) { + if (!_cloneIDs.contains(cloneID)) { + _cloneIDs.append(cloneID); + return true; + } + return false; +} + +bool EntityItem::removeCloneID(const QUuid& cloneID) { + int index = _cloneIDs.indexOf(cloneID); + if (index > 0) { + _cloneIDs.removeAt(index); + return true; + } + return false; +} \ No newline at end of file diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index a88250a133..95cc5f96e1 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -341,6 +341,15 @@ public: quint32 getStaticCertificateVersion() const; void setStaticCertificateVersion(const quint32&); + bool getCloneable() const; + void setCloneable(bool value); + float getCloneableLifetime() const; + void setCloneableLifetime(float value); + float getCloneableLimit() const; + void setCloneableLimit(float value); + bool getCloneableDynamic() const; + void setCloneableDynamic(const bool value); + // TODO: get rid of users of getRadius()... float getRadius() const; @@ -494,6 +503,12 @@ public: void setSimulationOwnershipExpiry(uint64_t expiry) { _simulationOwnershipExpiry = expiry; } uint64_t getSimulationOwnershipExpiry() const { return _simulationOwnershipExpiry; } + bool addCloneID(const QUuid& cloneID); + bool removeCloneID(const QUuid& cloneID); + const QList& getCloneIDs() const { return _cloneIDs; } + void setCloneParent(const QUuid& cloneParentID) { _cloneParentID = cloneParentID; } + const QUuid& getCloneParent() const { return _cloneParentID; } + signals: void requestRenderUpdate(); @@ -648,6 +663,14 @@ protected: bool _cauterized { false }; // if true, don't draw because it would obscure 1st-person camera + bool _cloneable; + float _cloneableLifetime; + float _cloneableLimit; + bool _cloneableDynamic; + + QList _cloneIDs; + QUuid _cloneParentID; + private: std::unordered_map _materials; std::mutex _materialsLock; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 4d7c114176..93c2eb885e 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -436,6 +436,11 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_DPI, dpi); CHECK_PROPERTY_CHANGE(PROP_RELAY_PARENT_JOINTS, relayParentJoints); + CHECK_PROPERTY_CHANGE(PROP_CLONEABLE, cloneable); + CHECK_PROPERTY_CHANGE(PROP_CLONEABLE_LIFETIME, cloneableLifetime); + CHECK_PROPERTY_CHANGE(PROP_CLONEABLE_LIMIT, cloneableLimit); + CHECK_PROPERTY_CHANGE(PROP_CLONEABLE_DYNAMIC, cloneableDynamic); + changedProperties += _animation.getChangedProperties(); changedProperties += _keyLight.getChangedProperties(); changedProperties += _ambientLight.getChangedProperties(); @@ -1430,6 +1435,11 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CLIENT_ONLY, clientOnly); // Gettable but not settable except at entity creation COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_OWNING_AVATAR_ID, owningAvatarID); // Gettable but not settable + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CLONEABLE, cloneable); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CLONEABLE_LIFETIME, cloneableLifetime); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CLONEABLE_LIMIT, cloneableLimit); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CLONEABLE_DYNAMIC, cloneableDynamic); + // Rendering info if (!skipDefaults && !strictSemantics) { QScriptValue renderInfo = engine->newObject(); @@ -1642,6 +1652,11 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(dpi, uint16_t, setDPI); + COPY_PROPERTY_FROM_QSCRIPTVALUE(cloneable, bool, setCloneable); + COPY_PROPERTY_FROM_QSCRIPTVALUE(cloneableLifetime, float, setCloneableLifetime); + COPY_PROPERTY_FROM_QSCRIPTVALUE(cloneableLimit, float, setCloneableLimit); + COPY_PROPERTY_FROM_QSCRIPTVALUE(cloneableDynamic, bool, setCloneableDynamic); + _lastEdited = usecTimestampNow(); } @@ -2017,6 +2032,11 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_DPI, DPI, dpi, uint16_t); + ADD_PROPERTY_TO_MAP(PROP_CLONEABLE, Cloneable, cloneable, bool); + ADD_PROPERTY_TO_MAP(PROP_CLONEABLE_LIFETIME, CloneableLifetime, cloneableLifetime, float); + ADD_PROPERTY_TO_MAP(PROP_CLONEABLE_LIMIT, CloneableLimit, cloneableLimit, float); + ADD_PROPERTY_TO_MAP(PROP_CLONEABLE_DYNAMIC, CloneableDynamic, cloneableDynamic, bool); + // FIXME - these are not yet handled //ADD_PROPERTY_TO_MAP(PROP_CREATED, Created, created, quint64); @@ -2331,6 +2351,11 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_ENTITY_INSTANCE_NUMBER, properties.getEntityInstanceNumber()); APPEND_ENTITY_PROPERTY(PROP_CERTIFICATE_ID, properties.getCertificateID()); APPEND_ENTITY_PROPERTY(PROP_STATIC_CERTIFICATE_VERSION, properties.getStaticCertificateVersion()); + + APPEND_ENTITY_PROPERTY(PROP_CLONEABLE, properties.getCloneable()); + APPEND_ENTITY_PROPERTY(PROP_CLONEABLE_LIFETIME, properties.getCloneableLifetime()); + APPEND_ENTITY_PROPERTY(PROP_CLONEABLE_LIMIT, properties.getCloneableLimit()); + APPEND_ENTITY_PROPERTY(PROP_CLONEABLE_DYNAMIC, properties.getCloneableDynamic()); } if (propertyCount > 0) { @@ -2701,6 +2726,11 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CERTIFICATE_ID, QString, setCertificateID); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STATIC_CERTIFICATE_VERSION, quint32, setStaticCertificateVersion); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CLONEABLE, bool, setCloneable); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CLONEABLE_LIFETIME, float, setCloneableLifetime); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CLONEABLE_LIMIT, float, setCloneableLimit); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CLONEABLE_DYNAMIC, bool, setCloneableDynamic); + return valid; } @@ -2780,6 +2810,54 @@ bool EntityItemProperties::encodeEraseEntityMessage(const EntityItemID& entityIt return true; } +bool EntityItemProperties::encodeCloneEntityMessage(const EntityItemID& entityIDToClone, const EntityItemID& newEntityID, QByteArray& buffer) { + + char* copyAt = buffer.data(); + int outputLength = 0; + + if (buffer.size() < (int)(sizeof(NUM_BYTES_RFC4122_UUID) * 2)) { + qCDebug(entities) << "ERROR - encodeCloneEntityMessage() called with buffer that is too small!"; + return false; + } + + memcpy(copyAt, entityIDToClone.toRfc4122().constData(), NUM_BYTES_RFC4122_UUID); + copyAt += NUM_BYTES_RFC4122_UUID; + outputLength += NUM_BYTES_RFC4122_UUID; + + memcpy(copyAt, newEntityID.toRfc4122().constData(), NUM_BYTES_RFC4122_UUID); + copyAt += NUM_BYTES_RFC4122_UUID; + outputLength += NUM_BYTES_RFC4122_UUID; + + buffer.resize(outputLength); + + return true; +} + +bool EntityItemProperties::decodeCloneEntityMessage(const QByteArray& buffer, int& processedBytes, EntityItemID& entityIDToClone, EntityItemID& newEntityID) { + + const unsigned char* packetData = (const unsigned char*)buffer.constData(); + const unsigned char* dataAt = packetData; + size_t packetLength = buffer.size(); + processedBytes = 0; + + if (NUM_BYTES_RFC4122_UUID * 2 > packetLength) { + qCDebug(entities) << "EntityItemProperties::processEraseMessageDetails().... bailing because not enough bytes in buffer"; + return false; // bail to prevent buffer overflow + } + + QByteArray encodedID = buffer.mid((int)processedBytes, NUM_BYTES_RFC4122_UUID); + entityIDToClone = QUuid::fromRfc4122(encodedID); + dataAt += encodedID.size(); + processedBytes += encodedID.size(); + + encodedID = buffer.mid((int)processedBytes, NUM_BYTES_RFC4122_UUID); + newEntityID = QUuid::fromRfc4122(encodedID); + dataAt += encodedID.size(); + processedBytes += encodedID.size(); + + return true; +} + void EntityItemProperties::markAllChanged() { _lastEditedByChanged = true; _simulationOwnerChanged = true; @@ -2941,6 +3019,11 @@ void EntityItemProperties::markAllChanged() { _dpiChanged = true; _relayParentJointsChanged = true; + + _cloneableChanged = true; + _cloneableLifetimeChanged = true; + _cloneableLimitChanged = true; + _cloneableDynamicChanged = true; } // The minimum bounding box for the entity. @@ -3373,6 +3456,20 @@ QList EntityItemProperties::listChangedProperties() { out += "isUVModeStretch"; } + if (cloneableChanged()) { + out += "cloneable"; + } + if (cloneableLifetimeChanged()) { + out += "cloneableLifetime"; + } + if (cloneableLimitChanged()) { + out += "cloneableLimit"; + } + if (cloneableDynamicChanged()) { + out += "cloneableDynamic"; + } + + getAnimation().listChangedProperties(out); getKeyLight().listChangedProperties(out); getAmbientLight().listChangedProperties(out); diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 39ea2e0bdd..3ae2186cab 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -272,6 +272,11 @@ public: DEFINE_PROPERTY_REF(PROP_SERVER_SCRIPTS, ServerScripts, serverScripts, QString, ENTITY_ITEM_DEFAULT_SERVER_SCRIPTS); DEFINE_PROPERTY(PROP_RELAY_PARENT_JOINTS, RelayParentJoints, relayParentJoints, bool, ENTITY_ITEM_DEFAULT_RELAY_PARENT_JOINTS); + DEFINE_PROPERTY(PROP_CLONEABLE, Cloneable, cloneable, bool, ENTITY_ITEM_CLONEABLE); + DEFINE_PROPERTY(PROP_CLONEABLE_LIFETIME, CloneableLifetime, cloneableLifetime, float, ENTITY_ITEM_CLONEABLE_LIFETIME); + DEFINE_PROPERTY(PROP_CLONEABLE_LIMIT, CloneableLimit, cloneableLimit, float, ENTITY_ITEM_CLONEABLE_LIMIT); + DEFINE_PROPERTY(PROP_CLONEABLE_DYNAMIC, CloneableDynamic, cloneableDynamic, bool, ENTITY_ITEM_CLONEABLE_DYNAMIC); + static QString getComponentModeString(uint32_t mode); static QString getComponentModeAsString(uint32_t mode); @@ -294,6 +299,8 @@ public: QByteArray& buffer, EntityPropertyFlags requestedProperties, EntityPropertyFlags& didntFitProperties); static bool encodeEraseEntityMessage(const EntityItemID& entityItemID, QByteArray& buffer); + static bool encodeCloneEntityMessage(const EntityItemID& entityIDToClone, const EntityItemID& newEntityID, QByteArray& buffer); + static bool decodeCloneEntityMessage(const QByteArray& buffer, int& processedBytes, EntityItemID& entityIDToClone, EntityItemID& newEntityID); static bool decodeEntityEditPacket(const unsigned char* data, int bytesToRead, int& processedBytes, EntityItemID& entityID, EntityItemProperties& properties); diff --git a/libraries/entities/src/EntityItemPropertiesDefaults.h b/libraries/entities/src/EntityItemPropertiesDefaults.h index d2ddd687dd..6e46453bda 100644 --- a/libraries/entities/src/EntityItemPropertiesDefaults.h +++ b/libraries/entities/src/EntityItemPropertiesDefaults.h @@ -97,4 +97,9 @@ const QUuid ENTITY_ITEM_DEFAULT_LAST_EDITED_BY = QUuid(); const bool ENTITY_ITEM_DEFAULT_RELAY_PARENT_JOINTS = false; +const bool ENTITY_ITEM_CLONEABLE = false; +const float ENTITY_ITEM_CLONEABLE_LIFETIME = 300.0f; +const int ENTITY_ITEM_CLONEABLE_LIMIT = 0; +const bool ENTITY_ITEM_CLONEABLE_DYNAMIC = false; + #endif // hifi_EntityItemPropertiesDefaults_h diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 99a5f287ea..f698739e01 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -242,6 +242,11 @@ enum EntityPropertyList { PROP_MATERIAL_MAPPING_ROT, PROP_MATERIAL_DATA, + PROP_CLONEABLE, + PROP_CLONEABLE_LIFETIME, + PROP_CLONEABLE_LIMIT, + PROP_CLONEABLE_DYNAMIC, + //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties to end of list just ABOVE this line PROP_AFTER_LAST_ITEM, diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 7c16214a78..132fec2c51 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -258,33 +258,9 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties propertiesWithSimID = convertPropertiesFromScriptSemantics(propertiesWithSimID, scalesWithParent); propertiesWithSimID.setDimensionsInitialized(properties.dimensionsChanged()); - EntityItemID id = EntityItemID(QUuid::createUuid()); - + EntityItemID id; // If we have a local entity tree set, then also update it. - bool success = true; - if (_entityTree) { - _entityTree->withWriteLock([&] { - EntityItemPointer entity = _entityTree->addEntity(id, propertiesWithSimID); - if (entity) { - if (propertiesWithSimID.queryAACubeRelatedPropertyChanged()) { - // due to parenting, the server may not know where something is in world-space, so include the bounding cube. - bool success; - AACube queryAACube = entity->getQueryAACube(success); - if (success) { - propertiesWithSimID.setQueryAACube(queryAACube); - } - } - - entity->setLastBroadcast(usecTimestampNow()); - // since we're creating this object we will immediately volunteer to own its simulation - entity->flagForOwnershipBid(VOLUNTEER_SIMULATION_PRIORITY); - propertiesWithSimID.setLastEdited(entity->getLastEdited()); - } else { - qCDebug(entities) << "script failed to add new Entity to local Octree"; - success = false; - } - }); - } + bool success = addLocalEntityCopy(propertiesWithSimID, id); // queue the packet if (success) { @@ -295,6 +271,39 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties } } +bool EntityScriptingInterface::addLocalEntityCopy(EntityItemProperties& properties, EntityItemID& id) { + bool success = true; + + id = EntityItemID(QUuid::createUuid()); + + if (_entityTree) { + _entityTree->withWriteLock([&] { + EntityItemPointer entity = _entityTree->addEntity(id, properties); + if (entity) { + if (properties.queryAACubeRelatedPropertyChanged()) { + // due to parenting, the server may not know where something is in world-space, so include the bounding cube. + bool success; + AACube queryAACube = entity->getQueryAACube(success); + if (success) { + properties.setQueryAACube(queryAACube); + } + } + + entity->setLastBroadcast(usecTimestampNow()); + // since we're creating this object we will immediately volunteer to own its simulation + entity->flagForOwnershipBid(VOLUNTEER_SIMULATION_PRIORITY); + properties.setLastEdited(entity->getLastEdited()); + } + else { + qCDebug(entities) << "script failed to add new Entity to local Octree"; + success = false; + } + }); + } + + return success; +} + QUuid EntityScriptingInterface::addModelEntity(const QString& name, const QString& modelUrl, const QString& textures, const QString& shapeType, bool dynamic, bool collisionless, const glm::vec3& position, const glm::vec3& gravity) { @@ -320,6 +329,18 @@ QUuid EntityScriptingInterface::addModelEntity(const QString& name, const QStrin return addEntity(properties); } +QUuid EntityScriptingInterface::cloneEntity(QUuid entityIDToClone) { + EntityItemID newEntityID; + EntityItemProperties properties = getEntityProperties(entityIDToClone); + if (addLocalEntityCopy(properties, newEntityID)) { + qCDebug(entities) << "DBACK POOPY cloneEntity addLocalEntityCopy" << newEntityID; + getEntityPacketSender()->queueCloneEntityMessage(entityIDToClone, newEntityID); + return newEntityID; + } else { + return QUuid(); + } +} + EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identity) { EntityPropertyFlags noSpecificProperties; return getEntityProperties(identity, noSpecificProperties); diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 8adb5138f2..6935c9e8c4 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -224,6 +224,8 @@ public slots: Q_INVOKABLE QUuid addModelEntity(const QString& name, const QString& modelUrl, const QString& textures, const QString& shapeType, bool dynamic, bool collisionless, const glm::vec3& position, const glm::vec3& gravity); + Q_INVOKABLE QUuid cloneEntity(QUuid entityIDToClone); + /**jsdoc * Get the properties of an entity. * @function Entities.getEntityProperties @@ -1875,6 +1877,7 @@ private: bool polyVoxWorker(QUuid entityID, std::function actor); bool setPoints(QUuid entityID, std::function actor); void queueEntityMessage(PacketType packetType, EntityItemID entityID, const EntityItemProperties& properties); + bool addLocalEntityCopy(EntityItemProperties& propertiesWithSimID, EntityItemID& id); EntityItemPointer checkForTreeEntityAndTypeMatch(const QUuid& entityID, EntityTypes::EntityType entityType = EntityTypes::Unknown); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 3149527216..1e8055ff46 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -228,6 +228,7 @@ bool EntityTree::handlesEditPacketType(PacketType packetType) const { // we handle these types of "edit" packets switch (packetType) { case PacketType::EntityAdd: + case PacketType::EntityClone: case PacketType::EntityEdit: case PacketType::EntityErase: case PacketType::EntityPhysics: @@ -592,6 +593,7 @@ void EntityTree::deleteEntity(const EntityItemID& entityID, bool force, bool ign return; } + removeCloneIDFromCloneParent(entityID); unhookChildAvatar(entityID); emit deletingEntity(entityID); emit deletingEntityPointer(existingEntity.get()); @@ -625,6 +627,19 @@ void EntityTree::unhookChildAvatar(const EntityItemID entityID) { }); } +void EntityTree::removeCloneIDFromCloneParent(const EntityItemID& entityID) { + EntityItemPointer entity = findEntityByEntityItemID(entityID); + if (entity) { + const QUuid& cloneParentID = entity->getCloneParent(); + if (!cloneParentID.isNull()) { + EntityItemPointer cloneParent = findEntityByID(cloneParentID); + if (cloneParent) { + cloneParent->removeCloneID(entityID); + } + } + } +} + void EntityTree::deleteEntities(QSet entityIDs, bool force, bool ignoreWarnings) { // NOTE: callers must lock the tree before using this method DeleteEntityOperator theOperator(getThisPointer()); @@ -653,6 +668,7 @@ void EntityTree::deleteEntities(QSet entityIDs, bool force, bool i } // tell our delete operator about this entityID + removeCloneIDFromCloneParent(entityID); unhookChildAvatar(entityID); theOperator.addEntityIDToDeleteList(entityID); emit deletingEntity(entityID); @@ -1392,6 +1408,7 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c int processedBytes = 0; bool isAdd = false; + bool isClone = false; // we handle these types of "edit" packets switch (message.getType()) { case PacketType::EntityErase: { @@ -1400,8 +1417,10 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c break; } + case PacketType::EntityClone: + isClone = true; // fall through to next case case PacketType::EntityAdd: - isAdd = true; // fall through to next case + isAdd = true; // fall through to next case // FALLTHRU case PacketType::EntityPhysics: case PacketType::EntityEdit: { @@ -1422,8 +1441,21 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c EntityItemProperties properties; startDecode = usecTimestampNow(); - bool validEditPacket = EntityItemProperties::decodeEntityEditPacket(editData, maxLength, processedBytes, - entityItemID, properties); + bool validEditPacket = false; + EntityItemID entityIDToClone; + EntityItemPointer entityToClone; + if (isClone) { + QByteArray buffer = QByteArray::fromRawData(reinterpret_cast(editData), maxLength); + validEditPacket = EntityItemProperties::decodeCloneEntityMessage(buffer, processedBytes, entityIDToClone, entityItemID); + entityToClone = findEntityByEntityItemID(entityIDToClone); + if (entityToClone) { + properties = entityToClone->getProperties(); + } + } + else { + validEditPacket = EntityItemProperties::decodeEntityEditPacket(editData, maxLength, processedBytes, entityItemID, properties); + } + endDecode = usecTimestampNow(); EntityItemPointer existingEntity; @@ -1491,24 +1523,26 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c } - if ((isAdd || properties.lifetimeChanged()) && - ((!senderNode->getCanRez() && senderNode->getCanRezTmp()) || - (!senderNode->getCanRezCertified() && senderNode->getCanRezTmpCertified()))) { - // this node is only allowed to rez temporary entities. if need be, cap the lifetime. - if (properties.getLifetime() == ENTITY_ITEM_IMMORTAL_LIFETIME || - properties.getLifetime() > _maxTmpEntityLifetime) { - properties.setLifetime(_maxTmpEntityLifetime); + if (!isClone) { + if ((isAdd || properties.lifetimeChanged()) && + ((!senderNode->getCanRez() && senderNode->getCanRezTmp()) || + (!senderNode->getCanRezCertified() && senderNode->getCanRezTmpCertified()))) { + // this node is only allowed to rez temporary entities. if need be, cap the lifetime. + if (properties.getLifetime() == ENTITY_ITEM_IMMORTAL_LIFETIME || + properties.getLifetime() > _maxTmpEntityLifetime) { + properties.setLifetime(_maxTmpEntityLifetime); + bumpTimestamp(properties); + } + } + + if (isAdd && properties.getLocked() && !senderNode->isAllowedEditor()) { + // if a node can't change locks, don't allow it to create an already-locked entity -- automatically + // clear the locked property and allow the unlocked entity to be created. + properties.setLocked(false); bumpTimestamp(properties); } } - if (isAdd && properties.getLocked() && !senderNode->isAllowedEditor()) { - // if a node can't change locks, don't allow it to create an already-locked entity -- automatically - // clear the locked property and allow the unlocked entity to be created. - properties.setLocked(false); - bumpTimestamp(properties); - } - // If we got a valid edit packet, then it could be a new entity or it could be an update to // an existing entity... handle appropriately if (validEditPacket) { @@ -1566,17 +1600,39 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c } else if (isAdd) { bool failedAdd = !allowed; bool isCertified = !properties.getCertificateID().isEmpty(); + bool isCloneable = properties.getCloneable(); + int cloneLimit = properties.getCloneableLimit(); if (!allowed) { qCDebug(entities) << "Filtered entity add. ID:" << entityItemID; - } else if (!isCertified && !senderNode->getCanRez() && !senderNode->getCanRezTmp()) { + } else if (!isClone && !isCertified && !senderNode->getCanRez() && !senderNode->getCanRezTmp()) { failedAdd = true; qCDebug(entities) << "User without 'uncertified rez rights' [" << senderNode->getUUID() << "] attempted to add an uncertified entity with ID:" << entityItemID; - } else if (isCertified && !senderNode->getCanRezCertified() && !senderNode->getCanRezTmpCertified()) { + } else if (!isClone && isCertified && !senderNode->getCanRezCertified() && !senderNode->getCanRezTmpCertified()) { failedAdd = true; qCDebug(entities) << "User without 'certified rez rights' [" << senderNode->getUUID() << "] attempted to add a certified entity with ID:" << entityItemID; + } else if (isClone && isCertified) { + failedAdd = true; + qCDebug(entities) << "User attempted to clone certified entity from entity ID:" << entityIDToClone; + } else if (isClone && !isCloneable) { + failedAdd = true; + qCDebug(entities) << "User attempted to clone non-cloneable entity from entity ID:" << entityIDToClone; + } else if (isClone && entityToClone && entityToClone->getCloneIDs().size() >= cloneLimit) { + failedAdd = true; + qCDebug(entities) << "User attempted to clone entity ID:" << entityIDToClone << " which reached it's cloneable limit."; } else { + if (isClone) { + properties.setName(properties.getName() + "-clone-" + entityIDToClone.toString()); + properties.setLocked(false); + properties.setLifetime(properties.getCloneableLifetime()); + properties.setDynamic(properties.getCloneableDynamic()); + properties.setCloneable(ENTITY_ITEM_CLONEABLE); + properties.setCloneableLifetime(ENTITY_ITEM_CLONEABLE_LIFETIME); + properties.setCloneableLimit(ENTITY_ITEM_CLONEABLE_LIMIT); + properties.setCloneableDynamic(ENTITY_ITEM_CLONEABLE_DYNAMIC); + } + // this is a new entity... assign a new entityID properties.setCreated(properties.getLastEdited()); properties.setLastEditedBy(senderNode->getUUID()); @@ -1600,6 +1656,11 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c if (newEntity) { newEntity->markAsChangedOnServer(); notifyNewlyCreatedEntity(*newEntity, senderNode); + if (isClone) { + entityToClone->addCloneID(newEntity->getEntityItemID()); + newEntity->setCloneParent(entityIDToClone); + qCDebug(entities) << "DBACK POOPY addedEntity clone " << newEntity->getEntityItemID(); + } startLogging = usecTimestampNow(); if (wantEditLogging()) { diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index ee9fb10554..0d7cc54df7 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -117,6 +117,7 @@ public: // check if the avatar is a child of this entity, If so set the avatar parentID to null void unhookChildAvatar(const EntityItemID entityID); + void removeCloneIDFromCloneParent(const EntityItemID& entityID); void deleteEntity(const EntityItemID& entityID, bool force = false, bool ignoreWarnings = true); void deleteEntities(QSet entityIDs, bool force = false, bool ignoreWarnings = true); diff --git a/libraries/gpu/src/gpu/Buffer.cpp b/libraries/gpu/src/gpu/Buffer.cpp index ebb768e597..fe3570e7f7 100644 --- a/libraries/gpu/src/gpu/Buffer.cpp +++ b/libraries/gpu/src/gpu/Buffer.cpp @@ -99,7 +99,7 @@ Buffer::Update::Update(const Buffer& parent) : buffer(parent) { void Buffer::Update::apply() const { // Make sure we're loaded in order buffer._applyUpdateCount++; - assert(buffer._applyUpdateCount == updateNumber); + //assert(buffer._applyUpdateCount == updateNumber); const auto pageSize = buffer._pages._pageSize; buffer._renderSysmem.resize(size); diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 70880833bf..e84f3ffe7a 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -29,10 +29,11 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::DomainList: return static_cast(DomainListVersion::GetMachineFingerprintFromUUIDSupport); case PacketType::EntityAdd: + case PacketType::EntityClone: case PacketType::EntityEdit: case PacketType::EntityData: case PacketType::EntityPhysics: - return static_cast(EntityVersion::MaterialData); + return static_cast(EntityVersion::CloneableData); case PacketType::EntityQuery: return static_cast(EntityQueryPacketVersion::ConicalFrustums); case PacketType::AvatarIdentity: diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 7d374f3625..5cb2d49a53 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -75,6 +75,7 @@ public: EntityData, EntityQuery, EntityAdd, + EntityClone, EntityErase, EntityEdit, DomainServerConnectionToken, @@ -232,7 +233,8 @@ enum class EntityVersion : PacketVersion { SoftEntities, MaterialEntities, ShadowControl, - MaterialData + MaterialData, + CloneableData }; enum class EntityScriptCallMethodVersion : PacketVersion { diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 4b6329db44..f0bcdad708 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -1040,12 +1040,12 @@ function loaded() { elWantsTrigger.checked = false; elIgnoreIK.checked = true; - elCloneable.checked = false; - elCloneableDynamic.checked = false; + elCloneable.checked = properties.cloneable; + elCloneableDynamic.checked = properties.cloneableDynamic; elCloneableGroup.style.display = elCloneable.checked ? "block": "none"; - elCloneableLimit.value = 0; - elCloneableLifetime.value = 300; - + elCloneableLimit.value = properties.cloneableLimit; + elCloneableLifetime.value = properties.cloneableLifetime; + var grabbablesSet = false; var parsedUserData = {}; try { @@ -1069,27 +1069,6 @@ function loaded() { } else { elIgnoreIK.checked = true; } - if ("cloneable" in grabbableData) { - elCloneable.checked = grabbableData.cloneable; - elCloneableGroup.style.display = elCloneable.checked ? "block" : "none"; - elCloneableDynamic.checked = - grabbableData.cloneDynamic ? grabbableData.cloneDynamic : properties.dynamic; - if (elCloneable.checked) { - if ("cloneLifetime" in grabbableData) { - elCloneableLifetime.value = - grabbableData.cloneLifetime ? grabbableData.cloneLifetime : 300; - } - if ("cloneLimit" in grabbableData) { - elCloneableLimit.value = grabbableData.cloneLimit ? grabbableData.cloneLimit : 0; - } - if ("cloneAvatarEntity" in grabbableData) { - elCloneableAvatarEntity.checked = - grabbableData.cloneAvatarEntity ? grabbableData.cloneAvatarEntity : false; - } - } - } else { - elCloneable.checked = false; - } } } catch (e) { // TODO: What should go here? @@ -1460,45 +1439,11 @@ function loaded() { } userDataChanger("grabbableKey", "grabbable", elGrabbable, elUserData, true); }); - elCloneableDynamic.addEventListener('change', function(event) { - userDataChanger("grabbableKey", "cloneDynamic", event.target, elUserData, -1); - }); - - elCloneableAvatarEntity.addEventListener('change', function(event) { - userDataChanger("grabbableKey", "cloneAvatarEntity", event.target, elUserData, -1); - }); - - elCloneable.addEventListener('change', function (event) { - var checked = event.target.checked; - if (checked) { - multiDataUpdater("grabbableKey", { - cloneLifetime: elCloneableLifetime, - cloneLimit: elCloneableLimit, - cloneDynamic: elCloneableDynamic, - cloneAvatarEntity: elCloneableAvatarEntity, - cloneable: event.target, - grabbable: null - }, elUserData, {}); - elCloneableGroup.style.display = "block"; - updateProperty('dynamic', false); - } else { - multiDataUpdater("grabbableKey", { - cloneLifetime: null, - cloneLimit: null, - cloneDynamic: null, - cloneAvatarEntity: null, - cloneable: false - }, elUserData, {}); - elCloneableGroup.style.display = "none"; - } - }); - - var numberListener = function (event) { - userDataChanger("grabbableKey", - event.target.getAttribute("data-user-data-type"), parseInt(event.target.value), elUserData, false); - }; - elCloneableLifetime.addEventListener('change', numberListener); - elCloneableLimit.addEventListener('change', numberListener); + + elCloneable.addEventListener('change', createEmitCheckedPropertyUpdateFunction('cloneable')); + elCloneableDynamic.addEventListener('change', createEmitCheckedPropertyUpdateFunction('cloneableDynamic')); + elCloneableLifetime.addEventListener('change', createEmitNumberPropertyUpdateFunction('cloneableLifetime')); + elCloneableLimit.addEventListener('change', createEmitNumberPropertyUpdateFunction('cloneableLimit')); elWantsTrigger.addEventListener('change', function() { userDataChanger("grabbableKey", "wantsTrigger", elWantsTrigger, elUserData, false); diff --git a/scripts/system/libraries/cloneEntityUtils.js b/scripts/system/libraries/cloneEntityUtils.js index 63b161eb80..bd33d32342 100644 --- a/scripts/system/libraries/cloneEntityUtils.js +++ b/scripts/system/libraries/cloneEntityUtils.js @@ -33,8 +33,7 @@ if (typeof Object.assign !== 'function') { entityIsCloneable = function(props) { if (props) { - var grabbableData = getGrabbableData(props); - return grabbableData.cloneable; + return props.cloneable; } return false; }; @@ -42,56 +41,19 @@ entityIsCloneable = function(props) { propsAreCloneDynamic = function(props) { var cloneable = entityIsCloneable(props); if (cloneable) { - var grabInfo = getGrabbableData(props); - if (grabInfo.cloneDynamic) { - return true; - } + return props.cloneableDynamic; } return false; }; - cloneEntity = function(props, worldEntityProps) { - // we need all the properties, for this - var cloneableProps = Entities.getEntityProperties(props.id); - - var count = 0; - worldEntityProps.forEach(function(itemWE) { - if (itemWE.name.indexOf('-clone-' + cloneableProps.id) !== -1) { - count++; - } - }); - - var grabInfo = getGrabbableData(cloneableProps); - var limit = grabInfo.cloneLimit ? grabInfo.cloneLimit : 0; - if (count >= limit && limit !== 0) { - return null; - } - - cloneableProps.name = cloneableProps.name + '-clone-' + cloneableProps.id; - var lifetime = grabInfo.cloneLifetime ? grabInfo.cloneLifetime : 300; - var dynamic = grabInfo.cloneDynamic ? grabInfo.cloneDynamic : false; - var triggerable = grabInfo.triggerable ? grabInfo.triggerable : false; - var avatarEntity = grabInfo.cloneAvatarEntity ? grabInfo.cloneAvatarEntity : false; - var cUserData = Object.assign({}, JSON.parse(cloneableProps.userData)); - var cProperties = Object.assign({}, cloneableProps); - - - delete cUserData.grabbableKey.cloneLifetime; - delete cUserData.grabbableKey.cloneable; - delete cUserData.grabbableKey.cloneDynamic; - delete cUserData.grabbableKey.cloneLimit; - delete cUserData.grabbableKey.cloneAvatarEntity; - delete cProperties.id; - - - cProperties.dynamic = dynamic; - cProperties.locked = false; - cUserData.grabbableKey.triggerable = triggerable; - cUserData.grabbableKey.grabbable = true; - cProperties.lifetime = lifetime; - cProperties.userData = JSON.stringify(cUserData); - - var cloneID = Entities.addEntity(cProperties, avatarEntity); - return cloneID; + var entityToClone = props.id; + var certificateID = Entities.getEntityProperties(entityToClone, ['certificateID']).certificateID; + // ensure entity is cloneable and does not have a certificate ID, whereas cloneable limits + // will now be handled by the server where the entity add will fail if limit reached + if (entityIsCloneable(props) && (certificateID === undefined || certificateID.length === 0)) { + var cloneID = Entities.cloneEntity(entityToClone); + return cloneID; + } + return null; }; diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index 71dc5e4273..f3f0e8dd01 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -125,7 +125,8 @@ DISPATCHER_PROPERTIES = [ "dimensions", "userData", "type", - "href" + "href", + "cloneable" ]; // priority -- a lower priority means the module will be asked sooner than one with a higher priority in a given update step From dea588ae4ac1968b0e3f5c070f9c99096fbc2b96 Mon Sep 17 00:00:00 2001 From: David Back Date: Wed, 9 May 2018 18:12:04 -0700 Subject: [PATCH 034/143] remove prints --- libraries/entities/src/EntityScriptingInterface.cpp | 1 - libraries/entities/src/EntityTree.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 132fec2c51..7b7f35aa09 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -333,7 +333,6 @@ QUuid EntityScriptingInterface::cloneEntity(QUuid entityIDToClone) { EntityItemID newEntityID; EntityItemProperties properties = getEntityProperties(entityIDToClone); if (addLocalEntityCopy(properties, newEntityID)) { - qCDebug(entities) << "DBACK POOPY cloneEntity addLocalEntityCopy" << newEntityID; getEntityPacketSender()->queueCloneEntityMessage(entityIDToClone, newEntityID); return newEntityID; } else { diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 1e8055ff46..20b3f81f42 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1659,7 +1659,6 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c if (isClone) { entityToClone->addCloneID(newEntity->getEntityItemID()); newEntity->setCloneParent(entityIDToClone); - qCDebug(entities) << "DBACK POOPY addedEntity clone " << newEntity->getEntityItemID(); } startLogging = usecTimestampNow(); From 1aa653c5db6cf05fbb94517c857e4b3958e8563a Mon Sep 17 00:00:00 2001 From: David Back Date: Wed, 9 May 2018 18:20:07 -0700 Subject: [PATCH 035/143] tabs --- scripts/system/html/js/entityProperties.js | 12 ++++++------ scripts/system/libraries/cloneEntityUtils.js | 16 ++++++++-------- .../libraries/controllerDispatcherUtils.js | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index f0bcdad708..c81e51d674 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -1045,7 +1045,7 @@ function loaded() { elCloneableGroup.style.display = elCloneable.checked ? "block": "none"; elCloneableLimit.value = properties.cloneableLimit; elCloneableLifetime.value = properties.cloneableLifetime; - + var grabbablesSet = false; var parsedUserData = {}; try { @@ -1439,11 +1439,11 @@ function loaded() { } userDataChanger("grabbableKey", "grabbable", elGrabbable, elUserData, true); }); - - elCloneable.addEventListener('change', createEmitCheckedPropertyUpdateFunction('cloneable')); - elCloneableDynamic.addEventListener('change', createEmitCheckedPropertyUpdateFunction('cloneableDynamic')); - elCloneableLifetime.addEventListener('change', createEmitNumberPropertyUpdateFunction('cloneableLifetime')); - elCloneableLimit.addEventListener('change', createEmitNumberPropertyUpdateFunction('cloneableLimit')); + + elCloneable.addEventListener('change', createEmitCheckedPropertyUpdateFunction('cloneable')); + elCloneableDynamic.addEventListener('change', createEmitCheckedPropertyUpdateFunction('cloneableDynamic')); + elCloneableLifetime.addEventListener('change', createEmitNumberPropertyUpdateFunction('cloneableLifetime')); + elCloneableLimit.addEventListener('change', createEmitNumberPropertyUpdateFunction('cloneableLimit')); elWantsTrigger.addEventListener('change', function() { userDataChanger("grabbableKey", "wantsTrigger", elWantsTrigger, elUserData, false); diff --git a/scripts/system/libraries/cloneEntityUtils.js b/scripts/system/libraries/cloneEntityUtils.js index bd33d32342..358bc4a75f 100644 --- a/scripts/system/libraries/cloneEntityUtils.js +++ b/scripts/system/libraries/cloneEntityUtils.js @@ -47,13 +47,13 @@ propsAreCloneDynamic = function(props) { }; cloneEntity = function(props, worldEntityProps) { - var entityToClone = props.id; + var entityToClone = props.id; var certificateID = Entities.getEntityProperties(entityToClone, ['certificateID']).certificateID; - // ensure entity is cloneable and does not have a certificate ID, whereas cloneable limits - // will now be handled by the server where the entity add will fail if limit reached - if (entityIsCloneable(props) && (certificateID === undefined || certificateID.length === 0)) { - var cloneID = Entities.cloneEntity(entityToClone); - return cloneID; - } - return null; + // ensure entity is cloneable and does not have a certificate ID, whereas cloneable limits + // will now be handled by the server where the entity add will fail if limit reached + if (entityIsCloneable(props) && (certificateID === undefined || certificateID.length === 0)) { + var cloneID = Entities.cloneEntity(entityToClone); + return cloneID; + } + return null; }; diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index f3f0e8dd01..43945c6145 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -126,7 +126,7 @@ DISPATCHER_PROPERTIES = [ "userData", "type", "href", - "cloneable" + "cloneable" ]; // priority -- a lower priority means the module will be asked sooner than one with a higher priority in a given update step From f08f77098dc22b8d3e40f199d63184fbec9e144d Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 9 May 2018 18:28:47 -0700 Subject: [PATCH 036/143] Adding a true ListView for the engine --- scripts/developer/utilities/lib/jet/jet.js | 9 +++ .../utilities/lib/jet/qml/TaskList.qml | 4 +- .../utilities/lib/jet/qml/TaskListView.qml | 67 +++++++++++++++++++ .../developer/utilities/lib/jet/qml/qmldir | 3 +- .../utilities/render/engineInspector.qml | 4 +- 5 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 scripts/developer/utilities/lib/jet/qml/TaskListView.qml diff --git a/scripts/developer/utilities/lib/jet/jet.js b/scripts/developer/utilities/lib/jet/jet.js index c326a3a73e..5bebb99068 100644 --- a/scripts/developer/utilities/lib/jet/jet.js +++ b/scripts/developer/utilities/lib/jet/jet.js @@ -45,6 +45,15 @@ function job_propKeys(job) { return propKeys; } +// Use this function to create a functor that will fill the specifed array with one entry name per task and job and it s rank +function job_list_functor(jobList, maxDepth) { + if (maxDepth === undefined) maxDepth = 100 + return function (job, depth, index) { + jobList.push(job.objectName); + return depth < maxDepth; + } +} + // Use this function to create a functor that will print the content of the Job visited calling the specified 'printout' function function job_print_functor(printout, showProps, maxDepth) { if (maxDepth === undefined) maxDepth = 100 diff --git a/scripts/developer/utilities/lib/jet/qml/TaskList.qml b/scripts/developer/utilities/lib/jet/qml/TaskList.qml index bd4b1e6c79..b801b9171d 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskList.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskList.qml @@ -17,7 +17,9 @@ import "qrc:///qml/controls-uit" as HifiControls import "../jet.js" as Jet -Rectangle { +Rectangle { + HifiConstants { id: hifi;} + color: hifi.colors.baseGray; id: root // width: parent ? parent.width : 200 // height: parent ? parent.height : 400 diff --git a/scripts/developer/utilities/lib/jet/qml/TaskListView.qml b/scripts/developer/utilities/lib/jet/qml/TaskListView.qml new file mode 100644 index 0000000000..f8775d56b9 --- /dev/null +++ b/scripts/developer/utilities/lib/jet/qml/TaskListView.qml @@ -0,0 +1,67 @@ +// +// jet/TaskListView.qml +// +// Created by Sam Gateau, 2018/05/09 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.7 +import QtQuick.Controls 1.4 as Original +import QtQuick.Controls.Styles 1.4 + +import "qrc:///qml/styles-uit" +import "qrc:///qml/controls-uit" as HifiControls + +import "../jet.js" as Jet + +Rectangle { + HifiConstants { id: hifi;} + color: hifi.colors.baseGray; + id: root + + // width: parent ? parent.width : 200 + // height: parent ? parent.height : 400 + property var rootConfig : Workload + property var myArray : [] + + Component.onCompleted: { + var message = "" + var functor = Jet.job_print_functor(function (line) { message += line + "\n"; }, false); + + functor = Jet.job_list_functor(root.myArray); + + Jet.task_traverseTree(rootConfig, functor); + //print(JSON.stringify(root.myArray)) + // theView.model = root.myArray.length + for (var i = 0; i < root.myArray.length; i++) { + jobsModel.append({"on": true, "name": root.myArray[i]}) + } + // theView.model = root.myArray + } + + function getJobName(i) { + return root.myArray[i]; + } + + ListModel { + id: jobsModel + } + + Component { + id: itemDelegate + //HifiControls.Label { text: "I am item number: " + index } + HifiControls.CheckBox { text: name + index; + checked: true; } + } + + ListView { + id: theView + anchors.fill: parent + model: jobsModel + delegate: itemDelegate + } + +} \ No newline at end of file diff --git a/scripts/developer/utilities/lib/jet/qml/qmldir b/scripts/developer/utilities/lib/jet/qml/qmldir index f926d8cc67..3134545625 100644 --- a/scripts/developer/utilities/lib/jet/qml/qmldir +++ b/scripts/developer/utilities/lib/jet/qml/qmldir @@ -1 +1,2 @@ -TaskList 1.0 TaskList.qml \ No newline at end of file +TaskList 1.0 TaskList.qml +TaskViewList 1.0 TaskViewList.qml \ No newline at end of file diff --git a/scripts/developer/utilities/render/engineInspector.qml b/scripts/developer/utilities/render/engineInspector.qml index 6461e5d834..1b9941e64e 100644 --- a/scripts/developer/utilities/render/engineInspector.qml +++ b/scripts/developer/utilities/render/engineInspector.qml @@ -20,10 +20,10 @@ Item { HifiConstants { id: hifi;} id: render; anchors.fill: parent - + property var mainViewTask: Render.getConfig("RenderMainView") - Jet.TaskList { + Jet.TaskListView { rootConfig: Render anchors.fill: render } From 5aab88be06edf0b56fe4b9c6dd690e73ded6b529 Mon Sep 17 00:00:00 2001 From: David Back Date: Wed, 9 May 2018 19:10:56 -0700 Subject: [PATCH 037/143] assert --- libraries/gpu/src/gpu/Buffer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/gpu/src/gpu/Buffer.cpp b/libraries/gpu/src/gpu/Buffer.cpp index fe3570e7f7..ebb768e597 100644 --- a/libraries/gpu/src/gpu/Buffer.cpp +++ b/libraries/gpu/src/gpu/Buffer.cpp @@ -99,7 +99,7 @@ Buffer::Update::Update(const Buffer& parent) : buffer(parent) { void Buffer::Update::apply() const { // Make sure we're loaded in order buffer._applyUpdateCount++; - //assert(buffer._applyUpdateCount == updateNumber); + assert(buffer._applyUpdateCount == updateNumber); const auto pageSize = buffer._pages._pageSize; buffer._renderSysmem.resize(size); From 399e18dfc16b779df23428cb1f1c3291d2024bee Mon Sep 17 00:00:00 2001 From: vladest Date: Thu, 10 May 2018 10:28:48 +0200 Subject: [PATCH 038/143] Disable non implemented sound notifications until further notice --- interface/src/Menu.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 33e185b954..b8fbfcd07f 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -285,6 +285,15 @@ Menu::Menu() { connect(action, &QAction::triggered, [action, settings] { settings->setValue(MenuOption::NotificationSoundsSnapshot, action->isChecked()); }); + // Settings > Notifications > Tablet + action = addCheckableActionToQMenuAndActionHash(notificationsMenu, "Tablet", 0, + settings->getValue(MenuOption::NotificationSoundsTablet).toBool()); + connect(action, &QAction::triggered, [action, settings] { + settings->setValue(MenuOption::NotificationSoundsTablet, action->isChecked()); + }); + + //Further sound notificaions disabled until new notification system will be implemented + /* // Settings > Notifications > Level of Detail action = addCheckableActionToQMenuAndActionHash(notificationsMenu, "Level of Detail", 0, settings->getValue("play_notification_sounds_type_1").toBool()); @@ -309,12 +318,6 @@ Menu::Menu() { connect(action, &QAction::triggered, [action, settings] { settings->setValue("play_notification_sounds_type_4", action->isChecked()); }); - // Settings > Notifications > Tablet - action = addCheckableActionToQMenuAndActionHash(notificationsMenu, "Tablet", 0, - settings->getValue(MenuOption::NotificationSoundsTablet).toBool()); - connect(action, &QAction::triggered, [action, settings] { - settings->setValue(MenuOption::NotificationSoundsTablet, action->isChecked()); - }); // Settings > Notifications > Wallet addActionToQMenuAndActionHash(notificationsMenu, "Wallet"); action = addCheckableActionToQMenuAndActionHash(notificationsMenu, "Wallet", 0, @@ -322,7 +325,7 @@ Menu::Menu() { connect(action, &QAction::triggered, [action, settings] { settings->setValue("play_notification_sounds_type_6", action->isChecked()); }); - +*/ // Settings > Developer Menu addCheckableActionToQMenuAndActionHash(settingsMenu, "Developer Menu", 0, false, this, SLOT(toggleDeveloperMenus())); From bf85034f3618d267f0187fe82ea05dbc6236a450 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 10 May 2018 02:08:19 -0700 Subject: [PATCH 039/143] Tree view comming together for the engine! --- scripts/developer/utilities/lib/jet/jet.js | 6 +- .../utilities/lib/jet/qml/TaskListView.qml | 90 +++++++++++++++---- 2 files changed, 76 insertions(+), 20 deletions(-) diff --git a/scripts/developer/utilities/lib/jet/jet.js b/scripts/developer/utilities/lib/jet/jet.js index 5bebb99068..18027ea4bd 100644 --- a/scripts/developer/utilities/lib/jet/jet.js +++ b/scripts/developer/utilities/lib/jet/jet.js @@ -12,15 +12,15 @@ // traverse task tree function task_traverse(root, functor, depth) { - // if (root.isTask()) { + if (root.isTask()) { depth++; for (var i = 0; i 0 ? "." : "") + node.get(jobTreePath[n]).name + node = node.get(jobTreePath[n]).subNode + } + node.append(newItem) + jobTreePath.push(0); + } else if (jobTreePath.length >= depth) { + var node = jobsRoot; + for (var n = 0; n < (depth - 1); n++) { + newItem.path += (n > 0 ? "." : "") + node.get(jobTreePath[n]).name + node = node.get(jobTreePath[n]).subNode + } + node.append(newItem) + jobTreePath[depth-1] = index; + while (jobTreePath.length > depth) { + jobTreePath.pop(); + } + } + } + return true; + } Jet.task_traverseTree(rootConfig, functor); - //print(JSON.stringify(root.myArray)) - // theView.model = root.myArray.length - for (var i = 0; i < root.myArray.length; i++) { - jobsModel.append({"on": true, "name": root.myArray[i]}) - } - // theView.model = root.myArray - } - - function getJobName(i) { - return root.myArray[i]; } ListModel { @@ -51,17 +77,47 @@ Rectangle { } Component { - id: itemDelegate - //HifiControls.Label { text: "I am item number: " + index } - HifiControls.CheckBox { text: name + index; - checked: true; } + id: objRecursiveDelegate + Column { + id: objRecursiveColumn + clip: true + visible: model.init + + MouseArea { + width: objRow.implicitWidth + height: objRow.implicitHeight + onDoubleClicked: { + for(var i = 1; i < parent.children.length - 1; ++i) { + parent.children[i].visible = !parent.children[i].visible + } + } + Row { + id: objRow + Item { + height: 1 + width: model.level * 15 + } + HifiControls.CheckBox { + property var config: root.rootConfig.getConfig(model.path + "." + model.name); + text: (objRecursiveColumn.children.length > 2 ? + objRecursiveColumn.children[1].visible ? + qsTr("- ") : qsTr("+ ") : qsTr(" ")) + model.name + " ms=" + config.cpuRunTime.toFixed(3) + checked: config.enabled + } + } + } + Repeater { + model: subNode + delegate: objRecursiveDelegate + } + } } ListView { id: theView anchors.fill: parent model: jobsModel - delegate: itemDelegate + delegate: objRecursiveDelegate } } \ No newline at end of file From a3f814816593148bf454633b2783fb8488a61ddb Mon Sep 17 00:00:00 2001 From: vladest Date: Thu, 10 May 2018 12:40:13 +0200 Subject: [PATCH 040/143] Added enable disable shadows menu --- interface/src/ui/PreferencesDialog.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 0ef2aa38a9..905991834d 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "Application.h" @@ -78,6 +79,29 @@ void setupPreferences() { auto getterSQ = []()->float { return 1.0; }; auto setterSQ = [](float value) { }; preferences->addPreference(new SliderPreference(GRAPHICS_QUALITY, "Shadow Quality", getterSQ, setterSQ)); + + auto getterShadow = []()->bool { + bool ret = false; + auto renderConfig = qApp->getRenderEngine()->getConfiguration(); + if (renderConfig) { + auto mainViewShadowTaskConfig = renderConfig->getConfig("RenderMainView.RenderShadowTask"); + if (mainViewShadowTaskConfig) { + ret = (mainViewShadowTaskConfig->getPreset() == QStringLiteral("Enabled")); + } + } + return ret; + }; + auto setterShadow = [](bool value) { + auto renderConfig = qApp->getRenderEngine()->getConfiguration(); + if (renderConfig) { + auto mainViewShadowTaskConfig = renderConfig->getConfig("RenderMainView.RenderShadowTask"); + if (mainViewShadowTaskConfig) { + mainViewShadowTaskConfig->setPreset(value ? QStringLiteral("Enabled") + : QStringLiteral("None")); + } + } + }; + preferences->addPreference(new CheckPreference(GRAPHICS_QUALITY, "Enable/disable shadows", getterShadow, setterShadow)); } // UI @@ -238,7 +262,6 @@ void setupPreferences() { auto setter = [=](bool value) { auto messagesClient = DependencyManager::get().data(); myAvatar->setUseAdvancedMovementControls(value); - qDebug() << "vladest movement" << value; if (value) { messagesClient->sendMessage(movementsControlChannel, QStringLiteral("enable_mappings"), true); } else { From 02be965271154c9b29dbdb3e60aaffdfe14431bf Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 10 May 2018 18:10:01 -0700 Subject: [PATCH 041/143] more stuff fixed --- .../src/procedural/ProceduralSkybox.cpp | 7 +++++- libraries/render/src/render/Engine.cpp | 3 +-- libraries/render/src/render/Engine.h | 14 ++++++----- libraries/task/src/task/Task.h | 2 +- .../utilities/lib/jet/qml/TaskListView.qml | 24 +++++++++---------- 5 files changed, 27 insertions(+), 23 deletions(-) diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.cpp b/libraries/procedural/src/procedural/ProceduralSkybox.cpp index 0c6501928b..806302d7ef 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.cpp +++ b/libraries/procedural/src/procedural/ProceduralSkybox.cpp @@ -21,6 +21,7 @@ ProceduralSkybox::ProceduralSkybox() : graphics::Skybox() { _procedural._vertexSource = skybox_vert::getSource(); _procedural._opaquefragmentSource = skybox_frag::getSource(); + _procedural._transparentfragmentSource = skybox_frag::getSource(); // Adjust the pipeline state for background using the stencil test _procedural.setDoesFade(false); // Must match PrepareStencil::STENCIL_BACKGROUND @@ -60,9 +61,13 @@ void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, batch.setModelTransform(Transform()); // only for Mac auto& procedural = skybox._procedural; - procedural.prepare(batch, glm::vec3(0), glm::vec3(1), glm::quat()); + +// procedural.prepare(batch, glm::vec3(0), glm::vec3(1), glm::quat()); + procedural.prepare(batch, glm::vec3(0), glm::vec3(1), glm::quat(), glm::vec4(glm::vec3(1.0f), 0.9)); + auto textureSlot = procedural.getOpaqueShader()->getTextures().findLocation("cubeMap"); auto bufferSlot = procedural.getOpaqueShader()->getUniformBuffers().findLocation("skyboxBuffer"); + skybox.prepare(batch, textureSlot, bufferSlot); batch.draw(gpu::TRIANGLE_STRIP, 4); } diff --git a/libraries/render/src/render/Engine.cpp b/libraries/render/src/render/Engine.cpp index b0842d63cd..de282bed9f 100644 --- a/libraries/render/src/render/Engine.cpp +++ b/libraries/render/src/render/Engine.cpp @@ -36,8 +36,7 @@ public: } }; -Engine::Engine() : Task(EngineTask::JobModel::create("Engine")), - _renderContext(std::make_shared()) +Engine::Engine() : _Engine(EngineTask::JobModel::create("Engine"), std::make_shared()) { } diff --git a/libraries/render/src/render/Engine.h b/libraries/render/src/render/Engine.h index f444416a3f..7a5f7b7ce8 100644 --- a/libraries/render/src/render/Engine.h +++ b/libraries/render/src/render/Engine.h @@ -82,7 +82,9 @@ namespace render { // The render engine holds all render tasks, and is itself a render task. // State flows through tasks to jobs via the render and scene contexts - // the engine should not be known from its jobs. - class Engine : public Task { + class Engine : public _Engine { + + //class Engine : public Task { public: Engine(); @@ -93,19 +95,19 @@ namespace render { void load(); // Register the scene - void registerScene(const ScenePointer& scene) { _renderContext->_scene = scene; } + void registerScene(const ScenePointer& scene) { _context->_scene = scene; } // acces the RenderContext - RenderContextPointer getRenderContext() const { return _renderContext; } + RenderContextPointer getRenderContext() const { return _context; } // Render a frame // Must have a scene registered and a context set - void run() { assert(_renderContext); Task::run(_renderContext); } + // void run() { assert(_renderContext); Task::run(_renderContext); } protected: - RenderContextPointer _renderContext; + // RenderContextPointer _renderContext; - void run(const RenderContextPointer& context) override { assert(_renderContext); Task::run(_renderContext); } + // void run(const RenderContextPointer& context) override { assert(_renderContext); Task::run(_renderContext); } }; using EnginePointer = std::shared_ptr; diff --git a/libraries/task/src/task/Task.h b/libraries/task/src/task/Task.h index c9a3285443..ef1ca60d57 100644 --- a/libraries/task/src/task/Task.h +++ b/libraries/task/src/task/Task.h @@ -379,7 +379,7 @@ public: using TaskType = Task; using ConceptPointer = typename TaskType::ConceptPointer; - Engine(ConceptPointer concept) : TaskType(concept) {} + Engine(const ConceptPointer& concept, const ContextPointer& context) : TaskType(concept), _context(context) {} ~Engine() = default; void reset(const ContextPointer& context) { _context = context; } diff --git a/scripts/developer/utilities/lib/jet/qml/TaskListView.qml b/scripts/developer/utilities/lib/jet/qml/TaskListView.qml index 998abdef0e..eff456d838 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskListView.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskListView.qml @@ -20,7 +20,7 @@ import "../jet.js" as Jet Rectangle { HifiConstants { id: hifi;} color: hifi.colors.baseGray; - id: root + id: root; // width: parent ? parent.width : 200 // height: parent ? parent.height : 400 @@ -29,11 +29,7 @@ Rectangle { Component.onCompleted: { var message = "" - // functor = Jet.job_print_functor(function (line) { message += line + "\n"; }, false); - - // functor = Jet.job_list_functor(root.myArray); - - var maxDepth = 4; + var maxDepth = 3; var jobTreePath = [] var jobsRoot; @@ -72,6 +68,7 @@ Rectangle { Jet.task_traverseTree(rootConfig, functor); } + ListModel { id: jobsModel } @@ -101,7 +98,7 @@ Rectangle { property var config: root.rootConfig.getConfig(model.path + "." + model.name); text: (objRecursiveColumn.children.length > 2 ? objRecursiveColumn.children[1].visible ? - qsTr("- ") : qsTr("+ ") : qsTr(" ")) + model.name + " ms=" + config.cpuRunTime.toFixed(3) + qsTr("- ") : qsTr("+ ") : qsTr(" ")) + model.name + " ms=" + config.cpuRunTime.toFixed(2) checked: config.enabled } } @@ -113,11 +110,12 @@ Rectangle { } } - ListView { - id: theView - anchors.fill: parent - model: jobsModel - delegate: objRecursiveDelegate + Original.ScrollView { + anchors.fill: parent + ListView { + id: theView + model: jobsModel + delegate: objRecursiveDelegate + } } - } \ No newline at end of file From a57c280813afc5478148db440e3ab1812a5efac0 Mon Sep 17 00:00:00 2001 From: David Back Date: Fri, 11 May 2018 17:54:08 -0700 Subject: [PATCH 042/143] convertToCloneProperties --- libraries/entities/src/EntityEditPacketSender.cpp | 4 ---- libraries/entities/src/EntityItemProperties.cpp | 11 +++++++++++ libraries/entities/src/EntityItemProperties.h | 2 ++ libraries/entities/src/EntityScriptingInterface.cpp | 1 + libraries/entities/src/EntityTree.cpp | 9 +-------- 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/libraries/entities/src/EntityEditPacketSender.cpp b/libraries/entities/src/EntityEditPacketSender.cpp index a33f9763e7..c2323b0a20 100644 --- a/libraries/entities/src/EntityEditPacketSender.cpp +++ b/libraries/entities/src/EntityEditPacketSender.cpp @@ -156,10 +156,6 @@ void EntityEditPacketSender::queueEraseEntityMessage(const EntityItemID& entityI } void EntityEditPacketSender::queueCloneEntityMessage(const EntityItemID& entityIDToClone, const EntityItemID& newEntityID) { - if (!_shouldSend) { - return; // bail early - } - QByteArray bufferOut(NLPacket::maxPayloadSize(PacketType::EntityClone), 0); if (EntityItemProperties::encodeCloneEntityMessage(entityIDToClone, newEntityID, bufferOut)) { diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 93c2eb885e..7c799a64e1 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -3633,3 +3633,14 @@ bool EntityItemProperties::verifyStaticCertificateProperties() { // I.e., if we can verify that the certificateID was produced by High Fidelity signing the static certificate hash. return verifySignature(EntityItem::_marketplacePublicKey, getStaticCertificateHash(), QByteArray::fromBase64(getCertificateID().toUtf8())); } + +void EntityItemProperties::convertToCloneProperties(const EntityItemID& entityIDToClone) { + setName(getName() + "-clone-" + entityIDToClone.toString()); + setLocked(false); + setLifetime(getCloneableLifetime()); + setDynamic(getCloneableDynamic()); + setCloneable(ENTITY_ITEM_CLONEABLE); + setCloneableLifetime(ENTITY_ITEM_CLONEABLE_LIFETIME); + setCloneableLimit(ENTITY_ITEM_CLONEABLE_LIMIT); + setCloneableDynamic(ENTITY_ITEM_CLONEABLE_DYNAMIC); +} \ No newline at end of file diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 3ae2186cab..12d4bdf919 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -376,6 +376,8 @@ public: bool verifyStaticCertificateProperties(); static bool verifySignature(const QString& key, const QByteArray& text, const QByteArray& signature); + void convertToCloneProperties(const EntityItemID& entityIDToClone); + protected: QString getCollisionMaskAsString() const; void setCollisionMaskFromString(const QString& maskString); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 7b7f35aa09..71e7d1c7c0 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -332,6 +332,7 @@ QUuid EntityScriptingInterface::addModelEntity(const QString& name, const QStrin QUuid EntityScriptingInterface::cloneEntity(QUuid entityIDToClone) { EntityItemID newEntityID; EntityItemProperties properties = getEntityProperties(entityIDToClone); + properties.convertToCloneProperties(entityIDToClone); if (addLocalEntityCopy(properties, newEntityID)) { getEntityPacketSender()->queueCloneEntityMessage(entityIDToClone, newEntityID); return newEntityID; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 20b3f81f42..bcea89232e 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1623,14 +1623,7 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c qCDebug(entities) << "User attempted to clone entity ID:" << entityIDToClone << " which reached it's cloneable limit."; } else { if (isClone) { - properties.setName(properties.getName() + "-clone-" + entityIDToClone.toString()); - properties.setLocked(false); - properties.setLifetime(properties.getCloneableLifetime()); - properties.setDynamic(properties.getCloneableDynamic()); - properties.setCloneable(ENTITY_ITEM_CLONEABLE); - properties.setCloneableLifetime(ENTITY_ITEM_CLONEABLE_LIFETIME); - properties.setCloneableLimit(ENTITY_ITEM_CLONEABLE_LIMIT); - properties.setCloneableDynamic(ENTITY_ITEM_CLONEABLE_DYNAMIC); + properties.convertToCloneProperties(entityIDToClone); } // this is a new entity... assign a new entityID From f8ebe7e6693f55ce502f66b2d5a656dc64b6e88c Mon Sep 17 00:00:00 2001 From: vladest Date: Sat, 12 May 2018 16:01:43 +0200 Subject: [PATCH 043/143] remoed no more used LOD dialogs. Fixed Slider properties min and max settings --- .../dialogs/preferences/SliderPreference.qml | 2 + .../qml/hifi/tablet/ControllerSettings.qml | 388 +++++++++--------- interface/src/Application.cpp | 14 - interface/src/Application.h | 2 - interface/src/LODManager.cpp | 5 +- interface/src/Menu.cpp | 4 - interface/src/Menu.h | 1 - interface/src/ui/DialogsManager.cpp | 11 - interface/src/ui/DialogsManager.h | 4 - interface/src/ui/HMDToolsDialog.cpp | 3 - interface/src/ui/LodToolsDialog.cpp | 133 ------ interface/src/ui/LodToolsDialog.h | 55 --- interface/src/ui/PreferencesDialog.cpp | 9 +- 13 files changed, 213 insertions(+), 418 deletions(-) delete mode 100644 interface/src/ui/LodToolsDialog.cpp delete mode 100644 interface/src/ui/LodToolsDialog.h diff --git a/interface/resources/qml/dialogs/preferences/SliderPreference.qml b/interface/resources/qml/dialogs/preferences/SliderPreference.qml index e9013bc17a..79c7149f3e 100644 --- a/interface/resources/qml/dialogs/preferences/SliderPreference.qml +++ b/interface/resources/qml/dialogs/preferences/SliderPreference.qml @@ -53,6 +53,8 @@ Preference { Slider { id: slider value: preference.value + minimumValue: preference.min + maximumValue: preference.max width: 130 anchors { right: parent.right diff --git a/interface/resources/qml/hifi/tablet/ControllerSettings.qml b/interface/resources/qml/hifi/tablet/ControllerSettings.qml index f134e280e6..4ee69c4982 100644 --- a/interface/resources/qml/hifi/tablet/ControllerSettings.qml +++ b/interface/resources/qml/hifi/tablet/ControllerSettings.qml @@ -14,218 +14,238 @@ import "../../styles-uit" import "../../controls" import "../../controls-uit" as HifiControls import "../../dialogs" +import "../../dialogs/preferences" -StackView { - id: stack - initialItem: inputConfiguration - property alias messageVisible: imageMessageBox.visible - property alias selectedPlugin: box.currentText - Rectangle { - id: inputConfiguration - anchors.fill: parent +PreferencesDialog { + id: root + objectName: "ControlSettings" + title: "Control Settings" + showCategories: ["VR Movement", inputConfigurationComponents] + property var settings: Settings { + category: root.objectName + property alias x: root.x + property alias y: root.y + property alias width: root.width + property alias height: root.height + } + Component { + id: inputConfigurationComponents - HifiConstants { id: hifi } + Preference { - color: hifi.colors.baseGray + StackView { + id: stack + initialItem: inputConfiguration + property alias messageVisible: imageMessageBox.visible + property alias selectedPlugin: box.currentText + Rectangle { + id: inputConfiguration + anchors.fill: parent - property var pluginSettings: null + HifiConstants { id: hifi } - HifiControls.ImageMessageBox { - id: imageMessageBox - anchors.fill: parent - z: 2000 - imageWidth: 442 - imageHeight: 670 - source: "../../../images/calibration-help.png" - } + color: hifi.colors.baseGray - Rectangle { - width: inputConfiguration.width - height: 1 - color: hifi.colors.baseGrayShadow - x: -hifi.dimensions.contentMargin.x - } + property var pluginSettings: null - RalewayRegular { - id: header - text: "Control Settings" - size: 22 - color: "white" + HifiControls.ImageMessageBox { + id: imageMessageBox + anchors.fill: parent + z: 2000 + imageWidth: 442 + imageHeight: 670 + source: "../../../images/calibration-help.png" + } - anchors.top: inputConfiguration.top - anchors.left: inputConfiguration.left - anchors.leftMargin: 20 - anchors.topMargin: 20 - } + Rectangle { + width: inputConfiguration.width + height: 1 + color: hifi.colors.baseGrayShadow + x: -hifi.dimensions.contentMargin.x + } + + RalewayRegular { + id: header + text: "Control Settings" + size: 22 + color: "white" + + anchors.top: inputConfiguration.top + anchors.left: inputConfiguration.left + anchors.leftMargin: 20 + anchors.topMargin: 20 + } + + Separator { + id: headerSeparator + width: inputConfiguration.width + anchors.top: header.bottom + anchors.topMargin: 10 + } + + HiFiGlyphs { + id: sourceGlyph + text: hifi.glyphs.source + size: 36 + color: hifi.colors.blueHighlight + + anchors.top: headerSeparator.bottom + anchors.left: inputConfiguration.left + anchors.leftMargin: 40 + anchors.topMargin: 20 + } + + RalewayRegular { + id: configuration + text: "SELECT DEVICE" + size: 15 + color: hifi.colors.lightGrayText - Separator { - id: headerSeparator - width: inputConfiguration.width - anchors.top: header.bottom - anchors.topMargin: 10 - } + anchors.top: headerSeparator.bottom + anchors.left: sourceGlyph.right + anchors.leftMargin: 10 + anchors.topMargin: 30 + } - HiFiGlyphs { - id: sourceGlyph - text: hifi.glyphs.source - size: 36 - color: hifi.colors.blueHighlight + Row { + id: configRow + z: 999 + anchors.top: sourceGlyph.bottom + anchors.topMargin: 20 + anchors.left: sourceGlyph.left + anchors.leftMargin: 40 + spacing: 10 + HifiControls.ComboBox { + id: box + width: 160 + z: 999 + editable: true + colorScheme: hifi.colorSchemes.dark + model: inputPlugins() + label: "" - anchors.top: headerSeparator.bottom - anchors.left: inputConfiguration.left - anchors.leftMargin: 40 - anchors.topMargin: 20 - } + onCurrentIndexChanged: { + changeSource(); + } + } - RalewayRegular { - id: configuration - text: "SELECT DEVICE" - size: 15 - color: hifi.colors.lightGrayText + HifiControls.CheckBox { + id: checkBox + colorScheme: hifi.colorSchemes.dark + text: "show all input devices" + + onClicked: { + inputPlugins(); + changeSource(); + } + } + } - anchors.top: headerSeparator.bottom - anchors.left: sourceGlyph.right - anchors.leftMargin: 10 - anchors.topMargin: 30 - } - - Row { - id: configRow - z: 999 - anchors.top: sourceGlyph.bottom - anchors.topMargin: 20 - anchors.left: sourceGlyph.left - anchors.leftMargin: 40 - spacing: 10 - HifiControls.ComboBox { - id: box - width: 160 - z: 999 - editable: true - colorScheme: hifi.colorSchemes.dark - model: inputPlugins() - label: "" - - onCurrentIndexChanged: { - changeSource(); - } - } - - HifiControls.CheckBox { - id: checkBox - colorScheme: hifi.colorSchemes.dark - text: "show all input devices" - - onClicked: { - inputPlugins(); - changeSource(); - } - } - } + Separator { + id: configurationSeparator + z: 0 + width: inputConfiguration.width + anchors.top: configRow.bottom + anchors.topMargin: 10 + } - Separator { - id: configurationSeparator - z: 0 - width: inputConfiguration.width - anchors.top: configRow.bottom - anchors.topMargin: 10 - } + HiFiGlyphs { + id: sliderGlyph + text: hifi.glyphs.sliders + size: 36 + color: hifi.colors.blueHighlight + + anchors.top: configurationSeparator.bottom + anchors.left: inputConfiguration.left + anchors.leftMargin: 40 + anchors.topMargin: 20 + } + + RalewayRegular { + id: configurationHeader + text: "CONFIGURATION" + size: 15 + color: hifi.colors.lightGrayText - HiFiGlyphs { - id: sliderGlyph - text: hifi.glyphs.sliders - size: 36 - color: hifi.colors.blueHighlight + anchors.top: configurationSeparator.bottom + anchors.left: sliderGlyph.right + anchors.leftMargin: 10 + anchors.topMargin: 30 + } - anchors.top: configurationSeparator.bottom - anchors.left: inputConfiguration.left - anchors.leftMargin: 40 - anchors.topMargin: 20 - } + Loader { + id: loader + asynchronous: false - RalewayRegular { - id: configurationHeader - text: "CONFIGURATION" - size: 15 - color: hifi.colors.lightGrayText + width: inputConfiguration.width + anchors.left: inputConfiguration.left + anchors.right: inputConfiguration.right + anchors.top: configurationHeader.bottom + anchors.topMargin: 10 + anchors.bottom: inputConfiguration.bottom + source: InputConfiguration.configurationLayout(box.currentText); + onLoaded: { + if (loader.item.hasOwnProperty("pluginName")) { + if (box.currentText === "Vive") { + loader.item.pluginName = "OpenVR"; + } else { + loader.item.pluginName = box.currentText; + } + } - anchors.top: configurationSeparator.bottom - anchors.left: sliderGlyph.right - anchors.leftMargin: 10 - anchors.topMargin: 30 - } - - Loader { - id: loader - asynchronous: false - - width: inputConfiguration.width - anchors.left: inputConfiguration.left - anchors.right: inputConfiguration.right - anchors.top: configurationHeader.bottom - anchors.topMargin: 10 - anchors.bottom: inputConfiguration.bottom - - source: InputConfiguration.configurationLayout(box.currentText); - onLoaded: { - if (loader.item.hasOwnProperty("pluginName")) { - if (box.currentText === "Vive") { - loader.item.pluginName = "OpenVR"; - } else { - loader.item.pluginName = box.currentText; + if (loader.item.hasOwnProperty("displayInformation")) { + loader.item.displayConfiguration(); + } + } } } - if (loader.item.hasOwnProperty("displayInformation")) { - loader.item.displayConfiguration(); + + function inputPlugins() { + if (checkBox.checked) { + return InputConfiguration.inputPlugins(); + } else { + return InputConfiguration.activeInputPlugins(); + } + } + + function initialize() { + changeSource(); + } + + function changeSource() { + loader.source = ""; + var source = ""; + if (box.currentText == "Vive") { + source = InputConfiguration.configurationLayout("OpenVR"); + } else { + source = InputConfiguration.configurationLayout(box.currentText); + } + + loader.source = source; + if (source === "") { + box.label = "(not configurable)"; + } else { + box.label = ""; + } + } + + Timer { + id: timer + repeat: false + interval: 300 + onTriggered: initialize() + } + + Component.onCompleted: { + timer.start(); } } } } - - - function inputPlugins() { - if (checkBox.checked) { - return InputConfiguration.inputPlugins(); - } else { - return InputConfiguration.activeInputPlugins(); - } - } - - function initialize() { - changeSource(); - } - - function changeSource() { - loader.source = ""; - var source = ""; - if (box.currentText == "Vive") { - source = InputConfiguration.configurationLayout("OpenVR"); - } else { - source = InputConfiguration.configurationLayout(box.currentText); - } - - loader.source = source; - if (source === "") { - box.label = "(not configurable)"; - } else { - box.label = ""; - } - } - - Timer { - id: timer - repeat: false - interval: 300 - onTriggered: initialize() - } - - Component.onCompleted: { - timer.start(); - } } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b57dd84d33..13dea71ba4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3690,8 +3690,6 @@ void Application::keyPressEvent(QKeyEvent* event) { Menu::getInstance()->triggerOption(MenuOption::Log); } else if (isMeta) { Menu::getInstance()->triggerOption(MenuOption::AddressBar); - } else if (isShifted) { - Menu::getInstance()->triggerOption(MenuOption::LodTools); } break; @@ -7509,18 +7507,6 @@ SharedSoundPointer Application::getSampleSound() const { return _sampleSound; } -void Application::loadLODToolsDialog() { - auto tabletScriptingInterface = DependencyManager::get(); - auto tablet = dynamic_cast(tabletScriptingInterface->getTablet(SYSTEM_TABLET)); - if (tablet->getToolbarMode() || (!tablet->getTabletRoot() && !isHMDMode())) { - auto dialogsManager = DependencyManager::get(); - dialogsManager->lodTools(); - } else { - tablet->pushOntoStack("hifi/dialogs/TabletLODTools.qml"); - } -} - - void Application::loadEntityStatisticsDialog() { auto tabletScriptingInterface = DependencyManager::get(); auto tablet = dynamic_cast(tabletScriptingInterface->getTablet(SYSTEM_TABLET)); diff --git a/interface/src/Application.h b/interface/src/Application.h index 4946dd7ad9..13c5056402 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -65,7 +65,6 @@ #include "scripting/DialogsManagerScriptingInterface.h" #include "ui/ApplicationOverlay.h" #include "ui/EntityScriptServerLogDialog.h" -#include "ui/LodToolsDialog.h" #include "ui/LogDialog.h" #include "ui/OctreeStatsDialog.h" #include "ui/OverlayConductor.h" @@ -403,7 +402,6 @@ public slots: void addAssetToWorldMessageClose(); - void loadLODToolsDialog(); void loadEntityStatisticsDialog(); void loadDomainConnectionDialog(); void showScriptLogs(); diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index d06ba14bcf..90318c2d30 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -122,10 +122,7 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { } if (oldOctreeSizeScale != _octreeSizeScale) { - auto lodToolsDialog = DependencyManager::get()->getLodToolsDialog(); - if (lodToolsDialog) { - lodToolsDialog->reloadSliders(); - } + //TODO: check Preferences dialog } } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index b8fbfcd07f..d60e59a1cb 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -469,10 +469,6 @@ Menu::Menu() { }); } - // Developer > Render > LOD Tools - addActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::LodTools, 0, - qApp, SLOT(loadLODToolsDialog())); - // HACK enable texture decimation { auto action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, "Decimate Textures"); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 86e44775c5..b8690d5b26 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -121,7 +121,6 @@ namespace MenuOption { const QString ActionMotorControl = "Enable Default Motor Control"; const QString LoadScript = "Open and Run Script File..."; const QString LoadScriptURL = "Open and Run Script from URL..."; - const QString LodTools = "LOD Tools"; const QString Login = "Login/Sign Up"; const QString Log = "Log"; const QString LogExtraTimings = "Log Extra Timing Details"; diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index d01e7d6671..05fc3e48ba 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -23,7 +23,6 @@ #include "ConnectionFailureDialog.h" #include "DomainConnectionDialog.h" #include "HMDToolsDialog.h" -#include "LodToolsDialog.h" #include "LoginDialog.h" #include "OctreeStatsDialog.h" #include "PreferencesDialog.h" @@ -126,16 +125,6 @@ void DialogsManager::octreeStatsDetails() { _octreeStatsDialog->raise(); } -void DialogsManager::lodTools() { - if (!_lodToolsDialog) { - maybeCreateDialog(_lodToolsDialog); - - connect(_lodToolsDialog, SIGNAL(closed()), _lodToolsDialog, SLOT(deleteLater())); - _lodToolsDialog->show(); - } - _lodToolsDialog->raise(); -} - void DialogsManager::hmdTools(bool showTools) { if (showTools) { if (!_hmdToolsDialog) { diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h index f17ac39a7e..c24f0fc4c0 100644 --- a/interface/src/ui/DialogsManager.h +++ b/interface/src/ui/DialogsManager.h @@ -22,7 +22,6 @@ class AnimationsDialog; class AttachmentsDialog; class CachesSizeDialog; -class LodToolsDialog; class OctreeStatsDialog; class ScriptEditorWindow; class TestingDialog; @@ -35,7 +34,6 @@ class DialogsManager : public QObject, public Dependency { public: QPointer getHMDToolsDialog() const { return _hmdToolsDialog; } - QPointer getLodToolsDialog() const { return _lodToolsDialog; } QPointer getOctreeStatsDialog() const { return _octreeStatsDialog; } QPointer getTestingDialog() const { return _testingDialog; } void emitAddressBarShown(bool visible) { emit addressBarShown(visible); } @@ -49,7 +47,6 @@ public slots: void toggleLoginDialog(); void showLoginDialog(); void octreeStatsDetails(); - void lodTools(); void hmdTools(bool showTools); void showDomainConnectionDialog(); void showTestingResults(); @@ -76,7 +73,6 @@ private: QPointer _cachesSizeDialog; QPointer _ircInfoBox; QPointer _hmdToolsDialog; - QPointer _lodToolsDialog; QPointer _octreeStatsDialog; QPointer _testingDialog; QPointer _domainConnectionDialog; diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index 63794da60f..d3ff239553 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -83,9 +83,6 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) : if (dialogsManager->getOctreeStatsDialog()) { watchWindow(dialogsManager->getOctreeStatsDialog()->windowHandle()); } - if (dialogsManager->getLodToolsDialog()) { - watchWindow(dialogsManager->getLodToolsDialog()->windowHandle()); - } connect(_switchModeButton, &QPushButton::clicked, [this]{ toggleHMDMode(); diff --git a/interface/src/ui/LodToolsDialog.cpp b/interface/src/ui/LodToolsDialog.cpp deleted file mode 100644 index 71e5293f30..0000000000 --- a/interface/src/ui/LodToolsDialog.cpp +++ /dev/null @@ -1,133 +0,0 @@ -// -// LodToolsDialog.cpp -// interface/src/ui -// -// Created by Brad Hefta-Gaub on 7/19/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "LodToolsDialog.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "Menu.h" - - -LodToolsDialog::LodToolsDialog(QWidget* parent) : - QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint) -{ - this->setWindowTitle("LOD Tools"); - auto lodManager = DependencyManager::get(); - - // Create layouter - QFormLayout* form = new QFormLayout(this); - - // Create a label with feedback... - _feedback = new QLabel(this); - QPalette palette = _feedback->palette(); - const unsigned redish = 0xfff00000; - palette.setColor(QPalette::WindowText, QColor::fromRgb(redish)); - _feedback->setPalette(palette); - _feedback->setText(lodManager->getLODFeedbackText()); - const int FEEDBACK_WIDTH = 350; - _feedback->setFixedWidth(FEEDBACK_WIDTH); - form->addRow("You can see... ", _feedback); - - form->addRow("Manually Adjust Level of Detail:", _manualLODAdjust = new QCheckBox(this)); - _manualLODAdjust->setChecked(!lodManager->getAutomaticLODAdjust()); - connect(_manualLODAdjust, SIGNAL(toggled(bool)), SLOT(updateAutomaticLODAdjust())); - - _lodSize = new QSlider(Qt::Horizontal, this); - const int MAX_LOD_SIZE = 2000; // ~20:4 vision -- really good. - const int MIN_LOD_SIZE = 5; // ~20:1600 vision -- really bad! - const int STEP_LOD_SIZE = 1; - const int PAGE_STEP_LOD_SIZE = 100; - const int SLIDER_WIDTH = 300; - _lodSize->setMaximum(MAX_LOD_SIZE); - _lodSize->setMinimum(MIN_LOD_SIZE); - _lodSize->setSingleStep(STEP_LOD_SIZE); - _lodSize->setTickInterval(PAGE_STEP_LOD_SIZE); - _lodSize->setTickPosition(QSlider::TicksBelow); - _lodSize->setFixedWidth(SLIDER_WIDTH); - _lodSize->setPageStep(PAGE_STEP_LOD_SIZE); - int sliderValue = lodManager->getOctreeSizeScale() / TREE_SCALE; - _lodSize->setValue(sliderValue); - form->addRow("Level of Detail:", _lodSize); - connect(_lodSize,SIGNAL(valueChanged(int)),this,SLOT(sizeScaleValueChanged(int))); - - // Add a button to reset - QPushButton* resetButton = new QPushButton("Reset", this); - form->addRow("", resetButton); - connect(resetButton, SIGNAL(clicked(bool)), this, SLOT(resetClicked(bool))); - - this->QDialog::setLayout(form); - - updateAutomaticLODAdjust(); -} - -void LodToolsDialog::reloadSliders() { - auto lodManager = DependencyManager::get(); - _lodSize->setValue(lodManager->getOctreeSizeScale() / TREE_SCALE); - _feedback->setText(lodManager->getLODFeedbackText()); -} - -void LodToolsDialog::updateAutomaticLODAdjust() { - auto lodManager = DependencyManager::get(); - lodManager->setAutomaticLODAdjust(!_manualLODAdjust->isChecked()); - _lodSize->setEnabled(_manualLODAdjust->isChecked()); -} - -void LodToolsDialog::sizeScaleValueChanged(int value) { - auto lodManager = DependencyManager::get(); - float realValue = value * TREE_SCALE; - lodManager->setOctreeSizeScale(realValue); - - _feedback->setText(lodManager->getLODFeedbackText()); -} - -void LodToolsDialog::resetClicked(bool checked) { - - int sliderValue = DEFAULT_OCTREE_SIZE_SCALE / TREE_SCALE; - _lodSize->setValue(sliderValue); - _manualLODAdjust->setChecked(false); - - updateAutomaticLODAdjust(); // tell our LOD manager about the reset -} - -void LodToolsDialog::reject() { - // Just regularly close upon ESC - this->QDialog::close(); -} - -void LodToolsDialog::closeEvent(QCloseEvent* event) { - this->QDialog::closeEvent(event); - emit closed(); - -#if RESET_TO_AUTOMATIC_WHEN_YOU_CLOSE_THE_DIALOG_BOX - auto lodManager = DependencyManager::get(); - - // always revert back to automatic LOD adjustment when closed - lodManager->setAutomaticLODAdjust(true); - - // if the user adjusted the LOD above "normal" then always revert back to default - if (lodManager->getOctreeSizeScale() > DEFAULT_OCTREE_SIZE_SCALE) { - lodManager->setOctreeSizeScale(DEFAULT_OCTREE_SIZE_SCALE); - } -#endif -} - - diff --git a/interface/src/ui/LodToolsDialog.h b/interface/src/ui/LodToolsDialog.h deleted file mode 100644 index b2390a1cd7..0000000000 --- a/interface/src/ui/LodToolsDialog.h +++ /dev/null @@ -1,55 +0,0 @@ -// -// LodToolsDialog.h -// interface/src/ui -// -// Created by Brad Hefta-Gaub on 7/19/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_LodToolsDialog_h -#define hifi_LodToolsDialog_h - -#include - -class QCheckBox; -class QDoubleSpinBox; -class QLabel; -class QSlider; - -class LodToolsDialog : public QDialog { - Q_OBJECT -public: - // Sets up the UI - LodToolsDialog(QWidget* parent); - -signals: - void closed(); - -public slots: - void reject() override; - void sizeScaleValueChanged(int value); - void resetClicked(bool checked); - void reloadSliders(); - void updateAutomaticLODAdjust(); - -protected: - - // Emits a 'closed' signal when this dialog is closed. - void closeEvent(QCloseEvent* event) override; - -private: - QSlider* _lodSize; - - QCheckBox* _manualLODAdjust; - - QDoubleSpinBox* _desktopLODDecreaseFPS; - - QDoubleSpinBox* _hmdLODDecreaseFPS; - - QLabel* _feedback; -}; - -#endif // hifi_LodToolsDialog_h diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 905991834d..a1b2c93adc 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -73,9 +73,12 @@ void setupPreferences() { // Graphics quality static const QString GRAPHICS_QUALITY { "Graphics Quality" }; { - auto getter = []()->float { return DependencyManager::get()->getLODLevel(); }; - auto setter = [](float value) { }; - preferences->addPreference(new SliderPreference(GRAPHICS_QUALITY, "World Detail", getter, setter)); + auto getter = []()->float { return DependencyManager::get()->getOctreeSizeScale()/TREE_SCALE; }; + auto setter = [](float value) { DependencyManager::get()->setOctreeSizeScale(value*TREE_SCALE); }; + auto wodSlider = new SliderPreference(GRAPHICS_QUALITY, "World Detail", getter, setter); + wodSlider->setMin(0); + wodSlider->setMax(2000); + preferences->addPreference(wodSlider); auto getterSQ = []()->float { return 1.0; }; auto setterSQ = [](float value) { }; preferences->addPreference(new SliderPreference(GRAPHICS_QUALITY, "Shadow Quality", getterSQ, setterSQ)); From 2a3004079e1a76926434f18f674d5ffdf0b15f6b Mon Sep 17 00:00:00 2001 From: vladest Date: Mon, 14 May 2018 23:22:06 +0200 Subject: [PATCH 044/143] About UI --- .../resources/images/about-highfidelity.png | Bin 0 -> 9935 bytes interface/resources/images/about-physics.png | Bin 0 -> 7895 bytes interface/resources/images/about-qt.png | Bin 0 -> 6170 bytes .../qml/hifi/dialogs/AboutDialog.qml | 32 +++++ .../qml/hifi/dialogs/TabletAboutDialog.qml | 120 ++++++++++++++++++ interface/src/Menu.cpp | 8 +- 6 files changed, 157 insertions(+), 3 deletions(-) create mode 100644 interface/resources/images/about-highfidelity.png create mode 100644 interface/resources/images/about-physics.png create mode 100644 interface/resources/images/about-qt.png create mode 100644 interface/resources/qml/hifi/dialogs/AboutDialog.qml create mode 100644 interface/resources/qml/hifi/dialogs/TabletAboutDialog.qml diff --git a/interface/resources/images/about-highfidelity.png b/interface/resources/images/about-highfidelity.png new file mode 100644 index 0000000000000000000000000000000000000000..718ed7d52547343ffd4be35e698017abc1bdecb2 GIT binary patch literal 9935 zcmV;=CNSBFP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3*tawIv9h5z#ueFQE5K^}*z+1y}`-yf(bC*GymlnUizFt$5_w#+__4zIR zdOXPdyeV_2@LIn9TF=*O8XVUjZ!q~BpT8atwm#Qsp9`h$3%{@8cg{Z!x6g%2{v7}O zJ@n5n)Fc`fH2tH%Nef_TXi-ts zs-{i5j#{czt+iTpt{PTMOs$$(vu>l62A8$kthLtL=(!iBziY4Edh5N9!A%EO9=v;S z#uzitGG*$l(`K7}js<*{EM0ZkYOAlY^Dbe-1G{e9ZTCG+IzZ{j(Nm9|cKR6?sNHhq z>aEvqyZw&uu6?@tYuA47+&_0MeY%!kqe|e1eRqw+W`A8GIi0BYjE-eVblkiH06Kfm zVoM^~J2#n{5PN1SG_y+e=IrDhql0o%)||2obf9hNQy>r1^_y5tk;H~?u zbARvKAG)?(|JLi+o5Jvl8Vlpc31?L9s{P!`9y9D{ogE%lU$X2{_o1eTdzF?!{La!= zQi)eX(KAYAAV$3nlBzb>Tt=afG@9SeST>n{mSlI?>6^-|QpVb|o}F|~3ZKGm$4fTa zQlnEkp+H9GHiO|NE81hOQ};>-daJ@MFKZM#Y@+~bPH%BaSTPst>_YdwP6$(AbiZmF zP$G5GbJJ#h+WtkQTDEEL*r#XKY%2Sbe1EtYt`Ra!$_zbjqwEr}wn+ z8+yyCeV1bp0mF07)v~tA2t#e`vnFJ6cD7q<89EODDidE&MlZ2xI{ScUwz#=ex%95Q z7LCEyZIvDr8CZK1ico9nG=2@SavD{YbcYy!E&BQ9wf)vsh)fTbZ+csKq+{GE!j6yx5w@vGcJXXni7AVbKS?lo(e)Dtdk>m)2nEv>HtZl;V(w`>BK8B05N zECoZN3)q}9x%&}GqWp(ep3tJczs3LZHT>-#(q4C!wqcA4$lHblw6tjne3yO-j6?^J zzjSw<(U$6fY8mLUg&tQRPi5w8Qp;^(41{dc2?6a)VQ-v=F_U^AE-uPE+*ae_eJUp~ z@~?7NPpb^#S(mXoU2IVJi|5pM>uyjyymNQA#mo#k%{!_|IdN}D4;t}HaQ#Jr)sR25 zFVoo4P{_+V8Ijg#|C-i8$u4U|Wq!CL_G2$?ksXJ=Y$&*D$%lmzJl*^^y_W3yD(9qq z>9$hiu5=H+f(a%KoCj71e^w#3V-Zi&Dd(dI=2u!?TR#9sMwU`BE3AVn}!T0|%V0cMb^rvIA`1yy32P(pOc)f9_P7 zi@DcImKjEbgCgH|hKB<<0>+~fLgnDW)95i&7TmsYV|W5F+gKMe&QaY>GAHydn8|MQ z9^_#T*osBSNYF6b*8+?LvZy=g0fuWVxd&bVoofATUMBpXZ^Oi1_n&Q~Qz|~-jJ?L7 zpKReIb|@e=w=j8^-i&hb4z!n5Ay_6fUG3D~`2+8IeKk2R>;e1>V|)C*cKdV|-eJ!( z`>J$U&fJd7th2+n$}-~9BXo%R5A*~f9g7yXs>&5~KUP|cC5IdPqS5n~GSj;@lIwDS z3?rH_*rEHDwDrh>8638>fh{B~6QPM5v%LezPqk1oM8C~kZJ_#~b6W)wy3sxWi2 zikEv$t?fCP*_u|hJRQi2^T!5!4F`6hm%GuN2ZIRBT`|PwCiH%zv$UB(F^mbdx{wRL zpkf?E8Cp8az3mL^X?5Q1ybxKY8;M~Ni-36nsxkoiW_lOGA2a0aG9S}J{K{dnZox=o zP?-QDXm$V>fy(q?eJBBrP!deNoa2^(B-H6R+IVj>?1{AiD6lhFiM?B47}>Yih#qTV zL4ZizFrB@p9MEcF~ z{64N}9mCgJ6$iq?3iOcJdpt}WV%9F>urVZv*8&6A=-5Q@7}(7ywIQj2C}zgtr`yg=zD8ss;Aeo~B{f%d`gcGZ3{Y5Lt;`kxT#$bT`hIIl z$b#2&u;TfUWOc3Q+9)UVk{B8%I~I)VLR6Vne1^7Dw9@`cG6esNW3XDDn-Rn5uvwP) zMY_DM4rxi6s4%A@E*7Res#shO}g;03i7Sq942-M9d7z6yMWNvA=jfFl+J zWzp+GudpkZiJ(|~YeQTkfFGI)!n1L=s4sd)2@nR5v=9ITm$HMQPi3@=7q6j?dmZ;o6!pyUb5L=vrsDV#z%hg8_Uf z1td?#VPqCcZ#gu^K-nY80#6uG3dHa1N|+j>FWw>p8Usi7T3%zFbPA1~@9(tOzEosf z5f`?8>yzW^)-C3Rpq=7@g*h_#BnpJ{?faa;4%#rf&tia7JyaPcz< z6OKv5dE_KmL!t{y-;|D;;(z!T{0P84ZDWt|(&F%UQX#%10t$d!5H$0SF>r=-duh%J z1Tl6E7wu7DoaSCw!89owoF(>FnSO@8UJyy`B@K+`$hb_B7bYXiG~V8n%(rBI4a!xI zNtjiBk|043)`I{D{f+@tHins*#4hM@2Lg>Drr}B=oMgY#iVl zN&twKxZpE`nHY*HcbFJwl_6l}Ip2yB<$ z7jFG}hG7ku38M#q8Se!H^{eSA*{Xs4Ly{SOh`GiAGG~ONrB6{9kSb zV{~#N95M?T&_O5a+?|}v7xtL_!|l@2x!r{ln}K)1QdOs#R#^vDiUWC}Zj-?Sbl6G& zPm2!SlQnT{87f-{SB7RWSWsd21R(B}v0hXe`kJVD+ZCulFHGy0HO<~zh9599$V!l0pS6%UbkpB=`w zbQHIEt}NUEFi!6bxea?Yyt!}zNGdGB-82ro z&=m7tBgrT&7cSVUuUaa0RxU2$RloW>qu9{*nlLf@!Q-50Hj+sjd^xb2IxhWh>ri8KX55@$^z;P5PihcC2WS* zFwq>QhijhI$ZmiD&jjkJXl06Mmj?%~Qlzg+X z7)Lw>(H|qr0B$(6$JE^QcoWUI?bI;Jc;?N6s%LDH==o;=~!XI>`Ld&qq zB4&}Ux@R)1)L0D6-q4vpnBdrjgArVJ*bJlcX0A%=f$zmYDGtL=xp^RvlVTY40UHM* z9&xc1^a`gYsQfzInr&mlAv=6sVG9UCu7Irha|mc^+!EA%2{KGHahpeXJcYqFJz=!S zEbh!14en0}eXM5w$riGF!4XJtjNAdU zT~T@s3qQnWZii?5@gzflK1EJMO~`5sHS&CuFmh=?eoWKGZYO!8-M1~wDCy{WOhrE~ z?nhXEuFowHZu|kkVKv>>1z#=uy|otwba z&7Xn{^cGXGNfdCk2yKRsS$r){PWV&|Wk3lGMWz2(rkA4CgGu+NFyham2HgPM4H=XS zJ#T)e{K{zZCe>A*KW}))y1~sVR2-bo?6r36c$%0^9-2 ziFp>b&V_I03!WdGcKvY{ERVfM$t#es=@9G|8LSDhkh?e742Uy)VegUCA9IGQGwcEa z(EY}ZFx3n=@!BvU723d%FAc~V8qIV$me~f4p~H!IPuhbPSs$~51a06s*&=ZeE5iCy z_u(XaH1BuVPYNMTz`~@$SeI)9a5o%etE%V=867|FL7=e+_^?NRu7~L{a;L!X7Q6gWCn9EKmcPm3a zmJ<R~0(0&M)hm?gAQnqp~Z}Q$c^xR@rw+1#=%I& zhKVAmo6JhOZvLSJZayJEB~^KknoOTYOb^%C`<4CE0D$O&j;9j@a`TEjOcV!43NRHs z(~=usXkq~1P<&S<2{9TNP!filWm-6@v+?sj0cIj^0yCx(i^3`iTzWl0Kas-8(_beC zw3s0U_zdk*^o~r1ejR12cLq-YoQ=%cU*^*FE;)7JuOMp}vqz~ONYm>6_}_V>Y=30s z;%?;sJOi{`-J~2(7*1w@jR=yqk?1(??8w{w5lD^au{0xzG8l}^e9?pp_uWt>ed~L| zN@D&fPa&FP1{r^Yc-S=GW;0`Hhq>cwc`#CB2CzE{$vyZ}+9TJDLRLU@p;@LpiQhF5 zHT;>ff8^p%YS9@K1pe_{4VU-0hGVs2{a^rGA2Umkf!-J$p9ueW3%G9VIzpK+4FaE# z!ISGe%Yy$$X3eMe=AW?kkRP&Ul>>9SZ*T)mc*v9=B{EMQ-B}77h-~6!DN4sRdw%z{ z;wc=?3jRnX`sYsU`69a{!|k8=82X77JD$#+-8u$F)elA37;=Uf(R_cHFlgBHm{rX~ zxyKxHljEPaBlhs^X|4(c_;cPTi1;j6GGmzSeegrY{8J*_;TXu#P;4vt39rr~#T6XK z<1xy~7%@86KT1Sh88L$mIMe?Z9$3@==MLmc2?xO+sIkQD{})4Z?}i7(Lu_1kzqt_v z1Y@+4Kdafu2k61CVgv|Z=E0wQ0uWL-gog?v<5;#9_wZ`YH^N{84MG`yIulI@pqNYq zcDb)#{xR$!d_X9dpCiu^0D5+lXOM7p6=hvp zG9mZjw!V*`K{;&JM$3q7!lXH4HveFa6bS@NOM%eipI2!f<#?dRj6t0_dcfjsawYn2 zSigUM4gcwcKfGSJq=$b48(uf`KhB0|00006VoOIv0RI600RN!9r;`8x010qNS#tmY zE+YT{E+YYWr9XB6000McNliru;sp*A6$W~qpyvPp5$H)oK~#9!?VWp+6xE%_Kh-=G zU)+KCKtYL$K)}t3Xmle+%_=NAcYNfaQSkwZC>l3G)TqQY5{-}LWKE0)5Je)2(MV#L znz*`AS4G4XG>Wbu!XgU3z`lqK=sfQJajQdhO?6LqPj}Nj^ZT4L=S<(*Rdw&Js&C)d z@Am^i5ClOG1fjTiJG}&cG67y6U?9*3*aPSRv;bcKn}H3$`)IXYZkZs6V3kpzOh4cR z;9J0v!0PWdrVQ`~upBo}wI0|4YzMjl zy8&MT2H@tn4hIIeQ|_(6OyCx@+9bDF5Ja#t3DscW4q#M0}a4aSo;=rHLZDG zqc<=T7!8~b^v@!OHvo6aJeMGdVC|s6bjNaKAP~F6d}C$M>v<5ZJ}Fx1>rDcWk-$XY zj11Ra3XDgqH|2HE(l#xuzWKTSODx3$ypCvjkWWstFdLRk#G6~x8YVLqxHKFxCE`fkXtVZT}iNf zb0%a(3%Gq*x{4{%^4=UL!XwAw7UUl6*2VEJYOZVN%TP^tkYpw(j) zQ#&_7KL_}3Bxe~g3avhsM?erdvtaq=JYX*A`>Iv~8m-=`$XfblDsWSzzRQ5`?DU?X zAP6NAEZ>X)76RQvsf&TSitnxX=G>sS)gzSp3@}FKv;?8E36^h$0xtr+L#fXLwP>{^ zhvSC;KL&;Z9|E({>Zvk|)>vSEM6~9h)eq!R5QNSmSiadEcsUT86t4g$<}{@8&GEor za68viSYQfT{i@8OH4c~;sryA}HCrABLFgQUbq^5kg}e_OjaD0SIJO(k%fi5z+-Be~ zwEDj?i`I2G)1efNzzDQjA&-P0R4$1eUhXjwvHB7io0C{MzLr6(z|Dn?E`PP{FMvOV z5_SXbqdu9CM?w&)Rj_>13%DzidL3H5l*cu8?O=ZK(KR*@;rBwR$KZLF$Ri;Ll}q<_ z@~;5C8v48#%P;f1#&X;qEtMhv`Ml2N><7;R{sriXTcwt!_c*?b7(v zEP1CDSgv)zj8Mv+z(w+C2txJru+GLsut_l&tv;-P@@Df5qdIWjU*c9jQ(S^?Jb63> zp*jR>eCU4*{JKKQ``=mep6NjEZv*g1DCIyhdrcJtp<)EfHwWTe5T|$+t=_JX^8N-` z7n9yd;d59iqC4HslE*_3DvP*n4bgd`2P>wuT5ZBN$Km{3ogAdT3S5jiJF)*Ffo z3~~UlKhCCdE3h{BAy|f1@3lF0VKPC&i`JzXtrlmz-ohloF^R}Md@iqc^vySL^NRUl z`5SeC*_g9qjXIfp9j#0r*VzVqjtl6!CC9S=Bk6Xlxw0Cq)(7Y42Mmhje}Go2@@&T= zNjHrHSd3Q9LH=N1-y*!FE79sBd~*zL+fkVJ+O=x&&7QzFBB@Pi^T;LTdP{}%^z_F+Tfz~d=pqw;2C$tISUN4ArOmfM34E5bc6H5 zW4`m(P z`~VFD{x|saZ@@W`Z=4jAFW>95;+vH?ONp7W0v~G4tZkH;vw`0S|JMPtBKfm$uE6tQ z9xx=5))z>5S^0P1lp?&Lrv{qwJz#PqZw2+qVeJH-nTlJv4|503@j~R+ufcSW3l z;kbo}gY!Ic9o_7PD!-2(qE%xVuCps}GoE)h^+ol#U0x&nhNMSZSK@`THW&#R;QE;S z>+ww{3!Cd>hOO6yEl;8cM(0LeE>RQhj&Js=IB%a?eU5LI1OE`D46jbH+S~)|!;v4K z6kC8rz^Y(4;NiB590D8xyu_G_k1VvD^ld0{`NiN(T*RdWuwO986SuN{A)Z|X{4R%c zK8mv%$wV{Ome(}QdV7b4&r$l2Zk`9QF+(qKW7-de$K6;i1%`#bGYB{j7Z4`=13L(~ zFmk@vi7bXi1#5WB4J!o$fOqlD4B*#j^-%@A3~z)4>rfiZF4R_=M^bw(&Pzs=+kxxR z>hsvc>XYDkyH|eo>?zdMtS!Tp#{S*qkZYU0aa(?-(KeLaFK93iQX5QSXD<7B)YWXS zupjD=fg>~Y)W-o2L{k5VRu{K>-dfd+Z>GddwOmJi@&W2 zN?*#ZsRFJA*5aEP_~zgWxqa_MhRKIiVIOOJOxirOnvzkh0P1Q$tE~u`+U66qnoj(d zmjkdF7CyQ%P4-D#r1vlf<9XvlqBsIKNgrkbP4?;N>7s&lXz2e<)YX(K#CuC*9$*q~ z0`s9@qIhTWe&qAMRrP>0m|n!sz1<{lPtjh&g}~D>Imb)mL~wzNuLPPRIX}hU+><{g z0d6LJ_1HN~hzWWe6|C@_M=2*>SK;;pJ&Ie=0T(jtEMO_Vc>>>@xRaXrqnMsx6^#ZN zO#J?rx8?0A>Pz_Nn4GUmDZ(as&#oEW(*}G9pqV+E3oK7!%b4H2Fe^^XfDa5Kr4s|Jw z2UpMg9=_R_dO+hbKLyy-Z_+gG`?xd@{KnFgZ$3MG~is)_oYpZ8PR+Y^ti}H zu)GYzwo(e$D&S&#a|3Rp*`!cU?=g{i094Y}ba+aCcQ!8fCDKG#nw;T8KwJ{NOS>&IyIwXEOpO-F|_tvU3hL92$S+|qqs_dWUM z9Cpm53=DR?-i%gF710vT2YWb3>qg*zs`S482IuOzcO-oZFd5&h#ckL466eQ!kZ4mZ zi^y%w_6uM#bvgJE^Sre=tOQ?yR`avupO5AIcFwVy=mJuw8xlIAMxEn|AXb;+f?1>t ziFd`hJ)KKKvNBr21&kOFE_J~HC@N!EcnQS5ZV8+h(j#zQ9fnbgtp{C)FM$it>XjV7 zzc0=iV79+vI38Ht85=upf6h9bN6Hk(C5TTMVD>YdT|tXWHF7mmR?;GR`=tZzXF#7-^H0bW!ib(g4;N}6c-UD-*RQD zOGm8|T5`NrzUQ!cUZ)kara3#|XDBDG^{fzNTi=WOkW zU_FEj`;&47F&^LCSYWvNZ5_-n2UkRfMKjQ6K2XS;>;fC6`kSP4S4 z36@)FnjT8&2F#@1E{B+q1Byvp6N2;y&2R{h|h9oOdSsFxG5M4 z3xZIAcPBz!*R)e5=0IuKW+l~pEBeo(W*}#=c>V(A`M6rM6K?U$3hUQZ%7DQ zZKLh#;7$1E=$%yFZ3X5<#473GCNjffwFGNt$Ri;L)hbv{v>qpYm7*u`D8A{p6UzIS zEO`xibS!@goE}PO1SXU*(1jofB@rygk4g8%+#m4q&0b|L?>#tglTp@?zM`3JC^!xm zWj4&^e~<7h2tvh@yZc(-34|gTr*Xj&UI3<}RWgTT#{%<7 z53(=^t$rYnf*^Dz!E!JB7+@jk8%`GkbrruA!1b)|i-^@Tz?d?G4if~Sj6*_)o6q__ z>D%bP1uVulm1`O9o2kIOh*&KHP7|>bgwEQ-+93cFfZ3$Sz%#%Ew0f*!YUi8Yz#P&y znx@2Rlxz?cgsvc1P7KZj?#Bh*Okr^=ic`uuuN7aulY+8DT?0P{oPt)H<@O6gR}m~H z3L}99w2jKL9=IB7=cgHRmPe@i1GfQZ$JB2w&hAi#fr8NG1Z#&t%*XjdkMb&T1D^G% zE%6>F-|UAAwmJ#g#EjbxOs2`s;`AE1>w?f_1q-0TbjNZP@UzGeF~tgC7VuzE{fXC` z1RlrY{A{0*;o3`q@o4p?+-^Y-!3y_s2IIUujLPthW}NYJ1Mn2qzLodxayOAa5*IMy zblOI0PGN9vnD0cZ7P-}eAcB=iR7L|g(tcb+gNyyQ9OuV+J7{vTh+@j0DzZS(*D N002ovPDHLkV1h~k?JfWS literal 0 HcmV?d00001 diff --git a/interface/resources/images/about-physics.png b/interface/resources/images/about-physics.png new file mode 100644 index 0000000000000000000000000000000000000000..62a7666da2ee541122eda1fdca3c70e9d89e5124 GIT binary patch literal 7895 zcmV;|9w_07P) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3*bavV7pMgOsiSpvLS4s68iV3t4UB9lc)t?rI7 zq(oE9OaRYZ1C-hS`sXqK;3JimO-!Zcmb2v}w%B~I-3sD#I+261H_2(Fx z&z$XNw4Z{Q&hKMr_j^TnUjKej{(S#AR`2UB{qlPF4DWxM5kYhB$o|I})#j4@@#BXW zp0nyX`(A8fkC~9=cTrzUygzZ_Af(~mmia9FPyAf&XXCTlZYPsi#!fr8f3J zIj;1Mhq;@<_tX6N%m4EEhX4v$oz;4I$h>_fPZ3X4o@GbEf?b9l*toH$gh_Mrsae)lj>_T$c+2Vb1jyP8G z)0w%a?1wYcxs?23mg5IMd9t%sSib%dcP-II!|6tFE^CcAHY#ai^Vk*>$(w z52bd(i6@j>#)t|HWYv%qsYwpdOzljQlFXfXpUM}V95l(QDlru8sqa))* z8K9uOa%QWG(JOO% z=8RJJOXmKVx8G!KiN@y5*zH1dgK7iq#|67~KhgoGEcd3iA~8#O@~Aj`87nyjYJTE_URTxodj)3hp zrQ5#Gi1E~vitCI>t8SLsonJLBpZ8k%_|@8)t!8g?f#8n5_fq;^K{uO{m<$Xyrt73@ z&2_?DcJHMacb7tAzGOSu0s^PL2cHZ{Bxa*9rys-bWAaHWq|@BqR2xg|dyhVNVWv|f zj1G#~+P6B2Sm#EZ$DGy9z$!^kox`_jcH!ZBpFPsjOMWKD-#0}alb^9&O6_HpaLDIk z{c$hnH}yo%jM?%Ec_!146{*&=iSI6bQE;9$4#$H-uN!XY<)kcnn4XMnttaJJM>vAo z=5vE(3?x*>8RXhAU1H7pX@=q^Nl0ZzT72hln8P4_eMCm{G4k`ElZVa6hTN-3{C(!a z;yS`B#??C&LCQ$opi(?N#0+WVsn4o%S?AOoW;vywu==8ChRHBgEIf$30>72A8;Lo3 zs*s{{X~S^CQ}`r$4+;UAruOUVp|-Lo!!3WhacylM7=ih8zuR$CKua^8-pGlsb;73$ z&g}y8wPpxfw_9PXLR?x8o2EpuMW4nZu+$vtXN{;jLM9RA9Xw6H?b(UODY=mgMxQ+l zNS8DfR_YjVquAV8r0LXpW@rS*&qtG(6@DEFl4G~Li5zS zafyoL{~7dH8ou}9(_C@Tb=-hl=!#j-#J?AA9Y7YV?+3_PR19d+2E4Wk_%~0YY&fI>4LQYS-(Nn(dLz*M}SOE5kI%eY$gjl^Nz<3mo7e1tiZvthg$(>lBZHUv?Qye za?oOjz6NX4sLewxG0kb1*Fn;ei$qaV3WH$)A4&$;FLsfcK^BJV$q^6Go*V-?$Jr6r zqD%4u4h+RU3ee$W&nb*1(TTQEBSbjF9@6ii!(C8=t}?gc>;zR#5DJDuqxM*;>2CF@ z#-nU9I)^TW;2gB!2;8D`8Qel#)2_(iz9w3WmO3P3x;D-j>fju!piK+I`NQmzO zkJ#oVYUV|+^s%;s#5&Bi>7QfvB3(iCHK-8qa)2w$thHHk*pxVo8N!6s)%Ov+1v2Sl zZrLQD!A78BG2ksJ-}HPbk+>3L2!=YyG%UrGG;vZl@dtqrgOP(WPsh85>?yQOl|tDf zeg_lHQws|qtwoT~Q3EFfVvNwr8Iy`0%(tCEmS98ph<2uo6U)mi&96eh3)PfMbl=ra zphQn~6Nj>tz`O___5e~K)Fq$3(wK`iSq%7R%sE6aBiXz2q-)r?{wy*3{Wqdn8DzQh+jISIq13jPtJ{Y@Q`iT z-XJk-rdli!OH{b9^mJI1>e#gMF0c%cUc^UvNU$`TrB2rEfE~KB5qDH=b+Cn)nBrSV zDLOqxYLtRcKnO}=lY>pyQ(h<&3IdoxPS%wQcwuL@Fsea7Kr6s{9F`VGbSzI{hwUgf zq+DIG2~XkG31lcU<8D~WKlq^1O>$QhU`TfFkNOw zF;WfFBfP;piWJzo3d0$N1APTEAKWY!YN3!4yjZ=Xk{e7;Gfv?ntX3VR!_^hF1v(5mFM91aPkNqnoPfXza| zF)+ZQh2Rq)3T8n`0Su@e0$rh3S}X(IjztF4RN7$<0}a!(qV1#1gwPpbDOO9n8=4AY zOY^BfZ?yWUTdD2)nr$}}H5vGgpZX2l?%@U;&4(dt%l+wJ%A`=?CyklzBMoQ-8)ZZ> zy+&^9299`8nX$*!vPyc&ilEMmNE4Dw2j~+Av1ZC3Wt~qj2~r5PpZ3 z^k6ETI-uf>N~LI^P0`*0nD$Ba6V6^)~k_R5HTT} zDljuK&5z0j9vyDF$u0DJ9f;!TA=HlMgH8c-IG+Ap25=4yRRDqq$;6tvdK5_#KsYMS zqyABFkbF@cA}KU)YRul5OM~33H4oQQtMrkR{Fe^{kwrDAq>-?xNe%|h0Fb$vT@;zq zUmzp>fX~6!_(5fZz{t#XCzd=ifYPR2EY}qb8v-eUxWPui0Jcg58P7cCO|Xq#t)-2q zJF%JGW^ME!Gh~HNcQu?lH})>ylZV8b6cSX~7lI+9H^k3F(D+CIqPzv<2zMt<%+xN-lIYOKZI91rcPzDc zZKmA*7GOH?3} zjY*B8I5CXniVKg&d^`p973RzRv>gtzu7jr9lVT)m3t6kBvJM{5sIi&x`KLfZ)LKz& zN_MG*-1-uIFl9b_s!6goEOhTSxFLLTPTF4e!8M(V%|1$;lWmj4!KilLY`p;KPB~wk0YrvJKLU{wb`NEMgO*Sh&RRgxw53q`)KfroNrpoBq(ynZklaWcy z@fkT{eausOfJLnS>IBq9hC!wPy5TZW>gs_Ti77EUqjV#hV^*a<$)^S(sz8p+2LP5X<3|K4*qnJNoU09e zp?Mrwxdc*DzYXgq!hmU4Aum&$B7O42O9JImAYPu=<14!Ek|ev*J@ksmS_*VmIDQyy zBw_Va1A*kN;5E-BXwkV?7mzB`2Fhs{8t4vpb#JD(WUH(kYQzFnqYE_X8pN^2I#`0j zEg9w{0dx|o2Vt_2c);Fr{O?pBUdXzj?LKXd9abf|gJXBpz{+?6R!y$~)>V6&2T~e7 zK**k6O1u``>~;%6xhtyjsws`Z1_1`hW&SXbHo``;;YV0za)Wy_x56^8djc3r5Hqn7 z=EZ_q1P#rMvKbY20wy<(j+*5TtNk{DE>n@E^_~ig7Y84uFw;|awohVi9wTGlVr$ox zU<%7+-wnvz%D!2Z_7#eD9HPwFJ^lb@)r-ks=^xWl-P4XC_#f>a1*RjcWu;<0kR_!6 z4sP(9N4mHE-J`R;d)?q~2h&*U5smbW^HArOWDNLrmA4@_XFS$2c$^XcifkT%IZk^F zYc+apiWP-xHLKJpclm$BCAtD6D_h_nYE7!}2;BNyu01@dQIrD(!n71DM^rIw)*fZUnZwT&Z#lh8Y^H^)5k)TxCk zKMmKBzpK-C@I5jrj7+GSx}*BeE0pC7$@HuP3%~@&5<708gJ~W%Y-lpu1#4J4?MF6* z40G{x(dg2vL)+t1ew(!$X6>|f1ojd-ZDUc+v``ZV6smyi^-ghWn;HiX24CK8_bf29 znuR6!{`6?tS zje_&}v1Dzp=B*PwFtRPird)e=RnUgq-2=pS;DWZ3kc80yXk;xv?2bfPXxxE%LX-#s zv(%%G!!D{mJP`wO8;B|8?)ass4L^gtm;)hzGV0p6MoXW&Q;4>WqYR`h5v~64YnTgp z;?XM+^lhxHAwS4O@N(I6r^Hkpk_@;zkD17rAQsmu+LTq|D-cQ&(r$uU?~W%qEc2e> zZZKOL_g?!{eRDlD+chg5=racMmD*B#Z_pAr-@jiYyaMSvcoxg$5Tp+CW6ilQV<{YCD|`(l)I#244N~_zW{1 zzYWJ;=65o;n5ROA=**u&1^kh*zHQ0hR4IWh+bIZlxFPyIxrMMS2!XT`GuJs7XvV}N zIz)~uKL~CjaG`yv3xbT!c<75M^R-+a+6B;ds_Pjh_j=0=^rlVo5?C9ALliO5-h`T+ zjyWL{+avB8(GNN1I*@&|HRHCE1NAtf&ZC!`@-aKbrWtOKY}{?=!Hi+pF`vzTpy_m- z^w-WaO2dQONr84)LFSBhk{~AmbL0Jp3jm6T&&V2-KMbr*f}wLcIw4Y90k??tnppG% zLY+t+ZB{k(gpr`7RU$g62HhZU6Z4{BaTXc01m14iUjn57 zKadT0TMck)ploqtUqvS`L2;Vn~oI;Y*9RciOW3k(*51@*=gVn#CNVO%OSKU zz-4ieV_~aF3Q+Z$Kw>gkD@1Bks054WA$PfLmw+UrN_!L+Gi# za^HE;0Cl~;MDM(SN<^|qz;X0WiHqcz6mS;d1<#!dGE=|^A|1h-=M27rUiegb4`Dt| z1u2kSs7xC&L1a_nJPWEzq;#b=iNSeNVuww|sH^i+}EX?NA*I{TPHN{ky+B& zSO8%nz;+h+%!9BAVh`vfBfJ;CK*92QMO$P|?_uH9yudpA^pvO!OQ$wTj1yMc(3WU+C01ztfYaY)`dOhQdlCX6O+c4|-iDlT3nENS7;6awwGa zQN)%!5~YvR$A4#SeCy=x+1oxQ&4GCvx)Ylky5}o>#QjTYO~ptXQNb^WEoG7!H6_t*P4D=z@0zyL|Qld_`#=3gONSx8|A2@!sTA4UGAT~ zHd#<51#zo4r|xU|2O>KAyIFo7E>@Q4{){427CmBtek0&g96CVCcbDkqd%XEhx)R5) zdO_el19$k>s4h@)w;HPUf;K`YZ*9Q=Y?te+-o10Dw5r}RgOe}8+Acq-(zO0! zsPeU%h!aSDb}yudV=bCMh6hz|z*AYz`;Mqs8BfJtH`M#yns+NMM6Bn$405&a+& zXS@sCIqvBV!WhEU+j!P}E6F{GfU^G$BF4=4brYXz<0$RYr00ULNpnQT4ifzcKQ zPz_9Q>i0$A&R1dam#}yy%&dTs!(u~#H-LMTNy9-0jJC)H76N9f0bgu~Db@YYCyau} zuZ9cD!8-(iAaJuXd1o*K<4FO^`{_XGj=((Ec7F)KqR(QUBvJsptu1apXn+Bp2d1Wb zdEGWxyE9ooZ#wwBN$N$~;<`Z(jJCKMxG~eqQ;&xY_ruhQ{kpr)hl=rO!_?9i;|Fby z(H1^om&2XLpBmxC^>E5K7+(a36~d@|7~+9d-@&afL(ROHErYzFOs*NMz*GXu-Nw~F z!n8#Lb@yKck6jhJ-`fNEL$jKvOqtXUCSY>p^V(F#-&&G&$CdWq3n+EKGr(8CzEt0{ zcGSu_wmtleG;3H0oN?(NMq8%*mQ4*R^LGLP`2^?&n&mkH^vHb&uonmceZr>A$|MAk zqhG*7lyg(f^h1hj(q%sWg zz|JQi5QN5d*wq5xH^h=}+(nhi*ICZ9CyQQeIWSG!zFRz}Uc6&3@Tcg5K$~14pi!B$ z9SC4_I^zf*Xkj6rH}>4ypG9)Cg;Hkv@!9rdA`QSUpb6M5`63|U(=8zt52YTUL79m> zazH#LE!wv(gBM*s@x`2k*W?1103T#A&mmca(u2T*|EEyeAsIT)Z9HLY@_-#pFuA|2 zd`??zRVF+4GtWsGY+(tdCx8pY8{#1o6vpTSTEv_BBsuSKgi}}&aTgFo(Wzz={YStk z6Rj;i2d2A?6GtZx*jxuUPUteS zM1Wb!WVNG@amr;tu}k;8gB^<{JmRuVYwh-`b8OpQ3aoSK&lLRzm%bRdTyoDZhGDd1 z4U96;dI>k7sFM&Fc*2*Wl*`RYQZAet%bc zd;6Zs%F3-kPIYzlxV*f)b4p7~hxYdN9_saaXG9{Ax~i(GhMJn1-W4lWJk{6N_jXZH zQLAgd4WUrzUBBNS1_*^hKA+E59|#0Cmz0#etF`uYc6JUQHf&h8*X!-8t*wnn(fL#` z82rfZ_lG~IRWMIA|$e}=$ z&@{jUz+5>CdJ=e8+LXCspATForNLr(&Pg%HT<4*pS zbyWeroD7xdM&K-MF-aD7;X?*xb1#dv2r7n5xHylEz=yyxWfIs=@>>;e#T?%FG;lBQ zJMa^5s_VeaBYn~cpaz%(jFuK+Kzj!q2mIpD?UoHAHB1B;35=DL@s`kcNNk^ow}jQ- z$zF0;K0!9wu1xB(96CZ=w?j5sDhuA_C=~07{h4Ot}#8GX($u002ovPDHLkV1fhf B2_66d literal 0 HcmV?d00001 diff --git a/interface/resources/images/about-qt.png b/interface/resources/images/about-qt.png new file mode 100644 index 0000000000000000000000000000000000000000..90230ecbf5d7c5df6461045ac1722c568d7659bf GIT binary patch literal 6170 zcmV+#80F`QP)X1^@s6RQmj^000!ZdQ@0+Qek%> zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3*rcI3Dfh5us}UIKDh4&pi9ftT;^f|ObvW~OIs zRktXySOoCG4WP{a&%clP7hlPHZ(=Gnx123svBl;)KUDjCJx6Eb{eHi^f8TT8pEs_( zZ+K1xj^X(=@Avx7`Sk4rCBEm!_vcNS?|tffBlmgZ`xP{@|8}~*Hwyke|Nd^;`$PY_ zocF(<@8>_3^~3M65R8?$U+~87;DY75^(*-p7>Uz?nS>fT$HaFRqAupu`5*81`h5(| z=bY{5Xx{~K%wNaQ?)QrDod0&C{CWI7R_}S2emEaKhxgyjh@iQ5WdC(WakyZ=etn7I zIjf$t@5Ltem{Ze8B z8B90Kl?8S?o?DFMzSUMxo(+e@E83@3Tv_i82oYl^CgTDbu-S#=va`ke;v8|T(QNKFf!WW|^$pAxH~hI$Gqrj&9j zsiu~C4mswOb1qp})k`R`q>@W1wY1V}sIjJ+YpJ!i+M92I?r*8(R$6VX_0FK3J9j?a zxuW;sM;LLWkw+PIw9zN!GviD%&ob+5voF7bS>V9RtE{@(>f3EfX~&&*-euR_c0ZKb z2`8R(@+qgDcKT=5-mHF~wI4J0=UH=a*8ELWFnlYYS>tpmAGdIVlcb!HF&`ZnFUkM~ z?UgfIU5s9t8+47a&C?ahGs~ppET@c-!ML4I$9?ARTjqY5HxuhW%A5Z&b4IEAe`L-m zbw6b8=e+$QYfJn$Z^mvHnj2IbXg@C4wfoV-g1y|z9#nF<0Xw6|b$n#f#Su~F7KCVl zxzI1u_SRI{DXr#`@5FM95Y7xFnPEcME$F9on$>aF?8mOUlIq%Hm6QA8zRc3pnX^B8 z1RwXxgD#E9rMUsb`y*BHTSxP|7yf*7Cv43V^c{Vha=;A=^`5e+=xF=tP_N?UnSV(n zA`Q1n9W#qo^60FG1@do$)DXVW&tm@1Vb_CVJ$Xwj58=xhdz?*qYlbzJlcIiV)WDgw>b;aUpge z6YdO%Zk75dAr!|U-gwi|pBXU!Fl9d-4QtOQ!;mZQ<5MVk5l)ui2zba~MK4ScedR6Z z`)*~1)MJ`)s2r)x;zpopDTcigaM|fCAL}~y&>*RGvTo;Lt+piJ#+=9RHA)VyF-R=^ zjFr!(^?dFo*foZqEuZRXp+kuI;B!R-&=wyWI|uL9p$nETBbPPS9+1u`HKg4VlEBRD z``){ZahbmQxYpj;Qw8mmMA-md2^5=WZKtdUP@-?8wUJ}=Lf>%}vxwAofY}sOP6;Xs zH|5zUscGf-`{|Lu>o^G89C3%9W*t;xxg8PaIR^MZ!2kffPe;s1wbA?l;i)U_#Q(Kw zj-J>)7~ndSg$%$P@Q8HG<>oMObSx9)lILV3;;YHG4bqN0tM1I2JoN`Qv~~8hOJz%( zzLaa}hMOYU7ifKQ2ENut%>hcxvZgqFOb4LfBc~NNwLy!dgOchL?_%lEjb0%a1JZ;4 z0CmfuqPeO&6%trLysx8@hUx;H3Z7(x9VnSsRxkY;*{k8`oQ$ck*%0fN1!DJ9H zS6XF261JWo2tB}zRj<`Gp$g{0G_7kh>zxHl9CK>S0jvbEFRV^@LupzN(XxXw0iNmp zPL0i(vO1Iiq&&uU;-r?=nkSpwb`r6)BXjR+&Gm`Q*k zfQ;U`57f4)Y?^8zFJlQigF^?wNp+-IsGQ#BA|_Ci@0VkfaP?-&TS1{8xQ+Xh!4*BH z{`wf=iBJYj0R9qdtX-{hlsU_q3U)!v3`Zf+z2R-EK}*NB>9kvdI|V86B9djvW007- zx$yxx@>tfJwJl1!l(`xO$#|VctbU^h1CTtB4LbsuSO1ZuJ}U*8_DF!tPT92{2wpQy zq7>8TU`~m&nZXQ4n;OaFV1Qc2YzY`h-xlg-50f#|=5*-x~o<=ivVY*0SCSt5@ zrpO9htBHC}CQ!lvuMeb%$Ti?CwQKRHEW~&~ZjA;Vv5?hzPQ4!#6`n^;woi7124!Rj z4qZJbM5T&zpcZoxw!}$7mfw4UWd(Hx_DvUvP~fv*DybWkEENNJm{J>6F<1mWNc4Rs zB0ho5b5y!&p2^4jWeV_>lCm?CI|M;MuT9kZ&cKA}h@LDMyr8+U6;=l6Dx@g;0ZU}C z3J$Mu$RzIc+d+?#3PfPXuU3 zmK8V>!GWP(C z6o;BdM8fchgZ$i-~*s9JYvU_l`(k zh`9{z+{^Lg@GN0NlPgktRP-=0%1W=5D`#Md9jG2D2m-=n>T=2 zioAq1rFjj44-LjJCp(Gsx*KqFA{B-@9_8opC?{0FCX*I$luloURbM&C zfF$KZi!X<)>CzAwAyR|g0{(BeA10^8K|v52gv9k}TI29P=v=AIeJ9k8kbr*i{UEOi zc|I#vf1rs3)1oK9{~+k~`QWXnh(@9a`{X8}g zpuE zG>Av-VJ0d#TVX~)BM@Zywe4Z{6uYF~u1rywzAfY%(FEKyr-nDfN`!456w0(R<*OsPGWgp26!J2?Th=9Wj zkkQy8V>|*Mw;SNZ+=MkQbHu=nXhxy|AB&J?9ta>B1Wrp}JQf5{RA8>X!9}pZeOsF# z)qI>ln-v*s{uY@IOow>v0IvlzNxGOlt7XaW2u(Y1)DCtW%$K-#+8H8^E#9RqO%AB< zXfsd-d4#0$+?YkX;2tlBE;=@T@pV5OKaAfQb4?Q_aC5 z0Is=^bQ~zY^K7IxNHUuC73-NY@uwnpS>6r#P{@Zz+0j`kUj>I~6ztg81O64~cz%5Xq0Sqe=rgG8gj@c~w^}t<@ zm@SnV>VSBbp&J-E9<H2?7x;O%*WH- z)*@n5Nri5aKky4F0WYK!K>1G0bFN`b%WWr!4oEayNS)Y`O~~aSE2m0plH2Rf>~ihMgctbGTON24plj&Y8;Iyoe1dhv4k#dtfGA( z(Qko6*P>_iNC6--LN~2^XyD~1(xc$^>LE|aYjgn2)|+IB$`5`4m#LFRssKtNj04&? zMnLa)_Vkd(T@nHdlO(dh8TDb`X!9jiQIOiWY|qLT)P$O1x-6#^niki9Gi65o^|V+g zZsi`E-0Po6XHWv5;@#k)!O2i|DVD-)m}rq0fd`+0K>N^V;aBf8GO0ZvkHVraO|={8 zT5bd`0BUnZC@27g4Do^Yy+`yyl1my_q8G~UGu_Cw8zbGXEsW`b+|%)AwvTPiS={e# zX&Kbyuptm*ul<>cPy~OilaV)Ro+@cDC1ACQ2?NqY#{(JO_tj02)zq-JYWT zs(q+3D#YbGs5WRAG-y!pnevyIsAdG)Dd4zn8IZX?*Vd(AIZOdR%60^_0vs#}cy|FX z0YaOlZPD!z?D#bn?`mB=0=U|@r_i*&$~>3LI5}1Y3Z!&%3Fto%XJg8;R4IC36s>3w zo47zt4$ZgG3bT+1BFY-bQ&C^-Ijd!39+z!J)0YOY|L>#<=OtewTj$i z&WHI}#NpBIQo&z?>FCCUyoMsF#HY5rOG0O>R2hg1E2~YUhXmWz1^%VLMvYPVdW?wG zCMb!r{G}!^R}>(it9#y@@0;}z6HZ_e$9C}0r88;v8Ks;aR$w-l6AU>=#+AD`za=MD z_-6f>xVx-@Y$yszf^%)o;SS5x^mIa8y3ErHz5M;1dcrZ0z?-;^;SD%Z^`w@}uo7T6 z%jwrb5r%@WLtU;U$&L8Hgm#&ND#YZhAqXh%(Ji#X_g?gC+h!U#@018ji>q4sjEfCji=^mv>A#sgZIwT?;|rV5UKOHFa zw>JGv1401dP2H`lx$W*m5^aIyl@Hu|7zB~_8#67N__(KP;V}5S2`G~th+b?2HY1~8 zfE2Heh0lt1Q2VnnjX5w_l#(ln$BQ8y`_!Xj0D=yv8RYMlxMBO4LS5QTrv4%6x$h1P zM2O)QftidkIq{0G%U5_u?Luk$4q1biYM!Q~3au=PRN`vQI_>#%6iw7doWC)ut`i^0 z#(}^RrG@A&wxK>gmCSosGG) z(HhPYQIrKxbE}QPBaSERPm}PQ$FM`TNUKK3>5*fIi5*2QmpXufgLptKQb$CI_D(z2gh>yuBq9>P457wpt93-M$d?Vhp}!D-Erv@0uq0R_FBGL7 zT5j!5EbyD;g2v{-#%AF)h?Uu8yx3g$XqR0mf-yuXl2k;h?X8}G9X)^vdMe;HL5Fw% zf3QURM7l2bfM(K`bPjsZ#vMR{hHM1q6Q)9OL3nE$v+K`6+{qNnj>s>wZb1qXsKGSvBL%Jyj$&h_LPt|-DTixYcmAA zVPFUpypo2t1)0W8V{h08cO=U70F{EI_TI+;mMVoeMryc=MqJw@a#c^#dq&AnF^T!I zZj3)vi5L}$;7ZCG+bn^XXeV@-KBM}>#eFi-dWc)uXN6;^GH|Ow+k6E^MOdMseZQ~d zjh;Qx5EJ8hC)OjL{}0{$A0N%H-q@G^i(hD8Y^VN;pb2U8I2i4efrveB`+`vRv0#S! z3q_zDv}*xic<{%mLXhsL>#f^y2Tj9S#49x#7h1?Fjo(7FjXjvjr8OF<6JP~O_Zr#?=k=&$ZTu=+39V*VBg{mJnUZiMn!EOY9yhT)ecfDef(L)BQz8JFPnrZgce)WZhu^K*{(Y+c%Fujg63iX zt)j<$(1*PvACR~yL|A%ytD#XaDhwVLG9=|owE*hSGbjiTV<4Sq77o??7eWC5#yW6o zF8}}l24YJ`L;(K){{a7>y{D4^000SaNLh0L04^f{04^f|c%?sf00007bV*G`2jT?| z6c`*bQYX*=00QDkL_t(Y$IX>pNK;`L$A3FJy3IQCG>3C&fgfONeW6wq^hJRMMWqyd z+|*Sc1O*XvQ5OXfBt+6pbt6I7l4TzR64^A0l1i3JVL7F8&6=xu=A5&Ox+Kp@%JV?TFZZ{$jC&7gZ8~t=50fkyx-u@QhhZHFfXB2AQB zpRt0Sb9W$1GFmKx$KOm{Pd$yj9{Qsp0G8X!IGJ-W;lE7Tio=qP!;<|^tr<6VId>o# zB(#{uiS{$JM?Z+1{jzk%Lg$!&pNG1hdWvQj;#OV6iF2pt9sq;!XlfuSEO5LXSyS)CtuDLIvDLw@{k$y zgS2Q~p%=_9PU=~ulnL#N^o-ryAn6AQ#DjeN(FH(hRtZZ@^AqxRNo7mUCIE)wG3tX2 zBKLDREVRRD(?3~neYwkV

An entity may collide with the following types of items:

@@ -72,35 +72,35 @@ const int16_t BULLET_COLLISION_MASK_COLLISIONLESS = 0; * * * 1Static entities — non-dynamic entities with no velocity. - * 2Dynamic entities — entities that have their dynamic property set to + * 2Dynamic entities — entities that have their dynamic property set to * true. * 4Kinematic entities — non-dynamic entities with velocity. * 8My avatar. * 16Other avatars. * * - *

The values for the collision types that are enabled are added together to give the CollisionMask value. For example, a + *

The values for the collision types that are enabled are added together to give the CollisionMask value. For example, a * value of 31 means that an entity will collide with all item types.

* @typedef {number} Entities.CollisionMask */ // The USER collision groups are exposed to script and can be used to generate per-object collision masks. // They are not necessarily the same as the BULLET_COLLISION_GROUPS, but we start them off with matching numbers. -const uint8_t USER_COLLISION_GROUP_STATIC = 1 << 0; -const uint8_t USER_COLLISION_GROUP_DYNAMIC = 1 << 1; -const uint8_t USER_COLLISION_GROUP_KINEMATIC = 1 << 2; -const uint8_t USER_COLLISION_GROUP_MY_AVATAR = 1 << 3; -const uint8_t USER_COLLISION_GROUP_OTHER_AVATAR = 1 << 4; +const uint16_t USER_COLLISION_GROUP_STATIC = 1 << 0; +const uint16_t USER_COLLISION_GROUP_DYNAMIC = 1 << 1; +const uint16_t USER_COLLISION_GROUP_KINEMATIC = 1 << 2; +const uint16_t USER_COLLISION_GROUP_MY_AVATAR = 1 << 3; +const uint16_t USER_COLLISION_GROUP_OTHER_AVATAR = 1 << 4; -const uint8_t ENTITY_COLLISION_MASK_DEFAULT = +const uint16_t ENTITY_COLLISION_MASK_DEFAULT = USER_COLLISION_GROUP_STATIC | USER_COLLISION_GROUP_DYNAMIC | USER_COLLISION_GROUP_KINEMATIC | USER_COLLISION_GROUP_MY_AVATAR | USER_COLLISION_GROUP_OTHER_AVATAR; -const uint8_t USER_COLLISION_MASK_AVATARS = USER_COLLISION_GROUP_MY_AVATAR | USER_COLLISION_GROUP_OTHER_AVATAR; +const uint16_t USER_COLLISION_MASK_AVATARS = USER_COLLISION_GROUP_MY_AVATAR | USER_COLLISION_GROUP_OTHER_AVATAR; -const int NUM_USER_COLLISION_GROUPS = 5; +const int32_t NUM_USER_COLLISION_GROUPS = 5; #endif // hifi_PhysicsCollisionGroups_h diff --git a/libraries/shared/src/PhysicsHelpers.cpp b/libraries/shared/src/PhysicsHelpers.cpp index 18accfd799..b43d55020e 100644 --- a/libraries/shared/src/PhysicsHelpers.cpp +++ b/libraries/shared/src/PhysicsHelpers.cpp @@ -61,7 +61,7 @@ glm::quat computeBulletRotationStep(const glm::vec3& angularVelocity, float time } /* end Bullet code derivation*/ -int16_t Physics::getDefaultCollisionMask(int16_t group) { +int32_t Physics::getDefaultCollisionMask(int32_t group) { switch(group) { case BULLET_COLLISION_GROUP_STATIC: return BULLET_COLLISION_MASK_STATIC; diff --git a/libraries/shared/src/PhysicsHelpers.h b/libraries/shared/src/PhysicsHelpers.h index 67442187a3..332100f03b 100644 --- a/libraries/shared/src/PhysicsHelpers.h +++ b/libraries/shared/src/PhysicsHelpers.h @@ -31,7 +31,7 @@ const float KINEMATIC_ANGULAR_SPEED_THRESHOLD = 0.008f; // ~0.5 deg/sec glm::quat computeBulletRotationStep(const glm::vec3& angularVelocity, float timeStep); namespace Physics { - int16_t getDefaultCollisionMask(int16_t group); + int32_t getDefaultCollisionMask(int32_t group); void setSessionUUID(const QUuid& sessionID); const QUuid& getSessionUUID(); From da7dc487cc2548cf85184bcaa506232dcf849522 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 8 May 2018 11:04:09 -0700 Subject: [PATCH 129/143] remove windows build warnings in Bullet lib --- cmake/externals/bullet/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index d08c7530ed..b1e91b1e05 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -18,7 +18,7 @@ if (WIN32) ExternalProject_Add( ${EXTERNAL_NAME} URL http://hifi-public.s3.amazonaws.com/dependencies/bullet-2.88.tgz - URL_MD5 d5f92d0ca60adcc863bcb547e6ef4082 + URL_MD5 1d57629ac7fdad008fd789d998a28a89 CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_BULLET3=0 -DBUILD_OPENGL3_DEMOS=0 -DBUILD_BULLET2_DEMOS=0 -DBUILD_UNIT_TESTS=0 -DUSE_GLUT=0 -DUSE_DX11=0 LOG_DOWNLOAD 1 LOG_CONFIGURE 1 @@ -29,7 +29,7 @@ else () ExternalProject_Add( ${EXTERNAL_NAME} URL http://hifi-public.s3.amazonaws.com/dependencies/bullet-2.88.tgz - URL_MD5 d5f92d0ca60adcc863bcb547e6ef4082 + URL_MD5 1d57629ac7fdad008fd789d998a28a89 CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_BULLET3=0 -DBUILD_OPENGL3_DEMOS=0 -DBUILD_BULLET2_DEMOS=0 -DBUILD_UNIT_TESTS=0 -DUSE_GLUT=0 LOG_DOWNLOAD 1 LOG_CONFIGURE 1 From 7e03b8b33c3931eb52472a0cbc4a703283d88b8a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 8 May 2018 16:33:01 -0700 Subject: [PATCH 130/143] one more try to eliminate windows compile warnings --- cmake/externals/bullet/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index b1e91b1e05..91860a7470 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -18,7 +18,7 @@ if (WIN32) ExternalProject_Add( ${EXTERNAL_NAME} URL http://hifi-public.s3.amazonaws.com/dependencies/bullet-2.88.tgz - URL_MD5 1d57629ac7fdad008fd789d998a28a89 + URL_MD5 0a6876607ebe83e227427215f15946fd CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_BULLET3=0 -DBUILD_OPENGL3_DEMOS=0 -DBUILD_BULLET2_DEMOS=0 -DBUILD_UNIT_TESTS=0 -DUSE_GLUT=0 -DUSE_DX11=0 LOG_DOWNLOAD 1 LOG_CONFIGURE 1 @@ -29,7 +29,7 @@ else () ExternalProject_Add( ${EXTERNAL_NAME} URL http://hifi-public.s3.amazonaws.com/dependencies/bullet-2.88.tgz - URL_MD5 1d57629ac7fdad008fd789d998a28a89 + URL_MD5 0a6876607ebe83e227427215f15946fd CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_BULLET3=0 -DBUILD_OPENGL3_DEMOS=0 -DBUILD_BULLET2_DEMOS=0 -DBUILD_UNIT_TESTS=0 -DUSE_GLUT=0 LOG_DOWNLOAD 1 LOG_CONFIGURE 1 From 14f776cfb7cb383717cb98186630d15b6edd5cc5 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 9 May 2018 13:46:50 -0700 Subject: [PATCH 131/143] upgrade android bullet dependency to 2.88 --- android/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 74047dccab..ff56bde315 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -89,9 +89,9 @@ def packages = [ checksum: qtChecksum, ], bullet: [ - file: 'https://hifi-public.s3.amazonaws.com/austin/android/bullet-2.83_armv8-libcpp.tgz', - versionId: 'ljb7v.1IjVRqyopUKVDbVnLA4z88J8Eo', - checksum: '2c558d604fce337f5eba3eb7ec1252fd', + file: 'https://hifi-public.s3.amazonaws.com/dependencies/android/bullet-2.88_armv8-libcpp.tgz', + versionId: 'S8YaoED0Cl8sSb8fSV7Q2G1lQJSNDxqg', + checksum: '81642779ccb110f8c7338e8739ac38a0', ], draco: [ file: 'https://hifi-public.s3.amazonaws.com/austin/android/draco_armv8-libcpp.tgz', From d42375e4fe0ca99d4a7d5b0257b31e90477f1a11 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 10 May 2018 09:15:06 -0700 Subject: [PATCH 132/143] finish uint8_t to uint16_t conversion --- libraries/entities/src/EntityItem.cpp | 4 ++-- libraries/entities/src/EntityItem.h | 2 +- libraries/entities/src/EntityItemProperties.cpp | 12 ++++++------ libraries/entities/src/EntityItemProperties.h | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index ec8ca76258..d9365b516f 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -817,7 +817,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_VISIBLE, bool, setVisible); READ_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow); READ_ENTITY_PROPERTY(PROP_COLLISIONLESS, bool, setCollisionless); - READ_ENTITY_PROPERTY(PROP_COLLISION_MASK, uint8_t, setCollisionMask); + READ_ENTITY_PROPERTY(PROP_COLLISION_MASK, uint16_t, setCollisionMask); READ_ENTITY_PROPERTY(PROP_DYNAMIC, bool, setDynamic); READ_ENTITY_PROPERTY(PROP_LOCKED, bool, setLocked); READ_ENTITY_PROPERTY(PROP_USER_DATA, QString, setUserData); @@ -1849,7 +1849,7 @@ void EntityItem::setCollisionless(bool value) { }); } -void EntityItem::setCollisionMask(uint8_t value) { +void EntityItem::setCollisionMask(uint16_t value) { withWriteLock([&] { if ((_collisionMask & ENTITY_COLLISION_MASK_DEFAULT) != (value & ENTITY_COLLISION_MASK_DEFAULT)) { _collisionMask = (value & ENTITY_COLLISION_MASK_DEFAULT); diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 431c87cf68..bc4767d3db 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -289,7 +289,7 @@ public: void setCollisionless(bool value); uint16_t getCollisionMask() const; - void setCollisionMask(uint8_t value); + void setCollisionMask(uint16_t value); void computeCollisionGroupAndFinalMask(int32_t& group, int32_t& mask) const; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 30e2b13daf..949b39bb7d 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -130,7 +130,7 @@ void buildStringToMaterialMappingModeLookup() { addMaterialMappingMode(PROJECTED); } -QString getCollisionGroupAsString(uint8_t group) { +QString getCollisionGroupAsString(uint16_t group) { switch (group) { case USER_COLLISION_GROUP_DYNAMIC: return "dynamic"; @@ -146,7 +146,7 @@ QString getCollisionGroupAsString(uint8_t group) { return ""; } -uint8_t getCollisionGroupAsBitMask(const QStringRef& name) { +uint16_t getCollisionGroupAsBitMask(const QStringRef& name) { if (0 == name.compare(QString("dynamic"))) { return USER_COLLISION_GROUP_DYNAMIC; } else if (0 == name.compare(QString("static"))) { @@ -164,7 +164,7 @@ uint8_t getCollisionGroupAsBitMask(const QStringRef& name) { QString EntityItemProperties::getCollisionMaskAsString() const { QString maskString(""); for (int i = 0; i < NUM_USER_COLLISION_GROUPS; ++i) { - uint8_t group = 0x01 << i; + uint16_t group = 0x0001 << i; if (group & _collisionMask) { maskString.append(getCollisionGroupAsString(group)); maskString.append(','); @@ -175,7 +175,7 @@ QString EntityItemProperties::getCollisionMaskAsString() const { void EntityItemProperties::setCollisionMaskFromString(const QString& maskString) { QVector groups = maskString.splitRef(','); - uint8_t mask = 0x00; + uint16_t mask = 0x0000; for (auto groupName : groups) { mask |= getCollisionGroupAsBitMask(groupName); } @@ -1520,7 +1520,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(localRenderAlpha, float, setLocalRenderAlpha); COPY_PROPERTY_FROM_QSCRIPTVALUE(collisionless, bool, setCollisionless); COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(ignoreForCollisions, bool, setCollisionless, getCollisionless); // legacy support - COPY_PROPERTY_FROM_QSCRIPTVALUE(collisionMask, uint8_t, setCollisionMask); + COPY_PROPERTY_FROM_QSCRIPTVALUE(collisionMask, uint16_t, setCollisionMask); COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(collidesWith, CollisionMask); COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(collisionsWillMove, bool, setDynamic, getDynamic); // legacy support COPY_PROPERTY_FROM_QSCRIPTVALUE(dynamic, bool, setDynamic); @@ -2576,7 +2576,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VISIBLE, bool, setVisible); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISIONLESS, bool, setCollisionless); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISION_MASK, uint8_t, setCollisionMask); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISION_MASK, uint16_t, setCollisionMask); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DYNAMIC, bool, setDynamic); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LOCKED, bool, setLocked); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_USER_DATA, QString, setUserData); diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index b616b70d68..01c43a46b3 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -148,7 +148,7 @@ public: DEFINE_PROPERTY_REF(PROP_ANGULAR_VELOCITY, AngularVelocity, angularVelocity, glm::vec3, ENTITY_ITEM_DEFAULT_ANGULAR_VELOCITY); DEFINE_PROPERTY(PROP_ANGULAR_DAMPING, AngularDamping, angularDamping, float, ENTITY_ITEM_DEFAULT_ANGULAR_DAMPING); DEFINE_PROPERTY(PROP_COLLISIONLESS, Collisionless, collisionless, bool, ENTITY_ITEM_DEFAULT_COLLISIONLESS); - DEFINE_PROPERTY(PROP_COLLISION_MASK, CollisionMask, collisionMask, uint8_t, ENTITY_COLLISION_MASK_DEFAULT); + DEFINE_PROPERTY(PROP_COLLISION_MASK, CollisionMask, collisionMask, uint16_t, ENTITY_COLLISION_MASK_DEFAULT); DEFINE_PROPERTY(PROP_DYNAMIC, Dynamic, dynamic, bool, ENTITY_ITEM_DEFAULT_DYNAMIC); DEFINE_PROPERTY(PROP_IS_SPOTLIGHT, IsSpotlight, isSpotlight, bool, LightEntityItem::DEFAULT_IS_SPOTLIGHT); DEFINE_PROPERTY(PROP_INTENSITY, Intensity, intensity, float, LightEntityItem::DEFAULT_INTENSITY); From 885c7bc97dc9b4ce62fbdc5e63ff6d7b8be25f10 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 10 May 2018 09:15:26 -0700 Subject: [PATCH 133/143] bump protocol for extra byte in collisionMask --- libraries/networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index c07c5905f6..b69733c18d 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -33,7 +33,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityEdit: case PacketType::EntityData: case PacketType::EntityPhysics: - return static_cast(EntityVersion::CloneableData); + return static_cast(EntityVersion::CollisionMask16Bytes); case PacketType::EntityQuery: return static_cast(EntityQueryPacketVersion::ConicalFrustums); case PacketType::AvatarIdentity: diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 29d4efed42..5203a9d178 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -235,7 +235,8 @@ enum class EntityVersion : PacketVersion { MaterialEntities, ShadowControl, MaterialData, - CloneableData + CloneableData, + CollisionMask16Bytes }; enum class EntityScriptCallMethodVersion : PacketVersion { From 288efb1f93fe930d16aed606eb09804d7f7d1a56 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 24 May 2018 11:30:12 -0700 Subject: [PATCH 134/143] remove cuft --- android/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/android/build.gradle b/android/build.gradle index ff56bde315..3719e548bc 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -66,7 +66,6 @@ ext { def baseFolder = new File(HIFI_ANDROID_PRECOMPILED) def appDir = new File(projectDir, 'app') def jniFolder = new File(appDir, 'src/main/jniLibs/arm64-v8a') -//def baseUrl = 'https://hifi-public.s3.amazonaws.com/austin/android/' def baseUrl = '' def qtFile='https://hifi-public.s3.amazonaws.com/austin/android/qt-5.9.3_linux_armv8-libcpp_openssl.tgz' From 802cedf1bcd8afb7fc0562004f3cee21b15a8518 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 24 May 2018 13:29:02 -0700 Subject: [PATCH 135/143] Removed messages in non-interactive mode. --- tools/auto-tester/src/Test.cpp | 6 +++--- tools/auto-tester/src/Test.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/auto-tester/src/Test.cpp b/tools/auto-tester/src/Test.cpp index 11c5428c26..23d097b855 100644 --- a/tools/auto-tester/src/Test.cpp +++ b/tools/auto-tester/src/Test.cpp @@ -71,7 +71,7 @@ bool Test::compareImageLists(bool isInteractiveMode, QProgressBar* progressBar) QImage resultImage(resultImagesFullFilenames[i]); QImage expectedImage(expectedImagesFullFilenames[i]); - if (resultImage.width() != expectedImage.width() || resultImage.height() != expectedImage.height()) { + if (isInteractiveMode && (resultImage.width() != expectedImage.width() || resultImage.height() != expectedImage.height())) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Images are not the same size"); exit(-1); } @@ -131,7 +131,7 @@ void Test::appendTestResultsToFile(const QString& testResultsFolderPath, TestFai exit(-1); } - QString failureFolderPath { testResultsFolderPath + "/" + "Failure_" + QString::number(index) }; + QString failureFolderPath { testResultsFolderPath + "/" + "Failure_" + QString::number(index) + "--" + testFailure._actualImageFilename.left(testFailure._actualImageFilename.length() - 4) }; if (!QDir().mkdir(failureFolderPath)) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create folder " + failureFolderPath); exit(-1); @@ -248,7 +248,7 @@ void Test::startTestsEvaluation(const QString& testFolder) { void Test::finishTestsEvaluation(bool isRunningFromCommandline, bool interactiveMode, QProgressBar* progressBar) { bool success = compareImageLists((!isRunningFromCommandline && interactiveMode), progressBar); - if (!isRunningFromCommandline) { + if (interactiveMode && !isRunningFromCommandline) { if (success) { QMessageBox::information(0, "Success", "All images are as expected"); } else { diff --git a/tools/auto-tester/src/Test.h b/tools/auto-tester/src/Test.h index 78c5dfb14c..32564035e7 100644 --- a/tools/auto-tester/src/Test.h +++ b/tools/auto-tester/src/Test.h @@ -102,9 +102,9 @@ private: QStringList resultImagesFullFilenames; // Used for accessing GitHub - const QString GIT_HUB_USER{ "NissimHadar" }; + const QString GIT_HUB_USER{ "highfidelity" }; const QString GIT_HUB_REPOSITORY{ "hifi_tests" }; - const QString GIT_HUB_BRANCH{ "newAvatar" }; + const QString GIT_HUB_BRANCH{ "master" }; const QString DATETIME_FORMAT{ "yyyy-MM-dd_hh-mm-ss" }; From bc757ddd41c7bb8c48636462478cb8ade231a94b Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 25 May 2018 09:04:06 +1200 Subject: [PATCH 136/143] Fix typo --- interface/src/ui/overlays/Overlays.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index d100b228ed..3debf74f26 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -482,7 +482,7 @@ public slots: /**jsdoc * Check if there is an overlay of a given ID. - * @function Overlays.isAddedOverly + * @function Overlays.isAddedOverlay * @param {Uuid} overlayID - The ID to check. * @returns {boolean} true if an overlay with the given ID exists, false otherwise. */ From d01482bf687dd768adc612e58b195bcb0394ce15 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 24 May 2018 17:44:39 -0700 Subject: [PATCH 137/143] Now looks for an actual change in the boom length (vs a change has been requested). --- interface/src/avatar/MyAvatar.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 0875966cbb..d3ab739649 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2245,12 +2245,13 @@ void MyAvatar::updateActionMotor(float deltaTime) { _actionMotorVelocity = getSensorToWorldScale() * (_walkSpeed.get() * _walkSpeedScalar) * direction; } + float previousBoomLength = _boomLength; float boomChange = getDriveKey(ZOOM); _boomLength += 2.0f * _boomLength * boomChange + boomChange * boomChange; _boomLength = glm::clamp(_boomLength, ZOOM_MIN, ZOOM_MAX); // May need to change view if boom length has changed - if (fabs(boomChange) > 0.0f) { + if (previousBoomLength != _boomLength) { qApp->changeViewAsNeeded(_boomLength); } } From e34d67fee4b7e164edab56ed049d5a3d7ba532ef Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 24 May 2018 17:54:53 -0700 Subject: [PATCH 138/143] fix crash --- interface/src/ui/overlays/Web3DOverlay.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index c678e3d2a2..8af818edc6 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -259,7 +259,6 @@ void Web3DOverlay::setupQmlSurface() { _webSurface->getSurfaceContext()->setContextProperty("Web3DOverlay", this); _webSurface->getSurfaceContext()->setContextProperty("Window", DependencyManager::get().data()); _webSurface->getSurfaceContext()->setContextProperty("Reticle", qApp->getApplicationCompositor().getReticleInterface()); - _webSurface->getSurfaceContext()->setContextProperty("desktop", DependencyManager::get()->getDesktop()); _webSurface->getSurfaceContext()->setContextProperty("HiFiAbout", AboutUtil::getInstance()); // Override min fps for tablet UI, for silky smooth scrolling From ed62a2fc37bd14b6a4230fa0bb0869be10d3e95c Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 19 Apr 2018 15:15:26 -0700 Subject: [PATCH 139/143] _lastKinematicStep now mutable, avoids explicit const_cast --- libraries/physics/src/ObjectMotionState.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index 24dd655342..bb3c00bd5d 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -184,7 +184,7 @@ protected: btRigidBody* _body { nullptr }; float _density { 1.0f }; - uint32_t _lastKinematicStep; + mutable uint32_t _lastKinematicStep; bool _hasInternalKinematicChanges { false }; }; From 1612d90cd338049736b725f91038e1dd5b4a5e51 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 19 Apr 2018 15:15:42 -0700 Subject: [PATCH 140/143] minor DynamicsWorld optimizations and track global steps count therein --- libraries/physics/src/EntityMotionState.cpp | 4 +- libraries/physics/src/PhysicsEngine.cpp | 8 +-- libraries/physics/src/PhysicsEngine.h | 3 +- .../physics/src/ThreadSafeDynamicsWorld.cpp | 63 +++++++------------ .../physics/src/ThreadSafeDynamicsWorld.h | 2 + 5 files changed, 28 insertions(+), 52 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 30bbcd1fb8..deb779b1f8 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -252,11 +252,9 @@ void EntityMotionState::getWorldTransform(btTransform& worldTrans) const { uint32_t thisStep = ObjectMotionState::getWorldSimulationStep(); float dt = (thisStep - _lastKinematicStep) * PHYSICS_ENGINE_FIXED_SUBSTEP; + _lastKinematicStep = thisStep; _entity->stepKinematicMotion(dt); - // bypass const-ness so we can remember the step - const_cast(this)->_lastKinematicStep = thisStep; - // and set the acceleration-matches-gravity count high so that if we send an update // it will use the correct acceleration for remote simulations _accelerationNearlyGravityCount = (uint8_t)(-1); diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 9aab27c3e9..21b5b38b13 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -71,8 +71,8 @@ void PhysicsEngine::init() { } } -uint32_t PhysicsEngine::getNumSubsteps() { - return _numSubsteps; +uint32_t PhysicsEngine::getNumSubsteps() const { + return _dynamicsWorld->getNumSubsteps(); } // private @@ -329,13 +329,9 @@ void PhysicsEngine::stepSimulation() { PHYSICS_ENGINE_FIXED_SUBSTEP, onSubStep); if (numSubsteps > 0) { BT_PROFILE("postSimulation"); - _numSubsteps += (uint32_t)numSubsteps; - ObjectMotionState::setWorldSimulationStep(_numSubsteps); - if (_myAvatarController) { _myAvatarController->postSimulation(); } - _hasOutgoingChanges = true; } diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index 0dfe3a7a7c..2ac195956a 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -52,7 +52,7 @@ public: ~PhysicsEngine(); void init(); - uint32_t getNumSubsteps(); + uint32_t getNumSubsteps() const; void removeObjects(const VectorOfMotionStates& objects); void removeSetOfObjects(const SetOfMotionStates& objects); // only called during teardown @@ -135,7 +135,6 @@ private: CharacterController* _myAvatarController; uint32_t _numContactFrames = 0; - uint32_t _numSubsteps; bool _dumpNextStats { false }; bool _saveNextStats { false }; diff --git a/libraries/physics/src/ThreadSafeDynamicsWorld.cpp b/libraries/physics/src/ThreadSafeDynamicsWorld.cpp index 3f24851dce..07d5ceb9ac 100644 --- a/libraries/physics/src/ThreadSafeDynamicsWorld.cpp +++ b/libraries/physics/src/ThreadSafeDynamicsWorld.cpp @@ -59,14 +59,11 @@ int ThreadSafeDynamicsWorld::stepSimulationWithSubstepCallback(btScalar timeStep } } - /*//process some debugging flags - if (getDebugDrawer()) { - btIDebugDraw* debugDrawer = getDebugDrawer(); - gDisableDeactivation = (debugDrawer->getDebugMode() & btIDebugDraw::DBG_NoDeactivation) != 0; - }*/ if (subSteps) { //clamp the number of substeps, to prevent simulation grinding spiralling down to a halt int clampedSimulationSteps = (subSteps > maxSubSteps)? maxSubSteps : subSteps; + _numSubsteps += clampedSimulationSteps; + ObjectMotionState::setWorldSimulationStep(_numSubsteps); saveKinematicState(fixedTimeStep*clampedSimulationSteps); @@ -98,28 +95,24 @@ int ThreadSafeDynamicsWorld::stepSimulationWithSubstepCallback(btScalar timeStep // call this instead of non-virtual btDiscreteDynamicsWorld::synchronizeSingleMotionState() void ThreadSafeDynamicsWorld::synchronizeMotionState(btRigidBody* body) { btAssert(body); - if (body->getMotionState() && !body->isStaticObject()) { - //we need to call the update at least once, even for sleeping objects - //otherwise the 'graphics' transform never updates properly - ///@todo: add 'dirty' flag - //if (body->getActivationState() != ISLAND_SLEEPING) - { - if (body->isKinematicObject()) { - ObjectMotionState* objectMotionState = static_cast(body->getMotionState()); - if (objectMotionState->hasInternalKinematicChanges()) { - objectMotionState->clearInternalKinematicChanges(); - body->getMotionState()->setWorldTransform(body->getWorldTransform()); - } - return; - } - btTransform interpolatedTransform; - btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(), - body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(), - (m_latencyMotionStateInterpolation && m_fixedTimeStep) ? m_localTime - m_fixedTimeStep : m_localTime*body->getHitFraction(), - interpolatedTransform); - body->getMotionState()->setWorldTransform(interpolatedTransform); + btAssert(body->getMotionState()); + + if (body->isKinematicObject()) { + ObjectMotionState* objectMotionState = static_cast(body->getMotionState()); + if (objectMotionState->hasInternalKinematicChanges()) { + // this is a special case where the kinematic motion has been updated by an Action + // so we supply the body's current transform to the MotionState + objectMotionState->clearInternalKinematicChanges(); + body->getMotionState()->setWorldTransform(body->getWorldTransform()); } + return; } + btTransform interpolatedTransform; + btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(), + body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(), + (m_latencyMotionStateInterpolation && m_fixedTimeStep) ? m_localTime - m_fixedTimeStep : m_localTime*body->getHitFraction(), + interpolatedTransform); + body->getMotionState()->setWorldTransform(interpolatedTransform); } void ThreadSafeDynamicsWorld::synchronizeMotionStates() { @@ -164,24 +157,12 @@ void ThreadSafeDynamicsWorld::synchronizeMotionStates() { } void ThreadSafeDynamicsWorld::saveKinematicState(btScalar timeStep) { -///would like to iterate over m_nonStaticRigidBodies, but unfortunately old API allows -///to switch status _after_ adding kinematic objects to the world -///fix it for Bullet 3.x release DETAILED_PROFILE_RANGE(simulation_physics, "saveKinematicState"); BT_PROFILE("saveKinematicState"); - for (int i=0;igetActivationState() != ISLAND_SLEEPING) - { - if (body->isKinematicObject()) - { - //to calculate velocities next frame - body->saveKinematicState(timeStep); - } + for (int i=0;iisKinematicObject() && body->getActivationState() != ISLAND_SLEEPING) { + body->saveKinematicState(timeStep); } } } - - diff --git a/libraries/physics/src/ThreadSafeDynamicsWorld.h b/libraries/physics/src/ThreadSafeDynamicsWorld.h index 54c3ddb756..d8cee4d2de 100644 --- a/libraries/physics/src/ThreadSafeDynamicsWorld.h +++ b/libraries/physics/src/ThreadSafeDynamicsWorld.h @@ -37,6 +37,7 @@ public: btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration); + int getNumSubsteps() const { return _numSubsteps; } int stepSimulationWithSubstepCallback(btScalar timeStep, int maxSubSteps = 1, btScalar fixedTimeStep = btScalar(1.)/btScalar(60.), SubStepCallback onSubStep = []() { }); @@ -61,6 +62,7 @@ private: VectorOfMotionStates _deactivatedStates; SetOfMotionStates _activeStates; SetOfMotionStates _lastActiveStates; + int _numSubsteps { 0 }; }; #endif // hifi_ThreadSafeDynamicsWorld_h From 89f7eb0b301e99ae908f212f807af9eee496eb5d Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Fri, 25 May 2018 09:20:55 -0700 Subject: [PATCH 141/143] Adding fix for enabling saved front/back advanced controls. --- ...oggleAdvancedMovementForHandControllers.js | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/scripts/system/controllers/toggleAdvancedMovementForHandControllers.js b/scripts/system/controllers/toggleAdvancedMovementForHandControllers.js index a1b96ac607..2f3a1d9628 100644 --- a/scripts/system/controllers/toggleAdvancedMovementForHandControllers.js +++ b/scripts/system/controllers/toggleAdvancedMovementForHandControllers.js @@ -171,4 +171,25 @@ Messages.subscribe(HIFI_ADVANCED_MOVEMENT_DISABLER_CHANNEL); Messages.messageReceived.connect(handleMessage); + function initializeControls() { + if(HMD.active) { + if (Controller.Hardware.Vive !== undefined || Controller.Hardware.OculusTouch !== undefined) { + if (MyAvatar.useAdvancedMovementControls) { + Controller.disableMapping(DRIVING_MAPPING_NAME); + } else { + Controller.enableMapping(DRIVING_MAPPING_NAME); + } + + if (MyAvatar.getFlyingEnabled()) { + Controller.disableMapping(FLYING_MAPPING_NAME); + } else { + Controller.enableMapping(FLYING_MAPPING_NAME); + } + }); + + } + } + + initializeControls(); + }()); // END LOCAL_SCOPE From 8453c7baba9ada9bf890f8ae380a7a63e0e3de37 Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Fri, 25 May 2018 09:25:05 -0700 Subject: [PATCH 142/143] =?UTF-8?q?reverting=20commit=20=C2=9D802cedf1bc?= =?UTF-8?q?=20regarding=20toggleSpaceMode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/libraries/entitySelectionTool.js | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 1b41559160..d03d4477f7 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -1036,29 +1036,6 @@ SelectionDisplay = (function() { } }; - // FUNCTION: TOGGLE SPACE MODE - that.toggleSpaceMode = function() { - var wantDebug = false; - if (wantDebug) { - print("========> ToggleSpaceMode called. ========="); - } - if ((spaceMode === SPACE_WORLD) && (SelectionManager.selections.length > 1)) { - if (wantDebug) { - print("Local space editing is not available with multiple selections"); - } - return; - } - if (wantDebug) { - print("PreToggle: " + spaceMode); - } - spaceMode = (spaceMode === SPACE_LOCAL) ? SPACE_WORLD : SPACE_LOCAL; - that.updateHandles(); - if (wantDebug) { - print("PostToggle: " + spaceMode); - print("======== ToggleSpaceMode called. <========="); - } - }; - function addHandleTool(overlay, tool) { handleTools[overlay] = tool; return tool; From f7710d126fb4165e4b96a0af82bf94be87ba9099 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 29 May 2018 10:45:43 -0700 Subject: [PATCH 143/143] split up wireshark dissectors for sub protocols --- tools/dissectors/hf-avatar.lua | 297 +++++++++++++++++ tools/dissectors/hf-entity.lua | 36 +++ tools/dissectors/hfudt.lua | 296 +++++++++++++++++ tools/hfudt.lua | 571 --------------------------------- 4 files changed, 629 insertions(+), 571 deletions(-) create mode 100644 tools/dissectors/hf-avatar.lua create mode 100644 tools/dissectors/hf-entity.lua create mode 100644 tools/dissectors/hfudt.lua delete mode 100644 tools/hfudt.lua diff --git a/tools/dissectors/hf-avatar.lua b/tools/dissectors/hf-avatar.lua new file mode 100644 index 0000000000..231fd1b354 --- /dev/null +++ b/tools/dissectors/hf-avatar.lua @@ -0,0 +1,297 @@ +-- create the avatar protocol +p_hf_avatar = Proto("hf-avatar", "HF Avatar Protocol") + +-- avatar data fields +local f_avatar_id = ProtoField.guid("hf_avatar.avatar_id", "Avatar ID") +local f_avatar_data_has_flags = ProtoField.string("hf_avatar.avatar_has_flags", "Has Flags") +local f_avatar_data_position = ProtoField.string("hf_avatar.avatar_data_position", "Position") +local f_avatar_data_dimensions = ProtoField.string("hf_avatar.avatar_data_dimensions", "Dimensions") +local f_avatar_data_offset = ProtoField.string("hf_avatar.avatar_data_offset", "Offset") +local f_avatar_data_look_at_position = ProtoField.string("hf_avatar.avatar_data_look_at_position", "Look At Position") +local f_avatar_data_audio_loudness = ProtoField.string("hf_avatar.avatar_data_audio_loudness", "Audio Loudness") +local f_avatar_data_additional_flags = ProtoField.string("hf_avatar.avatar_data_additional_flags", "Additional Flags") +local f_avatar_data_parent_id = ProtoField.guid("hf_avatar.avatar_data_parent_id", "Parent ID") +local f_avatar_data_parent_joint_index = ProtoField.string("hf_avatar.avatar_data_parent_joint_index", "Parent Joint Index") +local f_avatar_data_local_position = ProtoField.string("hf_avatar.avatar_data_local_position", "Local Position") +local f_avatar_data_valid_rotations = ProtoField.string("hf_avatar.avatar_data_valid_rotations", "Valid Rotations") +local f_avatar_data_valid_translations = ProtoField.string("hf_avatar.avatar_data_valid_translations", "Valid Translations") +local f_avatar_data_default_rotations = ProtoField.string("hf_avatar.avatar_data_default_rotations", "Valid Default") +local f_avatar_data_default_translations = ProtoField.string("hf_avatar.avatar_data_default_translations", "Valid Default") + +p_hf_avatar.fields = { + f_avatar_id, f_avatar_data_parent_id +} + +local packet_type_extractor = Field.new('hfudt.type') + +function p_hf_avatar.dissector(buf, pinfo, tree) + pinfo.cols.protocol = p_hf_avatar.name + + avatar_subtree = tree:add(p_hf_avatar, buf()) + + local i = 0 + + local avatar_data + + local packet_type = packet_type_extractor().value + + if packet_type == 6 then + -- AvatarData packet + + -- uint16 sequence_number + local sequence_number = buf(i, 2):le_uint() + i = i + 2 + + local avatar_data_packet_len = buf:len() - i + avatar_data = decode_avatar_data_packet(buf(i, avatar_data_packet_len)) + i = i + avatar_data_packet_len + + add_avatar_data_subtrees(avatar_data) + + else + -- BulkAvatarData packet + while i < buf:len() do + -- avatar_id is first 16 bytes + avatar_subtree:add(f_avatar_id, buf(i, 16)) + i = i + 16 + + local avatar_data_packet_len = buf:len() - i + avatar_data = decode_avatar_data_packet(buf(i, avatar_data_packet_len)) + i = i + avatar_data_packet_len + + add_avatar_data_subtrees(avatar_data) + end + end +end + + +function add_avatar_data_subtrees(avatar_data) + if avatar_data["has_flags"] then + avatar_subtree:add(f_avatar_data_has_flags, avatar_data["has_flags"]) + end + if avatar_data["position"] then + avatar_subtree:add(f_avatar_data_position, avatar_data["position"]) + end + if avatar_data["dimensions"] then + avatar_subtree:add(f_avatar_data_dimensions, avatar_data["dimensions"]) + end + if avatar_data["offset"] then + avatar_subtree:add(f_avatar_data_offset, avatar_data["offset"]) + end + if avatar_data["look_at_position"] then + avatar_subtree:add(f_avatar_data_look_at_position, avatar_data["look_at_position"]) + end + if avatar_data["audio_loudness"] then + avatar_subtree:add(f_avatar_data_audio_loudness, avatar_data["audio_loudness"]) + end + if avatar_data["additional_flags"] then + avatar_subtree:add(f_avatar_data_additional_flags, avatar_data["additional_flags"]) + end + if avatar_data["parent_id"] then + avatar_subtree:add(f_avatar_data_parent_id, avatar_data["parent_id"]) + end + if avatar_data["parent_joint_index"] then + avatar_subtree:add(f_avatar_data_parent_joint_index, avatar_data["parent_joint_index"]) + end + if avatar_data["local_position"] then + avatar_subtree:add(f_avatar_data_local_position, avatar_data["local_position"]) + end + if avatar_data["valid_rotations"] then + avatar_subtree:add(f_avatar_data_valid_rotations, avatar_data["valid_rotations"]) + end + if avatar_data["valid_translations"] then + avatar_subtree:add(f_avatar_data_valid_translations, avatar_data["valid_translations"]) + end + if avatar_data["default_rotations"] then + avatar_subtree:add(f_avatar_data_default_rotations, avatar_data["default_rotations"]) + end + if avatar_data["default_translations"] then + avatar_subtree:add(f_avatar_data_default_translations, avatar_data["default_translations"]) + end +end + +function decode_vec3(buf) + local i = 0 + local x = buf(i, 4):le_float() + i = i + 4 + local y = buf(i, 4):le_float() + i = i + 4 + local z = buf(i, 4):le_float() + i = i + 4 + return {x, y, z} +end + +function decode_validity_bits(buf, num_bits) + -- first pass, decode each bit into an array of booleans + local i = 0 + local bit = 0 + local booleans = {} + for n = 1, num_bits do + local value = (bit32.band(buf(i, 1):uint(), bit32.lshift(1, bit)) ~= 0) + booleans[#booleans + 1] = value + bit = bit + 1 + if bit == 8 then + i = i + 1 + bit = 0 + end + end + + -- second pass, create a list of indices whos booleans are true + local result = {} + for n = 1, #booleans do + if booleans[n] then + result[#result + 1] = n + end + end + + return result +end + +function decode_avatar_data_packet(buf) + + local i = 0 + local result = {} + + -- uint16 has_flags + local has_flags = buf(i, 2):le_uint() + i = i + 2 + + local has_global_position = (bit32.band(has_flags, 1) ~= 0) + local has_bounding_box = (bit32.band(has_flags, 2) ~= 0) + local has_orientation = (bit32.band(has_flags, 4) ~= 0) + local has_scale = (bit32.band(has_flags, 8) ~= 0) + local has_look_at_position = (bit32.band(has_flags, 16) ~= 0) + local has_audio_loudness = (bit32.band(has_flags, 32) ~= 0) + local has_sensor_to_world_matrix = (bit32.band(has_flags, 64) ~= 0) + local has_additional_flags = (bit32.band(has_flags, 128) ~= 0) + local has_parent_info = (bit32.band(has_flags, 256) ~= 0) + local has_local_position = (bit32.band(has_flags, 512) ~= 0) + local has_face_tracker_info = (bit32.band(has_flags, 1024) ~= 0) + local has_joint_data = (bit32.band(has_flags, 2048) ~= 0) + local has_joint_default_pose_flags = (bit32.band(has_flags, 4096) ~= 0) + + result["has_flags"] = string.format("HasFlags: 0x%x", has_flags) + + if has_global_position then + local position = decode_vec3(buf(i, 12)) + result["position"] = string.format("Position: %.3f, %.3f, %.3f", position[1], position[2], position[3]) + i = i + 12 + end + + if has_bounding_box then + local dimensions = decode_vec3(buf(i, 12)) + i = i + 12 + local offset = decode_vec3(buf(i, 12)) + i = i + 12 + result["dimensions"] = string.format("Dimensions: %.3f, %.3f, %.3f", dimensions[1], dimensions[2], dimensions[3]) + result["offset"] = string.format("Offset: %.3f, %.3f, %.3f", offset[1], offset[2], offset[3]) + end + + if has_orientation then + -- TODO: orientation is hard to decode... + i = i + 6 + end + + if has_scale then + -- TODO: scale is hard to decode... + i = i + 2 + end + + if has_look_at_position then + local look_at = decode_vec3(buf(i, 12)) + i = i + 12 + result["look_at_position"] = string.format("Look At Position: %.3f, %.3f, %.3f", look_at[1], look_at[2], look_at[3]) + end + + if has_audio_loudness then + local loudness = buf(i, 1):uint() + i = i + 1 + result["audio_loudness"] = string.format("Audio Loudness: %d", loudness) + end + + if has_sensor_to_world_matrix then + -- TODO: sensor to world matrix is hard to decode + i = i + 20 + end + + if has_additional_flags then + local flags = buf(i, 1):uint() + i = i + 1 + result["additional_flags"] = string.format("Additional Flags: 0x%x", flags) + end + + if has_parent_info then + local parent_id = buf(i, 16) + i = i + 16 + local parent_joint_index = buf(i, 2):le_int() + i = i + 2 + result["parent_id"] = parent_id + result["parent_joint_index"] = string.format("Parent Joint Index: %d", parent_joint_index) + end + + if has_local_position then + local local_pos = decode_vec3(buf(i, 12)) + i = i + 12 + result["local_position"] = string.format("Local Position: %.3f, %.3f, %.3f", local_pos[1], local_pos[2], local_pos[3]) + end + + if has_face_tracker_info then + local left_eye_blink = buf(i, 4):le_float() + i = i + 4 + local right_eye_blink = buf(i, 4):le_float() + i = i + 4 + local average_loudness = buf(i, 4):le_float() + i = i + 4 + local brow_audio_lift = buf(i, 4):le_float() + i = i + 4 + local num_blendshape_coefficients = buf(i, 1):uint() + i = i + 1 + local blendshape_coefficients = {} + for n = 1, num_blendshape_coefficients do + blendshape_coefficients[n] = buf(i, 4):le_float() + i = i + 4 + end + -- TODO: insert blendshapes into result + end + + if has_joint_data then + + local num_joints = buf(i, 1):uint() + i = i + 1 + local num_validity_bytes = math.ceil(num_joints / 8) + + local indices = decode_validity_bits(buf(i, num_validity_bytes), num_joints) + i = i + num_validity_bytes + result["valid_rotations"] = "Valid Rotations: " .. string.format("(%d/%d) {", #indices, num_joints) .. table.concat(indices, ", ") .. "}" + + -- TODO: skip rotations for now + i = i + #indices * 6 + + indices = decode_validity_bits(buf(i, num_validity_bytes), num_joints) + i = i + num_validity_bytes + result["valid_translations"] = "Valid Translations: " .. string.format("(%d/%d) {", #indices, num_joints) .. table.concat(indices, ", ") .. "}" + + -- TODO: skip translations for now + i = i + #indices * 6 + + -- TODO: skip hand controller data + i = i + 24 + + end + + if has_joint_default_pose_flags then + local num_joints = buf(i, 1):uint() + i = i + 1 + local num_validity_bytes = math.ceil(num_joints / 8) + + local indices = decode_validity_bits(buf(i, num_validity_bytes), num_joints) + i = i + num_validity_bytes + result["default_rotations"] = "Default Rotations: " .. string.format("(%d/%d) {", #indices, num_joints) .. table.concat(indices, ", ") .. "}" + + indices = decode_validity_bits(buf(i, num_validity_bytes), num_joints) + i = i + num_validity_bytes + result["default_translations"] = "Default Translations: " .. string.format("(%d/%d) {", #indices, num_joints) .. table.concat(indices, ", ") .. "}" + end + + return result +end diff --git a/tools/dissectors/hf-entity.lua b/tools/dissectors/hf-entity.lua new file mode 100644 index 0000000000..f4de5a995d --- /dev/null +++ b/tools/dissectors/hf-entity.lua @@ -0,0 +1,36 @@ +-- create the entity protocol +p_hf_entity = Proto("hf-entity", "HF Entity Protocol") + +-- entity packet fields +local f_entity_sequence_number = ProtoField.uint16("hf_entity.sequence_number", "Sequence Number") +local f_entity_timestamp = ProtoField.uint64("hf_entity.timestamp", "Timestamp") +local f_octal_code_bytes = ProtoField.uint8("hf_entity.octal_code_bytes", "Octal Code Bytes") +local f_entity_id = ProtoField.guid("hf_entity.entity_id", "Entity ID") + +p_hf_entity.fields = { + f_entity_sequence_number, f_entity_timestamp, f_octal_code_bytes, f_entity_id +} + +function p_hf_entity.dissector(buf, pinfo, tree) + pinfo.cols.protocol = p_hf_entity.name + + entity_subtree = tree:add(p_hf_entity, buf()) + + i = 0 + + entity_subtree:add_le(f_entity_sequence_number, buf(i, 2)) + i = i + 2 + + entity_subtree:add_le(f_entity_timestamp, buf(i, 4)) + i = i + 4 + + -- figure out the number of bytes the octal code takes + local octal_code_bytes = buf(i, 1):le_uint() + entity_subtree:add_le(f_octal_code_bytes, buf(i, 1)) + + -- skip over the octal code + i = i + 1 + octal_code_bytes + + -- read the entity ID + entity_subtree:add(f_entity_id, buf(i, 16)) +end diff --git a/tools/dissectors/hfudt.lua b/tools/dissectors/hfudt.lua new file mode 100644 index 0000000000..9d2df801b2 --- /dev/null +++ b/tools/dissectors/hfudt.lua @@ -0,0 +1,296 @@ +print("Loading hfudt") + +-- create the HFUDT protocol +p_hfudt = Proto("hfudt", "HFUDT Protocol") + +-- create fields shared between packets in HFUDT +local f_data = ProtoField.string("hfudt.data", "Data") + +-- create the fields for data packets in HFUDT +local f_length = ProtoField.uint16("hfudt.length", "Length", base.DEC) +local f_control_bit = ProtoField.uint8("hfudt.control", "Control Bit", base.DEC) +local f_reliable_bit = ProtoField.uint8("hfudt.reliable", "Reliability Bit", base.DEC) +local f_message_bit = ProtoField.uint8("hfudt.message", "Message Bit", base.DEC) +local f_obfuscation_level = ProtoField.uint8("hfudt.obfuscation_level", "Obfuscation Level", base.DEC) +local f_sequence_number = ProtoField.uint32("hfudt.sequence_number", "Sequence Number", base.DEC) +local f_message_position = ProtoField.uint8("hfudt.message_position", "Message Position", base.DEC) +local f_message_number = ProtoField.uint32("hfudt.message_number", "Message Number", base.DEC) +local f_message_part_number = ProtoField.uint32("hfudt.message_part_number", "Message Part Number", base.DEC) +local f_type = ProtoField.uint8("hfudt.type", "Type", base.DEC) +local f_version = ProtoField.uint8("hfudt.version", "Version", base.DEC) +local f_type_text = ProtoField.string("hfudt.type_text", "TypeText") +local f_sender_id = ProtoField.uint16("hfudt.sender_id", "Sender ID", base.DEC) +local f_hmac_hash = ProtoField.bytes("hfudt.hmac_hash", "HMAC Hash") + +-- create the fields for control packets in HFUDT +local f_control_type = ProtoField.uint16("hfudt.control_type", "Control Type", base.DEC) +local f_control_type_text = ProtoField.string("hfudt.control_type_text", "Control Type Text", base.ASCII) +local f_ack_sequence_number = ProtoField.uint32("hfudt.ack_sequence_number", "ACKed Sequence Number", base.DEC) +local f_control_sub_sequence = ProtoField.uint32("hfudt.control_sub_sequence", "Control Sub-Sequence Number", base.DEC) +local f_nak_sequence_number = ProtoField.uint32("hfudt.nak_sequence_number", "NAKed Sequence Number", base.DEC) +local f_nak_range_end = ProtoField.uint32("hfudt.nak_range_end", "NAK Range End", base.DEC) + +local SEQUENCE_NUMBER_MASK = 0x07FFFFFF + +p_hfudt.fields = { + f_length, + f_control_bit, f_reliable_bit, f_message_bit, f_sequence_number, f_type, f_type_text, f_version, + f_sender_id, f_hmac_hash, + f_message_position, f_message_number, f_message_part_number, f_obfuscation_level, + f_control_type, f_control_type_text, f_control_sub_sequence, f_ack_sequence_number, f_nak_sequence_number, f_nak_range_end, + f_data +} + +local control_types = { + [0] = { "ACK", "Acknowledgement" }, + [1] = { "ACK2", "Acknowledgement of acknowledgement" }, + [2] = { "LightACK", "Light Acknowledgement" }, + [3] = { "NAK", "Loss report (NAK)" }, + [4] = { "TimeoutNAK", "Loss report re-transmission (TimeoutNAK)" }, + [5] = { "Handshake", "Handshake" }, + [6] = { "HandshakeACK", "Acknowledgement of Handshake" }, + [7] = { "ProbeTail", "Probe tail" }, + [8] = { "HandshakeRequest", "Request a Handshake" } +} + +local message_positions = { + [0] = "ONLY", + [1] = "LAST", + [2] = "FIRST", + [3] = "MIDDLE" +} + +local packet_types = { + [0] = "Unknown", + [1] = "StunResponse", + [2] = "DomainList", + [3] = "Ping", + [4] = "PingReply", + [5] = "KillAvatar", + [6] = "AvatarData", + [7] = "InjectAudio", + [8] = "MixedAudio", + [9] = "MicrophoneAudioNoEcho", + [10] = "MicrophoneAudioWithEcho", + [11] = "BulkAvatarData", + [12] = "SilentAudioFrame", + [13] = "DomainListRequest", + [14] = "RequestAssignment", + [15] = "CreateAssignment", + [16] = "DomainConnectionDenied", + [17] = "MuteEnvironment", + [18] = "AudioStreamStats", + [19] = "DomainServerPathQuery", + [20] = "DomainServerPathResponse", + [21] = "DomainServerAddedNode", + [22] = "ICEServerPeerInformation", + [23] = "ICEServerQuery", + [24] = "OctreeStats", + [25] = "Jurisdiction", + [26] = "JurisdictionRequest", + [27] = "AssignmentClientStatus", + [28] = "NoisyMute", + [29] = "AvatarIdentity", + [30] = "AvatarBillboard", + [31] = "DomainConnectRequest", + [32] = "DomainServerRequireDTLS", + [33] = "NodeJsonStats", + [34] = "OctreeDataNack", + [35] = "StopNode", + [36] = "AudioEnvironment", + [37] = "EntityEditNack", + [38] = "ICEServerHeartbeat", + [39] = "ICEPing", + [40] = "ICEPingReply", + [41] = "EntityData", + [42] = "EntityQuery", + [43] = "EntityAdd", + [44] = "EntityErase", + [45] = "EntityEdit", + [46] = "DomainServerConnectionToken", + [47] = "DomainSettingsRequest", + [48] = "DomainSettings", + [49] = "AssetGet", + [50] = "AssetGetReply", + [51] = "AssetUpload", + [52] = "AssetUploadReply", + [53] = "AssetGetInfo", + [54] = "AssetGetInfoReply" +} + +function p_hfudt.dissector(buf, pinfo, tree) + + -- make sure this isn't a STUN packet - those don't follow HFUDT format + if pinfo.dst == Address.ip("stun.highfidelity.io") then return end + + -- validate that the packet length is at least the minimum control packet size + if buf:len() < 4 then return end + + -- create a subtree for HFUDT + subtree = tree:add(p_hfudt, buf(0)) + + -- set the packet length + subtree:add(f_length, buf:len()) + + -- pull out the entire first word + local first_word = buf(0, 4):le_uint() + + -- pull out the control bit and add it to the subtree + local control_bit = bit32.rshift(first_word, 31) + subtree:add(f_control_bit, control_bit) + + local data_length = 0 + + if control_bit == 1 then + -- dissect the control packet + pinfo.cols.protocol = p_hfudt.name .. " Control" + + -- remove the control bit and shift to the right to get the type value + local shifted_type = bit32.rshift(bit32.lshift(first_word, 1), 17) + local type = subtree:add(f_control_type, shifted_type) + + if control_types[shifted_type] ~= nil then + -- if we know this type then add the name + type:append_text(" (".. control_types[shifted_type][1] .. ")") + + subtree:add(f_control_type_text, control_types[shifted_type][1]) + end + + if shifted_type == 0 or shifted_type == 1 then + + -- this has a sub-sequence number + local second_word = buf(4, 4):le_uint() + subtree:add(f_control_sub_sequence, bit32.band(second_word, SEQUENCE_NUMBER_MASK)) + + local data_index = 8 + + if shifted_type == 0 then + -- if this is an ACK let's read out the sequence number + local sequence_number = buf(8, 4):le_uint() + subtree:add(f_ack_sequence_number, bit32.band(sequence_number, SEQUENCE_NUMBER_MASK)) + + data_index = data_index + 4 + end + + data_length = buf:len() - data_index + + -- set the data from whatever is left in the packet + subtree:add(f_data, buf(data_index, data_length)) + + elseif shifted_type == 2 then + -- this is a Light ACK let's read out the sequence number + local sequence_number = buf(4, 4):le_uint() + subtree:add(f_ack_sequence_number, bit32.band(sequence_number, SEQUENCE_NUMBER_MASK)) + + data_length = buf:len() - 4 + + -- set the data from whatever is left in the packet + subtree:add(f_data, buf(4, data_length)) + elseif shifted_type == 3 or shifted_type == 4 then + if buf:len() <= 12 then + -- this is a NAK pull the sequence number or range + local sequence_number = buf(4, 4):le_uint() + subtree:add(f_nak_sequence_number, bit32.band(sequence_number, SEQUENCE_NUMBER_MASK)) + + data_length = buf:len() - 4 + + if buf:len() > 8 then + local range_end = buf(8, 4):le_uint() + subtree:add(f_nak_range_end, bit32.band(range_end, SEQUENCE_NUMBER_MASK)) + + data_length = data_length - 4 + end + end + else + data_length = buf:len() - 4 + + -- no sub-sequence number, just read the data + subtree:add(f_data, buf(4, data_length)) + end + else + -- dissect the data packet + pinfo.cols.protocol = p_hfudt.name + + -- set the reliability bit + subtree:add(f_reliable_bit, bit32.rshift(first_word, 30)) + + local message_bit = bit32.band(0x01, bit32.rshift(first_word, 29)) + + -- set the message bit + subtree:add(f_message_bit, message_bit) + + -- read the obfuscation level + local obfuscation_bits = bit32.band(0x03, bit32.rshift(first_word, 27)) + subtree:add(f_obfuscation_level, obfuscation_bits) + + -- read the sequence number + subtree:add(f_sequence_number, bit32.band(first_word, SEQUENCE_NUMBER_MASK)) + + local payload_offset = 4 + + -- if the message bit is set, handle the second word + if message_bit == 1 then + payload_offset = 12 + + local second_word = buf(4, 4):le_uint() + + -- read message position from upper 2 bits + local message_position = bit32.rshift(second_word, 30) + local position = subtree:add(f_message_position, message_position) + + if message_positions[message_position] ~= nil then + -- if we know this position then add the name + position:append_text(" (".. message_positions[message_position] .. ")") + end + + -- read message number from lower 30 bits + subtree:add(f_message_number, bit32.band(second_word, 0x3FFFFFFF)) + + -- read the message part number + subtree:add(f_message_part_number, buf(8, 4):le_uint()) + end + + -- read the type + local packet_type = buf(payload_offset, 1):le_uint() + local ptype = subtree:add_le(f_type, buf(payload_offset, 1)) + if packet_types[packet_type] ~= nil then + subtree:add(f_type_text, packet_types[packet_type]) + -- if we know this packet type then add the name + ptype:append_text(" (".. packet_types[packet_type] .. ")") + end + + -- read the version + subtree:add_le(f_version, buf(payload_offset + 1, 1)) + + -- read node local ID + local sender_id = buf(payload_offset + 2, 2) + subtree:add_le(f_sender_id, sender_id) + + local i = payload_offset + 4 + + -- read HMAC MD5 hash + subtree:add(f_hmac_hash, buf(i, 16)) + i = i + 16 + + -- AvatarData or BulkAvatarDataPacket + if packet_types[packet_type] == "AvatarData" or packet_types[packet_type] == "BulkAvatarDataPacket" then + Dissector.get("hf-avatar"):call(buf(i):tvb(), pinfo, tree) + end + + if packet_types[packet_type] == "EntityEdit" then + Dissector.get("hf-entity"):call(buf(i):tvb(), pinfo, tree) + end + end + + -- return the size of the header + return buf:len() + +end + +function p_hfudt.init() + local udp_dissector_table = DissectorTable.get("udp.port") + + for port=1000, 65000 do + udp_dissector_table:add(port, p_hfudt) + end +end diff --git a/tools/hfudt.lua b/tools/hfudt.lua deleted file mode 100644 index f45315a3de..0000000000 --- a/tools/hfudt.lua +++ /dev/null @@ -1,571 +0,0 @@ -print("Loading hfudt") - --- create the HFUDT protocol -p_hfudt = Proto("hfudt", "HFUDT Protocol") - --- create fields shared between packets in HFUDT -local f_data = ProtoField.string("hfudt.data", "Data") - --- create the fields for data packets in HFUDT -local f_length = ProtoField.uint16("hfudt.length", "Length", base.DEC) -local f_control_bit = ProtoField.uint8("hfudt.control", "Control Bit", base.DEC) -local f_reliable_bit = ProtoField.uint8("hfudt.reliable", "Reliability Bit", base.DEC) -local f_message_bit = ProtoField.uint8("hfudt.message", "Message Bit", base.DEC) -local f_obfuscation_level = ProtoField.uint8("hfudt.obfuscation_level", "Obfuscation Level", base.DEC) -local f_sequence_number = ProtoField.uint32("hfudt.sequence_number", "Sequence Number", base.DEC) -local f_message_position = ProtoField.uint8("hfudt.message_position", "Message Position", base.DEC) -local f_message_number = ProtoField.uint32("hfudt.message_number", "Message Number", base.DEC) -local f_message_part_number = ProtoField.uint32("hfudt.message_part_number", "Message Part Number", base.DEC) -local f_type = ProtoField.uint8("hfudt.type", "Type", base.DEC) -local f_version = ProtoField.uint8("hfudt.version", "Version", base.DEC) -local f_type_text = ProtoField.string("hfudt.type_text", "TypeText") -local f_sender_id = ProtoField.guid("hfudt.sender_id", "Sender ID", base.DEC) - --- create the fields for control packets in HFUDT -local f_control_type = ProtoField.uint16("hfudt.control_type", "Control Type", base.DEC) -local f_control_type_text = ProtoField.string("hfudt.control_type_text", "Control Type Text", base.ASCII) -local f_ack_sequence_number = ProtoField.uint32("hfudt.ack_sequence_number", "ACKed Sequence Number", base.DEC) -local f_control_sub_sequence = ProtoField.uint32("hfudt.control_sub_sequence", "Control Sub-Sequence Number", base.DEC) -local f_nak_sequence_number = ProtoField.uint32("hfudt.nak_sequence_number", "NAKed Sequence Number", base.DEC) -local f_nak_range_end = ProtoField.uint32("hfudt.nak_range_end", "NAK Range End", base.DEC) - --- avatar data fields -local f_avatar_data_id = ProtoField.guid("hfudt.avatar_id", "Avatar ID", base.DEC) -local f_avatar_data_has_flags = ProtoField.string("hfudt.avatar_has_flags", "Has Flags") -local f_avatar_data_position = ProtoField.string("hfudt.avatar_data_position", "Position") -local f_avatar_data_dimensions = ProtoField.string("hfudt.avatar_data_dimensions", "Dimensions") -local f_avatar_data_offset = ProtoField.string("hfudt.avatar_data_offset", "Offset") -local f_avatar_data_look_at_position = ProtoField.string("hfudt.avatar_data_look_at_position", "Look At Position") -local f_avatar_data_audio_loudness = ProtoField.string("hfudt.avatar_data_audio_loudness", "Audio Loudness") -local f_avatar_data_additional_flags = ProtoField.string("hfudt.avatar_data_additional_flags", "Additional Flags") -local f_avatar_data_parent_id = ProtoField.guid("hfudt.avatar_data_parent_id", "Parent ID") -local f_avatar_data_parent_joint_index = ProtoField.string("hfudt.avatar_data_parent_joint_index", "Parent Joint Index") -local f_avatar_data_local_position = ProtoField.string("hfudt.avatar_data_local_position", "Local Position") -local f_avatar_data_valid_rotations = ProtoField.string("hfudt.avatar_data_valid_rotations", "Valid Rotations") -local f_avatar_data_valid_translations = ProtoField.string("hfudt.avatar_data_valid_translations", "Valid Translations") -local f_avatar_data_default_rotations = ProtoField.string("hfudt.avatar_data_default_rotations", "Valid Default") -local f_avatar_data_default_translations = ProtoField.string("hfudt.avatar_data_default_translations", "Valid Default") - -local SEQUENCE_NUMBER_MASK = 0x07FFFFFF - -p_hfudt.fields = { - f_length, - f_control_bit, f_reliable_bit, f_message_bit, f_sequence_number, f_type, f_type_text, f_version, - f_sender_id, f_avatar_data_id, f_avatar_data_parent_id, - f_message_position, f_message_number, f_message_part_number, f_obfuscation_level, - f_control_type, f_control_type_text, f_control_sub_sequence, f_ack_sequence_number, f_nak_sequence_number, f_nak_range_end, - f_data -} - -p_hfudt.prefs["udp_port"] = Pref.uint("UDP Port", 40102, "UDP Port for HFUDT Packets (udt::Socket bound port)") - -local control_types = { - [0] = { "ACK", "Acknowledgement" }, - [1] = { "ACK2", "Acknowledgement of acknowledgement" }, - [2] = { "LightACK", "Light Acknowledgement" }, - [3] = { "NAK", "Loss report (NAK)" }, - [4] = { "TimeoutNAK", "Loss report re-transmission (TimeoutNAK)" }, - [5] = { "Handshake", "Handshake" }, - [6] = { "HandshakeACK", "Acknowledgement of Handshake" }, - [7] = { "ProbeTail", "Probe tail" }, - [8] = { "HandshakeRequest", "Request a Handshake" } -} - -local message_positions = { - [0] = "ONLY", - [1] = "LAST", - [2] = "FIRST", - [3] = "MIDDLE" -} - -local packet_types = { - [0] = "Unknown", - [1] = "StunResponse", - [2] = "DomainList", - [3] = "Ping", - [4] = "PingReply", - [5] = "KillAvatar", - [6] = "AvatarData", - [7] = "InjectAudio", - [8] = "MixedAudio", - [9] = "MicrophoneAudioNoEcho", - [10] = "MicrophoneAudioWithEcho", - [11] = "BulkAvatarData", - [12] = "SilentAudioFrame", - [13] = "DomainListRequest", - [14] = "RequestAssignment", - [15] = "CreateAssignment", - [16] = "DomainConnectionDenied", - [17] = "MuteEnvironment", - [18] = "AudioStreamStats", - [19] = "DomainServerPathQuery", - [20] = "DomainServerPathResponse", - [21] = "DomainServerAddedNode", - [22] = "ICEServerPeerInformation", - [23] = "ICEServerQuery", - [24] = "OctreeStats", - [25] = "Jurisdiction", - [26] = "JurisdictionRequest", - [27] = "AssignmentClientStatus", - [28] = "NoisyMute", - [29] = "AvatarIdentity", - [30] = "AvatarBillboard", - [31] = "DomainConnectRequest", - [32] = "DomainServerRequireDTLS", - [33] = "NodeJsonStats", - [34] = "OctreeDataNack", - [35] = "StopNode", - [36] = "AudioEnvironment", - [37] = "EntityEditNack", - [38] = "ICEServerHeartbeat", - [39] = "ICEPing", - [40] = "ICEPingReply", - [41] = "EntityData", - [42] = "EntityQuery", - [43] = "EntityAdd", - [44] = "EntityErase", - [45] = "EntityEdit", - [46] = "DomainServerConnectionToken", - [47] = "DomainSettingsRequest", - [48] = "DomainSettings", - [49] = "AssetGet", - [50] = "AssetGetReply", - [51] = "AssetUpload", - [52] = "AssetUploadReply", - [53] = "AssetGetInfo", - [54] = "AssetGetInfoReply" -} - -function p_hfudt.dissector (buf, pinfo, root) - - -- make sure this isn't a STUN packet - those don't follow HFUDT format - if pinfo.dst == Address.ip("stun.highfidelity.io") then return end - - -- validate that the packet length is at least the minimum control packet size - if buf:len() < 4 then return end - - -- create a subtree for HFUDT - subtree = root:add(p_hfudt, buf(0)) - - -- set the packet length - subtree:add(f_length, buf:len()) - - -- pull out the entire first word - local first_word = buf(0, 4):le_uint() - - -- pull out the control bit and add it to the subtree - local control_bit = bit32.rshift(first_word, 31) - subtree:add(f_control_bit, control_bit) - - local data_length = 0 - - if control_bit == 1 then - -- dissect the control packet - pinfo.cols.protocol = p_hfudt.name .. " Control" - - -- remove the control bit and shift to the right to get the type value - local shifted_type = bit32.rshift(bit32.lshift(first_word, 1), 17) - local type = subtree:add(f_control_type, shifted_type) - - if control_types[shifted_type] ~= nil then - -- if we know this type then add the name - type:append_text(" (".. control_types[shifted_type][1] .. ")") - - subtree:add(f_control_type_text, control_types[shifted_type][1]) - end - - if shifted_type == 0 or shifted_type == 1 then - - -- this has a sub-sequence number - local second_word = buf(4, 4):le_uint() - subtree:add(f_control_sub_sequence, bit32.band(second_word, SEQUENCE_NUMBER_MASK)) - - local data_index = 8 - - if shifted_type == 0 then - -- if this is an ACK let's read out the sequence number - local sequence_number = buf(8, 4):le_uint() - subtree:add(f_ack_sequence_number, bit32.band(sequence_number, SEQUENCE_NUMBER_MASK)) - - data_index = data_index + 4 - end - - data_length = buf:len() - data_index - - -- set the data from whatever is left in the packet - subtree:add(f_data, buf(data_index, data_length)) - - elseif shifted_type == 2 then - -- this is a Light ACK let's read out the sequence number - local sequence_number = buf(4, 4):le_uint() - subtree:add(f_ack_sequence_number, bit32.band(sequence_number, SEQUENCE_NUMBER_MASK)) - - data_length = buf:len() - 4 - - -- set the data from whatever is left in the packet - subtree:add(f_data, buf(4, data_length)) - elseif shifted_type == 3 or shifted_type == 4 then - if buf:len() <= 12 then - -- this is a NAK pull the sequence number or range - local sequence_number = buf(4, 4):le_uint() - subtree:add(f_nak_sequence_number, bit32.band(sequence_number, SEQUENCE_NUMBER_MASK)) - - data_length = buf:len() - 4 - - if buf:len() > 8 then - local range_end = buf(8, 4):le_uint() - subtree:add(f_nak_range_end, bit32.band(range_end, SEQUENCE_NUMBER_MASK)) - - data_length = data_length - 4 - end - end - else - data_length = buf:len() - 4 - - -- no sub-sequence number, just read the data - subtree:add(f_data, buf(4, data_length)) - end - else - -- dissect the data packet - pinfo.cols.protocol = p_hfudt.name - - -- set the reliability bit - subtree:add(f_reliable_bit, bit32.rshift(first_word, 30)) - - local message_bit = bit32.band(0x01, bit32.rshift(first_word, 29)) - - -- set the message bit - subtree:add(f_message_bit, message_bit) - - -- read the obfuscation level - local obfuscation_bits = bit32.band(0x03, bit32.rshift(first_word, 27)) - subtree:add(f_obfuscation_level, obfuscation_bits) - - -- read the sequence number - subtree:add(f_sequence_number, bit32.band(first_word, SEQUENCE_NUMBER_MASK)) - - local payload_offset = 4 - - -- if the message bit is set, handle the second word - if message_bit == 1 then - payload_offset = 12 - - local second_word = buf(4, 4):le_uint() - - -- read message position from upper 2 bits - local message_position = bit32.rshift(second_word, 30) - local position = subtree:add(f_message_position, message_position) - - if message_positions[message_position] ~= nil then - -- if we know this position then add the name - position:append_text(" (".. message_positions[message_position] .. ")") - end - - -- read message number from lower 30 bits - subtree:add(f_message_number, bit32.band(second_word, 0x3FFFFFFF)) - - -- read the message part number - subtree:add(f_message_part_number, buf(8, 4):le_uint()) - end - - -- read the type - local packet_type = buf(payload_offset, 1):le_uint() - local ptype = subtree:add(f_type, packet_type) - if packet_types[packet_type] ~= nil then - subtree:add(f_type_text, packet_types[packet_type]) - -- if we know this packet type then add the name - ptype:append_text(" (".. packet_types[packet_type] .. ")") - end - - -- read the version - subtree:add(f_version, buf(payload_offset + 1, 1):le_uint()) - - -- read node GUID - local sender_id = buf(payload_offset + 2, 16) - subtree:add(f_sender_id, sender_id) - - local i = payload_offset + 18 - - -- skip MD6 checksum + 16 bytes - i = i + 16 - - -- AvatarData or BulkAvatarDataPacket - if packet_type == 6 or packet_type == 11 then - - local avatar_data - if packet_type == 6 then - -- AvatarData packet - - -- avatar_id is same as sender_id - subtree:add(f_avatar_data_id, sender_id) - - -- uint16 sequence_number - local sequence_number = buf(i, 2):le_uint() - i = i + 2 - - local avatar_data_packet_len = buf:len() - i - avatar_data = decode_avatar_data_packet(buf(i, avatar_data_packet_len)) - i = i + avatar_data_packet_len - - add_avatar_data_subtrees(avatar_data) - - else - -- BulkAvatarData packet - while i < buf:len() do - -- avatar_id is first 16 bytes - subtree:add(f_avatar_data_id, buf(i, 16)) - i = i + 16 - - local avatar_data_packet_len = buf:len() - i - avatar_data = decode_avatar_data_packet(buf(i, avatar_data_packet_len)) - i = i + avatar_data_packet_len - - add_avatar_data_subtrees(avatar_data) - end - end - end - end - - -- return the size of the header - return buf:len() - -end - -function add_avatar_data_subtrees(avatar_data) - if avatar_data["has_flags"] then - subtree:add(f_avatar_data_has_flags, avatar_data["has_flags"]) - end - if avatar_data["position"] then - subtree:add(f_avatar_data_position, avatar_data["position"]) - end - if avatar_data["dimensions"] then - subtree:add(f_avatar_data_dimensions, avatar_data["dimensions"]) - end - if avatar_data["offset"] then - subtree:add(f_avatar_data_offset, avatar_data["offset"]) - end - if avatar_data["look_at_position"] then - subtree:add(f_avatar_data_look_at_position, avatar_data["look_at_position"]) - end - if avatar_data["audio_loudness"] then - subtree:add(f_avatar_data_audio_loudness, avatar_data["audio_loudness"]) - end - if avatar_data["additional_flags"] then - subtree:add(f_avatar_data_additional_flags, avatar_data["additional_flags"]) - end - if avatar_data["parent_id"] then - subtree:add(f_avatar_data_parent_id, avatar_data["parent_id"]) - end - if avatar_data["parent_joint_index"] then - subtree:add(f_avatar_data_parent_joint_index, avatar_data["parent_joint_index"]) - end - if avatar_data["local_position"] then - subtree:add(f_avatar_data_local_position, avatar_data["local_position"]) - end - if avatar_data["valid_rotations"] then - subtree:add(f_avatar_data_valid_rotations, avatar_data["valid_rotations"]) - end - if avatar_data["valid_translations"] then - subtree:add(f_avatar_data_valid_translations, avatar_data["valid_translations"]) - end - if avatar_data["default_rotations"] then - subtree:add(f_avatar_data_default_rotations, avatar_data["default_rotations"]) - end - if avatar_data["default_translations"] then - subtree:add(f_avatar_data_default_translations, avatar_data["default_translations"]) - end -end - -function decode_vec3(buf) - local i = 0 - local x = buf(i, 4):le_float() - i = i + 4 - local y = buf(i, 4):le_float() - i = i + 4 - local z = buf(i, 4):le_float() - i = i + 4 - return {x, y, z} -end - -function decode_validity_bits(buf, num_bits) - -- first pass, decode each bit into an array of booleans - local i = 0 - local bit = 0 - local booleans = {} - for n = 1, num_bits do - local value = (bit32.band(buf(i, 1):uint(), bit32.lshift(1, bit)) ~= 0) - booleans[#booleans + 1] = value - bit = bit + 1 - if bit == 8 then - i = i + 1 - bit = 0 - end - end - - -- second pass, create a list of indices whos booleans are true - local result = {} - for n = 1, #booleans do - if booleans[n] then - result[#result + 1] = n - end - end - - return result -end - -function decode_avatar_data_packet(buf) - - local i = 0 - local result = {} - - -- uint16 has_flags - local has_flags = buf(i, 2):le_uint() - i = i + 2 - - local has_global_position = (bit32.band(has_flags, 1) ~= 0) - local has_bounding_box = (bit32.band(has_flags, 2) ~= 0) - local has_orientation = (bit32.band(has_flags, 4) ~= 0) - local has_scale = (bit32.band(has_flags, 8) ~= 0) - local has_look_at_position = (bit32.band(has_flags, 16) ~= 0) - local has_audio_loudness = (bit32.band(has_flags, 32) ~= 0) - local has_sensor_to_world_matrix = (bit32.band(has_flags, 64) ~= 0) - local has_additional_flags = (bit32.band(has_flags, 128) ~= 0) - local has_parent_info = (bit32.band(has_flags, 256) ~= 0) - local has_local_position = (bit32.band(has_flags, 512) ~= 0) - local has_face_tracker_info = (bit32.band(has_flags, 1024) ~= 0) - local has_joint_data = (bit32.band(has_flags, 2048) ~= 0) - local has_joint_default_pose_flags = (bit32.band(has_flags, 4096) ~= 0) - - result["has_flags"] = string.format("HasFlags: 0x%x", has_flags) - - if has_global_position then - local position = decode_vec3(buf(i, 12)) - result["position"] = string.format("Position: %.3f, %.3f, %.3f", position[1], position[2], position[3]) - i = i + 12 - end - - if has_bounding_box then - local dimensions = decode_vec3(buf(i, 12)) - i = i + 12 - local offset = decode_vec3(buf(i, 12)) - i = i + 12 - result["dimensions"] = string.format("Dimensions: %.3f, %.3f, %.3f", dimensions[1], dimensions[2], dimensions[3]) - result["offset"] = string.format("Offset: %.3f, %.3f, %.3f", offset[1], offset[2], offset[3]) - end - - if has_orientation then - -- TODO: orientation is hard to decode... - i = i + 6 - end - - if has_scale then - -- TODO: scale is hard to decode... - i = i + 2 - end - - if has_look_at_position then - local look_at = decode_vec3(buf(i, 12)) - i = i + 12 - result["look_at_position"] = string.format("Look At Position: %.3f, %.3f, %.3f", look_at[1], look_at[2], look_at[3]) - end - - if has_audio_loudness then - local loudness = buf(i, 1):uint() - i = i + 1 - result["audio_loudness"] = string.format("Audio Loudness: %d", loudness) - end - - if has_sensor_to_world_matrix then - -- TODO: sensor to world matrix is hard to decode - i = i + 20 - end - - if has_additional_flags then - local flags = buf(i, 1):uint() - i = i + 1 - result["additional_flags"] = string.format("Additional Flags: 0x%x", flags) - end - - if has_parent_info then - local parent_id = buf(i, 16) - i = i + 16 - local parent_joint_index = buf(i, 2):le_int() - i = i + 2 - result["parent_id"] = parent_id - result["parent_joint_index"] = string.format("Parent Joint Index: %d", parent_joint_index) - end - - if has_local_position then - local local_pos = decode_vec3(buf(i, 12)) - i = i + 12 - result["local_position"] = string.format("Local Position: %.3f, %.3f, %.3f", local_pos[1], local_pos[2], local_pos[3]) - end - - if has_face_tracker_info then - local left_eye_blink = buf(i, 4):le_float() - i = i + 4 - local right_eye_blink = buf(i, 4):le_float() - i = i + 4 - local average_loudness = buf(i, 4):le_float() - i = i + 4 - local brow_audio_lift = buf(i, 4):le_float() - i = i + 4 - local num_blendshape_coefficients = buf(i, 1):uint() - i = i + 1 - local blendshape_coefficients = {} - for n = 1, num_blendshape_coefficients do - blendshape_coefficients[n] = buf(i, 4):le_float() - i = i + 4 - end - -- TODO: insert blendshapes into result - end - - if has_joint_data then - - local num_joints = buf(i, 1):uint() - i = i + 1 - local num_validity_bytes = math.ceil(num_joints / 8) - - local indices = decode_validity_bits(buf(i, num_validity_bytes), num_joints) - i = i + num_validity_bytes - result["valid_rotations"] = "Valid Rotations: " .. string.format("(%d/%d) {", #indices, num_joints) .. table.concat(indices, ", ") .. "}" - - -- TODO: skip rotations for now - i = i + #indices * 6 - - indices = decode_validity_bits(buf(i, num_validity_bytes), num_joints) - i = i + num_validity_bytes - result["valid_translations"] = "Valid Translations: " .. string.format("(%d/%d) {", #indices, num_joints) .. table.concat(indices, ", ") .. "}" - - -- TODO: skip translations for now - i = i + #indices * 6 - - -- TODO: skip hand controller data - i = i + 24 - - end - - if has_joint_default_pose_flags then - local num_joints = buf(i, 1):uint() - i = i + 1 - local num_validity_bytes = math.ceil(num_joints / 8) - - local indices = decode_validity_bits(buf(i, num_validity_bytes), num_joints) - i = i + num_validity_bytes - result["default_rotations"] = "Default Rotations: " .. string.format("(%d/%d) {", #indices, num_joints) .. table.concat(indices, ", ") .. "}" - - indices = decode_validity_bits(buf(i, num_validity_bytes), num_joints) - i = i + num_validity_bytes - result["default_translations"] = "Default Translations: " .. string.format("(%d/%d) {", #indices, num_joints) .. table.concat(indices, ", ") .. "}" - end - - return result -end - -function p_hfudt.init() - local udp_dissector_table = DissectorTable.get("udp.port") - - for port=1000, 65000 do - udp_dissector_table:add(port, p_hfudt) - end -end

s|nTxKobcEh9G^mwlu9 z`hrUg#5DQ_`#9QpIyI2nKN@iQ9Bj|sipiLcTXl``c!O^_|LID?+RKQS*WX%MVq1ig zrl6!L*v)o*udir>x`BD-Jk<0|e#XL-W|d$un(=F2+1++1>3?NrH#VaRKxfp)`=M@q zAj#rb_5rqyj`#bY9_oGc8dDx<)&3fKH9r6)bC&9Xcmiye_3TjNyNT1};KsMwlq&&j sepFgJpbO+-xCz4OhM3N`CIJHA7ehMl0>ZgJnE(I)07*qoM6N<$g1Z#FTL1t6 literal 0 HcmV?d00001 diff --git a/interface/resources/qml/hifi/dialogs/AboutDialog.qml b/interface/resources/qml/hifi/dialogs/AboutDialog.qml new file mode 100644 index 0000000000..b8e6e89aec --- /dev/null +++ b/interface/resources/qml/hifi/dialogs/AboutDialog.qml @@ -0,0 +1,32 @@ +// +// AssetDialog.qml +// +// Created by David Rowe on 18 Apr 2017 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.8 + +import "../../styles-uit" +import "../../windows" + +ScrollingWindow { + id: root + resizable: false + implicitWidth: 480 + implicitHeight: 706 + objectName: "aboutDialog" + destroyOnCloseButton: true + destroyOnHidden: true + visible: true + minSize: Qt.vector2d(480, 706) + title: "About" + + TabletAboutDialog { + width: pane.width + height: pane.height + } +} diff --git a/interface/resources/qml/hifi/dialogs/TabletAboutDialog.qml b/interface/resources/qml/hifi/dialogs/TabletAboutDialog.qml new file mode 100644 index 0000000000..d89f8cafe3 --- /dev/null +++ b/interface/resources/qml/hifi/dialogs/TabletAboutDialog.qml @@ -0,0 +1,120 @@ +// +// TabletAssetDialog.qml +// +// Created by David Rowe on 18 Apr 2017 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 + +import "../../styles-uit" + +Rectangle { + width: 480 + height: 706 + + HifiConstants { id: hifi; } + + color: hifi.colors.baseGray + + Column { + x: 45 + y: 30 + spacing: 5 + + Image { + sourceSize.width: 295 + sourceSize.height: 75 + source: "../../../images/about-highfidelity.png" + } + Column { + id: buildColumm + anchors.left: parent.left + anchors.leftMargin: 70 + Row { + RalewayRegular { + text: "Build" + size: 16 + color: "white" + } + RalewayRegular { + id: build + size: 16 + color: "white" + } + } + Row { + RalewayRegular { + text: "Released" + size: 16 + color: "white" + } + RalewayRegular { + id: released + size: 16 + color: "white" + } + } + } + Item { height: 10; width: 1 } + RalewayRegular { + text: "An open-source virtual reality platform." + size: 20 + color: "white" + } + RalewayRegular { + textFormat: Text.RichText + color: "white" + text: "www.highfidelity.com." + size: 20 + } + Item { height: 40; width: 1 } + Row { + spacing: 5 + Image { + sourceSize.width: 34 + sourceSize.height: 25 + source: "../../../images/about-qt.png" + } + RalewayRegular { + color: "white" + text: "Built using Qt 5.10.1" + size: 12 + anchors.verticalCenter: parent.verticalCenter + } + Item { height: 1; width: 15 } + Image { + sourceSize.width: 70 + sourceSize.height: 26 + source: "../../../images/about-physics.png" + } + RalewayRegular { + color: "white" + text: "Physics powered by Bullet" + size: 12 + anchors.verticalCenter: parent.verticalCenter + } + } + Item { height: 20; width: 1 } + RalewayRegular { + textFormat: Text.RichText + color: "white" + text: "Blockchain technology from Elements." + size: 14 + } + RalewayRegular { + color: "white" + text: "© 2018 High Fidelity. All rights reserved." + size: 14 + } + RalewayRegular { + textFormat: Text.RichText + color: "white" + text: "Distributed under the Apache License, Version 2.0.." + size: 14 + } + } +} diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index d60e59a1cb..be50fe9119 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -814,9 +814,11 @@ Menu::Menu() { MenuWrapper * helpMenu = addMenu("Help"); // Help > About High Fidelity - //TODO: Add dialog to show about: Logo, Company, Version - addActionToQMenuAndActionHash(helpMenu, "About High Fidelity"); - + action = addActionToQMenuAndActionHash(helpMenu, "About High Fidelity"); + connect(action, &QAction::triggered, [] { + qApp->showDialog(QString("hifi/dialogs/AboutDialog.qml"), + QString("hifi/dialogs/TabletAboutDialog.qml"), "AboutDialog"); + }); helpMenu->addSeparator(); // Help > HiFi Docs From 82422edb59c3150c5a029ab22e53c1869d1dff5a Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 14 May 2018 18:51:39 -0700 Subject: [PATCH 045/143] fixinig the controller settings page and have menu option on by default --- .../qml/hifi/tablet/CalibratingScreen.qml | 2 +- .../qml/hifi/tablet/ControllerSettings.qml | 491 ++++++++++-------- .../tabletWindows/TabletPreferencesDialog.qml | 6 +- interface/src/Menu.cpp | 9 +- scripts/system/edit.js | 49 +- 5 files changed, 293 insertions(+), 264 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/CalibratingScreen.qml b/interface/resources/qml/hifi/tablet/CalibratingScreen.qml index 6c26bd87c5..e3115a5738 100644 --- a/interface/resources/qml/hifi/tablet/CalibratingScreen.qml +++ b/interface/resources/qml/hifi/tablet/CalibratingScreen.qml @@ -18,7 +18,7 @@ import "../../controls-uit" as HifiControls Rectangle { id: info - + anchors.fill: parent signal canceled() signal restart() diff --git a/interface/resources/qml/hifi/tablet/ControllerSettings.qml b/interface/resources/qml/hifi/tablet/ControllerSettings.qml index 4ee69c4982..f08d6899a3 100644 --- a/interface/resources/qml/hifi/tablet/ControllerSettings.qml +++ b/interface/resources/qml/hifi/tablet/ControllerSettings.qml @@ -8,6 +8,7 @@ import QtQuick 2.7 import QtQuick.Controls 2.2 +import QtQuick.Layouts 1.3 import QtGraphicalEffects 1.0 import Qt.labs.settings 1.0 import "../../styles-uit" @@ -15,237 +16,275 @@ import "../../controls" import "../../controls-uit" as HifiControls import "../../dialogs" import "../../dialogs/preferences" +import "tabletWindows" +import "../audio" -PreferencesDialog { - id: root - objectName: "ControlSettings" - title: "Control Settings" - showCategories: ["VR Movement", inputConfigurationComponents] - property var settings: Settings { - category: root.objectName - property alias x: root.x - property alias y: root.y - property alias width: root.width - property alias height: root.height - } - Component { - id: inputConfigurationComponents +Item { + id: controllerSettings + height: parent.height + width: parent.width - Preference { + HifiConstants { id: hifi } - StackView { - id: stack - initialItem: inputConfiguration - property alias messageVisible: imageMessageBox.visible - property alias selectedPlugin: box.currentText - Rectangle { - id: inputConfiguration - anchors.fill: parent + TabBar { + id: bar + spacing: 0 + width: parent.width - HifiConstants { id: hifi } - - color: hifi.colors.baseGray - - property var pluginSettings: null - - HifiControls.ImageMessageBox { - id: imageMessageBox - anchors.fill: parent - z: 2000 - imageWidth: 442 - imageHeight: 670 - source: "../../../images/calibration-help.png" - } - - Rectangle { - width: inputConfiguration.width - height: 1 - color: hifi.colors.baseGrayShadow - x: -hifi.dimensions.contentMargin.x - } - - RalewayRegular { - id: header - text: "Control Settings" - size: 22 - color: "white" - - anchors.top: inputConfiguration.top - anchors.left: inputConfiguration.left - anchors.leftMargin: 20 - anchors.topMargin: 20 - } - - Separator { - id: headerSeparator - width: inputConfiguration.width - anchors.top: header.bottom - anchors.topMargin: 10 - } - - HiFiGlyphs { - id: sourceGlyph - text: hifi.glyphs.source - size: 36 - color: hifi.colors.blueHighlight - - anchors.top: headerSeparator.bottom - anchors.left: inputConfiguration.left - anchors.leftMargin: 40 - anchors.topMargin: 20 - } - - RalewayRegular { - id: configuration - text: "SELECT DEVICE" - size: 15 - color: hifi.colors.lightGrayText - - - anchors.top: headerSeparator.bottom - anchors.left: sourceGlyph.right - anchors.leftMargin: 10 - anchors.topMargin: 30 - } - - Row { - id: configRow - z: 999 - anchors.top: sourceGlyph.bottom - anchors.topMargin: 20 - anchors.left: sourceGlyph.left - anchors.leftMargin: 40 - spacing: 10 - HifiControls.ComboBox { - id: box - width: 160 - z: 999 - editable: true - colorScheme: hifi.colorSchemes.dark - model: inputPlugins() - label: "" - - onCurrentIndexChanged: { - changeSource(); - } - } - - HifiControls.CheckBox { - id: checkBox - colorScheme: hifi.colorSchemes.dark - text: "show all input devices" - - onClicked: { - inputPlugins(); - changeSource(); - } - } - } - - - Separator { - id: configurationSeparator - z: 0 - width: inputConfiguration.width - anchors.top: configRow.bottom - anchors.topMargin: 10 - } - - - HiFiGlyphs { - id: sliderGlyph - text: hifi.glyphs.sliders - size: 36 - color: hifi.colors.blueHighlight - - anchors.top: configurationSeparator.bottom - anchors.left: inputConfiguration.left - anchors.leftMargin: 40 - anchors.topMargin: 20 - } - - RalewayRegular { - id: configurationHeader - text: "CONFIGURATION" - size: 15 - color: hifi.colors.lightGrayText - - - anchors.top: configurationSeparator.bottom - anchors.left: sliderGlyph.right - anchors.leftMargin: 10 - anchors.topMargin: 30 - } - - Loader { - id: loader - asynchronous: false - - width: inputConfiguration.width - anchors.left: inputConfiguration.left - anchors.right: inputConfiguration.right - anchors.top: configurationHeader.bottom - anchors.topMargin: 10 - anchors.bottom: inputConfiguration.bottom - - source: InputConfiguration.configurationLayout(box.currentText); - onLoaded: { - if (loader.item.hasOwnProperty("pluginName")) { - if (box.currentText === "Vive") { - loader.item.pluginName = "OpenVR"; - } else { - loader.item.pluginName = box.currentText; - } - } - - if (loader.item.hasOwnProperty("displayInformation")) { - loader.item.displayConfiguration(); - } - } - } - } - - - function inputPlugins() { - if (checkBox.checked) { - return InputConfiguration.inputPlugins(); - } else { - return InputConfiguration.activeInputPlugins(); - } - } - - function initialize() { - changeSource(); - } - - function changeSource() { - loader.source = ""; - var source = ""; - if (box.currentText == "Vive") { - source = InputConfiguration.configurationLayout("OpenVR"); - } else { - source = InputConfiguration.configurationLayout(box.currentText); - } - - loader.source = source; - if (source === "") { - box.label = "(not configurable)"; - } else { - box.label = ""; - } - } - - Timer { - id: timer - repeat: false - interval: 300 - onTriggered: initialize() - } - - Component.onCompleted: { - timer.start(); - } + TabButton { + height: parent.height + text: qsTr("Settings") + onClicked: { + stackView.clear(); + stackView.push(controllerPreferencesComponent); + } + } + TabButton { + height: parent.height + text: qsTr("Calibration") + onClicked: { + stackView.clear(); + stackView.push(inputConfigurationComponent); } } } + + + StackView { + id: stackView + anchors.top: bar.bottom + anchors.bottom: controllerSettings.bottom + anchors.left: controllerSettings.left + anchors.right: controllerSettings.right + + initialItem: controllerPreferencesComponent + } + + Component { + id: inputConfigurationComponent + StackView { + id: stack + initialItem: inputConfiguration + property alias messageVisible: imageMessageBox.visible + property alias selectedPlugin: box.currentText + Rectangle { + id: inputConfiguration + anchors.fill: parent + + HifiConstants { id: hifi } + + color: hifi.colors.baseGray + + property var pluginSettings: null + + HifiControls.ImageMessageBox { + id: imageMessageBox + anchors.fill: parent + z: 2000 + imageWidth: 442 + imageHeight: 670 + source: "../../../images/calibration-help.png" + } + + Rectangle { + width: inputConfiguration.width + height: 1 + color: hifi.colors.baseGrayShadow + x: -hifi.dimensions.contentMargin.x + } + + RalewayRegular { + id: header + text: "Control Settings" + size: 22 + color: "white" + + anchors.top: inputConfiguration.top + anchors.left: inputConfiguration.left + anchors.leftMargin: 20 + anchors.topMargin: 20 + } + + Separator { + id: headerSeparator + width: inputConfiguration.width + anchors.top: header.bottom + anchors.topMargin: 10 + } + + HiFiGlyphs { + id: sourceGlyph + text: hifi.glyphs.source + size: 36 + color: hifi.colors.blueHighlight + + anchors.top: headerSeparator.bottom + anchors.left: inputConfiguration.left + anchors.leftMargin: 40 + anchors.topMargin: 20 + } + + RalewayRegular { + id: configuration + text: "SELECT DEVICE" + size: 15 + color: hifi.colors.lightGrayText + + + anchors.top: headerSeparator.bottom + anchors.left: sourceGlyph.right + anchors.leftMargin: 10 + anchors.topMargin: 30 + } + + Row { + id: configRow + z: 999 + anchors.top: sourceGlyph.bottom + anchors.topMargin: 20 + anchors.left: sourceGlyph.left + anchors.leftMargin: 40 + spacing: 10 + HifiControls.ComboBox { + id: box + width: 160 + z: 999 + editable: true + colorScheme: hifi.colorSchemes.dark + model: inputPlugins() + label: "" + + onCurrentIndexChanged: { + changeSource(); + } + } + + HifiControls.CheckBox { + id: checkBox + colorScheme: hifi.colorSchemes.dark + text: "show all input devices" + + onClicked: { + inputPlugins(); + changeSource(); + } + } + } + + + Separator { + id: configurationSeparator + z: 0 + width: inputConfiguration.width + anchors.top: configRow.bottom + anchors.topMargin: 10 + } + + + HiFiGlyphs { + id: sliderGlyph + text: hifi.glyphs.sliders + size: 36 + color: hifi.colors.blueHighlight + + anchors.top: configurationSeparator.bottom + anchors.left: inputConfiguration.left + anchors.leftMargin: 40 + anchors.topMargin: 20 + } + + RalewayRegular { + id: configurationHeader + text: "CONFIGURATION" + size: 15 + color: hifi.colors.lightGrayText + + + anchors.top: configurationSeparator.bottom + anchors.left: sliderGlyph.right + anchors.leftMargin: 10 + anchors.topMargin: 30 + } + + Loader { + id: loader + asynchronous: false + + width: inputConfiguration.width + anchors.left: inputConfiguration.left + anchors.right: inputConfiguration.right + anchors.top: configurationHeader.bottom + anchors.topMargin: 10 + anchors.bottom: inputConfiguration.bottom + + source: InputConfiguration.configurationLayout(box.currentText); + onLoaded: { + if (loader.item.hasOwnProperty("pluginName")) { + if (box.currentText === "Vive") { + loader.item.pluginName = "OpenVR"; + } else { + loader.item.pluginName = box.currentText; + } + } + + if (loader.item.hasOwnProperty("displayInformation")) { + loader.item.displayConfiguration(); + } + } + } + } + + + function inputPlugins() { + if (checkBox.checked) { + return InputConfiguration.inputPlugins(); + } else { + return InputConfiguration.activeInputPlugins(); + } + } + + function initialize() { + changeSource(); + } + + function changeSource() { + loader.source = ""; + var source = ""; + if (box.currentText == "Vive") { + source = InputConfiguration.configurationLayout("OpenVR"); + } else { + source = InputConfiguration.configurationLayout(box.currentText); + } + + loader.source = source; + if (source === "") { + box.label = "(not configurable)"; + } else { + box.label = ""; + } + } + + Timer { + id: timer + repeat: false + interval: 300 + onTriggered: initialize() + } + + Component.onCompleted: { + timer.start(); + } + } + } + + + Component { + id: controllerPreferencesComponent + TabletPreferencesDialog { + anchors.fill: stackView + id: controllerPrefereneces + objectName: "TabletControllerPreferences" + showCategories: ["VR Movement"] + } + } } diff --git a/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml b/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml index a5ef3d2686..646a0d2c77 100644 --- a/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml +++ b/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml @@ -19,6 +19,7 @@ Item { id: dialog width: parent.width height: parent.height + anchors.fill: parent HifiConstants { id: hifi } property var sections: [] @@ -158,14 +159,15 @@ Item { Rectangle { id: footer - height: 40 + height: dialog.height * 0.15 + anchors.bottom: dialog.bottom anchors { bottom: keyboard.top left: parent.left right: parent.right } - + color: hifi.colors.baseGray Row { diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index be50fe9119..dad79faedf 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -236,8 +236,13 @@ Menu::Menu() { // Settings > Controls... action = addActionToQMenuAndActionHash(settingsMenu, "Controls..."); connect(action, &QAction::triggered, [] { - qApp->showDialog(QString("hifi/tablet/ControllerSettings.qml"), - QString("hifi/tablet/ControllerSettings.qml"), "ControlSettings"); + auto tablet = DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system"); + auto hmd = DependencyManager::get(); + tablet->loadQMLSource("hifi/tablet/ControllerSettings.qml"); + + if (!hmd->getShouldShowTablet()) { + hmd->toggleShouldShowTablet(); + } }); // Settings > Audio... diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 523582836f..f378389d0b 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1150,8 +1150,7 @@ function setupModelMenus() { Menu.addMenuItem({ menuName: "Edit", menuItemName: "Entities", - isSeparator: true, - grouping: "Advanced" + isSeparator: true }); if (!Menu.menuItemExists("Edit", "Delete")) { Menu.addMenuItem({ @@ -1161,7 +1160,6 @@ function setupModelMenus() { text: "delete" }, afterItem: "Entities", - grouping: "Advanced" }); modelMenuAddedDelete = true; } @@ -1169,15 +1167,13 @@ function setupModelMenus() { Menu.addMenuItem({ menuName: "Edit", menuItemName: "Parent Entity to Last", - afterItem: "Entities", - grouping: "Advanced" + afterItem: "Entities" }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Unparent Entity", - afterItem: "Parent Entity to Last", - grouping: "Advanced" + afterItem: "Parent Entity to Last" }); Menu.addMenuItem({ @@ -1185,8 +1181,7 @@ function setupModelMenus() { menuItemName: MENU_CREATE_ENTITIES_GRABBABLE, afterItem: "Unparent Entity", isCheckable: true, - isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_CREATE_ENTITIES_GRABBABLE, true), - grouping: "Advanced" + isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_CREATE_ENTITIES_GRABBABLE, true) }); Menu.addMenuItem({ @@ -1194,87 +1189,75 @@ function setupModelMenus() { menuItemName: MENU_ALLOW_SELECTION_LARGE, afterItem: MENU_CREATE_ENTITIES_GRABBABLE, isCheckable: true, - isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LARGE, true), - grouping: "Advanced" + isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LARGE, true) }); Menu.addMenuItem({ menuName: "Edit", menuItemName: MENU_ALLOW_SELECTION_SMALL, afterItem: MENU_ALLOW_SELECTION_LARGE, isCheckable: true, - isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_SMALL, true), - grouping: "Advanced" + isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_SMALL, true) }); Menu.addMenuItem({ menuName: "Edit", menuItemName: MENU_ALLOW_SELECTION_LIGHTS, afterItem: MENU_ALLOW_SELECTION_SMALL, isCheckable: true, - isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LIGHTS, false), - grouping: "Advanced" + isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LIGHTS, false) }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Select All Entities In Box", - afterItem: "Allow Selecting of Lights", - grouping: "Advanced" + afterItem: "Allow Selecting of Lights" }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Select All Entities Touching Box", - afterItem: "Select All Entities In Box", - grouping: "Advanced" + afterItem: "Select All Entities In Box" }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Export Entities", - afterItem: "Entities", - grouping: "Advanced" + afterItem: "Entities" }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Import Entities", - afterItem: "Export Entities", - grouping: "Advanced" + afterItem: "Export Entities" }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Import Entities from URL", - afterItem: "Import Entities", - grouping: "Advanced" + afterItem: "Import Entities" }); Menu.addMenuItem({ menuName: "Edit", menuItemName: MENU_AUTO_FOCUS_ON_SELECT, isCheckable: true, - isChecked: Settings.getValue(SETTING_AUTO_FOCUS_ON_SELECT) === "true", - grouping: "Advanced" + isChecked: Settings.getValue(SETTING_AUTO_FOCUS_ON_SELECT) === "true" }); Menu.addMenuItem({ menuName: "Edit", menuItemName: MENU_EASE_ON_FOCUS, afterItem: MENU_AUTO_FOCUS_ON_SELECT, isCheckable: true, - isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) === "true", - grouping: "Advanced" + isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) === "true" }); Menu.addMenuItem({ menuName: "Edit", menuItemName: MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE, afterItem: MENU_EASE_ON_FOCUS, isCheckable: true, - isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE) !== "false", - grouping: "Advanced" + isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE) !== "false" }); Menu.addMenuItem({ menuName: "Edit", menuItemName: MENU_SHOW_ZONES_IN_EDIT_MODE, afterItem: MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE, isCheckable: true, - isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) !== "false", - grouping: "Advanced" + isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) !== "false" }); Entities.setLightsArePickable(false); From 58f04121b72628db921552d6a1b43f4e6ba3ed35 Mon Sep 17 00:00:00 2001 From: vladest Date: Tue, 15 May 2018 06:21:40 +0200 Subject: [PATCH 046/143] Correct link colors --- .../resources/qml/hifi/dialogs/TabletAboutDialog.qml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/dialogs/TabletAboutDialog.qml b/interface/resources/qml/hifi/dialogs/TabletAboutDialog.qml index d89f8cafe3..1a51c33368 100644 --- a/interface/resources/qml/hifi/dialogs/TabletAboutDialog.qml +++ b/interface/resources/qml/hifi/dialogs/TabletAboutDialog.qml @@ -66,7 +66,8 @@ Rectangle { color: "white" } RalewayRegular { - textFormat: Text.RichText + textFormat: Text.StyledText + linkColor: "#00B4EF" color: "white" text: "www.highfidelity.com." size: 20 @@ -100,7 +101,8 @@ Rectangle { } Item { height: 20; width: 1 } RalewayRegular { - textFormat: Text.RichText + textFormat: Text.StyledText + linkColor: "#00B4EF" color: "white" text: "Blockchain technology from Elements." size: 14 @@ -111,8 +113,9 @@ Rectangle { size: 14 } RalewayRegular { - textFormat: Text.RichText + textFormat: Text.StyledText color: "white" + linkColor: "#00B4EF" text: "Distributed under the Apache License, Version 2.0.." size: 14 } From fee3cc0aca2e60f8b7d896128f2824820ba37947 Mon Sep 17 00:00:00 2001 From: vladest Date: Tue, 15 May 2018 15:49:20 +0200 Subject: [PATCH 047/143] Implemented backend for About dialog --- cmake/macros/SetPackagingParameters.cmake | 2 ++ cmake/templates/BuildInfo.h.in | 2 ++ .../qml/hifi/dialogs/TabletAboutDialog.qml | 33 +++++-------------- interface/src/Application.cpp | 4 +++ interface/src/ui/overlays/Web3DOverlay.cpp | 2 ++ 5 files changed, 19 insertions(+), 24 deletions(-) diff --git a/cmake/macros/SetPackagingParameters.cmake b/cmake/macros/SetPackagingParameters.cmake index 3ca5cb0e54..36e5a065df 100644 --- a/cmake/macros/SetPackagingParameters.cmake +++ b/cmake/macros/SetPackagingParameters.cmake @@ -73,6 +73,8 @@ macro(SET_PACKAGING_PARAMETERS) add_definitions(-DDEV_BUILD) endif () + string(TIMESTAMP BUILD_TIME "%d/%m/%Y") + if (DEPLOY_PACKAGE) # for deployed packages always grab the serverless content set(DOWNLOAD_SERVERLESS_CONTENT ON) diff --git a/cmake/templates/BuildInfo.h.in b/cmake/templates/BuildInfo.h.in index b0af1c0524..904d17293b 100644 --- a/cmake/templates/BuildInfo.h.in +++ b/cmake/templates/BuildInfo.h.in @@ -26,4 +26,6 @@ namespace BuildInfo { const QString VERSION = "@BUILD_VERSION@"; const QString BUILD_BRANCH = "@BUILD_BRANCH@"; const QString BUILD_GLOBAL_SERVICES = "@BUILD_GLOBAL_SERVICES@"; + const QString BUILD_TIME = "@BUILD_TIME@"; } + diff --git a/interface/resources/qml/hifi/dialogs/TabletAboutDialog.qml b/interface/resources/qml/hifi/dialogs/TabletAboutDialog.qml index 1a51c33368..34767c607d 100644 --- a/interface/resources/qml/hifi/dialogs/TabletAboutDialog.qml +++ b/interface/resources/qml/hifi/dialogs/TabletAboutDialog.qml @@ -9,7 +9,6 @@ // import QtQuick 2.5 - import "../../styles-uit" Rectangle { @@ -34,29 +33,15 @@ Rectangle { id: buildColumm anchors.left: parent.left anchors.leftMargin: 70 - Row { - RalewayRegular { - text: "Build" - size: 16 - color: "white" - } - RalewayRegular { - id: build - size: 16 - color: "white" - } + RalewayRegular { + text: "Build " + HiFiAbout.buildVersion + size: 16 + color: "white" } - Row { - RalewayRegular { - text: "Released" - size: 16 - color: "white" - } - RalewayRegular { - id: released - size: 16 - color: "white" - } + RalewayRegular { + text: "Released " + HiFiAbout.buildDate + size: 16 + color: "white" } } Item { height: 10; width: 1 } @@ -82,7 +67,7 @@ Rectangle { } RalewayRegular { color: "white" - text: "Built using Qt 5.10.1" + text: "Built using Qt " + HiFiAbout.qtVersion size: 12 anchors.verticalCenter: parent.verticalCenter } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 13dea71ba4..a4df3880f1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -220,6 +220,8 @@ #include "webbrowser/WebBrowserSuggestionsEngine.h" #include +#include "AboutUtil.h" + #if defined(Q_OS_WIN) #include @@ -2968,6 +2970,7 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) { surfaceContext->setContextProperty("Selection", DependencyManager::get().data()); surfaceContext->setContextProperty("ContextOverlay", DependencyManager::get().data()); surfaceContext->setContextProperty("Wallet", DependencyManager::get().data()); + surfaceContext->setContextProperty("HiFiAbout", AboutUtil::getInstance()); if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { surfaceContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get())); @@ -6577,6 +6580,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe scriptEngine->registerGlobalObject("ContextOverlay", DependencyManager::get().data()); scriptEngine->registerGlobalObject("Wallet", DependencyManager::get().data()); scriptEngine->registerGlobalObject("AddressManager", DependencyManager::get().data()); + scriptEngine->registerGlobalObject("HifiAbout", AboutUtil::getInstance()); scriptEngine->registerGlobalObject("App", this); diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index a48e5eaf54..c678e3d2a2 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -57,6 +57,7 @@ #include "SoundCache.h" #include "raypick/PointerScriptingInterface.h" #include +#include "AboutUtil.h" static int MAX_WINDOW_SIZE = 4096; static const float METERS_TO_INCHES = 39.3701f; @@ -259,6 +260,7 @@ void Web3DOverlay::setupQmlSurface() { _webSurface->getSurfaceContext()->setContextProperty("Window", DependencyManager::get().data()); _webSurface->getSurfaceContext()->setContextProperty("Reticle", qApp->getApplicationCompositor().getReticleInterface()); _webSurface->getSurfaceContext()->setContextProperty("desktop", DependencyManager::get()->getDesktop()); + _webSurface->getSurfaceContext()->setContextProperty("HiFiAbout", AboutUtil::getInstance()); // Override min fps for tablet UI, for silky smooth scrolling setMaxFPS(90); From a6ef459723cb994ff943450265e3467bc01e9b14 Mon Sep 17 00:00:00 2001 From: vladest Date: Tue, 15 May 2018 16:07:32 +0200 Subject: [PATCH 048/143] Open browser within Interface --- .../qml/hifi/dialogs/TabletAboutDialog.qml | 19 +++++- interface/src/AboutUtil.cpp | 63 +++++++++++++++++++ interface/src/AboutUtil.h | 40 ++++++++++++ 3 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 interface/src/AboutUtil.cpp create mode 100644 interface/src/AboutUtil.h diff --git a/interface/resources/qml/hifi/dialogs/TabletAboutDialog.qml b/interface/resources/qml/hifi/dialogs/TabletAboutDialog.qml index 34767c607d..2cb079a070 100644 --- a/interface/resources/qml/hifi/dialogs/TabletAboutDialog.qml +++ b/interface/resources/qml/hifi/dialogs/TabletAboutDialog.qml @@ -15,9 +15,7 @@ Rectangle { width: 480 height: 706 - HifiConstants { id: hifi; } - - color: hifi.colors.baseGray + color: "#404040" Column { x: 45 @@ -56,6 +54,9 @@ Rectangle { color: "white" text: "www.highfidelity.com." size: 20 + onLinkActivated: { + HiFiAbout.openUrl("https:/www.highfidelity.com"); + } } Item { height: 40; width: 1 } Row { @@ -64,6 +65,12 @@ Rectangle { sourceSize.width: 34 sourceSize.height: 25 source: "../../../images/about-qt.png" + MouseArea { + anchors.fill: parent + onClicked: { + HiFiAbout.openUrl("https://www.qt.io/"); + } + } } RalewayRegular { color: "white" @@ -91,6 +98,9 @@ Rectangle { color: "white" text: "Blockchain technology from Elements." size: 14 + onLinkActivated: { + HiFiAbout.openUrl("https://elementsproject.org/elements/"); + } } RalewayRegular { color: "white" @@ -103,6 +113,9 @@ Rectangle { linkColor: "#00B4EF" text: "Distributed under the Apache License, Version 2.0.." size: 14 + onLinkActivated: { + HiFiAbout.openUrl("http://www.apache.org/licenses/LICENSE-2.0.html"); + } } } } diff --git a/interface/src/AboutUtil.cpp b/interface/src/AboutUtil.cpp new file mode 100644 index 0000000000..e70ad9bbbf --- /dev/null +++ b/interface/src/AboutUtil.cpp @@ -0,0 +1,63 @@ +// +// AboutUtil.cpp +// interface/src +// +// Created by Vlad Stelmahovsky on 15/5/2018. +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "AboutUtil.h" +#include "BuildInfo.h" +#include +#include "DependencyManager.h" +#include "scripting/HMDScriptingInterface.h" +#include "Application.h" +#include + +AboutUtil::AboutUtil(QObject *parent) : QObject(parent) {} + +AboutUtil *AboutUtil::getInstance() +{ + static AboutUtil instance; + return &instance; +} + +QString AboutUtil::buildDate() const +{ + return BuildInfo::BUILD_TIME; +} + +QString AboutUtil::buildVersion() const +{ + return BuildInfo::VERSION; +} + +QString AboutUtil::qtVersion() const +{ + return qVersion(); +} + +void AboutUtil::openUrl(const QString& url) const { + + auto tabletScriptingInterface = DependencyManager::get(); + auto tablet = dynamic_cast(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system")); + auto hmd = DependencyManager::get(); + auto offscreenUi = DependencyManager::get(); + + if (tablet->getToolbarMode()) { + offscreenUi->load("Browser.qml", [=](QQmlContext* context, QObject* newObject) { + newObject->setProperty("url", url); + }); + } else { + if (!hmd->getShouldShowTablet() && !qApp->isHMDMode()) { + offscreenUi->load("Browser.qml", [=](QQmlContext* context, QObject* newObject) { + newObject->setProperty("url", url); + }); + } else { + tablet->gotoWebScreen(url); + } + } +} diff --git a/interface/src/AboutUtil.h b/interface/src/AboutUtil.h new file mode 100644 index 0000000000..94e9e7b8f3 --- /dev/null +++ b/interface/src/AboutUtil.h @@ -0,0 +1,40 @@ +// +// AboutUtil.h +// interface/src +// +// Created by Vlad Stelmahovsky on 15/5/2018. +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +#ifndef hifi_AboutUtil_h +#define hifi_AboutUtil_h + +#include + +class AboutUtil : public QObject { + + Q_OBJECT + + Q_PROPERTY(QString buildDate READ buildDate CONSTANT) + Q_PROPERTY(QString buildVersion READ buildVersion CONSTANT) + Q_PROPERTY(QString qtVersion READ qtVersion CONSTANT) + + AboutUtil(QObject* parent = nullptr); +public: + static AboutUtil* getInstance(); + ~AboutUtil() {} + + QString buildDate() const; + QString buildVersion() const; + QString qtVersion() const; + +public slots: + void openUrl(const QString &url) const; +private: +}; + +#endif // hifi_AboutUtil_h From e2a8ee2a4cf690100e6df38550c403e189e773b8 Mon Sep 17 00:00:00 2001 From: vladest Date: Tue, 15 May 2018 20:02:29 +0200 Subject: [PATCH 049/143] Fixed About date format. Increased space between logo and build info --- .../resources/qml/hifi/dialogs/TabletAboutDialog.qml | 1 + interface/src/AboutUtil.cpp | 10 ++++++++-- interface/src/AboutUtil.h | 2 ++ interface/src/ui/PreferencesDialog.cpp | 5 ++++- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/dialogs/TabletAboutDialog.qml b/interface/resources/qml/hifi/dialogs/TabletAboutDialog.qml index 2cb079a070..579aa1cb1e 100644 --- a/interface/resources/qml/hifi/dialogs/TabletAboutDialog.qml +++ b/interface/resources/qml/hifi/dialogs/TabletAboutDialog.qml @@ -27,6 +27,7 @@ Rectangle { sourceSize.height: 75 source: "../../../images/about-highfidelity.png" } + Item { height: 30; width: 1 } Column { id: buildColumm anchors.left: parent.left diff --git a/interface/src/AboutUtil.cpp b/interface/src/AboutUtil.cpp index e70ad9bbbf..5179897443 100644 --- a/interface/src/AboutUtil.cpp +++ b/interface/src/AboutUtil.cpp @@ -8,6 +8,8 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include +#include #include "AboutUtil.h" #include "BuildInfo.h" @@ -17,7 +19,11 @@ #include "Application.h" #include -AboutUtil::AboutUtil(QObject *parent) : QObject(parent) {} +AboutUtil::AboutUtil(QObject *parent) : QObject(parent) { + QLocale locale_; + m_DateConverted = QDate::fromString(BuildInfo::BUILD_TIME, "dd/MM/yyyy"). + toString(locale_.dateFormat(QLocale::ShortFormat)); +} AboutUtil *AboutUtil::getInstance() { @@ -27,7 +33,7 @@ AboutUtil *AboutUtil::getInstance() QString AboutUtil::buildDate() const { - return BuildInfo::BUILD_TIME; + return m_DateConverted; } QString AboutUtil::buildVersion() const diff --git a/interface/src/AboutUtil.h b/interface/src/AboutUtil.h index 94e9e7b8f3..9b65b887b9 100644 --- a/interface/src/AboutUtil.h +++ b/interface/src/AboutUtil.h @@ -35,6 +35,8 @@ public: public slots: void openUrl(const QString &url) const; private: + + QString m_DateConverted; }; #endif // hifi_AboutUtil_h diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index a1b2c93adc..269db65cd5 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -252,9 +252,12 @@ void setupPreferences() { static const QString MOVEMENT{ "VR Movement" }; { + auto getterFJ = [=]()->bool { return myAvatar->getFlyingEnabled(); }; + auto setterFJ = [=](bool value) { myAvatar->setFlyingEnabled(value); }; + preferences->addPreference(new CheckPreference(MOVEMENT, "Flying & jumping", getterFJ, setterFJ)); auto getter = [=]()->bool { return myAvatar->getSnapTurn(); }; auto setter = [=](bool value) { myAvatar->setSnapTurn(value); }; - preferences->addPreference(new CheckPreference(MOVEMENT, "Snap turn rotation", getter, setter)); + preferences->addPreference(new CheckPreference(MOVEMENT, "Snap turn / Smooth turn", getter, setter)); } //TODO: Update with advanced movement logic, test that it works From 71633105de77e193ad7f66c005a879f421ce2d48 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 15 May 2018 11:31:58 -0700 Subject: [PATCH 050/143] adding back some menus --- interface/src/Menu.cpp | 27 ++++++++++++++++++++++++++ interface/src/ui/PreferencesDialog.cpp | 6 +++--- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index dad79faedf..5633089019 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -141,9 +141,20 @@ Menu::Menu() { // Edit > Reload All Content addActionToQMenuAndActionHash(editMenu, MenuOption::ReloadContent, 0, qApp, SLOT(reloadResourceCaches())); + + MenuWrapper* avatarMenu = addMenu("Avatar"); auto avatarManager = DependencyManager::get(); auto avatar = avatarManager->getMyAvatar(); + // Avatar > Attachments... + action = addActionToQMenuAndActionHash(avatarMenu, MenuOption::Attachments); + connect(action, &QAction::triggered, [] { + qApp->showDialog(QString("hifi/dialogs/AttachmentsDialog.qml"), + QString("hifi/tablet/TabletAttachmentsDialog.qml"), "AttachmentsDialog"); + }); + + auto avatarBookmarks = DependencyManager::get(); + avatarBookmarks->setupMenus(this, avatarMenu); // Display menu ---------------------------------- // FIXME - this is not yet matching Alan's spec because it doesn't have // menus for "2D"/"3D" - we need to add support for detecting the appropriate @@ -772,6 +783,22 @@ Menu::Menu() { connect(speechRecognizer.data(), SIGNAL(enabledUpdated(bool)), speechRecognizerAction, SLOT(setChecked(bool))); #endif + // console + addActionToQMenuAndActionHash(developerMenu, MenuOption::Console, Qt::CTRL | Qt::ALT | Qt::Key_J, + DependencyManager::get().data(), + SLOT(toggleConsole()), + QAction::NoRole, + UNSPECIFIED_POSITION); + + // Developer > API Debugger + action = addActionToQMenuAndActionHash(developerMenu, "API Debugger"); + connect(action, &QAction::triggered, [] { + auto scriptEngines = DependencyManager::get(); + QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation(); + defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/utilities/tools/currentAPI.js"); + scriptEngines->loadScript(defaultScriptsLoc.toString()); + }); + // Developer > Log... addActionToQMenuAndActionHash(developerMenu, MenuOption::Log, Qt::CTRL | Qt::SHIFT | Qt::Key_L, qApp, SLOT(toggleLogDialog())); diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index a1b2c93adc..7e373ac160 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -62,13 +62,13 @@ void setupPreferences() { { auto getterY = []()->float { return 1.0; }; auto setterY = [](float value) { }; - preferences->addPreference(new SliderPreference(MOUSE_SENSIVITY, "Y Input", getterY, setterY)); + preferences->addPreference(new SliderPreference(MOUSE_SENSIVITY, "Mouse Look Y", getterY, setterY)); auto getterX = []()->float { return 1.0; }; auto setterX = [](float value) { }; - preferences->addPreference(new SliderPreference(MOUSE_SENSIVITY, "X Input", getterX, setterX)); + preferences->addPreference(new SliderPreference(MOUSE_SENSIVITY, "Mouse Look X", getterX, setterX)); auto getterSW = []()->float { return 1.0; }; auto setterSW = [](float value) { }; - preferences->addPreference(new SliderPreference(MOUSE_SENSIVITY, "Scroll Wheel", getterSW, setterSW)); + preferences->addPreference(new SliderPreference(MOUSE_SENSIVITY, "Mouse Look Zoom", getterSW, setterSW)); } // Graphics quality static const QString GRAPHICS_QUALITY { "Graphics Quality" }; From dd05afa9748e2b2684b3e7d2450d2883ed6ad160 Mon Sep 17 00:00:00 2001 From: vladest Date: Tue, 15 May 2018 21:41:48 +0200 Subject: [PATCH 051/143] Remove double setting --- interface/src/ui/PreferencesDialog.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 994bc8119a..3e23e57bd0 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -250,11 +250,12 @@ void setupPreferences() { } static const QString MOVEMENT{ "VR Movement" }; - { - auto getterFJ = [=]()->bool { return myAvatar->getFlyingEnabled(); }; - auto setterFJ = [=](bool value) { myAvatar->setFlyingEnabled(value); }; - preferences->addPreference(new CheckPreference(MOVEMENT, "Flying & jumping", getterFJ, setterFJ)); + auto getter = [=]()->bool { return myAvatar->getFlyingEnabled(); }; + auto setter = [=](bool value) { myAvatar->setFlyingEnabled(value); }; + preferences->addPreference(new CheckPreference(MOVEMENT, "Flying & jumping", getter, setter)); + } + { auto getter = [=]()->bool { return myAvatar->getSnapTurn(); }; auto setter = [=](bool value) { myAvatar->setSnapTurn(value); }; preferences->addPreference(new CheckPreference(MOVEMENT, "Snap turn / Smooth turn", getter, setter)); @@ -290,11 +291,6 @@ void setupPreferences() { preference->setStep(0.001f); preferences->addPreference(preference); } - { - auto getter = [=]()->bool { return myAvatar->getFlyingEnabled(); }; - auto setter = [=](bool value) { myAvatar->setFlyingEnabled(value); }; - preferences->addPreference(new CheckPreference(MOVEMENT, "Enable Flying", getter, setter)); - } static const QString AVATAR_CAMERA{ "Mouse Sensitivity" }; { From f74e21902995af02fc39885eb2386868d38136ef Mon Sep 17 00:00:00 2001 From: David Back Date: Tue, 15 May 2018 17:24:14 -0700 Subject: [PATCH 052/143] rename properties, add clone avatar entity, remove worldEntityProps arg, fix clone ID cleanup on delete --- libraries/entities/src/EntityItem.cpp | 94 +++++++++++++------ libraries/entities/src/EntityItem.h | 28 +++--- .../entities/src/EntityItemProperties.cpp | 90 +++++++++++------- libraries/entities/src/EntityItemProperties.h | 8 +- .../src/EntityItemPropertiesDefaults.h | 8 +- libraries/entities/src/EntityPropertyFlags.h | 8 +- .../entities/src/EntityScriptingInterface.cpp | 3 +- libraries/entities/src/EntityTree.cpp | 38 +++++--- libraries/entities/src/EntityTree.h | 2 +- .../controllerModules/equipEntity.js | 3 +- .../controllerModules/nearActionGrabEntity.js | 3 +- .../controllerModules/nearParentGrabEntity.js | 3 +- scripts/system/html/js/entityProperties.js | 14 +-- scripts/system/libraries/cloneEntityUtils.js | 4 +- 14 files changed, 192 insertions(+), 114 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 9d7e536f25..1e95e999b1 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -125,9 +125,11 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param requestedProperties += PROP_LAST_EDITED_BY; requestedProperties += PROP_CLONEABLE; - requestedProperties += PROP_CLONEABLE_LIFETIME; - requestedProperties += PROP_CLONEABLE_LIMIT; - requestedProperties += PROP_CLONEABLE_DYNAMIC; + requestedProperties += PROP_CLONE_LIFETIME; + requestedProperties += PROP_CLONE_LIMIT; + requestedProperties += PROP_CLONE_DYNAMIC; + requestedProperties += PROP_CLONE_AVATAR_ENTITY; + requestedProperties += PROP_CLONE_ORIGIN_ID; return requestedProperties; } @@ -294,9 +296,11 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_LAST_EDITED_BY, getLastEditedBy()); APPEND_ENTITY_PROPERTY(PROP_CLONEABLE, getCloneable()); - APPEND_ENTITY_PROPERTY(PROP_CLONEABLE_LIFETIME, getCloneableLifetime()); - APPEND_ENTITY_PROPERTY(PROP_CLONEABLE_LIMIT, getCloneableLimit()); - APPEND_ENTITY_PROPERTY(PROP_CLONEABLE_DYNAMIC, getCloneableDynamic()); + APPEND_ENTITY_PROPERTY(PROP_CLONE_LIFETIME, getCloneLifetime()); + APPEND_ENTITY_PROPERTY(PROP_CLONE_LIMIT, getCloneLimit()); + APPEND_ENTITY_PROPERTY(PROP_CLONE_DYNAMIC, getCloneDynamic()); + APPEND_ENTITY_PROPERTY(PROP_CLONE_AVATAR_ENTITY, getCloneAvatarEntity()); + APPEND_ENTITY_PROPERTY(PROP_CLONE_ORIGIN_ID, getCloneOriginID()); appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, @@ -859,9 +863,11 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_LAST_EDITED_BY, QUuid, setLastEditedBy); READ_ENTITY_PROPERTY(PROP_CLONEABLE, bool, setCloneable); - READ_ENTITY_PROPERTY(PROP_CLONEABLE_LIFETIME, float, setCloneableLifetime); - READ_ENTITY_PROPERTY(PROP_CLONEABLE_LIMIT, float, setCloneableLimit); - READ_ENTITY_PROPERTY(PROP_CLONEABLE_DYNAMIC, bool, setCloneableDynamic); + READ_ENTITY_PROPERTY(PROP_CLONE_LIFETIME, float, setCloneLifetime); + READ_ENTITY_PROPERTY(PROP_CLONE_LIMIT, float, setCloneLimit); + READ_ENTITY_PROPERTY(PROP_CLONE_DYNAMIC, bool, setCloneDynamic); + READ_ENTITY_PROPERTY(PROP_CLONE_AVATAR_ENTITY, bool, setCloneAvatarEntity); + READ_ENTITY_PROPERTY(PROP_CLONE_ORIGIN_ID, QUuid, setCloneOriginID); bytesRead += readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, propertyFlags, overwriteLocalData, somethingChanged); @@ -1291,9 +1297,11 @@ EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProper COPY_ENTITY_PROPERTY_TO_PROPERTIES(lastEditedBy, getLastEditedBy); COPY_ENTITY_PROPERTY_TO_PROPERTIES(cloneable, getCloneable); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(cloneableLifetime, getCloneableLifetime); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(cloneableLimit, getCloneableLimit); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(cloneableDynamic, getCloneableDynamic); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(cloneLifetime, getCloneLifetime); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(cloneLimit, getCloneLimit); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(cloneDynamic, getCloneDynamic); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(cloneAvatarEntity, getCloneAvatarEntity); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(cloneOriginID, getCloneOriginID); properties._defaultSettings = false; @@ -1403,9 +1411,11 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(lastEditedBy, setLastEditedBy); SET_ENTITY_PROPERTY_FROM_PROPERTIES(cloneable, setCloneable); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(cloneableLifetime, setCloneableLifetime); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(cloneableLimit, setCloneableLimit); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(cloneableDynamic, setCloneableDynamic); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(cloneLifetime, setCloneLifetime); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(cloneLimit, setCloneLimit); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(cloneDynamic, setCloneDynamic); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(cloneAvatarEntity, setCloneAvatarEntity); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(cloneOriginID, setCloneOriginID); if (updateQueryAACube()) { somethingChanged = true; @@ -3015,45 +3025,73 @@ void EntityItem::setCloneable(bool value) { }); } -float EntityItem::getCloneableLifetime() const { +float EntityItem::getCloneLifetime() const { float result; withReadLock([&] { - result = _cloneableLifetime; + result = _cloneLifetime; }); return result; } -void EntityItem::setCloneableLifetime(float value) { +void EntityItem::setCloneLifetime(float value) { withWriteLock([&] { - _cloneableLifetime = value; + _cloneLifetime = value; }); } -float EntityItem::getCloneableLimit() const { +float EntityItem::getCloneLimit() const { float result; withReadLock([&] { - result = _cloneableLimit; + result = _cloneLimit; }); return result; } -void EntityItem::setCloneableLimit(float value) { +void EntityItem::setCloneLimit(float value) { withWriteLock([&] { - _cloneableLimit = value; + _cloneLimit = value; }); } -bool EntityItem::getCloneableDynamic() const { +bool EntityItem::getCloneDynamic() const { bool result; withReadLock([&] { - result = _cloneableDynamic; + result = _cloneDynamic; }); return result; } -void EntityItem::setCloneableDynamic(const bool value) { +void EntityItem::setCloneDynamic(const bool value) { withWriteLock([&] { - _cloneableDynamic = value; + _cloneDynamic = value; + }); +} + +bool EntityItem::getCloneAvatarEntity() const { + bool result; + withReadLock([&] { + result = _cloneAvatarEntity; + }); + return result; +} + +void EntityItem::setCloneAvatarEntity(const bool value) { + withWriteLock([&] { + _cloneAvatarEntity = value; + }); +} + +const QUuid EntityItem::getCloneOriginID() const { + QUuid result; + withReadLock([&] { + result = _cloneOriginID; + }); + return result; +} + +void EntityItem::setCloneOriginID(const QUuid& value) { + withWriteLock([&] { + _cloneOriginID = value; }); } @@ -3072,4 +3110,4 @@ bool EntityItem::removeCloneID(const QUuid& cloneID) { return true; } return false; -} \ No newline at end of file +} diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 95cc5f96e1..f314cd1418 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -343,12 +343,16 @@ public: bool getCloneable() const; void setCloneable(bool value); - float getCloneableLifetime() const; - void setCloneableLifetime(float value); - float getCloneableLimit() const; - void setCloneableLimit(float value); - bool getCloneableDynamic() const; - void setCloneableDynamic(const bool value); + float getCloneLifetime() const; + void setCloneLifetime(float value); + float getCloneLimit() const; + void setCloneLimit(float value); + bool getCloneDynamic() const; + void setCloneDynamic(const bool value); + bool getCloneAvatarEntity() const; + void setCloneAvatarEntity(const bool value); + const QUuid getCloneOriginID() const; + void setCloneOriginID(const QUuid& value); // TODO: get rid of users of getRadius()... float getRadius() const; @@ -506,8 +510,6 @@ public: bool addCloneID(const QUuid& cloneID); bool removeCloneID(const QUuid& cloneID); const QList& getCloneIDs() const { return _cloneIDs; } - void setCloneParent(const QUuid& cloneParentID) { _cloneParentID = cloneParentID; } - const QUuid& getCloneParent() const { return _cloneParentID; } signals: void requestRenderUpdate(); @@ -664,12 +666,12 @@ protected: bool _cauterized { false }; // if true, don't draw because it would obscure 1st-person camera bool _cloneable; - float _cloneableLifetime; - float _cloneableLimit; - bool _cloneableDynamic; - + float _cloneLifetime; + float _cloneLimit; + bool _cloneDynamic; + bool _cloneAvatarEntity; + QUuid _cloneOriginID; QList _cloneIDs; - QUuid _cloneParentID; private: std::unordered_map _materials; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 7c799a64e1..11ef5a4a84 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -437,9 +437,11 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_RELAY_PARENT_JOINTS, relayParentJoints); CHECK_PROPERTY_CHANGE(PROP_CLONEABLE, cloneable); - CHECK_PROPERTY_CHANGE(PROP_CLONEABLE_LIFETIME, cloneableLifetime); - CHECK_PROPERTY_CHANGE(PROP_CLONEABLE_LIMIT, cloneableLimit); - CHECK_PROPERTY_CHANGE(PROP_CLONEABLE_DYNAMIC, cloneableDynamic); + CHECK_PROPERTY_CHANGE(PROP_CLONE_LIFETIME, cloneLifetime); + CHECK_PROPERTY_CHANGE(PROP_CLONE_LIMIT, cloneLimit); + CHECK_PROPERTY_CHANGE(PROP_CLONE_DYNAMIC, cloneDynamic); + CHECK_PROPERTY_CHANGE(PROP_CLONE_AVATAR_ENTITY, cloneAvatarEntity); + CHECK_PROPERTY_CHANGE(PROP_CLONE_ORIGIN_ID, cloneOriginID); changedProperties += _animation.getChangedProperties(); changedProperties += _keyLight.getChangedProperties(); @@ -1436,9 +1438,11 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_OWNING_AVATAR_ID, owningAvatarID); // Gettable but not settable COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CLONEABLE, cloneable); - COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CLONEABLE_LIFETIME, cloneableLifetime); - COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CLONEABLE_LIMIT, cloneableLimit); - COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CLONEABLE_DYNAMIC, cloneableDynamic); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CLONE_LIFETIME, cloneLifetime); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CLONE_LIMIT, cloneLimit); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CLONE_DYNAMIC, cloneDynamic); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CLONE_AVATAR_ENTITY, cloneAvatarEntity); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CLONE_ORIGIN_ID, cloneOriginID); // Rendering info if (!skipDefaults && !strictSemantics) { @@ -1653,9 +1657,11 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(dpi, uint16_t, setDPI); COPY_PROPERTY_FROM_QSCRIPTVALUE(cloneable, bool, setCloneable); - COPY_PROPERTY_FROM_QSCRIPTVALUE(cloneableLifetime, float, setCloneableLifetime); - COPY_PROPERTY_FROM_QSCRIPTVALUE(cloneableLimit, float, setCloneableLimit); - COPY_PROPERTY_FROM_QSCRIPTVALUE(cloneableDynamic, bool, setCloneableDynamic); + COPY_PROPERTY_FROM_QSCRIPTVALUE(cloneLifetime, float, setCloneLifetime); + COPY_PROPERTY_FROM_QSCRIPTVALUE(cloneLimit, float, setCloneLimit); + COPY_PROPERTY_FROM_QSCRIPTVALUE(cloneDynamic, bool, setCloneDynamic); + COPY_PROPERTY_FROM_QSCRIPTVALUE(cloneAvatarEntity, bool, setCloneAvatarEntity); + COPY_PROPERTY_FROM_QSCRIPTVALUE(cloneOriginID, QUuid, setCloneOriginID); _lastEdited = usecTimestampNow(); } @@ -2033,9 +2039,11 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_DPI, DPI, dpi, uint16_t); ADD_PROPERTY_TO_MAP(PROP_CLONEABLE, Cloneable, cloneable, bool); - ADD_PROPERTY_TO_MAP(PROP_CLONEABLE_LIFETIME, CloneableLifetime, cloneableLifetime, float); - ADD_PROPERTY_TO_MAP(PROP_CLONEABLE_LIMIT, CloneableLimit, cloneableLimit, float); - ADD_PROPERTY_TO_MAP(PROP_CLONEABLE_DYNAMIC, CloneableDynamic, cloneableDynamic, bool); + ADD_PROPERTY_TO_MAP(PROP_CLONE_LIFETIME, CloneLifetime, cloneLifetime, float); + ADD_PROPERTY_TO_MAP(PROP_CLONE_LIMIT, CloneLimit, cloneLimit, float); + ADD_PROPERTY_TO_MAP(PROP_CLONE_DYNAMIC, CloneDynamic, cloneDynamic, bool); + ADD_PROPERTY_TO_MAP(PROP_CLONE_AVATAR_ENTITY, CloneAvatarEntity, cloneAvatarEntity, bool); + ADD_PROPERTY_TO_MAP(PROP_CLONE_ORIGIN_ID, CloneOriginID, cloneOriginID, QUuid); // FIXME - these are not yet handled //ADD_PROPERTY_TO_MAP(PROP_CREATED, Created, created, quint64); @@ -2353,9 +2361,11 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_STATIC_CERTIFICATE_VERSION, properties.getStaticCertificateVersion()); APPEND_ENTITY_PROPERTY(PROP_CLONEABLE, properties.getCloneable()); - APPEND_ENTITY_PROPERTY(PROP_CLONEABLE_LIFETIME, properties.getCloneableLifetime()); - APPEND_ENTITY_PROPERTY(PROP_CLONEABLE_LIMIT, properties.getCloneableLimit()); - APPEND_ENTITY_PROPERTY(PROP_CLONEABLE_DYNAMIC, properties.getCloneableDynamic()); + APPEND_ENTITY_PROPERTY(PROP_CLONE_LIFETIME, properties.getCloneLifetime()); + APPEND_ENTITY_PROPERTY(PROP_CLONE_LIMIT, properties.getCloneLimit()); + APPEND_ENTITY_PROPERTY(PROP_CLONE_DYNAMIC, properties.getCloneDynamic()); + APPEND_ENTITY_PROPERTY(PROP_CLONE_AVATAR_ENTITY, properties.getCloneAvatarEntity()); + APPEND_ENTITY_PROPERTY(PROP_CLONE_ORIGIN_ID, properties.getCloneOriginID()); } if (propertyCount > 0) { @@ -2727,9 +2737,11 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STATIC_CERTIFICATE_VERSION, quint32, setStaticCertificateVersion); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CLONEABLE, bool, setCloneable); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CLONEABLE_LIFETIME, float, setCloneableLifetime); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CLONEABLE_LIMIT, float, setCloneableLimit); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CLONEABLE_DYNAMIC, bool, setCloneableDynamic); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CLONE_LIFETIME, float, setCloneLifetime); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CLONE_LIMIT, float, setCloneLimit); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CLONE_DYNAMIC, bool, setCloneDynamic); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CLONE_AVATAR_ENTITY, bool, setCloneAvatarEntity); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CLONE_ORIGIN_ID, QUuid, setCloneOriginID); return valid; } @@ -2815,7 +2827,7 @@ bool EntityItemProperties::encodeCloneEntityMessage(const EntityItemID& entityID char* copyAt = buffer.data(); int outputLength = 0; - if (buffer.size() < (int)(sizeof(NUM_BYTES_RFC4122_UUID) * 2)) { + if (buffer.size() < (int)(NUM_BYTES_RFC4122_UUID * 2)) { qCDebug(entities) << "ERROR - encodeCloneEntityMessage() called with buffer that is too small!"; return false; } @@ -3021,9 +3033,11 @@ void EntityItemProperties::markAllChanged() { _relayParentJointsChanged = true; _cloneableChanged = true; - _cloneableLifetimeChanged = true; - _cloneableLimitChanged = true; - _cloneableDynamicChanged = true; + _cloneLifetimeChanged = true; + _cloneLimitChanged = true; + _cloneDynamicChanged = true; + _cloneAvatarEntityChanged = true; + _cloneOriginIDChanged = true; } // The minimum bounding box for the entity. @@ -3459,14 +3473,20 @@ QList EntityItemProperties::listChangedProperties() { if (cloneableChanged()) { out += "cloneable"; } - if (cloneableLifetimeChanged()) { - out += "cloneableLifetime"; + if (cloneLifetimeChanged()) { + out += "cloneLifetime"; } - if (cloneableLimitChanged()) { - out += "cloneableLimit"; + if (cloneLimitChanged()) { + out += "cloneLimit"; } - if (cloneableDynamicChanged()) { - out += "cloneableDynamic"; + if (cloneDynamicChanged()) { + out += "cloneDynamic"; + } + if (cloneAvatarEntityChanged()) { + out += "cloneAvatarEntity"; + } + if (cloneOriginIDChanged()) { + out += "cloneOriginID"; } @@ -3637,10 +3657,12 @@ bool EntityItemProperties::verifyStaticCertificateProperties() { void EntityItemProperties::convertToCloneProperties(const EntityItemID& entityIDToClone) { setName(getName() + "-clone-" + entityIDToClone.toString()); setLocked(false); - setLifetime(getCloneableLifetime()); - setDynamic(getCloneableDynamic()); + setLifetime(getCloneLifetime()); + setDynamic(getCloneDynamic()); + setClientOnly(getCloneAvatarEntity()); setCloneable(ENTITY_ITEM_CLONEABLE); - setCloneableLifetime(ENTITY_ITEM_CLONEABLE_LIFETIME); - setCloneableLimit(ENTITY_ITEM_CLONEABLE_LIMIT); - setCloneableDynamic(ENTITY_ITEM_CLONEABLE_DYNAMIC); -} \ No newline at end of file + setCloneLifetime(ENTITY_ITEM_CLONE_LIFETIME); + setCloneLimit(ENTITY_ITEM_CLONE_LIMIT); + setCloneDynamic(ENTITY_ITEM_CLONE_DYNAMIC); + setCloneAvatarEntity(ENTITY_ITEM_CLONE_AVATAR_ENTITY); +} diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 12d4bdf919..a34058c010 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -273,9 +273,11 @@ public: DEFINE_PROPERTY(PROP_RELAY_PARENT_JOINTS, RelayParentJoints, relayParentJoints, bool, ENTITY_ITEM_DEFAULT_RELAY_PARENT_JOINTS); DEFINE_PROPERTY(PROP_CLONEABLE, Cloneable, cloneable, bool, ENTITY_ITEM_CLONEABLE); - DEFINE_PROPERTY(PROP_CLONEABLE_LIFETIME, CloneableLifetime, cloneableLifetime, float, ENTITY_ITEM_CLONEABLE_LIFETIME); - DEFINE_PROPERTY(PROP_CLONEABLE_LIMIT, CloneableLimit, cloneableLimit, float, ENTITY_ITEM_CLONEABLE_LIMIT); - DEFINE_PROPERTY(PROP_CLONEABLE_DYNAMIC, CloneableDynamic, cloneableDynamic, bool, ENTITY_ITEM_CLONEABLE_DYNAMIC); + DEFINE_PROPERTY(PROP_CLONE_LIFETIME, CloneLifetime, cloneLifetime, float, ENTITY_ITEM_CLONE_LIFETIME); + DEFINE_PROPERTY(PROP_CLONE_LIMIT, CloneLimit, cloneLimit, float, ENTITY_ITEM_CLONE_LIMIT); + DEFINE_PROPERTY(PROP_CLONE_DYNAMIC, CloneDynamic, cloneDynamic, bool, ENTITY_ITEM_CLONE_DYNAMIC); + DEFINE_PROPERTY(PROP_CLONE_AVATAR_ENTITY, CloneAvatarEntity, cloneAvatarEntity, bool, ENTITY_ITEM_CLONE_AVATAR_ENTITY); + DEFINE_PROPERTY(PROP_CLONE_ORIGIN_ID, CloneOriginID, cloneOriginID, QUuid, ENTITY_ITEM_CLONE_ORIGIN_ID); static QString getComponentModeString(uint32_t mode); static QString getComponentModeAsString(uint32_t mode); diff --git a/libraries/entities/src/EntityItemPropertiesDefaults.h b/libraries/entities/src/EntityItemPropertiesDefaults.h index 6e46453bda..1a31bddebe 100644 --- a/libraries/entities/src/EntityItemPropertiesDefaults.h +++ b/libraries/entities/src/EntityItemPropertiesDefaults.h @@ -98,8 +98,10 @@ const QUuid ENTITY_ITEM_DEFAULT_LAST_EDITED_BY = QUuid(); const bool ENTITY_ITEM_DEFAULT_RELAY_PARENT_JOINTS = false; const bool ENTITY_ITEM_CLONEABLE = false; -const float ENTITY_ITEM_CLONEABLE_LIFETIME = 300.0f; -const int ENTITY_ITEM_CLONEABLE_LIMIT = 0; -const bool ENTITY_ITEM_CLONEABLE_DYNAMIC = false; +const float ENTITY_ITEM_CLONE_LIFETIME = 300.0f; +const int ENTITY_ITEM_CLONE_LIMIT = 0; +const bool ENTITY_ITEM_CLONE_DYNAMIC = false; +const bool ENTITY_ITEM_CLONE_AVATAR_ENTITY = false; +const QUuid ENTITY_ITEM_CLONE_ORIGIN_ID = QUuid(); #endif // hifi_EntityItemPropertiesDefaults_h diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index f698739e01..85ab28afdc 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -243,9 +243,11 @@ enum EntityPropertyList { PROP_MATERIAL_DATA, PROP_CLONEABLE, - PROP_CLONEABLE_LIFETIME, - PROP_CLONEABLE_LIMIT, - PROP_CLONEABLE_DYNAMIC, + PROP_CLONE_LIFETIME, + PROP_CLONE_LIMIT, + PROP_CLONE_DYNAMIC, + PROP_CLONE_AVATAR_ENTITY, + PROP_CLONE_ORIGIN_ID, //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties to end of list just ABOVE this line diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 71e7d1c7c0..f47a353ae8 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -333,7 +333,8 @@ QUuid EntityScriptingInterface::cloneEntity(QUuid entityIDToClone) { EntityItemID newEntityID; EntityItemProperties properties = getEntityProperties(entityIDToClone); properties.convertToCloneProperties(entityIDToClone); - if (addLocalEntityCopy(properties, newEntityID)) { + bool success = addLocalEntityCopy(properties, newEntityID); + if (success) { getEntityPacketSender()->queueCloneEntityMessage(entityIDToClone, newEntityID); return newEntityID; } else { diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index bcea89232e..647edaccc0 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -593,7 +593,7 @@ void EntityTree::deleteEntity(const EntityItemID& entityID, bool force, bool ign return; } - removeCloneIDFromCloneParent(entityID); + cleanupCloneIDs(entityID); unhookChildAvatar(entityID); emit deletingEntity(entityID); emit deletingEntityPointer(existingEntity.get()); @@ -627,14 +627,23 @@ void EntityTree::unhookChildAvatar(const EntityItemID entityID) { }); } -void EntityTree::removeCloneIDFromCloneParent(const EntityItemID& entityID) { +void EntityTree::cleanupCloneIDs(const EntityItemID& entityID) { EntityItemPointer entity = findEntityByEntityItemID(entityID); if (entity) { - const QUuid& cloneParentID = entity->getCloneParent(); - if (!cloneParentID.isNull()) { - EntityItemPointer cloneParent = findEntityByID(cloneParentID); - if (cloneParent) { - cloneParent->removeCloneID(entityID); + // remove clone ID from it's clone origin's clone ID list if clone origin exists + const QUuid cloneOriginID = entity->getCloneOriginID(); + if (!cloneOriginID.isNull()) { + EntityItemPointer cloneOrigin = findEntityByID(cloneOriginID); + if (cloneOrigin) { + cloneOrigin->removeCloneID(entityID); + } + } + // clear the clone origin ID on any clones that this entity had + const QList& cloneIDs = entity->getCloneIDs(); + foreach(const QUuid& cloneChildID, cloneIDs) { + EntityItemPointer cloneChild = findEntityByEntityItemID(cloneChildID); + if (cloneChild) { + cloneChild->setCloneOriginID(QUuid()); } } } @@ -668,7 +677,7 @@ void EntityTree::deleteEntities(QSet entityIDs, bool force, bool i } // tell our delete operator about this entityID - removeCloneIDFromCloneParent(entityID); + cleanupCloneIDs(entityID); unhookChildAvatar(entityID); theOperator.addEntityIDToDeleteList(entityID); emit deletingEntity(entityID); @@ -1601,7 +1610,7 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c bool failedAdd = !allowed; bool isCertified = !properties.getCertificateID().isEmpty(); bool isCloneable = properties.getCloneable(); - int cloneLimit = properties.getCloneableLimit(); + int cloneLimit = properties.getCloneLimit(); if (!allowed) { qCDebug(entities) << "Filtered entity add. ID:" << entityItemID; } else if (!isClone && !isCertified && !senderNode->getCanRez() && !senderNode->getCanRezTmp()) { @@ -1646,14 +1655,15 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c } } + if (newEntity && isClone) { + entityToClone->addCloneID(newEntity->getEntityItemID()); + newEntity->setCloneOriginID(entityIDToClone); + } + if (newEntity) { newEntity->markAsChangedOnServer(); notifyNewlyCreatedEntity(*newEntity, senderNode); - if (isClone) { - entityToClone->addCloneID(newEntity->getEntityItemID()); - newEntity->setCloneParent(entityIDToClone); - } - + startLogging = usecTimestampNow(); if (wantEditLogging()) { qCDebug(entities) << "User [" << senderNode->getUUID() << "] added entity. ID:" diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 0d7cc54df7..aa6e382112 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -117,7 +117,7 @@ public: // check if the avatar is a child of this entity, If so set the avatar parentID to null void unhookChildAvatar(const EntityItemID entityID); - void removeCloneIDFromCloneParent(const EntityItemID& entityID); + void cleanupCloneIDs(const EntityItemID& entityID); void deleteEntity(const EntityItemID& entityID, bool force = false, bool ignoreWarnings = true); void deleteEntities(QSet entityIDs, bool force = false, bool ignoreWarnings = true); diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js index 1fce772ec8..b6cad6841d 100644 --- a/scripts/system/controllers/controllerModules/equipEntity.js +++ b/scripts/system/controllers/controllerModules/equipEntity.js @@ -413,8 +413,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa this.cloneHotspot = function(props, controllerData) { if (entityIsCloneable(props)) { - var worldEntityProps = controllerData.nearbyEntityProperties[this.hand]; - var cloneID = cloneEntity(props, worldEntityProps); + var cloneID = cloneEntity(props); return cloneID; } diff --git a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js index a4e439fe2f..5e06ed762d 100644 --- a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js @@ -235,8 +235,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); // switch to grabbing var targetCloneable = entityIsCloneable(targetProps); if (targetCloneable) { - var worldEntityProps = controllerData.nearbyEntityProperties[this.hand]; - var cloneID = cloneEntity(targetProps, worldEntityProps); + var cloneID = cloneEntity(targetProps); var cloneProps = Entities.getEntityProperties(cloneID); this.targetEntityID = cloneID; this.startNearGrabAction(controllerData, cloneProps); diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index d454d20a02..cda0a683c7 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -342,8 +342,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); var targetCloneable = entityIsCloneable(targetProps); if (targetCloneable) { - var worldEntityProps = controllerData.nearbyEntityProperties[this.hand]; - var cloneID = cloneEntity(targetProps, worldEntityProps); + var cloneID = cloneEntity(targetProps); var cloneProps = Entities.getEntityProperties(cloneID); this.grabbing = true; this.targetEntityID = cloneID; diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index c81e51d674..10e7b4b60e 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -1041,10 +1041,11 @@ function loaded() { elIgnoreIK.checked = true; elCloneable.checked = properties.cloneable; - elCloneableDynamic.checked = properties.cloneableDynamic; + elCloneableDynamic.checked = properties.cloneDynamic; + elCloneableAvatarEntity.checked = properties.cloneAvatarEntity; elCloneableGroup.style.display = elCloneable.checked ? "block": "none"; - elCloneableLimit.value = properties.cloneableLimit; - elCloneableLifetime.value = properties.cloneableLifetime; + elCloneableLimit.value = properties.cloneLimit; + elCloneableLifetime.value = properties.cloneLifetime; var grabbablesSet = false; var parsedUserData = {}; @@ -1441,9 +1442,10 @@ function loaded() { }); elCloneable.addEventListener('change', createEmitCheckedPropertyUpdateFunction('cloneable')); - elCloneableDynamic.addEventListener('change', createEmitCheckedPropertyUpdateFunction('cloneableDynamic')); - elCloneableLifetime.addEventListener('change', createEmitNumberPropertyUpdateFunction('cloneableLifetime')); - elCloneableLimit.addEventListener('change', createEmitNumberPropertyUpdateFunction('cloneableLimit')); + elCloneableDynamic.addEventListener('change', createEmitCheckedPropertyUpdateFunction('cloneDynamic')); + elCloneableAvatarEntity.addEventListener('change', createEmitCheckedPropertyUpdateFunction('cloneAvatarEntity')); + elCloneableLifetime.addEventListener('change', createEmitNumberPropertyUpdateFunction('cloneLifetime')); + elCloneableLimit.addEventListener('change', createEmitNumberPropertyUpdateFunction('cloneLimit')); elWantsTrigger.addEventListener('change', function() { userDataChanger("grabbableKey", "wantsTrigger", elWantsTrigger, elUserData, false); diff --git a/scripts/system/libraries/cloneEntityUtils.js b/scripts/system/libraries/cloneEntityUtils.js index 358bc4a75f..5381d39116 100644 --- a/scripts/system/libraries/cloneEntityUtils.js +++ b/scripts/system/libraries/cloneEntityUtils.js @@ -41,12 +41,12 @@ entityIsCloneable = function(props) { propsAreCloneDynamic = function(props) { var cloneable = entityIsCloneable(props); if (cloneable) { - return props.cloneableDynamic; + return props.cloneDynamic; } return false; }; -cloneEntity = function(props, worldEntityProps) { +cloneEntity = function(props) { var entityToClone = props.id; var certificateID = Entities.getEntityProperties(entityToClone, ['certificateID']).certificateID; // ensure entity is cloneable and does not have a certificate ID, whereas cloneable limits From 1e2d2819d512056db75701321e0674ec2c031a41 Mon Sep 17 00:00:00 2001 From: David Back Date: Tue, 15 May 2018 17:36:39 -0700 Subject: [PATCH 053/143] tweaks --- libraries/entities/src/EntityItemProperties.cpp | 3 --- libraries/entities/src/EntityTree.cpp | 2 +- scripts/system/html/js/entityProperties.js | 4 ++-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 11ef5a4a84..5a2f3a8fc5 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -2823,7 +2823,6 @@ bool EntityItemProperties::encodeEraseEntityMessage(const EntityItemID& entityIt } bool EntityItemProperties::encodeCloneEntityMessage(const EntityItemID& entityIDToClone, const EntityItemID& newEntityID, QByteArray& buffer) { - char* copyAt = buffer.data(); int outputLength = 0; @@ -2846,7 +2845,6 @@ bool EntityItemProperties::encodeCloneEntityMessage(const EntityItemID& entityID } bool EntityItemProperties::decodeCloneEntityMessage(const QByteArray& buffer, int& processedBytes, EntityItemID& entityIDToClone, EntityItemID& newEntityID) { - const unsigned char* packetData = (const unsigned char*)buffer.constData(); const unsigned char* dataAt = packetData; size_t packetLength = buffer.size(); @@ -3489,7 +3487,6 @@ QList EntityItemProperties::listChangedProperties() { out += "cloneOriginID"; } - getAnimation().listChangedProperties(out); getKeyLight().listChangedProperties(out); getAmbientLight().listChangedProperties(out); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 647edaccc0..b2daed4e72 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1429,7 +1429,7 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c case PacketType::EntityClone: isClone = true; // fall through to next case case PacketType::EntityAdd: - isAdd = true; // fall through to next case + isAdd = true; // fall through to next case // FALLTHRU case PacketType::EntityPhysics: case PacketType::EntityEdit: { diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index e016a21731..4271aa9b09 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -1042,7 +1042,7 @@ function loaded() { elCloneable.checked = properties.cloneable; elCloneableDynamic.checked = properties.cloneDynamic; - elCloneableAvatarEntity.checked = properties.cloneAvatarEntity; + elCloneableAvatarEntity.checked = properties.cloneAvatarEntity; elCloneableGroup.style.display = elCloneable.checked ? "block": "none"; elCloneableLimit.value = properties.cloneLimit; elCloneableLifetime.value = properties.cloneLifetime; @@ -1443,7 +1443,7 @@ function loaded() { elCloneable.addEventListener('change', createEmitCheckedPropertyUpdateFunction('cloneable')); elCloneableDynamic.addEventListener('change', createEmitCheckedPropertyUpdateFunction('cloneDynamic')); - elCloneableAvatarEntity.addEventListener('change', createEmitCheckedPropertyUpdateFunction('cloneAvatarEntity')); + elCloneableAvatarEntity.addEventListener('change', createEmitCheckedPropertyUpdateFunction('cloneAvatarEntity')); elCloneableLifetime.addEventListener('change', createEmitNumberPropertyUpdateFunction('cloneLifetime')); elCloneableLimit.addEventListener('change', createEmitNumberPropertyUpdateFunction('cloneLimit')); From a9930d53a9f604a4f2ba3132ecd53131d76d02e5 Mon Sep 17 00:00:00 2001 From: vladest Date: Wed, 16 May 2018 14:25:58 +0200 Subject: [PATCH 054/143] Reorder VR menu --- interface/src/ui/PreferencesDialog.cpp | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 3e23e57bd0..3d23a371b5 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -250,18 +250,6 @@ void setupPreferences() { } static const QString MOVEMENT{ "VR Movement" }; - { - auto getter = [=]()->bool { return myAvatar->getFlyingEnabled(); }; - auto setter = [=](bool value) { myAvatar->setFlyingEnabled(value); }; - preferences->addPreference(new CheckPreference(MOVEMENT, "Flying & jumping", getter, setter)); - } - { - auto getter = [=]()->bool { return myAvatar->getSnapTurn(); }; - auto setter = [=](bool value) { myAvatar->setSnapTurn(value); }; - preferences->addPreference(new CheckPreference(MOVEMENT, "Snap turn / Smooth turn", getter, setter)); - } - - //TODO: Update with advanced movement logic, test that it works { static const QString movementsControlChannel = QStringLiteral("Hifi-Advanced-Movement-Disabler"); @@ -280,7 +268,16 @@ void setupPreferences() { QStringLiteral("Advanced movement for hand controllers"), getter, setter)); } - + { + auto getter = [=]()->bool { return myAvatar->getFlyingEnabled(); }; + auto setter = [=](bool value) { myAvatar->setFlyingEnabled(value); }; + preferences->addPreference(new CheckPreference(MOVEMENT, "Flying & jumping", getter, setter)); + } + { + auto getter = [=]()->bool { return myAvatar->getSnapTurn(); }; + auto setter = [=](bool value) { myAvatar->setSnapTurn(value); }; + preferences->addPreference(new CheckPreference(MOVEMENT, "Snap turn / Smooth turn", getter, setter)); + } { auto getter = [=]()->float { return myAvatar->getUserHeight(); }; auto setter = [=](float value) { myAvatar->setUserHeight(value); }; From 72838f6d34f8375501c7facdb1af94b0ac99c5f5 Mon Sep 17 00:00:00 2001 From: vladest Date: Wed, 16 May 2018 17:06:31 +0200 Subject: [PATCH 055/143] Implemented radio button preferences. Reimplemented snap smooth turn to radio buttons --- .../preferences/RadioButtonsPreference.qml | 57 +++++++++++++++++++ .../qml/dialogs/preferences/Section.qml | 5 ++ .../tabletWindows/preferences/Section.qml | 5 ++ interface/src/ui/PreferencesDialog.cpp | 10 +++- libraries/shared/src/Preferences.h | 17 +++++- 5 files changed, 90 insertions(+), 4 deletions(-) create mode 100644 interface/resources/qml/dialogs/preferences/RadioButtonsPreference.qml diff --git a/interface/resources/qml/dialogs/preferences/RadioButtonsPreference.qml b/interface/resources/qml/dialogs/preferences/RadioButtonsPreference.qml new file mode 100644 index 0000000000..77c94c2ae5 --- /dev/null +++ b/interface/resources/qml/dialogs/preferences/RadioButtonsPreference.qml @@ -0,0 +1,57 @@ +// +// RadioButtonsPreference.qml +// +// Created by Cain Kilgore on 20th July 2017 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 + +import "../../controls-uit" + +Preference { + id: root + + height: control.height + hifi.dimensions.controlInterlineHeight + + Component.onCompleted: { + repeater.itemAt(preference.value).checked = true + } + + function save() { + var value = 0; + for (var i = 0; i < repeater.count; i++) { + if (repeater.itemAt(i).checked) { + value = i; + break; + } + } + preference.value = value; + preference.save(); + } + + Row { + id: control + anchors { + left: parent.left + right: parent.right + bottom: parent.bottom + } + spacing: 5 + + Repeater { + id: repeater + model: preference.items.length + delegate: RadioButton { + text: preference.items[index] + anchors { + verticalCenter: parent.verticalCenter + } + colorScheme: hifi.colorSchemes.dark + } + } + } +} diff --git a/interface/resources/qml/dialogs/preferences/Section.qml b/interface/resources/qml/dialogs/preferences/Section.qml index 4a16036a69..0284af9d9c 100644 --- a/interface/resources/qml/dialogs/preferences/Section.qml +++ b/interface/resources/qml/dialogs/preferences/Section.qml @@ -74,6 +74,7 @@ Preference { property var comboBoxBuilder: Component { ComboBoxPreference { } } property var spinnerSliderBuilder: Component { SpinnerSliderPreference { } } property var primaryHandBuilder: Component { PrimaryHandPreference { } } + property var radioButtonsBuilder: Component { RadioButtonsPreference { } } property var preferences: [] property int checkBoxCount: 0 @@ -140,6 +141,10 @@ Preference { checkBoxCount++; builder = primaryHandBuilder; break; + case Preference.RadioButtons: + checkBoxCount++; + builder = radioButtonsBuilder; + break; }; if (builder) { diff --git a/interface/resources/qml/hifi/tablet/tabletWindows/preferences/Section.qml b/interface/resources/qml/hifi/tablet/tabletWindows/preferences/Section.qml index 5036569031..15db58decc 100644 --- a/interface/resources/qml/hifi/tablet/tabletWindows/preferences/Section.qml +++ b/interface/resources/qml/hifi/tablet/tabletWindows/preferences/Section.qml @@ -82,6 +82,7 @@ Preference { property var comboBoxBuilder: Component { ComboBoxPreference { } } property var spinnerSliderBuilder: Component { SpinnerSliderPreference { } } property var primaryHandBuilder: Component { PrimaryHandPreference { } } + property var radioButtonsBuilder: Component { RadioButtonsPreference { } } property var preferences: [] property int checkBoxCount: 0 @@ -154,6 +155,10 @@ Preference { checkBoxCount++; builder = primaryHandBuilder; break; + case Preference.RadioButtons: + checkBoxCount++; + builder = radioButtonsBuilder; + break; }; if (builder) { diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 3d23a371b5..e338c28bed 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -274,9 +274,13 @@ void setupPreferences() { preferences->addPreference(new CheckPreference(MOVEMENT, "Flying & jumping", getter, setter)); } { - auto getter = [=]()->bool { return myAvatar->getSnapTurn(); }; - auto setter = [=](bool value) { myAvatar->setSnapTurn(value); }; - preferences->addPreference(new CheckPreference(MOVEMENT, "Snap turn / Smooth turn", getter, setter)); + auto getter = [=]()->int { return myAvatar->getSnapTurn() ? 0 : 1; }; + auto setter = [=](int value) { myAvatar->setSnapTurn(value == 0); }; + auto preference = new RadioButtonsPreference(MOVEMENT, "Snap turn / Smooth turn", getter, setter); + QStringList items; + items << "Snap turn" << "Smooth turn"; + preference->setItems(items); + preferences->addPreference(preference); } { auto getter = [=]()->float { return myAvatar->getUserHeight(); }; diff --git a/libraries/shared/src/Preferences.h b/libraries/shared/src/Preferences.h index 76d61fe3f6..931508e825 100644 --- a/libraries/shared/src/Preferences.h +++ b/libraries/shared/src/Preferences.h @@ -58,7 +58,8 @@ public: ComboBox, PrimaryHand, // Special casing for an unusual preference - Avatar + Avatar, + RadioButtons }; explicit Preference(QObject* parent = nullptr) : QObject(parent) {} @@ -353,6 +354,20 @@ public: Type getType() override { return PrimaryHand; } }; +class RadioButtonsPreference : public IntPreference { + Q_OBJECT + Q_PROPERTY(QStringList items READ getItems CONSTANT) +public: + RadioButtonsPreference(const QString& category, const QString& name, Getter getter, Setter setter) + : IntPreference(category, name, getter, setter) { } + Type getType() override { return RadioButtons; } + + const QStringList& getItems() { return _items; } + void setItems(const QStringList& items) { _items = items; } + +protected: + QStringList _items; +}; #endif From e676348c4f4bff3ed348eb96a79435abb5f839a5 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 16 May 2018 10:40:28 -0700 Subject: [PATCH 056/143] fixing some menu reog bugs --- .../qml/hifi/dialogs/RunningScripts.qml | 4 +- .../qml/hifi/dialogs/TabletRunningScripts.qml | 4 +- interface/src/Menu.cpp | 66 ++--- interface/src/avatar/MyAvatar.cpp | 1 - interface/src/ui/PreferencesDialog.cpp | 11 +- ...oggleAdvancedMovementForHandControllers.js | 246 ++++++++++-------- 6 files changed, 160 insertions(+), 172 deletions(-) diff --git a/interface/resources/qml/hifi/dialogs/RunningScripts.qml b/interface/resources/qml/hifi/dialogs/RunningScripts.qml index 9e3ebcbab0..9a180a66f6 100644 --- a/interface/resources/qml/hifi/dialogs/RunningScripts.qml +++ b/interface/resources/qml/hifi/dialogs/RunningScripts.qml @@ -79,7 +79,7 @@ ScrollingWindow { interval: 1000 repeat: true running: false - onTriggered: developerMenuEnabled = MenuInterface.isMenuEnabled("Developer Menus"); + onTriggered: developerMenuEnabled = MenuInterface.isOptionChecked("Developer Menu"); } Component { @@ -98,7 +98,7 @@ ScrollingWindow { Component.onCompleted: { isHMD = HMD.active; updateRunningScripts(); - developerMenuEnabled = MenuInterface.isMenuEnabled("Developer Menus"); + developerMenuEnabled = MenuInterface.isOptionChecked("Developer Menu"); checkMenu.restart(); } diff --git a/interface/resources/qml/hifi/dialogs/TabletRunningScripts.qml b/interface/resources/qml/hifi/dialogs/TabletRunningScripts.qml index 83f91c78c5..018c8f5737 100644 --- a/interface/resources/qml/hifi/dialogs/TabletRunningScripts.qml +++ b/interface/resources/qml/hifi/dialogs/TabletRunningScripts.qml @@ -65,7 +65,7 @@ Rectangle { interval: 1000 repeat: true running: false - onTriggered: developerMenuEnabled = MenuInterface.isMenuEnabled("Developer Menus"); + onTriggered: developerMenuEnabled = MenuInterface.isOptionChecked("Developer Menu"); } Component { @@ -84,7 +84,7 @@ Rectangle { Component.onCompleted: { isHMD = HMD.active; updateRunningScripts(); - developerMenuEnabled = MenuInterface.isMenuEnabled("Developer Menus"); + developerMenuEnabled = MenuInterface.isOptionChecked("Developer Menu"); checkMenu.restart(); } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 5633089019..1cde12a13c 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -100,19 +100,19 @@ Menu::Menu() { addActionToQMenuAndActionHash(editMenu, redoAction); editMenu->addSeparator(); - + // Edit > Cut addActionToQMenuAndActionHash(editMenu, "Cut", Qt::CTRL | Qt::Key_X); - + // Edit > Copy addActionToQMenuAndActionHash(editMenu, "Copy", Qt::CTRL | Qt::Key_C); - + // Edit > Paste addActionToQMenuAndActionHash(editMenu, "Paste", Qt::CTRL | Qt::Key_V); - + // Edit > Delete addActionToQMenuAndActionHash(editMenu, "Delete", Qt::Key_Delete); - + editMenu->addSeparator(); // Edit > Running Scripts @@ -280,7 +280,7 @@ Menu::Menu() { }); // Settings > Notifications - MenuWrapper * notificationsMenu = settingsMenu->addMenu("Notifications"); //This was in notifications.js. The menu needs to be moved here. + MenuWrapper * notificationsMenu = settingsMenu->addMenu("Notifications"); //This was in notifications.js. The menu needs to be moved here. //TODO: Hookup notification actions below. // Settings > Notifications > Play Notification Sounds @@ -308,43 +308,9 @@ Menu::Menu() { settings->setValue(MenuOption::NotificationSoundsTablet, action->isChecked()); }); - //Further sound notificaions disabled until new notification system will be implemented - /* - // Settings > Notifications > Level of Detail - action = addCheckableActionToQMenuAndActionHash(notificationsMenu, "Level of Detail", 0, - settings->getValue("play_notification_sounds_type_1").toBool()); - connect(action, &QAction::triggered, [action, settings] { - settings->setValue("play_notification_sounds_type_1", action->isChecked()); - }); - // Settings > Notifications > Connection - action = addCheckableActionToQMenuAndActionHash(notificationsMenu, "Connection", 0, - settings->getValue("play_notification_sounds_type_2").toBool()); - connect(action, &QAction::triggered, [action, settings] { - settings->setValue("play_notification_sounds_type_2", action->isChecked()); - }); - // Settings > Notifications > Connection Refused - action = addCheckableActionToQMenuAndActionHash(notificationsMenu, "Connection Refused", 0, - settings->getValue("play_notification_sounds_type_3").toBool()); - connect(action, &QAction::triggered, [action, settings] { - settings->setValue("play_notification_sounds_type_3", action->isChecked()); - }); - // Settings > Notifications > Edit Error - action = addCheckableActionToQMenuAndActionHash(notificationsMenu, "Edit Error", 0, - settings->getValue("play_notification_sounds_type_4").toBool()); - connect(action, &QAction::triggered, [action, settings] { - settings->setValue("play_notification_sounds_type_4", action->isChecked()); - }); - // Settings > Notifications > Wallet - addActionToQMenuAndActionHash(notificationsMenu, "Wallet"); - action = addCheckableActionToQMenuAndActionHash(notificationsMenu, "Wallet", 0, - settings->getValue("play_notification_sounds_type_6").toBool()); - connect(action, &QAction::triggered, [action, settings] { - settings->setValue("play_notification_sounds_type_6", action->isChecked()); - }); -*/ // Settings > Developer Menu addCheckableActionToQMenuAndActionHash(settingsMenu, "Developer Menu", 0, false, this, SLOT(toggleDeveloperMenus())); - + // Settings > Ask to Reset Settings addCheckableActionToQMenuAndActionHash(settingsMenu, MenuOption::AskToResetSettings, 0, false); @@ -375,7 +341,7 @@ Menu::Menu() { if (mainViewShadowTaskConfig) { if (action->isChecked()) { mainViewShadowTaskConfig->setPreset("Enabled"); - } else { + } else { mainViewShadowTaskConfig->setPreset("None"); } } @@ -844,7 +810,7 @@ Menu::Menu() { // Help/Application menu ---------------------------------- MenuWrapper * helpMenu = addMenu("Help"); - + // Help > About High Fidelity action = addActionToQMenuAndActionHash(helpMenu, "About High Fidelity"); connect(action, &QAction::triggered, [] { @@ -852,35 +818,35 @@ Menu::Menu() { QString("hifi/dialogs/TabletAboutDialog.qml"), "AboutDialog"); }); helpMenu->addSeparator(); - + // Help > HiFi Docs action = addActionToQMenuAndActionHash(helpMenu, "Online Documentation"); connect(action, &QAction::triggered, qApp, [] { QDesktopServices::openUrl(QUrl("https://docs.highfidelity.com/")); }); - + // Help > HiFi Forum action = addActionToQMenuAndActionHash(helpMenu, "Online Forums"); connect(action, &QAction::triggered, qApp, [] { QDesktopServices::openUrl(QUrl("https://forums.highfidelity.com/")); }); - + // Help > Scripting Reference action = addActionToQMenuAndActionHash(helpMenu, "Online Script Reference"); connect(action, &QAction::triggered, qApp, [] { QDesktopServices::openUrl(QUrl("https://docs.highfidelity.com/api-reference")); }); - + addActionToQMenuAndActionHash(helpMenu, "Controls Reference", 0, qApp, SLOT(showHelp())); - + helpMenu->addSeparator(); - + // Help > Release Notes action = addActionToQMenuAndActionHash(helpMenu, "Release Notes"); connect(action, &QAction::triggered, qApp, [] { QDesktopServices::openUrl(QUrl("http://steamcommunity.com/games/390540/announcements/")); }); - + // Help > Report a Bug! action = addActionToQMenuAndActionHash(helpMenu, "Report a Bug!"); connect(action, &QAction::triggered, qApp, [] { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 046dbafcc3..5fb4e80b80 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2654,7 +2654,6 @@ void MyAvatar::updateMotionBehaviorFromMenu() { } else { _motionBehaviors &= ~AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED; } - setCollisionsEnabled(menu->isOptionChecked(MenuOption::EnableAvatarCollisions)); setProperty("lookAtSnappingEnabled", menu->isOptionChecked(MenuOption::EnableLookAtSnapping)); } diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 3e23e57bd0..3af5848d2a 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -266,16 +266,7 @@ void setupPreferences() { static const QString movementsControlChannel = QStringLiteral("Hifi-Advanced-Movement-Disabler"); auto getter = [=]()->bool { return myAvatar->useAdvancedMovementControls(); }; - auto setter = [=](bool value) { - auto messagesClient = DependencyManager::get().data(); - myAvatar->setUseAdvancedMovementControls(value); - if (value) { - messagesClient->sendMessage(movementsControlChannel, QStringLiteral("enable_mappings"), true); - } else { - messagesClient->sendMessage(movementsControlChannel, QStringLiteral("disable_mappings"), true); - } - - }; + auto setter = [=](bool value) { myAvatar->setUseAdvancedMovementControls(value); }; preferences->addPreference(new CheckPreference(MOVEMENT, QStringLiteral("Advanced movement for hand controllers"), getter, setter)); diff --git a/scripts/system/controllers/toggleAdvancedMovementForHandControllers.js b/scripts/system/controllers/toggleAdvancedMovementForHandControllers.js index 40721e7f72..a1b96ac607 100644 --- a/scripts/system/controllers/toggleAdvancedMovementForHandControllers.js +++ b/scripts/system/controllers/toggleAdvancedMovementForHandControllers.js @@ -11,132 +11,164 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +/* jslint bitwise: true */ + +/* global Script, Quat, MyAvatar, HMD, Controller, Messages*/ + (function() { // BEGIN LOCAL_SCOPE -var mappingName, basicMapping, isChecked; + var TWO_SECONDS_INTERVAL = 2000; + var FLYING_MAPPING_NAME = 'Hifi-Flying-Dev-' + Math.random(); + var DRIVING_MAPPING_NAME = 'Hifi-Driving-Dev-' + Math.random(); -var TURN_RATE = 1000; -var isDisabled = false; -var previousSetting = MyAvatar.useAdvancedMovementControls; -if (previousSetting === false) { - previousSetting = false; - isChecked = false; -} + var flyingMapping = null; + var drivingMapping = null; -if (previousSetting === true) { - previousSetting = true; - isChecked = true; -} + var TURN_RATE = 1000; + var isDisabled = false; -function rotate180() { - var newOrientation = Quat.multiply(MyAvatar.orientation, Quat.angleAxis(180, { - x: 0, - y: 1, - z: 0 - })) - MyAvatar.orientation = newOrientation -} + var previousFlyingState = MyAvatar.getFlyingEnabled(); + var previousDrivingState = MyAvatar.useAdvancedMovementControls; -var inFlipTurn = false; + function rotate180() { + var newOrientation = Quat.multiply(MyAvatar.orientation, Quat.angleAxis(180, { + x: 0, + y: 1, + z: 0 + })); + MyAvatar.orientation = newOrientation; + } -function registerBasicMapping() { - mappingName = 'Hifi-AdvancedMovement-Dev-' + Math.random(); - basicMapping = Controller.newMapping(mappingName); - basicMapping.from(Controller.Standard.LY).to(function(value) { - if (isDisabled) { - return; - } - var stick = Controller.getValue(Controller.Standard.LS); - if (value === 1 && Controller.Hardware.OculusTouch !== undefined) { - rotate180(); - } else if (Controller.Hardware.Vive !== undefined) { - if (value > 0.75 && inFlipTurn === false) { - inFlipTurn = true; + var inFlipTurn = false; + + function registerBasicMapping() { + + drivingMapping = Controller.newMapping(DRIVING_MAPPING_NAME); + drivingMapping.from(Controller.Standard.LY).to(function(value) { + if (isDisabled) { + return; + } + + if (value === 1 && Controller.Hardware.OculusTouch !== undefined) { rotate180(); - Script.setTimeout(function() { - inFlipTurn = false; - }, TURN_RATE) + } else if (Controller.Hardware.Vive !== undefined) { + if (value > 0.75 && inFlipTurn === false) { + inFlipTurn = true; + rotate180(); + Script.setTimeout(function() { + inFlipTurn = false; + }, TURN_RATE); + } + } + return; + }); + + flyingMapping = Controller.newMapping(FLYING_MAPPING_NAME); + flyingMapping.from(Controller.Standard.RY).to(function(value) { + if (isDisabled) { + return; + } + + if (value === 1 && Controller.Hardware.OculusTouch !== undefined) { + rotate180(); + } else if (Controller.Hardware.Vive !== undefined) { + if (value > 0.75 && inFlipTurn === false) { + inFlipTurn = true; + rotate180(); + Script.setTimeout(function() { + inFlipTurn = false; + }, TURN_RATE); + } + } + return; + }); + } + + function scriptEnding() { + Controller.disableMapping(FLYING_MAPPING_NAME); + Controller.disableMapping(DRIVING_MAPPING_NAME); + } + + Script.scriptEnding.connect(scriptEnding); + + registerBasicMapping(); + + Script.setTimeout(function() { + if (MyAvatar.useAdvanceMovementControls) { + Controller.disableMapping(DRIVING_MAPPING_NAME); + } else { + Controller.enableMapping(DRIVING_MAPPING_NAME); + } + + if (MyAvatar.getFyingEnabled()) { + Controller.disableMapping(FLYING_MAPPING_NAME); + } else { + Controller.enableMapping(FLYING_MAPPING_NAME); + } + }, 100); + + + HMD.displayModeChanged.connect(function(isHMDMode) { + if (isHMDMode) { + if (Controller.Hardware.Vive !== undefined || Controller.Hardware.OculusTouch !== undefined) { + if (MyAvatar.useAdvancedMovementControls) { + Controller.disableMapping(DRIVING_MAPPING_NAME); + } else { + Controller.enableMapping(DRIVING_MAPPING_NAME); + } + + if (MyAvatar.getFlyingEnabled()) { + Controller.disableMapping(FLYING_MAPPING_NAME); + } else { + Controller.enableMapping(FLYING_MAPPING_NAME); + } + } } - return; }); - basicMapping.from(Controller.Standard.RY).to(function(value) { - if (isDisabled) { - return; - } - var stick = Controller.getValue(Controller.Standard.RS); - if (value === 1 && Controller.Hardware.OculusTouch !== undefined) { - rotate180(); - } else if (Controller.Hardware.Vive !== undefined) { - if (value > 0.75 && inFlipTurn === false) { - inFlipTurn = true; - rotate180(); - Script.setTimeout(function() { - inFlipTurn = false; - }, TURN_RATE) - } - } - return; - }) -} -function enableMappings() { - Controller.enableMapping(mappingName); -} + function update() { + if ((Controller.Hardware.Vive !== undefined || Controller.Hardware.OculusTouch !== undefined) && HMD.active) { + var flying = MyAvatar.getFlyingEnabled(); + var driving = MyAvatar.useAdvancedMovementControls; -function disableMappings() { - Controller.disableMapping(mappingName); -} + if (flying !== previousFlyingState) { + if (flying) { + Controller.disableMapping(FLYING_MAPPING_NAME); + } else { + Controller.enableMapping(FLYING_MAPPING_NAME); + } -function scriptEnding() { - disableMappings(); -} - -Script.scriptEnding.connect(scriptEnding); - -registerBasicMapping(); - -Script.setTimeout(function() { - if (previousSetting === true) { - disableMappings(); - } else { - enableMappings(); - } -}, 100) - - -HMD.displayModeChanged.connect(function(isHMDMode) { - if (isHMDMode) { - if (Controller.Hardware.Vive !== undefined || Controller.Hardware.OculusTouch !== undefined) { - if (isChecked === true) { - disableMappings(); - } else if (isChecked === false) { - enableMappings(); + previousFlyingState = flying; } + if (driving !== previousDrivingState) { + if (driving) { + Controller.disableMapping(DRIVING_MAPPING_NAME); + } else { + Controller.enableMapping(DRIVING_MAPPING_NAME); + } + previousDrivingState = driving; + } + } + Script.setTimeout(update, TWO_SECONDS_INTERVAL); + } + + Script.setTimeout(update, TWO_SECONDS_INTERVAL); + + var HIFI_ADVANCED_MOVEMENT_DISABLER_CHANNEL = 'Hifi-Advanced-Movement-Disabler'; + function handleMessage(channel, message, sender) { + if (channel === HIFI_ADVANCED_MOVEMENT_DISABLER_CHANNEL) { + if (message === 'disable') { + isDisabled = true; + } else if (message === 'enable') { + isDisabled = false; + } } } -}); - -var HIFI_ADVANCED_MOVEMENT_DISABLER_CHANNEL = 'Hifi-Advanced-Movement-Disabler'; -function handleMessage(channel, message, sender) { - if (channel === HIFI_ADVANCED_MOVEMENT_DISABLER_CHANNEL) { - if (message === 'disable') { - isDisabled = true; - } else if (message === 'enable') { - isDisabled = false; - } else if (message === 'enable_mappings') { - print("enable mappings") - enableMappings(); - } else if (message === 'disable_mappings') { - disableMappings(); - } - } -} - -Messages.subscribe(HIFI_ADVANCED_MOVEMENT_DISABLER_CHANNEL); -Messages.messageReceived.connect(handleMessage); + Messages.subscribe(HIFI_ADVANCED_MOVEMENT_DISABLER_CHANNEL); + Messages.messageReceived.connect(handleMessage); }()); // END LOCAL_SCOPE From 6c946d7ac5e7f9da7640ef21258f7d60e944609c Mon Sep 17 00:00:00 2001 From: David Back Date: Wed, 16 May 2018 11:36:57 -0700 Subject: [PATCH 057/143] prevent continuous clone calls --- .../controllerModules/nearParentGrabEntity.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index 0ebd4efb2f..5f310e471f 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -35,6 +35,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); this.lastUnexpectedChildrenCheckTime = 0; this.robbed = false; this.highlightedEntity = null; + this.cloneAllowed = true; this.parameters = makeDispatcherModuleParameters( 500, @@ -272,6 +273,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); controllerData.secondaryValues[this.hand] < TRIGGER_OFF_VALUE) { this.checkForUnexpectedChildren(controllerData); this.robbed = false; + this.cloneAllowed = true; return makeRunningValues(false, [], []); } @@ -335,12 +337,14 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); var targetCloneable = entityIsCloneable(targetProps); if (targetCloneable) { - var cloneID = cloneEntity(targetProps); - var cloneProps = Entities.getEntityProperties(cloneID); - this.grabbing = true; - this.targetEntityID = cloneID; - this.startNearParentingGrabEntity(controllerData, cloneProps); - + if (this.cloneAllowed) { + var cloneID = cloneEntity(targetProps); + var cloneProps = Entities.getEntityProperties(cloneID); + this.grabbing = true; + this.targetEntityID = cloneID; + this.startNearParentingGrabEntity(controllerData, cloneProps); + this.cloneAllowed = false; + } } else if (targetProps) { this.grabbing = true; this.startNearParentingGrabEntity(controllerData, targetProps); From 06fa4efe055240e900c109bd1b5a9ba705b327b7 Mon Sep 17 00:00:00 2001 From: David Back Date: Wed, 16 May 2018 11:39:53 -0700 Subject: [PATCH 058/143] add comment --- .../controllers/controllerModules/nearParentGrabEntity.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index 5f310e471f..4ab45b33f7 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -343,7 +343,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); this.grabbing = true; this.targetEntityID = cloneID; this.startNearParentingGrabEntity(controllerData, cloneProps); - this.cloneAllowed = false; + this.cloneAllowed = false; // prevent another clone call until inputs released } } else if (targetProps) { this.grabbing = true; From 7501b8818e50e3e5ed61fa09ec30121d014d37eb Mon Sep 17 00:00:00 2001 From: vladest Date: Wed, 16 May 2018 21:01:50 +0200 Subject: [PATCH 059/143] removed shadows quality --- interface/src/ui/PreferencesDialog.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index ca001eb406..2e6c9c8e64 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -79,9 +79,6 @@ void setupPreferences() { wodSlider->setMin(0); wodSlider->setMax(2000); preferences->addPreference(wodSlider); - auto getterSQ = []()->float { return 1.0; }; - auto setterSQ = [](float value) { }; - preferences->addPreference(new SliderPreference(GRAPHICS_QUALITY, "Shadow Quality", getterSQ, setterSQ)); auto getterShadow = []()->bool { bool ret = false; @@ -104,7 +101,7 @@ void setupPreferences() { } } }; - preferences->addPreference(new CheckPreference(GRAPHICS_QUALITY, "Enable/disable shadows", getterShadow, setterShadow)); + preferences->addPreference(new CheckPreference(GRAPHICS_QUALITY, "Show Shadows", getterShadow, setterShadow)); } // UI From 8c146521cf8d5764458bfcf2cdec4c2c9c0340d8 Mon Sep 17 00:00:00 2001 From: vladest Date: Wed, 16 May 2018 21:10:51 +0200 Subject: [PATCH 060/143] remove double crash options --- interface/src/Menu.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 1cde12a13c..4fe2ce8f04 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -731,9 +731,6 @@ Menu::Menu() { action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashNewFaultThreaded); connect(action, &QAction::triggered, qApp, []() { std::thread(crash::newFault).join(); }); - // Developer > Display Crash Options - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::DisplayCrashOptions, 0, true); - // Developer > Stats addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::Stats); From fbc3d97af33c2e8e1599f057ea9c4da13520b6a7 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 16 May 2018 13:48:29 -0700 Subject: [PATCH 061/143] adding back overlay menu and avatar size --- interface/src/Application.cpp | 2 +- interface/src/Application.h | 3 +++ interface/src/Menu.cpp | 26 ++++++++++++++++++++++++++ interface/src/ui/OverlayConductor.cpp | 2 +- interface/src/ui/PreferencesDialog.cpp | 12 ++++++++++++ 5 files changed, 43 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b590a100dc..0bdf358aa2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5107,7 +5107,7 @@ void Application::updateThreads(float deltaTime) { void Application::toggleOverlays() {} void Application::setOverlaysVisible(bool visible) { - Q_UNUSED(visible) + _overlaysVisible = visible; } void Application::centerUI() { diff --git a/interface/src/Application.h b/interface/src/Application.h index 5a29dd23e8..4a3bc22de0 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -377,6 +377,7 @@ public slots: void cameraMenuChanged(); void toggleOverlays(); void setOverlaysVisible(bool visible); + bool getOverlaysVisible() { return _overlaysVisible; }; Q_INVOKABLE void centerUI(); void resetPhysicsReadyInformation(); @@ -693,6 +694,8 @@ private: bool _fakedMouseEvent { false }; + bool _overlaysVisible { true }; + void checkChangeCursor(); mutable QMutex _changeCursorLock { QMutex::Recursive }; Qt::CursorShape _desiredCursor{ Qt::BlankCursor }; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 1cde12a13c..366494bcac 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -146,6 +146,32 @@ Menu::Menu() { auto avatarManager = DependencyManager::get(); auto avatar = avatarManager->getMyAvatar(); + // Avatar > Size + MenuWrapper* avatarSizeMenu = avatarMenu->addMenu("Size"); + // Avatar > Size > Increase + addActionToQMenuAndActionHash(avatarSizeMenu, + MenuOption::IncreaseAvatarSize, + 0, // QML Qt::Key_Plus, + avatar.get(), SLOT(increaseSize())); + + // Avatar > Size > Decrease + addActionToQMenuAndActionHash(avatarSizeMenu, + MenuOption::DecreaseAvatarSize, + 0, // QML Qt::Key_Minus, + avatar.get(), SLOT(decreaseSize())); + + // Avatar > Size > Reset + addActionToQMenuAndActionHash(avatarSizeMenu, + MenuOption::ResetAvatarSize, + 0, // QML Qt::Key_Equal, + avatar.get(), SLOT(resetSize())); + + // Avatar > Reset Sensors + addActionToQMenuAndActionHash(avatarMenu, + MenuOption::ResetSensors, + 0, // QML Qt::Key_Apostrophe, + qApp, SLOT(resetSensors())); + // Avatar > Attachments... action = addActionToQMenuAndActionHash(avatarMenu, MenuOption::Attachments); connect(action, &QAction::triggered, [] { diff --git a/interface/src/ui/OverlayConductor.cpp b/interface/src/ui/OverlayConductor.cpp index 66789422f4..5393306286 100644 --- a/interface/src/ui/OverlayConductor.cpp +++ b/interface/src/ui/OverlayConductor.cpp @@ -144,7 +144,7 @@ void OverlayConductor::update(float dt) { } - bool targetVisible = (0 == (_flags & SuppressMask)); + bool targetVisible = qApp->getOverlaysVisible() && (0 == (_flags & SuppressMask)); if (targetVisible != currentVisible) { offscreenUi->setPinned(!targetVisible); } diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index ca001eb406..b5095ab123 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -146,6 +146,18 @@ void setupPreferences() { preferences->addPreference(new CheckPreference(UI_CATEGORY, "Use reticle cursor instead of arrow", getter, setter)); } + { + auto getter = [=]()->bool { return myAvatar->getClearOverlayWhenMoving(); }; + auto setter = [=](bool value) { myAvatar->setClearOverlayWhenMoving(value); }; + preferences->addPreference(new CheckPreference(UI_CATEGORY, "Clear overlays when moving", getter, setter)); + } + + { + auto getter = [=]()->bool { return qApp->getOverlaysVisible(); }; + auto setter = [=](bool value) { qApp->setOverlaysVisible(value); }; + preferences->addPreference(new CheckPreference(UI_CATEGORY, "Show Overlays", getter, setter)); + } + static const QString VIEW_CATEGORY{ "View" }; { auto getter = [=]()->float { return myAvatar->getRealWorldFieldOfView(); }; From 3be4b01d2c7e815bf2781284f2f55c526049a88d Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 16 May 2018 14:36:55 -0700 Subject: [PATCH 062/143] move overlays menu back --- interface/src/Application.cpp | 8 ++++++-- interface/src/Application.h | 3 --- interface/src/Menu.cpp | 2 ++ interface/src/ui/OverlayConductor.cpp | 2 +- interface/src/ui/PreferencesDialog.cpp | 12 ------------ 5 files changed, 9 insertions(+), 18 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0bdf358aa2..303089fc14 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5104,10 +5104,14 @@ void Application::updateThreads(float deltaTime) { } } -void Application::toggleOverlays() {} +void Application::toggleOverlays() { + auto meu = Menu::getInstance(); + menu->setIsOptionChecked(MenuOption::Overlays, !menu->isOptionChecked(menuOption::Overlays)); +} void Application::setOverlaysVisible(bool visible) { - _overlaysVisible = visible; + auto menu = Menu::getInstance(); + menu->setIsOptionChecked(MenuOption::Overlays, visible) } void Application::centerUI() { diff --git a/interface/src/Application.h b/interface/src/Application.h index 4a3bc22de0..5a29dd23e8 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -377,7 +377,6 @@ public slots: void cameraMenuChanged(); void toggleOverlays(); void setOverlaysVisible(bool visible); - bool getOverlaysVisible() { return _overlaysVisible; }; Q_INVOKABLE void centerUI(); void resetPhysicsReadyInformation(); @@ -694,8 +693,6 @@ private: bool _fakedMouseEvent { false }; - bool _overlaysVisible { true }; - void checkChangeCursor(); mutable QMutex _changeCursorLock { QMutex::Recursive }; Qt::CursorShape _desiredCursor{ Qt::BlankCursor }; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index fe49ec3d8a..9b21a06483 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -239,6 +239,8 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::CenterPlayerInView, 0, true, qApp, SLOT(rotationModeChanged())); + addCheckableActrionToQMenuActionHash(viewMenu, MenuOption::Overlays, 0, true); + // View > Enter First Person Mode in HMD addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPersonHMD, 0, true); diff --git a/interface/src/ui/OverlayConductor.cpp b/interface/src/ui/OverlayConductor.cpp index 5393306286..e7e3c91d13 100644 --- a/interface/src/ui/OverlayConductor.cpp +++ b/interface/src/ui/OverlayConductor.cpp @@ -144,7 +144,7 @@ void OverlayConductor::update(float dt) { } - bool targetVisible = qApp->getOverlaysVisible() && (0 == (_flags & SuppressMask)); + bool targetVisible = Menu::getInstance()->isOptionChecked(MenuOption::Overlays) && (0 == (_flags & SuppressMask)); if (targetVisible != currentVisible) { offscreenUi->setPinned(!targetVisible); } diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index ede02c5016..083ed68090 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -58,18 +58,6 @@ void setupPreferences() { preferences->addPreference(preference); } - static const QString MOUSE_SENSIVITY { "Mouse Sensivity" }; - { - auto getterY = []()->float { return 1.0; }; - auto setterY = [](float value) { }; - preferences->addPreference(new SliderPreference(MOUSE_SENSIVITY, "Mouse Look Y", getterY, setterY)); - auto getterX = []()->float { return 1.0; }; - auto setterX = [](float value) { }; - preferences->addPreference(new SliderPreference(MOUSE_SENSIVITY, "Mouse Look X", getterX, setterX)); - auto getterSW = []()->float { return 1.0; }; - auto setterSW = [](float value) { }; - preferences->addPreference(new SliderPreference(MOUSE_SENSIVITY, "Mouse Look Zoom", getterSW, setterSW)); - } // Graphics quality static const QString GRAPHICS_QUALITY { "Graphics Quality" }; { From f8e9afb115e433af44f9d54120c3dedfc95f7213 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 16 May 2018 15:08:09 -0700 Subject: [PATCH 063/143] fixing damn build issues --- interface/src/Application.cpp | 6 +++--- interface/src/Menu.cpp | 2 +- interface/src/ui/PreferencesDialog.cpp | 6 ------ 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 303089fc14..c9afdb3064 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5105,13 +5105,13 @@ void Application::updateThreads(float deltaTime) { } void Application::toggleOverlays() { - auto meu = Menu::getInstance(); - menu->setIsOptionChecked(MenuOption::Overlays, !menu->isOptionChecked(menuOption::Overlays)); + auto menu = Menu::getInstance(); + menu->setIsOptionChecked(MenuOption::Overlays, !menu->isOptionChecked(MenuOption::Overlays)); } void Application::setOverlaysVisible(bool visible) { auto menu = Menu::getInstance(); - menu->setIsOptionChecked(MenuOption::Overlays, visible) + menu->setIsOptionChecked(MenuOption::Overlays, visible); } void Application::centerUI() { diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 9b21a06483..6bc93c2e5c 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -239,7 +239,7 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::CenterPlayerInView, 0, true, qApp, SLOT(rotationModeChanged())); - addCheckableActrionToQMenuActionHash(viewMenu, MenuOption::Overlays, 0, true); + addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Overlays, 0, true); // View > Enter First Person Mode in HMD addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPersonHMD, 0, true); diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 083ed68090..a7aff4ebe3 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -137,12 +137,6 @@ void setupPreferences() { preferences->addPreference(new CheckPreference(UI_CATEGORY, "Clear overlays when moving", getter, setter)); } - { - auto getter = [=]()->bool { return qApp->getOverlaysVisible(); }; - auto setter = [=](bool value) { qApp->setOverlaysVisible(value); }; - preferences->addPreference(new CheckPreference(UI_CATEGORY, "Show Overlays", getter, setter)); - } - static const QString VIEW_CATEGORY{ "View" }; { auto getter = [=]()->float { return myAvatar->getRealWorldFieldOfView(); }; From 2a6204ca8dca0eda3a5bd9d3ea98ed5fd663b8f6 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 16 May 2018 15:47:55 -0700 Subject: [PATCH 064/143] remove option for mouse sensivtity --- .../resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml | 2 +- .../resources/qml/hifi/tablet/TabletGeneralPreferences.qml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml b/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml index b6441573d8..cb4913f999 100644 --- a/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml +++ b/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml @@ -17,7 +17,7 @@ PreferencesDialog { id: root objectName: "GeneralPreferencesDialog" title: "General Settings" - showCategories: ["User Interface", "HMD", "Snapshots", "Privacy", "Mouse Sensivity"] + showCategories: ["User Interface", "HMD", "Snapshots", "Privacy"] property var settings: Settings { category: root.objectName property alias x: root.x diff --git a/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml b/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml index f754bd4ea5..810f5bb43f 100644 --- a/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml +++ b/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml @@ -32,6 +32,6 @@ StackView { TabletPreferencesDialog { id: root objectName: "TabletGeneralPreferences" - showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "Game Controller", "Sixense Controllers", "Perception Neuron", "Kinect", "Leap Motion", "Mouse Sensivity"] + showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "Game Controller", "Sixense Controllers", "Perception Neuron", "Kinect", "Leap Motion"] } } From 95cd9476c3eea38d0957bd2bf45d68cbefc68e78 Mon Sep 17 00:00:00 2001 From: vladest Date: Thu, 17 May 2018 16:11:28 +0200 Subject: [PATCH 065/143] Fixed modality in Desktop --- interface/resources/qml/desktop/Desktop.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml index a59b9d5ac0..a1b89e1529 100644 --- a/interface/resources/qml/desktop/Desktop.qml +++ b/interface/resources/qml/desktop/Desktop.qml @@ -149,7 +149,7 @@ FocusScope { } function isModalWindow(window) { - return true;//window.modality !== (typeof Qt !== 'undefined' ? Qt.NonModal : 0); + return window.modality !== (typeof Qt !== 'undefined' ? Qt.NonModal : 0); } function getTopLevelWindows(predicate) { From 3730cbe36c829fa46a2bd83d340e5e2f21bf5d4c Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 17 May 2018 10:28:48 -0700 Subject: [PATCH 066/143] reconstruct cloneIDs lists on start, read/write locks on clone ID functions, fix removing last cloneable --- libraries/entities/src/EntityItem.cpp | 36 ++++++++++++++++++++------- libraries/entities/src/EntityItem.h | 3 ++- libraries/entities/src/EntityTree.cpp | 18 +++++++++++++- 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 1e95e999b1..e6aa572330 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -3096,18 +3096,36 @@ void EntityItem::setCloneOriginID(const QUuid& value) { } bool EntityItem::addCloneID(const QUuid& cloneID) { - if (!_cloneIDs.contains(cloneID)) { - _cloneIDs.append(cloneID); - return true; - } + withWriteLock([&] { + if (!_cloneIDs.contains(cloneID)) { + _cloneIDs.append(cloneID); + return true; + } + }); return false; } bool EntityItem::removeCloneID(const QUuid& cloneID) { - int index = _cloneIDs.indexOf(cloneID); - if (index > 0) { - _cloneIDs.removeAt(index); - return true; - } + withWriteLock([&] { + int index = _cloneIDs.indexOf(cloneID); + if (index >= 0) { + _cloneIDs.removeAt(index); + return true; + } + }); return false; } + +const QList EntityItem::getCloneIDs() const { + QList result; + withReadLock([&] { + result = _cloneIDs; + }); + return result; +} + +void EntityItem::setCloneIDs(const QList& cloneIDs) { + withWriteLock([&] { + _cloneIDs = cloneIDs; + }); +} diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index f314cd1418..cc8cefb17b 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -509,7 +509,8 @@ public: bool addCloneID(const QUuid& cloneID); bool removeCloneID(const QUuid& cloneID); - const QList& getCloneIDs() const { return _cloneIDs; } + const QList getCloneIDs() const; + void setCloneIDs(const QList& cloneIDs); signals: void requestRenderUpdate(); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index b2daed4e72..c87f6d771a 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -631,7 +631,7 @@ void EntityTree::cleanupCloneIDs(const EntityItemID& entityID) { EntityItemPointer entity = findEntityByEntityItemID(entityID); if (entity) { // remove clone ID from it's clone origin's clone ID list if clone origin exists - const QUuid cloneOriginID = entity->getCloneOriginID(); + const QUuid& cloneOriginID = entity->getCloneOriginID(); if (!cloneOriginID.isNull()) { EntityItemPointer cloneOrigin = findEntityByID(cloneOriginID); if (cloneOrigin) { @@ -2385,6 +2385,8 @@ bool EntityTree::readFromMap(QVariantMap& map) { return false; } + QMap> cloneIDs; + bool success = true; foreach (QVariant entityVariant, entitiesQList) { // QVariantMap --> QScriptValue --> EntityItemProperties --> Entity @@ -2477,6 +2479,20 @@ bool EntityTree::readFromMap(QVariantMap& map) { qCDebug(entities) << "adding Entity failed:" << entityItemID << properties.getType(); success = false; } + + const QUuid& cloneOriginID = entity->getCloneOriginID(); + if (!cloneOriginID.isNull()) { + cloneIDs[cloneOriginID].push_back(entity->getEntityItemID()); + } + } + + for (auto iter = cloneIDs.begin(); iter != cloneIDs.end(); ++iter) { + const QUuid& entityID = iter.key(); + const QList& cloneIDs = iter.value(); + EntityItemPointer entity = findEntityByID(entityID); + if (entity) { + entity->setCloneIDs(cloneIDs); + } } return success; From 42d84924274def80ade80cafeb5b7d84aaa3ec44 Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 17 May 2018 11:17:04 -0700 Subject: [PATCH 067/143] no clock skew --- libraries/entities/src/EntityEditPacketSender.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityEditPacketSender.cpp b/libraries/entities/src/EntityEditPacketSender.cpp index c2323b0a20..9ca102d016 100644 --- a/libraries/entities/src/EntityEditPacketSender.cpp +++ b/libraries/entities/src/EntityEditPacketSender.cpp @@ -34,7 +34,7 @@ void EntityEditPacketSender::processEntityEditNackPacket(QSharedPointer Date: Thu, 17 May 2018 11:25:20 -0700 Subject: [PATCH 068/143] Add JSDoc header to new clone function in Entity API --- libraries/entities/src/EntityScriptingInterface.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 883990418a..febc33ffde 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -224,6 +224,14 @@ public slots: Q_INVOKABLE QUuid addModelEntity(const QString& name, const QString& modelUrl, const QString& textures, const QString& shapeType, bool dynamic, bool collisionless, const glm::vec3& position, const glm::vec3& gravity); + /**jsdoc + * Request a clone of an entity. Only entities that have been marked as 'cloneable' will be able to be cloned using this method. + * A cloned entity has most of the properties of the orignal entity, and can be requested from clients that do not have rez permissions. + * The client requests a clone from the entity server, which returns back the entityID of a valid clone if the operation was allowed. + * @function Entities.cloneEntity + * @param {Uuid} entityIDToClone - the ID of the entity to clone + * @returns {Entities.EntityID} The ID of the newly created clone + */ Q_INVOKABLE QUuid cloneEntity(QUuid entityIDToClone); /**jsdoc From 201b8a51406381fe32221841aefd048dd908cc47 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 17 May 2018 11:35:34 -0700 Subject: [PATCH 069/143] fixing the graphics preference --- interface/src/ui/PreferencesDialog.cpp | 61 ++++++++++++++++---------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index a7aff4ebe3..ac4ee40ebe 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -15,7 +15,6 @@ #include #include #include -#include #include #include @@ -27,9 +26,6 @@ #include "SnapshotAnimated.h" #include "UserActivityLogger.h" -#include "controllers/impl/MappingBuilderProxy.h" -#include "controllers/impl/RouteBuilderProxy.h" - void setupPreferences() { auto preferences = DependencyManager::get(); auto nodeList = DependencyManager::get(); @@ -61,33 +57,50 @@ void setupPreferences() { // Graphics quality static const QString GRAPHICS_QUALITY { "Graphics Quality" }; { - auto getter = []()->float { return DependencyManager::get()->getOctreeSizeScale()/TREE_SCALE; }; - auto setter = [](float value) { DependencyManager::get()->setOctreeSizeScale(value*TREE_SCALE); }; + static const float MAX_DESKTOP_FPS = 60; + static const float MAX_HMD_FPS = 90; + static const float MIN_HMD_FPS = 35; + auto getter = []()->float { + auto lodManager = DependencyManager::get(); + float sliderValue = 0; + bool inHMD = qApp->isHMDMode(); + + if (inHMD) { + float hmdMinFPS = lodManager->getHMDLODDecreaseFPS(); + sliderValue = (MAX_HMD_FPS - hmdMinFPS) / MAX_HMD_FPS; + } else { + float desktopMinFPS = lodManager->getDesktopLODDecreaseFPS(); + sliderValue = (MAX_DESKTOP_FPS - desktopMinFPS) / MAX_DESKTOP_FPS; + } + return sliderValue; + }; + + auto setter = [](float value) { + static const float THRASHING_DIFFERENCE = 10; + auto lodManager = DependencyManager::get(); + if (qApp->isHMDMode()) { + float desiredHMDFPS = (MAX_HMD_FPS - (MAX_HMD_FPS * value)) - THRASHING_DIFFERENCE; + float actualHMDFPS = desiredHMDFPS > MIN_HMD_FPS ? desiredHMDFPS : MIN_HMD_FPS; + lodManager->setHMDLODDecreaseFPS(actualHMDFPS); + } else { + float desiredDesktopFPS = (MAX_DESKTOP_FPS - (MAX_DESKTOP_FPS * value)) - THRASHING_DIFFERENCE; + lodManager->setDesktopLODDecreaseFPS(desiredDesktopFPS); + } + }; + auto wodSlider = new SliderPreference(GRAPHICS_QUALITY, "World Detail", getter, setter); wodSlider->setMin(0); - wodSlider->setMax(2000); + wodSlider->setMax(1); + wodSlider->setStep(0.1); preferences->addPreference(wodSlider); auto getterShadow = []()->bool { - bool ret = false; - auto renderConfig = qApp->getRenderEngine()->getConfiguration(); - if (renderConfig) { - auto mainViewShadowTaskConfig = renderConfig->getConfig("RenderMainView.RenderShadowTask"); - if (mainViewShadowTaskConfig) { - ret = (mainViewShadowTaskConfig->getPreset() == QStringLiteral("Enabled")); - } - } - return ret; + auto menu = Menu::getInstance(); + return menu->isOptionChecked(MenuOption::Shadows); }; auto setterShadow = [](bool value) { - auto renderConfig = qApp->getRenderEngine()->getConfiguration(); - if (renderConfig) { - auto mainViewShadowTaskConfig = renderConfig->getConfig("RenderMainView.RenderShadowTask"); - if (mainViewShadowTaskConfig) { - mainViewShadowTaskConfig->setPreset(value ? QStringLiteral("Enabled") - : QStringLiteral("None")); - } - } + auto menu = Menu::getInstance(); + menu->setIsOptionChecked(MenuOption::Shadows, value); }; preferences->addPreference(new CheckPreference(GRAPHICS_QUALITY, "Show Shadows", getterShadow, setterShadow)); } From eb25601856a707d08e9a890c9e0dd345e21edee1 Mon Sep 17 00:00:00 2001 From: vladest Date: Thu, 17 May 2018 20:41:38 +0200 Subject: [PATCH 070/143] Return back LOD tools --- interface/src/Application.cpp | 13 +++ interface/src/Application.h | 2 + interface/src/LODManager.cpp | 5 +- interface/src/Menu.cpp | 4 + interface/src/Menu.h | 1 + interface/src/ui/DialogsManager.cpp | 11 +++ interface/src/ui/DialogsManager.h | 4 + interface/src/ui/HMDToolsDialog.cpp | 5 +- interface/src/ui/LodToolsDialog.cpp | 132 ++++++++++++++++++++++++++++ interface/src/ui/LodToolsDialog.h | 55 ++++++++++++ 10 files changed, 230 insertions(+), 2 deletions(-) create mode 100644 interface/src/ui/LodToolsDialog.cpp create mode 100644 interface/src/ui/LodToolsDialog.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c9afdb3064..33735ab5f0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3705,6 +3705,8 @@ void Application::keyPressEvent(QKeyEvent* event) { Menu::getInstance()->triggerOption(MenuOption::Log); } else if (isMeta) { Menu::getInstance()->triggerOption(MenuOption::AddressBar); + } else if (isShifted) { + Menu::getInstance()->triggerOption(MenuOption::LodTools); } break; @@ -7527,6 +7529,17 @@ SharedSoundPointer Application::getSampleSound() const { return _sampleSound; } +void Application::loadLODToolsDialog() { + auto tabletScriptingInterface = DependencyManager::get(); + auto tablet = dynamic_cast(tabletScriptingInterface->getTablet(SYSTEM_TABLET)); + if (tablet->getToolbarMode() || (!tablet->getTabletRoot() && !isHMDMode())) { + auto dialogsManager = DependencyManager::get(); + dialogsManager->lodTools(); + } else { + tablet->pushOntoStack("hifi/dialogs/TabletLODTools.qml"); + } +} + void Application::loadEntityStatisticsDialog() { auto tabletScriptingInterface = DependencyManager::get(); auto tablet = dynamic_cast(tabletScriptingInterface->getTablet(SYSTEM_TABLET)); diff --git a/interface/src/Application.h b/interface/src/Application.h index 5a29dd23e8..17e28f0e6e 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -65,6 +65,7 @@ #include "scripting/DialogsManagerScriptingInterface.h" #include "ui/ApplicationOverlay.h" #include "ui/EntityScriptServerLogDialog.h" +#include "ui/LodToolsDialog.h" #include "ui/LogDialog.h" #include "ui/OctreeStatsDialog.h" #include "ui/OverlayConductor.h" @@ -402,6 +403,7 @@ public slots: void addAssetToWorldMessageClose(); + void loadLODToolsDialog(); void loadEntityStatisticsDialog(); void loadDomainConnectionDialog(); void showScriptLogs(); diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 090bec89b1..da1f14c450 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -122,7 +122,10 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { } if (oldOctreeSizeScale != _octreeSizeScale) { - //TODO: check Preferences dialog + auto lodToolsDialog = DependencyManager::get()->getLodToolsDialog(); + if (lodToolsDialog) { + lodToolsDialog->reloadSliders(); + } } } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6bc93c2e5c..499ceae81c 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -479,6 +479,10 @@ Menu::Menu() { }); } + // Developer > Render > LOD Tools + addActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::LodTools, 0, + qApp, SLOT(loadLODToolsDialog())); + // HACK enable texture decimation { auto action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, "Decimate Textures"); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 526ca5f88f..4a957fcb69 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -121,6 +121,7 @@ namespace MenuOption { const QString ActionMotorControl = "Enable Default Motor Control"; const QString LoadScript = "Open and Run Script File..."; const QString LoadScriptURL = "Open and Run Script from URL..."; + const QString LodTools = "LOD Tools"; const QString Login = "Login/Sign Up"; const QString Log = "Log"; const QString LogExtraTimings = "Log Extra Timing Details"; diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 05fc3e48ba..d01e7d6671 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -23,6 +23,7 @@ #include "ConnectionFailureDialog.h" #include "DomainConnectionDialog.h" #include "HMDToolsDialog.h" +#include "LodToolsDialog.h" #include "LoginDialog.h" #include "OctreeStatsDialog.h" #include "PreferencesDialog.h" @@ -125,6 +126,16 @@ void DialogsManager::octreeStatsDetails() { _octreeStatsDialog->raise(); } +void DialogsManager::lodTools() { + if (!_lodToolsDialog) { + maybeCreateDialog(_lodToolsDialog); + + connect(_lodToolsDialog, SIGNAL(closed()), _lodToolsDialog, SLOT(deleteLater())); + _lodToolsDialog->show(); + } + _lodToolsDialog->raise(); +} + void DialogsManager::hmdTools(bool showTools) { if (showTools) { if (!_hmdToolsDialog) { diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h index c24f0fc4c0..f17ac39a7e 100644 --- a/interface/src/ui/DialogsManager.h +++ b/interface/src/ui/DialogsManager.h @@ -22,6 +22,7 @@ class AnimationsDialog; class AttachmentsDialog; class CachesSizeDialog; +class LodToolsDialog; class OctreeStatsDialog; class ScriptEditorWindow; class TestingDialog; @@ -34,6 +35,7 @@ class DialogsManager : public QObject, public Dependency { public: QPointer getHMDToolsDialog() const { return _hmdToolsDialog; } + QPointer getLodToolsDialog() const { return _lodToolsDialog; } QPointer getOctreeStatsDialog() const { return _octreeStatsDialog; } QPointer getTestingDialog() const { return _testingDialog; } void emitAddressBarShown(bool visible) { emit addressBarShown(visible); } @@ -47,6 +49,7 @@ public slots: void toggleLoginDialog(); void showLoginDialog(); void octreeStatsDetails(); + void lodTools(); void hmdTools(bool showTools); void showDomainConnectionDialog(); void showTestingResults(); @@ -73,6 +76,7 @@ private: QPointer _cachesSizeDialog; QPointer _ircInfoBox; QPointer _hmdToolsDialog; + QPointer _lodToolsDialog; QPointer _octreeStatsDialog; QPointer _testingDialog; QPointer _domainConnectionDialog; diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index d3ff239553..fb49c4f4c4 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -83,7 +83,10 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) : if (dialogsManager->getOctreeStatsDialog()) { watchWindow(dialogsManager->getOctreeStatsDialog()->windowHandle()); } - + if (dialogsManager->getLodToolsDialog()) { + watchWindow(dialogsManager->getLodToolsDialog()->windowHandle()); + } + connect(_switchModeButton, &QPushButton::clicked, [this]{ toggleHMDMode(); }); diff --git a/interface/src/ui/LodToolsDialog.cpp b/interface/src/ui/LodToolsDialog.cpp new file mode 100644 index 0000000000..e2f2d9e011 --- /dev/null +++ b/interface/src/ui/LodToolsDialog.cpp @@ -0,0 +1,132 @@ +// +// LodToolsDialog.cpp +// interface/src/ui +// +// Created by Brad Hefta-Gaub on 7/19/13. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "LodToolsDialog.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "Menu.h" + + +LodToolsDialog::LodToolsDialog(QWidget* parent) : + QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint) +{ + this->setWindowTitle("LOD Tools"); + auto lodManager = DependencyManager::get(); + + // Create layouter + QFormLayout* form = new QFormLayout(this); + + // Create a label with feedback... + _feedback = new QLabel(this); + QPalette palette = _feedback->palette(); + const unsigned redish = 0xfff00000; + palette.setColor(QPalette::WindowText, QColor::fromRgb(redish)); + _feedback->setPalette(palette); + _feedback->setText(lodManager->getLODFeedbackText()); + const int FEEDBACK_WIDTH = 350; + _feedback->setFixedWidth(FEEDBACK_WIDTH); + form->addRow("You can see... ", _feedback); + + form->addRow("Manually Adjust Level of Detail:", _manualLODAdjust = new QCheckBox(this)); + _manualLODAdjust->setChecked(!lodManager->getAutomaticLODAdjust()); + connect(_manualLODAdjust, SIGNAL(toggled(bool)), SLOT(updateAutomaticLODAdjust())); + + _lodSize = new QSlider(Qt::Horizontal, this); + const int MAX_LOD_SIZE = 2000; // ~20:4 vision -- really good. + const int MIN_LOD_SIZE = 5; // ~20:1600 vision -- really bad! + const int STEP_LOD_SIZE = 1; + const int PAGE_STEP_LOD_SIZE = 100; + const int SLIDER_WIDTH = 300; + _lodSize->setMaximum(MAX_LOD_SIZE); + _lodSize->setMinimum(MIN_LOD_SIZE); + _lodSize->setSingleStep(STEP_LOD_SIZE); + _lodSize->setTickInterval(PAGE_STEP_LOD_SIZE); + _lodSize->setTickPosition(QSlider::TicksBelow); + _lodSize->setFixedWidth(SLIDER_WIDTH); + _lodSize->setPageStep(PAGE_STEP_LOD_SIZE); + int sliderValue = lodManager->getOctreeSizeScale() / TREE_SCALE; + _lodSize->setValue(sliderValue); + form->addRow("Level of Detail:", _lodSize); + connect(_lodSize,SIGNAL(valueChanged(int)),this,SLOT(sizeScaleValueChanged(int))); + + // Add a button to reset + QPushButton* resetButton = new QPushButton("Reset", this); + form->addRow("", resetButton); + connect(resetButton, SIGNAL(clicked(bool)), this, SLOT(resetClicked(bool))); + + this->QDialog::setLayout(form); + + updateAutomaticLODAdjust(); +} + +void LodToolsDialog::reloadSliders() { + auto lodManager = DependencyManager::get(); + _lodSize->setValue(lodManager->getOctreeSizeScale() / TREE_SCALE); + _feedback->setText(lodManager->getLODFeedbackText()); +} + +void LodToolsDialog::updateAutomaticLODAdjust() { + auto lodManager = DependencyManager::get(); + lodManager->setAutomaticLODAdjust(!_manualLODAdjust->isChecked()); + _lodSize->setEnabled(_manualLODAdjust->isChecked()); +} + +void LodToolsDialog::sizeScaleValueChanged(int value) { + auto lodManager = DependencyManager::get(); + float realValue = value * TREE_SCALE; + lodManager->setOctreeSizeScale(realValue); + + _feedback->setText(lodManager->getLODFeedbackText()); +} + +void LodToolsDialog::resetClicked(bool checked) { + + int sliderValue = DEFAULT_OCTREE_SIZE_SCALE / TREE_SCALE; + _lodSize->setValue(sliderValue); + _manualLODAdjust->setChecked(false); + + updateAutomaticLODAdjust(); // tell our LOD manager about the reset +} + +void LodToolsDialog::reject() { + // Just regularly close upon ESC + this->QDialog::close(); +} + +void LodToolsDialog::closeEvent(QCloseEvent* event) { + this->QDialog::closeEvent(event); + emit closed(); + +#if RESET_TO_AUTOMATIC_WHEN_YOU_CLOSE_THE_DIALOG_BOX + auto lodManager = DependencyManager::get(); + + // always revert back to automatic LOD adjustment when closed + lodManager->setAutomaticLODAdjust(true); + + // if the user adjusted the LOD above "normal" then always revert back to default + if (lodManager->getOctreeSizeScale() > DEFAULT_OCTREE_SIZE_SCALE) { + lodManager->setOctreeSizeScale(DEFAULT_OCTREE_SIZE_SCALE); + } +#endif +} + diff --git a/interface/src/ui/LodToolsDialog.h b/interface/src/ui/LodToolsDialog.h new file mode 100644 index 0000000000..3ae59661dc --- /dev/null +++ b/interface/src/ui/LodToolsDialog.h @@ -0,0 +1,55 @@ +// +// LodToolsDialog.h +// interface/src/ui +// +// Created by Brad Hefta-Gaub on 7/19/13. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_LodToolsDialog_h +#define hifi_LodToolsDialog_h + +#include + +class QCheckBox; +class QDoubleSpinBox; +class QLabel; +class QSlider; + +class LodToolsDialog : public QDialog { + Q_OBJECT +public: + // Sets up the UI + LodToolsDialog(QWidget* parent); + +signals: + void closed(); + +public slots: + void reject() override; + void sizeScaleValueChanged(int value); + void resetClicked(bool checked); + void reloadSliders(); + void updateAutomaticLODAdjust(); + +protected: + + // Emits a 'closed' signal when this dialog is closed. + void closeEvent(QCloseEvent* event) override; + +private: + QSlider* _lodSize; + + QCheckBox* _manualLODAdjust; + + QDoubleSpinBox* _desktopLODDecreaseFPS; + + QDoubleSpinBox* _hmdLODDecreaseFPS; + + QLabel* _feedback; +}; + +#endif // hifi_LodToolsDialog_h \ No newline at end of file From e760912fd2f8e1d3ff1b1a4fb4b4cbcfa9233a34 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 17 May 2018 13:33:19 -0700 Subject: [PATCH 071/143] fix warning --- interface/src/ui/PreferencesDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index ac4ee40ebe..4083c7036f 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -91,7 +91,7 @@ void setupPreferences() { auto wodSlider = new SliderPreference(GRAPHICS_QUALITY, "World Detail", getter, setter); wodSlider->setMin(0); wodSlider->setMax(1); - wodSlider->setStep(0.1); + wodSlider->setStep(0.1f); preferences->addPreference(wodSlider); auto getterShadow = []()->bool { From b8ce07744da6d0c2c8a963644172529038cd0024 Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 17 May 2018 14:50:14 -0700 Subject: [PATCH 072/143] initialize prop defaults, no bool returns --- libraries/entities/src/EntityItem.cpp | 8 ++------ libraries/entities/src/EntityItem.h | 14 +++++++------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index e6aa572330..667ca9296d 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -3095,25 +3095,21 @@ void EntityItem::setCloneOriginID(const QUuid& value) { }); } -bool EntityItem::addCloneID(const QUuid& cloneID) { +void EntityItem::addCloneID(const QUuid& cloneID) { withWriteLock([&] { if (!_cloneIDs.contains(cloneID)) { _cloneIDs.append(cloneID); - return true; } }); - return false; } -bool EntityItem::removeCloneID(const QUuid& cloneID) { +void EntityItem::removeCloneID(const QUuid& cloneID) { withWriteLock([&] { int index = _cloneIDs.indexOf(cloneID); if (index >= 0) { _cloneIDs.removeAt(index); - return true; } }); - return false; } const QList EntityItem::getCloneIDs() const { diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index cc8cefb17b..9b1230c843 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -507,8 +507,8 @@ public: void setSimulationOwnershipExpiry(uint64_t expiry) { _simulationOwnershipExpiry = expiry; } uint64_t getSimulationOwnershipExpiry() const { return _simulationOwnershipExpiry; } - bool addCloneID(const QUuid& cloneID); - bool removeCloneID(const QUuid& cloneID); + void addCloneID(const QUuid& cloneID); + void removeCloneID(const QUuid& cloneID); const QList getCloneIDs() const; void setCloneIDs(const QList& cloneIDs); @@ -666,11 +666,11 @@ protected: bool _cauterized { false }; // if true, don't draw because it would obscure 1st-person camera - bool _cloneable; - float _cloneLifetime; - float _cloneLimit; - bool _cloneDynamic; - bool _cloneAvatarEntity; + bool _cloneable { ENTITY_ITEM_CLONEABLE }; + float _cloneLifetime { ENTITY_ITEM_CLONE_LIFETIME }; + float _cloneLimit { ENTITY_ITEM_CLONE_LIMIT }; + bool _cloneDynamic { ENTITY_ITEM_CLONE_DYNAMIC }; + bool _cloneAvatarEntity { ENTITY_ITEM_CLONE_AVATAR_ENTITY }; QUuid _cloneOriginID; QList _cloneIDs; From 30855f94eb3baed58067ad7d1af8bba1086d9726 Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 17 May 2018 16:02:58 -0700 Subject: [PATCH 073/143] set last edited to 0 to ensure server update --- libraries/entities/src/EntityScriptingInterface.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index f47a353ae8..905474fd68 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -333,6 +333,7 @@ QUuid EntityScriptingInterface::cloneEntity(QUuid entityIDToClone) { EntityItemID newEntityID; EntityItemProperties properties = getEntityProperties(entityIDToClone); properties.convertToCloneProperties(entityIDToClone); + properties.setLastEdited(0); // to ensure we take the properties from the server-created entity bool success = addLocalEntityCopy(properties, newEntityID); if (success) { getEntityPacketSender()->queueCloneEntityMessage(entityIDToClone, newEntityID); From 4e14eb37e304d1216545eb5ba44ccb7187b5bac3 Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 17 May 2018 16:34:19 -0700 Subject: [PATCH 074/143] update comment --- libraries/entities/src/EntityScriptingInterface.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 905474fd68..ca64b3b09d 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -333,7 +333,9 @@ QUuid EntityScriptingInterface::cloneEntity(QUuid entityIDToClone) { EntityItemID newEntityID; EntityItemProperties properties = getEntityProperties(entityIDToClone); properties.convertToCloneProperties(entityIDToClone); - properties.setLastEdited(0); // to ensure we take the properties from the server-created entity + // setLastEdited timestamp to 0 to ensure this entity gets updated with the properties + // from the server-created entity, don't change this unless you know what you are doing + properties.setLastEdited(0); bool success = addLocalEntityCopy(properties, newEntityID); if (success) { getEntityPacketSender()->queueCloneEntityMessage(entityIDToClone, newEntityID); From ea771c232576982e5fdb364a758d2ba90b9608db Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 18 May 2018 09:21:41 -0700 Subject: [PATCH 075/143] make final changes --- interface/src/CrashHandler.cpp | 2 ++ interface/src/Menu.cpp | 32 -------------------------------- interface/src/Menu.h | 2 +- 3 files changed, 3 insertions(+), 33 deletions(-) diff --git a/interface/src/CrashHandler.cpp b/interface/src/CrashHandler.cpp index f7d71de3fe..d3079b9bf4 100644 --- a/interface/src/CrashHandler.cpp +++ b/interface/src/CrashHandler.cpp @@ -35,6 +35,8 @@ bool CrashHandler::checkForResetSettings(bool wasLikelyCrash, bool suppressPromp QSettings settings; settings.beginGroup("Developer"); QVariant displayCrashOptions = settings.value(MenuOption::DisplayCrashOptions); + settings.endGroup(); + settings.beginGroup("Settings"); QVariant askToResetSettingsOption = settings.value(MenuOption::AskToResetSettings); settings.endGroup(); bool askToResetSettings = askToResetSettingsOption.isValid() && askToResetSettingsOption.toBool(); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 499ceae81c..2fed4fc5cd 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -307,35 +307,6 @@ Menu::Menu() { QString("hifi/tablet/TabletAvatarPreferences.qml"), "AvatarPreferencesDialog"); }); - // Settings > Notifications - MenuWrapper * notificationsMenu = settingsMenu->addMenu("Notifications"); //This was in notifications.js. The menu needs to be moved here. - - //TODO: Hookup notification actions below. - // Settings > Notifications > Play Notification Sounds - SettingsScriptingInterface* settings = SettingsScriptingInterface::getInstance(); - action = addCheckableActionToQMenuAndActionHash(notificationsMenu, "Play Notification Sounds", 0, - settings->getValue(MenuOption::NotificationSounds).toBool()); - connect(action, &QAction::triggered, [action, settings] { - settings->setValue(MenuOption::NotificationSounds, action->isChecked()); - }); - notificationsMenu->addSeparator(); - - // Settings > Notifications > Play Sounds for: - addDisabledActionAndSeparator(notificationsMenu, "Show notifications for:"); - - // Settings > Notifications > Snapshot - action = addCheckableActionToQMenuAndActionHash(notificationsMenu, "Snapshot", 0, - settings->getValue(MenuOption::NotificationSoundsSnapshot).toBool()); - connect(action, &QAction::triggered, [action, settings] { - settings->setValue(MenuOption::NotificationSoundsSnapshot, action->isChecked()); - }); - // Settings > Notifications > Tablet - action = addCheckableActionToQMenuAndActionHash(notificationsMenu, "Tablet", 0, - settings->getValue(MenuOption::NotificationSoundsTablet).toBool()); - connect(action, &QAction::triggered, [action, settings] { - settings->setValue(MenuOption::NotificationSoundsTablet, action->isChecked()); - }); - // Settings > Developer Menu addCheckableActionToQMenuAndActionHash(settingsMenu, "Developer Menu", 0, false, this, SLOT(toggleDeveloperMenus())); @@ -722,9 +693,6 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowBulletConstraints, 0, false, qApp, SLOT(setShowBulletConstraints(bool))); addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowBulletConstraintLimits, 0, false, qApp, SLOT(setShowBulletConstraintLimits(bool))); - // Developer > Ask to Reset Settings - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::AskToResetSettings, 0, false); - // Developer > Display Crash Options addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::DisplayCrashOptions, 0, true); // Developer > Crash >>> diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 4a957fcb69..9be24aa1d9 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -137,7 +137,7 @@ namespace MenuOption { const QString OnlyDisplayTopTen = "Only Display Top Ten"; const QString OpenVrThreadedSubmit = "OpenVR Threaded Submit"; const QString OutputMenu = "Display"; - const QString Overlays = "Overlays"; + const QString Overlays = "Show Overlays"; const QString PackageModel = "Package Model as .fst..."; const QString Pair = "Pair"; const QString PhysicsShowHulls = "Draw Collision Shapes"; From 6eb5a78611f91f4cff73720147077c9e6644350b Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 18 May 2018 10:33:03 -0700 Subject: [PATCH 076/143] fixing code that breaks andriod build --- interface/src/ui/PreferencesDialog.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 4083c7036f..a4e7e49026 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include From 60dd7e49ab77055d255d8be2c0dc5a58737b3f9f Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 18 May 2018 16:41:39 -0700 Subject: [PATCH 077/143] making requested changes --- .../resources/qml/controls-uit/Slider.qml | 1 + .../dialogs/preferences/SliderPreference.qml | 1 + .../qml/hifi/tablet/ControllerSettings.qml | 5 +- .../hifi/tablet/TabletGeneralPreferences.qml | 2 +- .../resources/qml/hifi/toolbars/Toolbar.qml | 2 - interface/src/ui/PreferencesDialog.cpp | 48 ++++++++++++------- scripts/system/menu.js | 42 +++++++++++++--- 7 files changed, 75 insertions(+), 26 deletions(-) diff --git a/interface/resources/qml/controls-uit/Slider.qml b/interface/resources/qml/controls-uit/Slider.qml index 5ddd97f3f6..2a5d4c137d 100644 --- a/interface/resources/qml/controls-uit/Slider.qml +++ b/interface/resources/qml/controls-uit/Slider.qml @@ -24,6 +24,7 @@ Slider { property alias minimumValue: slider.from property alias maximumValue: slider.to + property alias step: slider.stepSize property bool tickmarksEnabled: false height: hifi.fontSizes.textFieldInput + 14 // Match height of TextField control. diff --git a/interface/resources/qml/dialogs/preferences/SliderPreference.qml b/interface/resources/qml/dialogs/preferences/SliderPreference.qml index 79c7149f3e..2bdda09fc3 100644 --- a/interface/resources/qml/dialogs/preferences/SliderPreference.qml +++ b/interface/resources/qml/dialogs/preferences/SliderPreference.qml @@ -55,6 +55,7 @@ Preference { value: preference.value minimumValue: preference.min maximumValue: preference.max + step: preference.step width: 130 anchors { right: parent.right diff --git a/interface/resources/qml/hifi/tablet/ControllerSettings.qml b/interface/resources/qml/hifi/tablet/ControllerSettings.qml index 5cad32cf34..da8334f831 100644 --- a/interface/resources/qml/hifi/tablet/ControllerSettings.qml +++ b/interface/resources/qml/hifi/tablet/ControllerSettings.qml @@ -29,7 +29,10 @@ Item { TabBar { id: bar spacing: 0 + anchors.top: controllerSettings.top width: parent.width + height: 40 + z: 10 TabButton { height: parent.height @@ -284,7 +287,7 @@ Item { anchors.fill: stackView id: controllerPrefereneces objectName: "TabletControllerPreferences" - showCategories: ["VR Movement"] + showCategories: ["VR Movement", "Game Controller", "Sixense Controllers", "Perception Neuron", "Leap Motion"] } } } diff --git a/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml b/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml index 810f5bb43f..63801019b9 100644 --- a/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml +++ b/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml @@ -32,6 +32,6 @@ StackView { TabletPreferencesDialog { id: root objectName: "TabletGeneralPreferences" - showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "Game Controller", "Sixense Controllers", "Perception Neuron", "Kinect", "Leap Motion"] + showCategories: ["User Interface", "HMD", "Snapshots", "Privacy"] } } diff --git a/interface/resources/qml/hifi/toolbars/Toolbar.qml b/interface/resources/qml/hifi/toolbars/Toolbar.qml index b31a61e066..b32d9c7428 100644 --- a/interface/resources/qml/hifi/toolbars/Toolbar.qml +++ b/interface/resources/qml/hifi/toolbars/Toolbar.qml @@ -50,8 +50,6 @@ Window { property var proxy: modelData; onClicked: proxy.clicked() Component.onCompleted: updateProperties() - //menu button should be visible only in VR mode - visible: text !== "MENU" Connections { target: proxy; diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index a4e7e49026..d79ac1c644 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -58,39 +58,55 @@ void setupPreferences() { { static const float MAX_DESKTOP_FPS = 60; static const float MAX_HMD_FPS = 90; - static const float MIN_HMD_FPS = 35; + static const float LOW = 0.25f; + static const float MEDIUM = 0.5f; + static const float HIGH = 0.75f; auto getter = []()->float { auto lodManager = DependencyManager::get(); - float sliderValue = 0; bool inHMD = qApp->isHMDMode(); + float increaseFPS = 0; if (inHMD) { - float hmdMinFPS = lodManager->getHMDLODDecreaseFPS(); - sliderValue = (MAX_HMD_FPS - hmdMinFPS) / MAX_HMD_FPS; + increaseFPS = lodManager->getHMDLODDecreaseFPS(); } else { - float desktopMinFPS = lodManager->getDesktopLODDecreaseFPS(); - sliderValue = (MAX_DESKTOP_FPS - desktopMinFPS) / MAX_DESKTOP_FPS; + increaseFPS = lodManager->getDesktopLODDecreaseFPS(); } - return sliderValue; + float maxFPS = inHMD ? MAX_HMD_FPS : MAX_DESKTOP_FPS; + float percentage = increaseFPS / maxFPS; + + if (percentage >= HIGH) { + return HIGH; + } else if (percentage >= LOW) { + return MEDIUM; + } + return LOW; }; auto setter = [](float value) { static const float THRASHING_DIFFERENCE = 10; auto lodManager = DependencyManager::get(); - if (qApp->isHMDMode()) { - float desiredHMDFPS = (MAX_HMD_FPS - (MAX_HMD_FPS * value)) - THRASHING_DIFFERENCE; - float actualHMDFPS = desiredHMDFPS > MIN_HMD_FPS ? desiredHMDFPS : MIN_HMD_FPS; - lodManager->setHMDLODDecreaseFPS(actualHMDFPS); + + bool isMaxValue = value == HIGH; + bool isHMDMode = qApp->isHMDMode(); + + float maxFPS = isHMDMode ? MAX_HMD_FPS : MAX_DESKTOP_FPS; + float desiredFPS = maxFPS - THRASHING_DIFFERENCE; + + if (!isMaxValue) { + desiredFPS = (maxFPS * value) - THRASHING_DIFFERENCE; + } + + if (isHMDMode) { + lodManager->setHMDLODDecreaseFPS(desiredFPS); } else { - float desiredDesktopFPS = (MAX_DESKTOP_FPS - (MAX_DESKTOP_FPS * value)) - THRASHING_DIFFERENCE; - lodManager->setDesktopLODDecreaseFPS(desiredDesktopFPS); + lodManager->setDesktopLODDecreaseFPS(desiredFPS); } }; auto wodSlider = new SliderPreference(GRAPHICS_QUALITY, "World Detail", getter, setter); - wodSlider->setMin(0); - wodSlider->setMax(1); - wodSlider->setStep(0.1f); + wodSlider->setMin(0.25f); + wodSlider->setMax(0.75f); + wodSlider->setStep(0.25f); preferences->addPreference(wodSlider); auto getterShadow = []()->bool { diff --git a/scripts/system/menu.js b/scripts/system/menu.js index c27dae6780..d669d3d918 100644 --- a/scripts/system/menu.js +++ b/scripts/system/menu.js @@ -9,17 +9,29 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/* jslint bitwise: true */ + +/* global Script, HMD, Tablet, Entities */ + var HOME_BUTTON_TEXTURE = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet-with-home-button.fbx/tablet-with-home-button.fbm/button-root.png"; // var HOME_BUTTON_TEXTURE = Script.resourcesPath() + "meshes/tablet-with-home-button.fbx/tablet-with-home-button.fbm/button-root.png"; (function() { - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - var button = tablet.addButton({ + var lastHMDStatus = false; + var buttonProperties = { icon: "icons/tablet-icons/menu-i.svg", activeIcon: "icons/tablet-icons/menu-a.svg", text: "MENU", sortOrder: 3 - }); + }; + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var button = null; + + if (HMD.active) { + button = tablet.addButton(buttonProperties); + button.clicked.connect(onClicked); + lastHMDStatus = true; + } var onMenuScreen = false; @@ -35,19 +47,37 @@ var HOME_BUTTON_TEXTURE = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet- } } + HMD.displayModeChanged.connect(function(isHMDMode) { + if (lastHMDStatus !== isHMDMode) { + if (isHMDMode) { + button = tablet.addButton(buttonProperties); + button.clicked.connect(onClicked); + } else if (button) { + button.clicked.disconnect(onClicked); + tablet.removeButton(button); + button = null; + } + lastHMDStatus = isHMDMode; + } + }); + function onScreenChanged(type, url) { onMenuScreen = type === "Menu"; - button.editProperties({isActive: onMenuScreen}); + if (button) { + button.editProperties({isActive: onMenuScreen}); + } } - button.clicked.connect(onClicked); tablet.screenChanged.connect(onScreenChanged); Script.scriptEnding.connect(function () { if (onMenuScreen) { tablet.gotoHomeScreen(); } - button.clicked.disconnect(onClicked); + + if (button) { + button.clicked.disconnect(onClicked); + } tablet.removeButton(button); tablet.screenChanged.disconnect(onScreenChanged); }); From 8a2b54c2b71734f0a9207cc57c6720d66f5aff58 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 18 May 2018 17:09:41 -0700 Subject: [PATCH 078/143] fixing mistakes --- interface/src/ui/PreferencesDialog.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 54a1a87d0b..3d3c432e92 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -58,6 +58,7 @@ void setupPreferences() { { static const float MAX_DESKTOP_FPS = 60; static const float MAX_HMD_FPS = 90; + static const float MIN_FPS = 10; static const float LOW = 0.25f; static const float MEDIUM = 0.5f; static const float HIGH = 0.75f; @@ -75,25 +76,26 @@ void setupPreferences() { float percentage = increaseFPS / maxFPS; if (percentage >= HIGH) { - return HIGH; + return LOW; } else if (percentage >= LOW) { return MEDIUM; } - return LOW; + return HIGH; }; auto setter = [](float value) { static const float THRASHING_DIFFERENCE = 10; auto lodManager = DependencyManager::get(); - bool isMaxValue = value == HIGH; + bool isLowestValue = value == LOW; bool isHMDMode = qApp->isHMDMode(); float maxFPS = isHMDMode ? MAX_HMD_FPS : MAX_DESKTOP_FPS; float desiredFPS = maxFPS - THRASHING_DIFFERENCE; - if (!isMaxValue) { - desiredFPS = (maxFPS * value) - THRASHING_DIFFERENCE; + if (!isLowestValue) { + float calculatedFPS = (maxFPS - (maxFPS * value)) - THRASHING_DIFFERENCE; + desiredFPS = calculatedFPS < MIN_FPS ? MIN_FPS : calculatedFPS; } if (isHMDMode) { From 29b11b910124640c39e59131de2e2443d904368b Mon Sep 17 00:00:00 2001 From: Liv Erickson Date: Fri, 18 May 2018 17:12:41 -0700 Subject: [PATCH 079/143] some fixes to server cloneables --- libraries/entities/src/EntityItem.cpp | 6 +++--- libraries/entities/src/EntityItem.h | 16 ++++++++-------- libraries/entities/src/EntityItemProperties.cpp | 10 +++++----- libraries/entities/src/EntityItemProperties.h | 12 ++++++------ .../entities/src/EntityItemPropertiesDefaults.h | 12 ++++++------ .../entities/src/EntityScriptingInterface.cpp | 17 ++++++++++++----- libraries/entities/src/EntityTree.cpp | 9 +++++---- 7 files changed, 45 insertions(+), 37 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 667ca9296d..9bad6f2519 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -3112,15 +3112,15 @@ void EntityItem::removeCloneID(const QUuid& cloneID) { }); } -const QList EntityItem::getCloneIDs() const { - QList result; +const QVector EntityItem::getCloneIDs() const { + QVector result; withReadLock([&] { result = _cloneIDs; }); return result; } -void EntityItem::setCloneIDs(const QList& cloneIDs) { +void EntityItem::setCloneIDs(const QVector& cloneIDs) { withWriteLock([&] { _cloneIDs = cloneIDs; }); diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 9b1230c843..42c4605e44 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -509,8 +509,8 @@ public: void addCloneID(const QUuid& cloneID); void removeCloneID(const QUuid& cloneID); - const QList getCloneIDs() const; - void setCloneIDs(const QList& cloneIDs); + const QVector getCloneIDs() const; + void setCloneIDs(const QVector& cloneIDs); signals: void requestRenderUpdate(); @@ -666,13 +666,13 @@ protected: bool _cauterized { false }; // if true, don't draw because it would obscure 1st-person camera - bool _cloneable { ENTITY_ITEM_CLONEABLE }; - float _cloneLifetime { ENTITY_ITEM_CLONE_LIFETIME }; - float _cloneLimit { ENTITY_ITEM_CLONE_LIMIT }; - bool _cloneDynamic { ENTITY_ITEM_CLONE_DYNAMIC }; - bool _cloneAvatarEntity { ENTITY_ITEM_CLONE_AVATAR_ENTITY }; + bool _cloneable { ENTITY_ITEM_DEFAULT_CLONEABLE }; + float _cloneLifetime { ENTITY_ITEM_DEFAULT_CLONE_LIFETIME }; + float _cloneLimit { ENTITY_ITEM_DEFAULT_CLONE_LIMIT }; + bool _cloneDynamic { ENTITY_ITEM_DEFAULT_CLONE_DYNAMIC }; + bool _cloneAvatarEntity { ENTITY_ITEM_DEFAULT_CLONE_AVATAR_ENTITY }; QUuid _cloneOriginID; - QList _cloneIDs; + QVector _cloneIDs; private: std::unordered_map _materials; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 5a2f3a8fc5..39449c7cd1 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -3657,9 +3657,9 @@ void EntityItemProperties::convertToCloneProperties(const EntityItemID& entityID setLifetime(getCloneLifetime()); setDynamic(getCloneDynamic()); setClientOnly(getCloneAvatarEntity()); - setCloneable(ENTITY_ITEM_CLONEABLE); - setCloneLifetime(ENTITY_ITEM_CLONE_LIFETIME); - setCloneLimit(ENTITY_ITEM_CLONE_LIMIT); - setCloneDynamic(ENTITY_ITEM_CLONE_DYNAMIC); - setCloneAvatarEntity(ENTITY_ITEM_CLONE_AVATAR_ENTITY); + setCloneable(ENTITY_ITEM_DEFAULT_CLONEABLE); + setCloneLifetime(ENTITY_ITEM_DEFAULT_CLONE_LIFETIME); + setCloneLimit(ENTITY_ITEM_DEFAULT_CLONE_LIMIT); + setCloneDynamic(ENTITY_ITEM_DEFAULT_CLONE_DYNAMIC); + setCloneAvatarEntity(ENTITY_ITEM_DEFAULT_CLONE_AVATAR_ENTITY); } diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index a34058c010..d00a21435c 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -272,12 +272,12 @@ public: DEFINE_PROPERTY_REF(PROP_SERVER_SCRIPTS, ServerScripts, serverScripts, QString, ENTITY_ITEM_DEFAULT_SERVER_SCRIPTS); DEFINE_PROPERTY(PROP_RELAY_PARENT_JOINTS, RelayParentJoints, relayParentJoints, bool, ENTITY_ITEM_DEFAULT_RELAY_PARENT_JOINTS); - DEFINE_PROPERTY(PROP_CLONEABLE, Cloneable, cloneable, bool, ENTITY_ITEM_CLONEABLE); - DEFINE_PROPERTY(PROP_CLONE_LIFETIME, CloneLifetime, cloneLifetime, float, ENTITY_ITEM_CLONE_LIFETIME); - DEFINE_PROPERTY(PROP_CLONE_LIMIT, CloneLimit, cloneLimit, float, ENTITY_ITEM_CLONE_LIMIT); - DEFINE_PROPERTY(PROP_CLONE_DYNAMIC, CloneDynamic, cloneDynamic, bool, ENTITY_ITEM_CLONE_DYNAMIC); - DEFINE_PROPERTY(PROP_CLONE_AVATAR_ENTITY, CloneAvatarEntity, cloneAvatarEntity, bool, ENTITY_ITEM_CLONE_AVATAR_ENTITY); - DEFINE_PROPERTY(PROP_CLONE_ORIGIN_ID, CloneOriginID, cloneOriginID, QUuid, ENTITY_ITEM_CLONE_ORIGIN_ID); + DEFINE_PROPERTY(PROP_CLONEABLE, Cloneable, cloneable, bool, ENTITY_ITEM_DEFAULT_CLONEABLE); + DEFINE_PROPERTY(PROP_CLONE_LIFETIME, CloneLifetime, cloneLifetime, float, ENTITY_ITEM_DEFAULT_CLONE_LIFETIME); + DEFINE_PROPERTY(PROP_CLONE_LIMIT, CloneLimit, cloneLimit, float, ENTITY_ITEM_DEFAULT_CLONE_LIMIT); + DEFINE_PROPERTY(PROP_CLONE_DYNAMIC, CloneDynamic, cloneDynamic, bool, ENTITY_ITEM_DEFAULT_CLONE_DYNAMIC); + DEFINE_PROPERTY(PROP_CLONE_AVATAR_ENTITY, CloneAvatarEntity, cloneAvatarEntity, bool, ENTITY_ITEM_DEFAULT_CLONE_AVATAR_ENTITY); + DEFINE_PROPERTY(PROP_CLONE_ORIGIN_ID, CloneOriginID, cloneOriginID, QUuid, ENTITY_ITEM_DEFAULT_CLONE_ORIGIN_ID); static QString getComponentModeString(uint32_t mode); static QString getComponentModeAsString(uint32_t mode); diff --git a/libraries/entities/src/EntityItemPropertiesDefaults.h b/libraries/entities/src/EntityItemPropertiesDefaults.h index 1a31bddebe..0fd926e677 100644 --- a/libraries/entities/src/EntityItemPropertiesDefaults.h +++ b/libraries/entities/src/EntityItemPropertiesDefaults.h @@ -97,11 +97,11 @@ const QUuid ENTITY_ITEM_DEFAULT_LAST_EDITED_BY = QUuid(); const bool ENTITY_ITEM_DEFAULT_RELAY_PARENT_JOINTS = false; -const bool ENTITY_ITEM_CLONEABLE = false; -const float ENTITY_ITEM_CLONE_LIFETIME = 300.0f; -const int ENTITY_ITEM_CLONE_LIMIT = 0; -const bool ENTITY_ITEM_CLONE_DYNAMIC = false; -const bool ENTITY_ITEM_CLONE_AVATAR_ENTITY = false; -const QUuid ENTITY_ITEM_CLONE_ORIGIN_ID = QUuid(); +const bool ENTITY_ITEM_DEFAULT_CLONEABLE = false; +const float ENTITY_ITEM_DEFAULT_CLONE_LIFETIME = 300.0f; +const int ENTITY_ITEM_DEFAULT_CLONE_LIMIT = 0; +const bool ENTITY_ITEM_DEFAULT_CLONE_DYNAMIC = false; +const bool ENTITY_ITEM_DEFAULT_CLONE_AVATAR_ENTITY = false; +const QUuid ENTITY_ITEM_DEFAULT_CLONE_ORIGIN_ID = QUuid(); #endif // hifi_EntityItemPropertiesDefaults_h diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index f47a353ae8..ace4670fef 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -332,13 +332,20 @@ QUuid EntityScriptingInterface::addModelEntity(const QString& name, const QStrin QUuid EntityScriptingInterface::cloneEntity(QUuid entityIDToClone) { EntityItemID newEntityID; EntityItemProperties properties = getEntityProperties(entityIDToClone); + bool cloneAvatarEntity = properties.getCloneAvatarEntity(); properties.convertToCloneProperties(entityIDToClone); - bool success = addLocalEntityCopy(properties, newEntityID); - if (success) { - getEntityPacketSender()->queueCloneEntityMessage(entityIDToClone, newEntityID); - return newEntityID; + + if (cloneAvatarEntity) { + return addEntity(properties, true); } else { - return QUuid(); + bool success = addLocalEntityCopy(properties, newEntityID); + if (success) { + getEntityPacketSender()->queueCloneEntityMessage(entityIDToClone, newEntityID); + return newEntityID; + } + else { + return QUuid(); + } } } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index c87f6d771a..a36ee4be9d 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -639,7 +639,7 @@ void EntityTree::cleanupCloneIDs(const EntityItemID& entityID) { } } // clear the clone origin ID on any clones that this entity had - const QList& cloneIDs = entity->getCloneIDs(); + const QVector& cloneIDs = entity->getCloneIDs(); foreach(const QUuid& cloneChildID, cloneIDs) { EntityItemPointer cloneChild = findEntityByEntityItemID(cloneChildID); if (cloneChild) { @@ -1627,7 +1627,7 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c } else if (isClone && !isCloneable) { failedAdd = true; qCDebug(entities) << "User attempted to clone non-cloneable entity from entity ID:" << entityIDToClone; - } else if (isClone && entityToClone && entityToClone->getCloneIDs().size() >= cloneLimit) { + } else if (isClone && entityToClone && entityToClone->getCloneIDs().size() >= cloneLimit && cloneLimit != 0) { failedAdd = true; qCDebug(entities) << "User attempted to clone entity ID:" << entityIDToClone << " which reached it's cloneable limit."; } else { @@ -2039,6 +2039,7 @@ int EntityTree::processEraseMessageDetails(const QByteArray& dataByteArray, cons if (shouldEraseEntity(entityID, sourceNode)) { entityItemIDsToDelete << entityItemID; + cleanupCloneIDs(entityItemID); } } @@ -2385,7 +2386,7 @@ bool EntityTree::readFromMap(QVariantMap& map) { return false; } - QMap> cloneIDs; + QMap> cloneIDs; bool success = true; foreach (QVariant entityVariant, entitiesQList) { @@ -2488,7 +2489,7 @@ bool EntityTree::readFromMap(QVariantMap& map) { for (auto iter = cloneIDs.begin(); iter != cloneIDs.end(); ++iter) { const QUuid& entityID = iter.key(); - const QList& cloneIDs = iter.value(); + const QVector& cloneIDs = iter.value(); EntityItemPointer entity = findEntityByID(entityID); if (entity) { entity->setCloneIDs(cloneIDs); From 6c8d68afc61ccc917f019664f7bed1b1f6a9d2ff Mon Sep 17 00:00:00 2001 From: Liv Erickson Date: Fri, 18 May 2018 18:18:42 -0700 Subject: [PATCH 080/143] add extra cleanup in delete messages and simulation, as a fall back --- libraries/entities/src/EntitySimulation.cpp | 1 + libraries/entities/src/EntityTree.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/libraries/entities/src/EntitySimulation.cpp b/libraries/entities/src/EntitySimulation.cpp index d034ddedbe..ba088cb7fd 100644 --- a/libraries/entities/src/EntitySimulation.cpp +++ b/libraries/entities/src/EntitySimulation.cpp @@ -65,6 +65,7 @@ void EntitySimulation::prepareEntityForDelete(EntityItemPointer entity) { removeEntityInternal(entity); if (entity->getElement()) { _deadEntities.insert(entity); + _entityTree->cleanupCloneIDs(entity->getEntityItemID()); } } } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index a36ee4be9d..b698ac6eb8 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1990,6 +1990,7 @@ int EntityTree::processEraseMessage(ReceivedMessage& message, const SharedNodePo if (shouldEraseEntity(entityID, sourceNode)) { entityItemIDsToDelete << entityItemID; + cleanupCloneIDs(entityItemID); } } deleteEntities(entityItemIDsToDelete, true, true); From 1130f9998d8e6e8b92d8ec709d3ad2e1ba01c159 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Sat, 19 May 2018 10:42:55 -0700 Subject: [PATCH 081/143] Minor fix allows import GLTF from Substance Painter --- libraries/fbx/src/GLTFReader.cpp | 2 +- libraries/fbx/src/GLTFReader.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/fbx/src/GLTFReader.cpp b/libraries/fbx/src/GLTFReader.cpp index f322c2319e..1fa4b3873e 100644 --- a/libraries/fbx/src/GLTFReader.cpp +++ b/libraries/fbx/src/GLTFReader.cpp @@ -1174,7 +1174,7 @@ bool GLTFReader::addArrayOfType(const QByteArray& bin, int byteOffset, int byteL break; } case GLTFAccessorComponentType::UNSIGNED_INT: { - readArray(bin, byteOffset, byteLength, outarray, accessorType); + readArray(bin, byteOffset, byteLength, outarray, accessorType); break; } case GLTFAccessorComponentType::UNSIGNED_SHORT: { diff --git a/libraries/fbx/src/GLTFReader.h b/libraries/fbx/src/GLTFReader.h index 3554594768..28c1d8282f 100644 --- a/libraries/fbx/src/GLTFReader.h +++ b/libraries/fbx/src/GLTFReader.h @@ -190,7 +190,7 @@ namespace GLTFBufferViewTarget { struct GLTFBufferView { int buffer; //required int byteLength; //required - int byteOffset; + int byteOffset { 0 }; int target; QMap defined; void dump() { @@ -470,7 +470,7 @@ namespace GLTFAccessorComponentType { } struct GLTFAccessor { int bufferView; - int byteOffset; + int byteOffset { 0 }; int componentType; //required int count; //required int type; //required From f2807e38f97e6ce9f1d356b23ec1e9f0065a58ce Mon Sep 17 00:00:00 2001 From: druiz17 Date: Sat, 19 May 2018 17:36:46 -0700 Subject: [PATCH 082/143] fix goto shortcut --- interface/src/Application.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6e70d4b9ae..1ae9dc6d26 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3721,7 +3721,8 @@ void Application::keyPressEvent(QKeyEvent* event) { if (isShifted && isMeta) { Menu::getInstance()->triggerOption(MenuOption::Log); } else if (isMeta) { - Menu::getInstance()->triggerOption(MenuOption::AddressBar); + auto dialogsManager = DependencyManager::get(); + dialogsManager->toggleAddressBar(); } else if (isShifted) { Menu::getInstance()->triggerOption(MenuOption::LodTools); } From bd3a9865bfa288703230d87129cc4c8aa03717a4 Mon Sep 17 00:00:00 2001 From: druiz17 Date: Sat, 19 May 2018 18:27:28 -0700 Subject: [PATCH 083/143] moving control speech to developer menu --- interface/src/Menu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 51fb6443b4..3551a11a0b 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -757,7 +757,7 @@ Menu::Menu() { // Settings > Enable Speech Control API #if defined(Q_OS_MAC) || defined(Q_OS_WIN) auto speechRecognizer = DependencyManager::get(); - QAction* speechRecognizerAction = addCheckableActionToQMenuAndActionHash(settingsMenu, MenuOption::ControlWithSpeech, + QAction* speechRecognizerAction = addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::ControlWithSpeech, Qt::CTRL | Qt::SHIFT | Qt::Key_C, speechRecognizer->getEnabled(), speechRecognizer.data(), From 6d4f70427921ef9d94509d3a2d820a464b695067 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 21 May 2018 09:32:10 +1200 Subject: [PATCH 084/143] Regularize some JSDoc usage --- interface/src/Application.cpp | 2 +- interface/src/FancyCamera.h | 2 +- interface/src/avatar/MyAvatar.h | 2 +- .../src/raypick/PickScriptingInterface.h | 33 ++++++++++--------- .../src/raypick/PointerScriptingInterface.cpp | 6 ++-- .../scripting/WindowScriptingInterface.cpp | 2 +- .../src/scripting/WindowScriptingInterface.h | 2 +- interface/src/ui/overlays/Overlays.h | 2 +- .../src/avatars-renderer/Avatar.h | 2 +- libraries/avatars/src/AvatarData.cpp | 2 +- .../controllers/src/controllers/Actions.cpp | 2 +- .../controllers/src/controllers/InputDevice.h | 2 +- .../src/controllers/StandardController.cpp | 2 +- .../entities/src/AnimationPropertyGroup.cpp | 2 +- .../entities/src/EntityItemProperties.cpp | 2 +- .../src/input-plugins/KeyboardMouseDevice.cpp | 2 +- libraries/networking/src/AddressManager.h | 2 +- libraries/networking/src/DomainHandler.h | 2 +- .../src/AssetScriptingInterface.h | 8 ++--- libraries/script-engine/src/Quat.h | 2 +- .../src/SceneScriptingInterface.h | 6 ++-- libraries/script-engine/src/ScriptUUID.h | 2 +- libraries/shared/src/shared/Camera.h | 13 ++++---- libraries/ui/src/QmlFragmentClass.h | 2 +- .../ui/src/ui/TabletScriptingInterface.h | 2 +- .../oculus/src/OculusControllerManager.cpp | 2 +- plugins/openvr/src/ViveControllerManager.cpp | 2 +- 27 files changed, 56 insertions(+), 54 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 467c8c9a2c..266c085d99 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -715,7 +715,7 @@ private: * NavigationFocusednumbernumberNot used. * * - * @typedef Controller.Hardware-Application + * @typedef {object} Controller.Hardware-Application */ static const QString STATE_IN_HMD = "InHMD"; diff --git a/interface/src/FancyCamera.h b/interface/src/FancyCamera.h index bee21bad22..4ca073fb4f 100644 --- a/interface/src/FancyCamera.h +++ b/interface/src/FancyCamera.h @@ -25,7 +25,7 @@ class FancyCamera : public Camera { // FIXME: JSDoc 3.5.5 doesn't augment @property definitions. The following definition is repeated in Camera.h. /**jsdoc - * @property cameraEntity {Uuid} The ID of the entity that the camera position and orientation follow when the camera is in + * @property {Uuid} cameraEntity The ID of the entity that the camera position and orientation follow when the camera is in * entity mode. */ Q_PROPERTY(QUuid cameraEntity READ getCameraEntity WRITE setCameraEntity) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index fa6a675d99..fe6ba71c13 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -121,7 +121,7 @@ class MyAvatar : public Avatar { * while flying. * @property {number} hmdRollControlDeadZone=8 - The amount of HMD roll, in degrees, required before your avatar turns if * hmdRollControlEnabled is enabled. - * @property hmdRollControlRate {number} If hmdRollControlEnabled is true, this value determines the maximum turn rate of + * @property {number} hmdRollControlRate If hmdRollControlEnabled is true, this value determines the maximum turn rate of * your avatar when rolling your HMD in degrees per second. * @property {number} userHeight=1.75 - The height of the user in sensor space. * @property {number} userEyeHeight=1.65 - The estimated height of the user's eyes in sensor space. Read-only. diff --git a/interface/src/raypick/PickScriptingInterface.h b/interface/src/raypick/PickScriptingInterface.h index a39aa3a4a1..5ef5d27d74 100644 --- a/interface/src/raypick/PickScriptingInterface.h +++ b/interface/src/raypick/PickScriptingInterface.h @@ -22,21 +22,22 @@ * @hifi-interface * @hifi-client-entity * - * @property PICK_NOTHING {number} A filter flag. Don't intersect with anything. Read-only. - * @property PICK_ENTITIES {number} A filter flag. Include entities when intersecting. Read-only. - * @property PICK_OVERLAYS {number} A filter flag. Include overlays when intersecting. Read-only. - * @property PICK_AVATARS {number} A filter flag. Include avatars when intersecting. Read-only. - * @property PICK_HUD {number} A filter flag. Include the HUD sphere when intersecting in HMD mode. Read-only. - * @property PICK_COARSE {number} A filter flag. Pick against coarse meshes, instead of exact meshes. Read-only. - * @property PICK_INCLUDE_INVISIBLE {number} A filter flag. Include invisible objects when intersecting. Read-only. - * @property PICK_INCLUDE_NONCOLLIDABLE {number} A filter flag. Include non-collidable objects when intersecting. + * @property {number} PICK_NOTHING A filter flag. Don't intersect with anything. Read-only. + * @property {number} PICK_ENTITIES A filter flag. Include entities when intersecting. Read-only. + * @property {number} PICK_OVERLAYS A filter flag. Include overlays when intersecting. Read-only. + * @property {number} PICK_AVATARS A filter flag. Include avatars when intersecting. Read-only. + * @property {number} PICK_HUD A filter flag. Include the HUD sphere when intersecting in HMD mode. Read-only. + * @property {number} PICK_COARSE A filter flag. Pick against coarse meshes, instead of exact meshes. Read-only. + * @property {number} PICK_INCLUDE_INVISIBLE A filter flag. Include invisible objects when intersecting. Read-only. + * @property {number} PICK_INCLUDE_NONCOLLIDABLE A filter flag. Include non-collidable objects when intersecting. * Read-only. - * @property PICK_ALL_INTERSECTIONS {number} Read-only. - * @property INTERSECTED_NONE {number} An intersection type. Intersected nothing with the given filter flags. Read-only. - * @property INTERSECTED_ENTITY {number} An intersection type. Intersected an entity. Read-only. - * @property INTERSECTED_OVERLAY {number} An intersection type. Intersected an overlay. Read-only. - * @property INTERSECTED_AVATAR {number} An intersection type. Intersected an avatar. Read-only. - * @property INTERSECTED_HUD {number} An intersection type. Intersected the HUD sphere. Read-only. + * @property {number} PICK_ALL_INTERSECTIONS Read-only. + * @property {number} INTERSECTED_NONE An intersection type. Intersected nothing with the given filter flags. + * Read-only. + * @property {number} INTERSECTED_ENTITY An intersection type. Intersected an entity. Read-only. + * @property {number} INTERSECTED_OVERLAY An intersection type. Intersected an overlay. Read-only. + * @property {number} INTERSECTED_AVATAR An intersection type. Intersected an avatar. Read-only. + * @property {number} INTERSECTED_HUD An intersection type. Intersected the HUD sphere. Read-only. * @property {number} perFrameTimeBudget - The max number of usec to spend per frame updating Pick results. Read-only. */ @@ -99,7 +100,7 @@ public: /**jsdoc * An intersection result for a Ray Pick. * - * @typedef {Object} RayPickResult + * @typedef {object} RayPickResult * @property {number} type The intersection type. * @property {boolean} intersects If there was a valid intersection (type != INTERSECTED_NONE) * @property {Uuid} objectID The ID of the intersected object. Uuid.NULL for the HUD or invalid intersections. @@ -113,7 +114,7 @@ public: /**jsdoc * An intersection result for a Stylus Pick. * - * @typedef {Object} StylusPickResult + * @typedef {object} StylusPickResult * @property {number} type The intersection type. * @property {boolean} intersects If there was a valid intersection (type != INTERSECTED_NONE) * @property {Uuid} objectID The ID of the intersected object. Uuid.NULL for the HUD or invalid intersections. diff --git a/interface/src/raypick/PointerScriptingInterface.cpp b/interface/src/raypick/PointerScriptingInterface.cpp index b7ac899c8d..4e953a5cb8 100644 --- a/interface/src/raypick/PointerScriptingInterface.cpp +++ b/interface/src/raypick/PointerScriptingInterface.cpp @@ -68,14 +68,14 @@ unsigned int PointerScriptingInterface::createStylus(const QVariant& properties) * A set of properties used to define the visual aspect of a Ray Pointer in the case that the Pointer is not intersecting something. Same as a {@link Pointers.RayPointerRenderState}, * but with an additional distance field. * - * @typedef {Object} Pointers.DefaultRayPointerRenderState + * @typedef {object} Pointers.DefaultRayPointerRenderState * @augments Pointers.RayPointerRenderState * @property {number} distance The distance at which to render the end of this Ray Pointer, if one is defined. */ /**jsdoc * A set of properties used to define the visual aspect of a Ray Pointer in the case that the Pointer is intersecting something. * - * @typedef {Object} Pointers.RayPointerRenderState + * @typedef {object} Pointers.RayPointerRenderState * @property {string} name The name of this render state, used by {@link Pointers.setRenderState} and {@link Pointers.editRenderState} * @property {Overlays.OverlayProperties} [start] All of the properties you would normally pass to {@link Overlays.addOverlay}, plus the type (as a type field). * An overlay to represent the beginning of the Ray Pointer, if desired. @@ -87,7 +87,7 @@ unsigned int PointerScriptingInterface::createStylus(const QVariant& properties) /**jsdoc * A trigger mechanism for Ray Pointers. * - * @typedef {Object} Pointers.Trigger + * @typedef {object} Pointers.Trigger * @property {Controller.Standard|Controller.Actions|function} action This can be a built-in Controller action, like Controller.Standard.LTClick, or a function that evaluates to >= 1.0 when you want to trigger button. * @property {string} button Which button to trigger. "Primary", "Secondary", "Tertiary", and "Focus" are currently supported. Only "Primary" will trigger clicks on web surfaces. If "Focus" is triggered, * it will try to set the entity or overlay focus to the object at which the Pointer is aimed. Buttons besides the first three will still trigger events, but event.button will be "None". diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 6f6e83842c..af9b5c8a46 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -522,7 +522,7 @@ int WindowScriptingInterface::openMessageBox(QString title, QString text, int bu * RestoreDefaults 0x8000000 "Restore Defaults" * * - * @typedef Window.MessageBoxButton + * @typedef {number} Window.MessageBoxButton */ int WindowScriptingInterface::createMessageBox(QString title, QString text, int buttons, int defaultButton) { auto messageBox = DependencyManager::get()->createMessageBox(OffscreenUi::ICON_INFORMATION, title, text, diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 1d06f33ec0..d280d797d6 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -470,7 +470,7 @@ public slots: * * * - * @typedef Window.DisplayTexture + * @typedef {string} Window.DisplayTexture */ bool setDisplayTexture(const QString& name); diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 3ff782da99..d100b228ed 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -53,7 +53,7 @@ const OverlayID UNKNOWN_OVERLAY_ID = OverlayID(); * @property {number} distance - The distance from the {@link PickRay} origin to the intersection point. * @property {Vec3} surfaceNormal - The normal of the overlay surface at the intersection point. * @property {Vec3} intersection - The position of the intersection point. - * @property {Object} extraInfo Additional intersection details, if available. + * @property {object} extraInfo Additional intersection details, if available. */ class RayToOverlayIntersectionResult { public: diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 01114b5f6d..0f48e03e55 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -292,7 +292,7 @@ public: */ /**jsdoc * Information about a single joint in an Avatar's skeleton hierarchy. - * @typedef MyAvatar.SkeletonJoint + * @typedef {object} MyAvatar.SkeletonJoint * @property {string} name - Joint name. * @property {number} index - Joint index. * @property {number} parentIndex - Index of this joint's parent (-1 if no parent). diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 7a28686f8c..48ef1fb881 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -2363,7 +2363,7 @@ glm::vec3 AvatarData::getAbsoluteJointTranslationInObjectFrame(int index) const } /**jsdoc - * @typedef AttachmentData + * @typedef {object} AttachmentData * @property {string} modelUrl * @property {string} jointName * @property {Vec3} translation diff --git a/libraries/controllers/src/controllers/Actions.cpp b/libraries/controllers/src/controllers/Actions.cpp index 978b0888ba..6923ef4b98 100644 --- a/libraries/controllers/src/controllers/Actions.cpp +++ b/libraries/controllers/src/controllers/Actions.cpp @@ -307,7 +307,7 @@ namespace controller { * action. * * - * @typedef Controller.Actions + * @typedef {object} Controller.Actions */ // Device functions Input::NamedVector ActionsDevice::getAvailableInputs() const { diff --git a/libraries/controllers/src/controllers/InputDevice.h b/libraries/controllers/src/controllers/InputDevice.h index 30a58eb2f0..1e626e6a3c 100644 --- a/libraries/controllers/src/controllers/InputDevice.h +++ b/libraries/controllers/src/controllers/InputDevice.h @@ -79,7 +79,7 @@ enum Hand { * {@link Controller.Hardware-Vive}. * * - * @typedef Controller.Hardware + * @typedef {object} Controller.Hardware * @example List all the currently available Controller.Hardware properties. * function printProperties(string, item) { * print(string); diff --git a/libraries/controllers/src/controllers/StandardController.cpp b/libraries/controllers/src/controllers/StandardController.cpp index 471943400d..e1733d2524 100644 --- a/libraries/controllers/src/controllers/StandardController.cpp +++ b/libraries/controllers/src/controllers/StandardController.cpp @@ -231,7 +231,7 @@ void StandardController::focusOutEvent() { * * * - * @typedef Controller.Standard + * @typedef {object} Controller.Standard */ Input::NamedVector StandardController::getAvailableInputs() const { static Input::NamedVector availableInputs { diff --git a/libraries/entities/src/AnimationPropertyGroup.cpp b/libraries/entities/src/AnimationPropertyGroup.cpp index 43c6b7a6a5..2db85eb7ac 100644 --- a/libraries/entities/src/AnimationPropertyGroup.cpp +++ b/libraries/entities/src/AnimationPropertyGroup.cpp @@ -46,7 +46,7 @@ bool operator!=(const AnimationPropertyGroup& a, const AnimationPropertyGroup& b /**jsdoc * The AnimationProperties are used to configure an animation. - * @typedef Entities.AnimationProperties + * @typedef {object} Entities.AnimationProperties * @property {string} url="" - The URL of the FBX file that has the animation. * @property {number} fps=30 - The speed in frames/s that the animation is played at. * @property {number} firstFrame=0 - The first frame to play in the animation. diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 4d7c114176..0def76f1bb 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1391,7 +1391,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool /**jsdoc * The axis-aligned bounding box of an entity. - * @typedef Entities.BoundingBox + * @typedef {object} Entities.BoundingBox * @property {Vec3} brn - The bottom right near (minimum axes values) corner of the AA box. * @property {Vec3} tfl - The top far left (maximum axes values) corner of the AA box. * @property {Vec3} center - The center of the AA box. diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index 8ecf527a14..650c9675a7 100755 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -279,7 +279,7 @@ controller::Input KeyboardMouseDevice::InputDevice::makeInput(KeyboardMouseDevic * moved down. The data value is how far the average position of all touch points moved. * * - * @typedef Controller.Hardware-Keyboard + * @typedef {object} Controller.Hardware-Keyboard * @todo Currently, the mouse wheel in an ordinary mouse generates left/right wheel events instead of up/down. */ controller::Input::NamedVector KeyboardMouseDevice::InputDevice::getAvailableInputs() const { diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 7832b26c96..a12a18fa6a 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -138,7 +138,7 @@ public: * * * - * @typedef location.LookupTrigger + * @typedef {number} location.LookupTrigger */ enum LookupTrigger { UserInput, diff --git a/libraries/networking/src/DomainHandler.h b/libraries/networking/src/DomainHandler.h index 08908dbaf6..4d98391104 100644 --- a/libraries/networking/src/DomainHandler.h +++ b/libraries/networking/src/DomainHandler.h @@ -137,7 +137,7 @@ public: * * * - * @typedef Window.ConnectionRefusedReason + * @typedef {number} Window.ConnectionRefusedReason */ enum class ConnectionRefusedReason : uint8_t { Unknown, diff --git a/libraries/script-engine/src/AssetScriptingInterface.h b/libraries/script-engine/src/AssetScriptingInterface.h index 7f7a3a68b0..72d6901fb5 100644 --- a/libraries/script-engine/src/AssetScriptingInterface.h +++ b/libraries/script-engine/src/AssetScriptingInterface.h @@ -121,7 +121,7 @@ public: /**jsdoc * A set of properties that can be passed to {@link Assets.getAsset}. - * @typedef {Object} Assets.GetOptions + * @typedef {object} Assets.GetOptions * @property {string} [url] an "atp:" style URL, hash, or relative mapped path to fetch * @property {string} [responseType=text] the desired reponse type (text | arraybuffer | json) * @property {boolean} [decompress=false] whether to attempt gunzip decompression on the fetched data @@ -137,7 +137,7 @@ public: /**jsdoc * Result value returned by {@link Assets.getAsset}. - * @typedef {Object} Assets~getAssetResult + * @typedef {object} Assets~getAssetResult * @property {string} [url] the resolved "atp:" style URL for the fetched asset * @property {string} [hash] the resolved hash for the fetched asset * @property {string|ArrayBuffer|Object} [response] response data (possibly converted per .responseType value) @@ -159,7 +159,7 @@ public: /**jsdoc * A set of properties that can be passed to {@link Assets.putAsset}. - * @typedef {Object} Assets.PutOptions + * @typedef {object} Assets.PutOptions * @property {ArrayBuffer|string} [data] byte buffer or string value representing the new asset's content * @property {string} [path=null] ATP path mapping to automatically create (upon successful upload to hash) * @property {boolean} [compress=false] whether to gzip compress data before uploading @@ -174,7 +174,7 @@ public: /**jsdoc * Result value returned by {@link Assets.putAsset}. - * @typedef {Object} Assets~putAssetResult + * @typedef {object} Assets~putAssetResult * @property {string} [url] the resolved "atp:" style URL for the uploaded asset (based on .path if specified, otherwise on the resulting ATP hash) * @property {string} [path] the uploaded asset's resulting ATP path (or undefined if no path mapping was assigned) * @property {string} [hash] the uploaded asset's resulting ATP hash diff --git a/libraries/script-engine/src/Quat.h b/libraries/script-engine/src/Quat.h index 1ccdfdbf31..76b7ac45e3 100644 --- a/libraries/script-engine/src/Quat.h +++ b/libraries/script-engine/src/Quat.h @@ -43,7 +43,7 @@ * @hifi-server-entity * @hifi-assignment-client * - * @property IDENTITY {Quat} { x: 0, y: 0, z: 0, w: 1 } : The identity rotation, i.e., no rotation. + * @property {Quat} IDENTITY - { x: 0, y: 0, z: 0, w: 1 } : The identity rotation, i.e., no rotation. * Read-only. * @example Print the IDENTITY value. * print(JSON.stringify(Quat.IDENTITY)); // { x: 0, y: 0, z: 0, w: 1 } diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h index fdfbc6f6c0..da42cf2df3 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.h +++ b/libraries/script-engine/src/SceneScriptingInterface.h @@ -21,7 +21,7 @@ namespace SceneScripting { /**jsdoc - * @typedef Scene.Stage.Location + * @typedef {object} Scene.Stage.Location * @property {number} longitude * @property {number} latitude * @property {number} altitude @@ -49,7 +49,7 @@ namespace SceneScripting { using LocationPointer = std::unique_ptr; /**jsdoc - * @typedef Scene.Stage.Time + * @typedef {object} Scene.Stage.Time * @property {number} hour * @property {number} day */ @@ -73,7 +73,7 @@ namespace SceneScripting { using TimePointer = std::unique_ptr