From 8c9c7248d4a00b3233becfa60c2934e25be9ccf7 Mon Sep 17 00:00:00 2001 From: Alexia Mandeville Date: Mon, 12 Mar 2018 12:52:12 -0700 Subject: [PATCH 001/376] 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/376] 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/376] 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/376] 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/376] 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/376] 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 fc86525863df9eb5a2a01c948fa08f30e6cf616d Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 4 Apr 2018 12:00:06 +0200 Subject: [PATCH 007/376] Cleaned up a bit shadow map clear --- libraries/render-utils/src/RenderShadowTask.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 69c5b3c689..faa5889307 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -149,9 +149,7 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, con batch.setStateScissorRect(viewport); batch.setFramebuffer(fbo); - batch.clearFramebuffer( - gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH, - vec4(vec3(1.0, 1.0, 1.0), 0.0), 1.0, 0, true); + batch.clearDepthFramebuffer(1.0, false); glm::mat4 projMat; Transform viewMat; From 573f399023eafd625212284f827ea3207f006f76 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 6 Apr 2018 14:45:16 +0200 Subject: [PATCH 008/376] Fixed incorrect shadow frustum far clip computation due to not taking into account shadow receivers --- .../render-utils/src/RenderShadowTask.cpp | 27 ++++++++++-------- libraries/render-utils/src/RenderShadowTask.h | 2 +- libraries/render/src/render/CullTask.cpp | 28 +++++++++++++------ libraries/render/src/render/CullTask.h | 2 +- 4 files changed, 38 insertions(+), 21 deletions(-) diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index faa5889307..fbb4bba263 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -230,12 +230,11 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende const auto queryResolution = setupOutput.getN(2); // Fetch and cull the items from the scene - // Enable models to not cast shadows (otherwise, models will always cast shadows) - static const auto shadowCasterFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(tagBits, tagMask).withShadowCaster(); + static const auto shadowCasterReceiverFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(tagBits, tagMask); - const auto fetchInput = FetchSpatialTree::Inputs(shadowCasterFilter, queryResolution).asVarying(); + const auto fetchInput = FetchSpatialTree::Inputs(shadowCasterReceiverFilter, queryResolution).asVarying(); const auto shadowSelection = task.addJob("FetchShadowTree", fetchInput); - const auto selectionInputs = FetchSpatialSelection::Inputs(shadowSelection, shadowCasterFilter).asVarying(); + const auto selectionInputs = FetchSpatialSelection::Inputs(shadowSelection, shadowCasterReceiverFilter).asVarying(); const auto shadowItems = task.addJob("FetchShadowSelection", selectionInputs); // Cull objects that are not visible in camera view. Hopefully the cull functor only performs LOD culling, not @@ -259,21 +258,22 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende char jobName[64]; sprintf(jobName, "ShadowCascadeSetup%d", i); const auto cascadeSetupOutput = task.addJob(jobName, i, _cullFunctor, tagBits, tagMask); - const auto shadowFilter = cascadeSetupOutput.getN(0); + const auto shadowRenderFilter = cascadeSetupOutput.getN(0); + const auto shadowBoundsFilter = cascadeSetupOutput.getN(1); auto antiFrustum = render::Varying(ViewFrustumPointer()); - cascadeFrustums[i] = cascadeSetupOutput.getN(1); + cascadeFrustums[i] = cascadeSetupOutput.getN(2); if (i > 1) { antiFrustum = cascadeFrustums[i - 2]; } // CPU jobs: finer grained culling - const auto cullInputs = CullShapeBounds::Inputs(sortedShapes, shadowFilter, antiFrustum).asVarying(); + const auto cullInputs = CullShapeBounds::Inputs(sortedShapes, shadowRenderFilter, shadowBoundsFilter, antiFrustum).asVarying(); const auto culledShadowItemsAndBounds = task.addJob("CullShadowCascade", cullInputs, shadowCullFunctor, RenderDetails::SHADOW); // GPU jobs: Render to shadow map sprintf(jobName, "RenderShadowMap%d", i); task.addJob(jobName, culledShadowItemsAndBounds, shapePlumber, i); - task.addJob("ShadowCascadeTeardown", shadowFilter); + task.addJob("ShadowCascadeTeardown", shadowRenderFilter); } task.addJob("ShadowTeardown", setupOutput); @@ -404,7 +404,11 @@ void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderCon const auto globalShadow = lightStage->getCurrentKeyShadow(); if (globalShadow && _cascadeIndexgetCascadeCount()) { - output.edit0() = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(_tagBits, _tagMask).withShadowCaster(); + auto baseFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(_tagBits, _tagMask); + // Second item filter is to filter items to keep in shadow frustum computation (here we need to keep shadow receivers) + output.edit1() = baseFilter; + // First item filter is to filter items to render in shadow map (so only keep casters) + output.edit0() = baseFilter.withShadowCaster(); // Set the keylight render args auto& cascade = globalShadow->getCascade(_cascadeIndex); @@ -417,10 +421,11 @@ void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderCon texelSize *= minTexelCount; _cullFunctor._minSquareSize = texelSize * texelSize; - output.edit1() = cascadeFrustum; + output.edit2() = cascadeFrustum; } else { output.edit0() = ItemFilter::Builder::nothing(); - output.edit1() = ViewFrustumPointer(); + output.edit1() = ItemFilter::Builder::nothing(); + output.edit2() = ViewFrustumPointer(); } } diff --git a/libraries/render-utils/src/RenderShadowTask.h b/libraries/render-utils/src/RenderShadowTask.h index 98b70c0c9f..19ffcb4234 100644 --- a/libraries/render-utils/src/RenderShadowTask.h +++ b/libraries/render-utils/src/RenderShadowTask.h @@ -118,7 +118,7 @@ private: class RenderShadowCascadeSetup { public: - using Outputs = render::VaryingSet2; + using Outputs = render::VaryingSet3; using JobModel = render::Job::ModelO; RenderShadowCascadeSetup(unsigned int cascadeIndex, RenderShadowTask::CullFunctor& cullFunctor, uint8_t tagBits = 0x00, uint8_t tagMask = 0x00) : diff --git a/libraries/render/src/render/CullTask.cpp b/libraries/render/src/render/CullTask.cpp index f04427540a..b5819f114f 100644 --- a/libraries/render/src/render/CullTask.cpp +++ b/libraries/render/src/render/CullTask.cpp @@ -368,17 +368,19 @@ void CullShapeBounds::run(const RenderContextPointer& renderContext, const Input RenderArgs* args = renderContext->args; const auto& inShapes = inputs.get0(); - const auto& filter = inputs.get1(); - const auto& antiFrustum = inputs.get2(); + const auto& cullFilter = inputs.get1(); + const auto& boundsFilter = inputs.get2(); + const auto& antiFrustum = inputs.get3(); auto& outShapes = outputs.edit0(); auto& outBounds = outputs.edit1(); outShapes.clear(); outBounds = AABox(); - if (!filter.selectsNothing()) { + if (!cullFilter.selectsNothing() || !boundsFilter.selectsNothing()) { auto& details = args->_details.edit(_detailType); Test test(_cullFunctor, args, details, antiFrustum); + auto scene = args->_scene; for (auto& inItems : inShapes) { auto key = inItems.first; @@ -393,16 +395,26 @@ void CullShapeBounds::run(const RenderContextPointer& renderContext, const Input if (antiFrustum == nullptr) { for (auto& item : inItems.second) { if (test.solidAngleTest(item.bound) && test.frustumTest(item.bound)) { - outItems->second.emplace_back(item); - outBounds += item.bound; + const auto shapeKey = scene->getItem(item.id).getKey(); + if (cullFilter.test(shapeKey)) { + outItems->second.emplace_back(item); + } + if (boundsFilter.test(shapeKey)) { + outBounds += item.bound; + } } } } else { for (auto& item : inItems.second) { if (test.solidAngleTest(item.bound) && test.frustumTest(item.bound) && test.antiFrustumTest(item.bound)) { - outItems->second.emplace_back(item); - outBounds += item.bound; - } + const auto shapeKey = scene->getItem(item.id).getKey(); + if (cullFilter.test(shapeKey)) { + outItems->second.emplace_back(item); + } + if (boundsFilter.test(shapeKey)) { + outBounds += item.bound; + } + } } } details._rendered += (int)outItems->second.size(); diff --git a/libraries/render/src/render/CullTask.h b/libraries/render/src/render/CullTask.h index 3c5a30de89..47abe8a960 100644 --- a/libraries/render/src/render/CullTask.h +++ b/libraries/render/src/render/CullTask.h @@ -110,7 +110,7 @@ namespace render { class CullShapeBounds { public: - using Inputs = render::VaryingSet3; + using Inputs = render::VaryingSet4; using Outputs = render::VaryingSet2; using JobModel = Job::ModelIO; From 86cfb1448a19eee833920804515a55eccd2c3698 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Mon, 16 Apr 2018 21:54:14 +0100 Subject: [PATCH 009/376] move inspect script --- {script-archive => scripts/system}/inspect.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {script-archive => scripts/system}/inspect.js (100%) diff --git a/script-archive/inspect.js b/scripts/system/inspect.js similarity index 100% rename from script-archive/inspect.js rename to scripts/system/inspect.js From 8a5d80de312fbe7512a6a1b40fe18c2c32edaf16 Mon Sep 17 00:00:00 2001 From: vladest Date: Tue, 17 Apr 2018 19:51:24 +0200 Subject: [PATCH 010/376] 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 011/376] 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 012/376] 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 120de92c9e284bf5b792bc8d85845536583204f8 Mon Sep 17 00:00:00 2001 From: Gabriel Calero Date: Wed, 18 Apr 2018 15:52:02 -0300 Subject: [PATCH 013/376] Add login activity --- android/app/src/main/AndroidManifest.xml | 9 +- android/app/src/main/cpp/native.cpp | 76 ++++- .../hifiinterface/GotoActivity.java | 14 +- .../hifiinterface/HomeActivity.java | 105 +++--- .../hifiinterface/InterfaceActivity.java | 8 +- .../hifiinterface/LoginActivity.java | 106 ++++++ .../hifiinterface/PermissionChecker.java | 2 +- .../QtPreloader/QtPreloader.java | 315 ------------------ .../hifiinterface/SplashActivity.java | 32 ++ .../qt5/android/bindings/QtActivity.java | 8 +- .../app/src/main/res/drawable/hifi_header.xml | 50 +++ .../src/main/res/drawable/rounded_button.xml | 24 ++ .../src/main/res/drawable/rounded_edit.xml | 7 + .../app/src/main/res/layout/activity_goto.xml | 4 +- .../app/src/main/res/layout/activity_home.xml | 25 +- .../src/main/res/layout/activity_login.xml | 106 ++++++ .../src/main/res/layout/activity_splash.xml | 12 + android/app/src/main/res/values/colors.xml | 5 + android/app/src/main/res/values/strings.xml | 7 + android/app/src/main/res/values/styles.xml | 9 +- interface/src/AndroidHelper.cpp | 29 ++ interface/src/AndroidHelper.h | 16 +- interface/src/Application.cpp | 4 + 23 files changed, 577 insertions(+), 396 deletions(-) create mode 100644 android/app/src/main/java/io/highfidelity/hifiinterface/LoginActivity.java delete mode 100644 android/app/src/main/java/io/highfidelity/hifiinterface/QtPreloader/QtPreloader.java create mode 100644 android/app/src/main/java/io/highfidelity/hifiinterface/SplashActivity.java create mode 100644 android/app/src/main/res/drawable/hifi_header.xml create mode 100644 android/app/src/main/res/drawable/rounded_button.xml create mode 100644 android/app/src/main/res/drawable/rounded_edit.xml create mode 100644 android/app/src/main/res/layout/activity_login.xml create mode 100644 android/app/src/main/res/layout/activity_splash.xml diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index ed9caee58b..8828335cd1 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -47,8 +47,9 @@ - + android:theme="@style/AppTheme" /> + + + diff --git a/android/app/src/main/cpp/native.cpp b/android/app/src/main/cpp/native.cpp index c71be76b3e..3fad01db9b 100644 --- a/android/app/src/main/cpp/native.cpp +++ b/android/app/src/main/cpp/native.cpp @@ -22,7 +22,9 @@ #include #include "AndroidHelper.h" -QAndroidJniObject __activity; +QAndroidJniObject __interfaceActivity; +QAndroidJniObject __loginActivity; +QAndroidJniObject __loadCompleteListener; void tempMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) { if (!message.isEmpty()) { @@ -142,16 +144,16 @@ void unpackAndroidAssets() { extern "C" { JNIEXPORT void Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeOnCreate(JNIEnv* env, jobject obj, jobject instance, jobject asset_mgr) { - qDebug() << "nativeOnCreate On thread " << QThread::currentThreadId(); g_assetManager = AAssetManager_fromJava(env, asset_mgr); - __activity = QAndroidJniObject(instance); + qRegisterMetaType("QAndroidJniObject"); + __interfaceActivity = QAndroidJniObject(instance); auto oldMessageHandler = qInstallMessageHandler(tempMessageHandler); unpackAndroidAssets(); qInstallMessageHandler(oldMessageHandler); QObject::connect(&AndroidHelper::instance(), &AndroidHelper::androidActivityRequested, [](const QString& a) { QAndroidJniObject string = QAndroidJniObject::fromString(a); - __activity.callMethod("openGotoActivity", "(Ljava/lang/String;)V", string.object()); + __interfaceActivity.callMethod("openGotoActivity", "(Ljava/lang/String;)V", string.object()); }); } @@ -167,15 +169,12 @@ JNIEXPORT void Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeGotoUr } JNIEXPORT void Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeOnPause(JNIEnv* env, jobject obj) { - qDebug() << "nativeOnPause"; } JNIEXPORT void Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeOnResume(JNIEnv* env, jobject obj) { - qDebug() << "nativeOnResume"; } JNIEXPORT void Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeOnExitVr(JNIEnv* env, jobject obj) { - qDebug() << "nativeOnCreate On thread " << QThread::currentThreadId(); } JNIEXPORT void Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeGoBackFromAndroidActivity(JNIEnv *env, jobject instance) { @@ -204,4 +203,67 @@ JNIEXPORT jstring JNICALL Java_io_highfidelity_hifiinterface_HifiUtils_getCurren return env->NewStringUTF(str.toLatin1().data()); } +JNIEXPORT void JNICALL +Java_io_highfidelity_hifiinterface_LoginActivity_nativeLogin(JNIEnv *env, jobject instance, + jstring username_, jstring password_) { + const char *c_username = env->GetStringUTFChars(username_, 0); + const char *c_password = env->GetStringUTFChars(password_, 0); + QString username = QString(c_username); + QString password = QString(c_password); + env->ReleaseStringUTFChars(username_, c_username); + env->ReleaseStringUTFChars(password_, c_password); + + QSharedPointer accountManager = AndroidHelper::instance().getAccountManager(); + + __loginActivity = QAndroidJniObject(instance); + + QObject::connect(accountManager.data(), &AccountManager::loginComplete, [](const QUrl& authURL) { + AndroidHelper::instance().notifyLoginComplete(true); + }); + + QObject::connect(accountManager.data(), &AccountManager::loginFailed, []() { + AndroidHelper::instance().notifyLoginComplete(false); + }); + + QObject::connect(&AndroidHelper::instance(), &AndroidHelper::loginComplete, [](bool success) { + jboolean jSuccess = (jboolean) success; + __loginActivity.callMethod("handleLoginCompleted", "(Z)V", jSuccess); + }); + + QMetaObject::invokeMethod(accountManager.data(), "requestAccessToken", Q_ARG(const QString&, username), Q_ARG(const QString&, password)); +} + +JNIEXPORT void JNICALL +Java_io_highfidelity_hifiinterface_SplashActivity_registerLoadCompleteListener(JNIEnv *env, + jobject instance) { + + __loadCompleteListener = QAndroidJniObject(instance); + + QObject::connect(&AndroidHelper::instance(), &AndroidHelper::qtAppLoadComplete, []() { + + __loadCompleteListener.callMethod("onAppLoadedComplete", "()V"); + __interfaceActivity.callMethod("onAppLoadedComplete", "()V"); + + QObject::disconnect(&AndroidHelper::instance(), &AndroidHelper::qtAppLoadComplete, nullptr, + nullptr); + }); + +} +JNIEXPORT jboolean JNICALL +Java_io_highfidelity_hifiinterface_HomeActivity_nativeIsLoggedIn(JNIEnv *env, jobject instance) { + return AndroidHelper::instance().getAccountManager()->isLoggedIn(); +} + +JNIEXPORT void JNICALL +Java_io_highfidelity_hifiinterface_HomeActivity_nativeLogout(JNIEnv *env, jobject instance) { + AndroidHelper::instance().getAccountManager()->logout(); +} + +JNIEXPORT jstring JNICALL +Java_io_highfidelity_hifiinterface_HomeActivity_nativeGetDisplayName(JNIEnv *env, + jobject instance) { + QString username = AndroidHelper::instance().getAccountManager()->getAccountInfo().getUsername(); + return env->NewStringUTF(username.toLatin1().data()); +} + } diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java index 65221bc21c..f1ecc21d84 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java @@ -9,7 +9,6 @@ import android.support.v7.widget.Toolbar; import android.view.KeyEvent; import android.view.MenuItem; import android.view.View; -import android.view.inputmethod.EditorInfo; import android.widget.EditText; import java.net.URI; @@ -17,6 +16,8 @@ import java.net.URISyntaxException; public class GotoActivity extends AppCompatActivity { + public static final String PARAM_DOMAIN_URL = "domain_url"; + private EditText mUrlEditText; private AppCompatButton mGoBtn; @@ -69,15 +70,10 @@ public class GotoActivity extends AppCompatActivity { urlString = "hifi://" + urlString; } - Intent intent = new Intent(this, InterfaceActivity.class); - intent.putExtra(InterfaceActivity.DOMAIN_URL, urlString); + Intent intent = new Intent(); + intent.putExtra(GotoActivity.PARAM_DOMAIN_URL, urlString); + setResult(RESULT_OK, intent); finish(); - if (getIntent() != null && - getIntent().hasExtra(HomeActivity.PARAM_NOT_START_INTERFACE_ACTIVITY) && - getIntent().getBooleanExtra(HomeActivity.PARAM_NOT_START_INTERFACE_ACTIVITY, false)) { - intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); - } - startActivity(intent); } } diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/HomeActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/HomeActivity.java index ed442e2d8d..117e1f2cc4 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/HomeActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/HomeActivity.java @@ -1,9 +1,7 @@ package io.highfidelity.hifiinterface; -import android.app.ProgressDialog; import android.content.Intent; import android.graphics.Color; -import android.os.AsyncTask; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.design.widget.NavigationView; @@ -22,18 +20,23 @@ import android.widget.TabHost; import android.widget.TabWidget; import android.widget.TextView; -import io.highfidelity.hifiinterface.QtPreloader.QtPreloader; import io.highfidelity.hifiinterface.view.DomainAdapter; public class HomeActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener { + public native boolean nativeIsLoggedIn(); + public native void nativeLogout(); + public native String nativeGetDisplayName(); + /** * Set this intent extra param to NOT start a new InterfaceActivity after a domain is selected" */ - public static final String PARAM_NOT_START_INTERFACE_ACTIVITY = "not_start_interface_activity"; + //public static final String PARAM_NOT_START_INTERFACE_ACTIVITY = "not_start_interface_activity"; + + public static final int ENTER_DOMAIN_URL = 1; + private DomainAdapter domainAdapter; private DrawerLayout mDrawerLayout; - private ProgressDialog mDialog; private NavigationView mNavigationView; @Override @@ -89,15 +92,7 @@ public class HomeActivity extends AppCompatActivity implements NavigationView.On @Override public void onItemClick(View view, int position, DomainAdapter.Domain domain) { - Intent intent = new Intent(HomeActivity.this, InterfaceActivity.class); - intent.putExtra(InterfaceActivity.DOMAIN_URL, domain.url); - HomeActivity.this.finish(); - if (getIntent() != null && - getIntent().hasExtra(PARAM_NOT_START_INTERFACE_ACTIVITY) && - getIntent().getBooleanExtra(PARAM_NOT_START_INTERFACE_ACTIVITY, false)) { - intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); - } - startActivity(intent); + gotoDomain(domain.url); } }); domainsView.setAdapter(domainAdapter); @@ -112,49 +107,28 @@ public class HomeActivity extends AppCompatActivity implements NavigationView.On searchTextView.setTextAppearance(R.style.SearchText); } - if (getIntent() == null || - !getIntent().hasExtra(PARAM_NOT_START_INTERFACE_ACTIVITY) || - !getIntent().getBooleanExtra(PARAM_NOT_START_INTERFACE_ACTIVITY, false)) { - preloadQt(); - showActivityIndicator(); - } + updateLoginMenu(); } - private void showActivityIndicator() { - if (mDialog == null) { - mDialog = new ProgressDialog(this); - } - mDialog.setMessage("Please wait..."); - mDialog.setCancelable(false); - mDialog.show(); - } - - private void cancelActivityIndicator() { - if (mDialog != null) { - mDialog.cancel(); + private void updateLoginMenu() { + TextView loginOption = findViewById(R.id.login); + TextView logoutOption = findViewById(R.id.logout); + if (nativeIsLoggedIn()) { + loginOption.setVisibility(View.GONE); + logoutOption.setVisibility(View.VISIBLE); + } else { + loginOption.setVisibility(View.VISIBLE); + logoutOption.setVisibility(View.GONE); } } - private AsyncTask preloadTask; - - private void preloadQt() { - if (preloadTask == null) { - preloadTask = new AsyncTask() { - @Override - protected Object doInBackground(Object[] objects) { - new QtPreloader(HomeActivity.this).initQt(); - runOnUiThread(new Runnable() { - @Override - public void run() { - cancelActivityIndicator(); - } - }); - return null; - } - }; - preloadTask.execute(); - } + private void gotoDomain(String domainUrl) { + Intent intent = new Intent(HomeActivity.this, InterfaceActivity.class); + intent.putExtra(InterfaceActivity.DOMAIN_URL, domainUrl); + HomeActivity.this.finish(); + intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + startActivity(intent); } @Override @@ -181,7 +155,6 @@ public class HomeActivity extends AppCompatActivity implements NavigationView.On @Override protected void onDestroy() { - cancelActivityIndicator(); super.onDestroy(); } @@ -190,11 +163,33 @@ public class HomeActivity extends AppCompatActivity implements NavigationView.On switch(item.getItemId()) { case R.id.action_goto: Intent i = new Intent(this, GotoActivity.class); - startActivity(i); - return true; - case R.id.action_settings: + startActivityForResult(i, ENTER_DOMAIN_URL); return true; } return false; } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == ENTER_DOMAIN_URL && resultCode == RESULT_OK) { + gotoDomain(data.getStringExtra(GotoActivity.PARAM_DOMAIN_URL)); + } + } + + @Override + protected void onStart() { + super.onStart(); + updateLoginMenu(); + } + + public void onLoginClicked(View view) { + Intent intent = new Intent(this, LoginActivity.class); + startActivity(intent); + } + + public void onLogoutClicked(View view) { + nativeLogout(); + updateLoginMenu(); + } } diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java index 678f7e8aac..2b86abc9da 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java @@ -63,6 +63,7 @@ public class InterfaceActivity extends QtActivity { @Override public void onCreate(Bundle savedInstanceState) { + super.isLoading = true; Intent intent = getIntent(); if (intent.hasExtra(DOMAIN_URL) && !intent.getStringExtra(DOMAIN_URL).isEmpty()) { intent.putExtra("applicationArguments", "--url "+intent.getStringExtra(DOMAIN_URL)); @@ -112,6 +113,8 @@ public class InterfaceActivity extends QtActivity { } } }); + startActivity(new Intent(this, SplashActivity.class)); + } @Override @@ -201,7 +204,6 @@ public class InterfaceActivity extends QtActivity { switch (activityName) { case "Goto": { Intent intent = new Intent(this, HomeActivity.class); - intent.putExtra(HomeActivity.PARAM_NOT_START_INTERFACE_ACTIVITY, true); startActivity(intent); break; } @@ -212,4 +214,8 @@ public class InterfaceActivity extends QtActivity { } } + public void onAppLoadedComplete() { + super.isLoading = false; + } + } \ No newline at end of file diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/LoginActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/LoginActivity.java new file mode 100644 index 0000000000..9fd256aa82 --- /dev/null +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/LoginActivity.java @@ -0,0 +1,106 @@ +package io.highfidelity.hifiinterface; + +import android.app.ProgressDialog; +import android.support.annotation.MainThread; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.util.Log; +import android.view.KeyEvent; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +public class LoginActivity extends AppCompatActivity { + + public native void nativeLogin(String username, String password); + + private EditText mUsername; + private EditText mPassword; + private TextView mError; + private Button mLoginButton; + + private ProgressDialog mDialog; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_login); + + mUsername = findViewById(R.id.username); + mPassword = findViewById(R.id.password); + mError = findViewById(R.id.error); + mLoginButton = findViewById(R.id.loginButton); + + mPassword.setOnEditorActionListener( + new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) { + if (actionId == EditorInfo.IME_ACTION_DONE) { + mLoginButton.performClick(); + return true; + } + return false; + } + }); + + } + + @Override + protected void onStop() { + super.onStop(); + cancelActivityIndicator(); + } + + public void login(View view) { + String username = mUsername.getText().toString(); + String password = mPassword.getText().toString(); + if (username.isEmpty() || password.isEmpty()) { + showError(getString(R.string.login_username_or_password_incorrect)); + } else { + mLoginButton.setEnabled(false); + hideError(); + showActivityIndicator(); + nativeLogin(username, password); + } + } + + private void showActivityIndicator() { + if (mDialog == null) { + mDialog = new ProgressDialog(this); + } + mDialog.setMessage(getString(R.string.logging_in)); + mDialog.setCancelable(false); + mDialog.show(); + } + + private void cancelActivityIndicator() { + if (mDialog != null) { + mDialog.cancel(); + } + } + private void showError(String error) { + mError.setText(error); + mError.setVisibility(View.VISIBLE); + } + + private void hideError() { + mError.setText(""); + mError.setVisibility(View.INVISIBLE); + } + + public void handleLoginCompleted(boolean success) { + runOnUiThread(() -> { + mLoginButton.setEnabled(true); + cancelActivityIndicator(); + if (success) { + finish(); + } else { + showError(getString(R.string.login_username_or_password_incorrect)); + } + }); + } + +} diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/PermissionChecker.java b/android/app/src/main/java/io/highfidelity/hifiinterface/PermissionChecker.java index b1c5f570c8..2b48d85a48 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/PermissionChecker.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/PermissionChecker.java @@ -64,7 +64,7 @@ public class PermissionChecker extends Activity { private void launchActivityWithPermissions(){ finish(); - Intent i = new Intent(this, HomeActivity.class); + Intent i = new Intent(this, InterfaceActivity.class); startActivity(i); finish(); } diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/QtPreloader/QtPreloader.java b/android/app/src/main/java/io/highfidelity/hifiinterface/QtPreloader/QtPreloader.java deleted file mode 100644 index d9ecdb9710..0000000000 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/QtPreloader/QtPreloader.java +++ /dev/null @@ -1,315 +0,0 @@ -package io.highfidelity.hifiinterface.QtPreloader; - -import android.content.ComponentName; -import android.content.Context; -import android.content.pm.ComponentInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.res.AssetManager; -import android.os.Bundle; -import android.util.Log; - -import org.qtproject.qt5.android.bindings.QtApplication; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.reflect.Method; -import java.util.ArrayList; - -import dalvik.system.DexClassLoader; - -/** - * Created by Gabriel Calero & Cristian Duarte on 3/22/18. - */ - -public class QtPreloader { - - public String ENVIRONMENT_VARIABLES = "QT_USE_ANDROID_NATIVE_DIALOGS=1"; - private ComponentInfo m_contextInfo; - private String[] m_qtLibs = null; // required qt libs - private Context m_context; - - private static final String DEX_PATH_KEY = "dex.path"; - private static final String LIB_PATH_KEY = "lib.path"; - private static final String NATIVE_LIBRARIES_KEY = "native.libraries"; - private static final String ENVIRONMENT_VARIABLES_KEY = "environment.variables"; - private static final String BUNDLED_LIBRARIES_KEY = "bundled.libraries"; - private static final String BUNDLED_IN_LIB_RESOURCE_ID_KEY = "android.app.bundled_in_lib_resource_id"; - private static final String BUNDLED_IN_ASSETS_RESOURCE_ID_KEY = "android.app.bundled_in_assets_resource_id"; - private static final String MAIN_LIBRARY_KEY = "main.library"; - - private static final int BUFFER_SIZE = 1024; - - public QtPreloader(Context context) { - m_context = context; - } - - public void initQt() { - - try { - m_contextInfo = m_context.getPackageManager().getActivityInfo(new ComponentName("io.highfidelity.hifiinterface", "io.highfidelity.hifiinterface.InterfaceActivity"), - PackageManager.GET_META_DATA); - - if (m_contextInfo.metaData.containsKey("android.app.qt_libs_resource_id")) { - int resourceId = m_contextInfo.metaData.getInt("android.app.qt_libs_resource_id"); - m_qtLibs = m_context.getResources().getStringArray(resourceId); - } - ArrayList libraryList = new ArrayList<>(); - String localPrefix = m_context.getApplicationInfo().dataDir + "/"; - String pluginsPrefix = localPrefix + "qt-reserved-files/"; - cleanOldCacheIfNecessary(localPrefix, pluginsPrefix); - extractBundledPluginsAndImports(pluginsPrefix); - - for (String lib : m_qtLibs) { - libraryList.add(localPrefix + "lib/lib" + lib + ".so"); - } - - if (m_contextInfo.metaData.containsKey("android.app.load_local_libs")) { - String[] extraLibs = m_contextInfo.metaData.getString("android.app.load_local_libs").split(":"); - for (String lib : extraLibs) { - if (lib.length() > 0) { - if (lib.startsWith("lib/")) { - libraryList.add(localPrefix + lib); - } else { - libraryList.add(pluginsPrefix + lib); - } - } - } - } - - Bundle loaderParams = new Bundle(); - loaderParams.putString(DEX_PATH_KEY, new String()); - - loaderParams.putStringArrayList(NATIVE_LIBRARIES_KEY, libraryList); - - loaderParams.putString(ENVIRONMENT_VARIABLES_KEY, ENVIRONMENT_VARIABLES - + "\tQML2_IMPORT_PATH=" + pluginsPrefix + "/qml" - + "\tQML_IMPORT_PATH=" + pluginsPrefix + "/imports" - + "\tQT_PLUGIN_PATH=" + pluginsPrefix + "/plugins"); - - - // add all bundled Qt libs to loader params - ArrayList libs = new ArrayList<>(); - - String libName = m_contextInfo.metaData.getString("android.app.lib_name"); - loaderParams.putString(MAIN_LIBRARY_KEY, libName); //main library contains main() function - loaderParams.putStringArrayList(BUNDLED_LIBRARIES_KEY, libs); - - // load and start QtLoader class - DexClassLoader classLoader = new DexClassLoader(loaderParams.getString(DEX_PATH_KEY), // .jar/.apk files - m_context.getDir("outdex", Context.MODE_PRIVATE).getAbsolutePath(), // directory where optimized DEX files should be written. - loaderParams.containsKey(LIB_PATH_KEY) ? loaderParams.getString(LIB_PATH_KEY) : null, // libs folder (if exists) - m_context.getClassLoader()); // parent loader - - Class loaderClass = classLoader.loadClass(loaderClassName()); // load QtLoader class - Object qtLoader = loaderClass.newInstance(); // create an instance - Method prepareAppMethod = qtLoader.getClass().getMethod("loadApplication", - contextClassName(), - ClassLoader.class, - Bundle.class); - prepareAppMethod.invoke(qtLoader, m_context, classLoader, loaderParams); - - // now load the application library so it's accessible from this class loader - if (libName != null) { - System.loadLibrary(libName); - } - } catch (Exception e) { - Log.e(QtApplication.QtTAG, "Error pre-loading HiFi Qt app", e); - } - } - - protected String loaderClassName() { - return "org.qtproject.qt5.android.QtActivityDelegate"; - } - - protected Class contextClassName() { - return android.app.Activity.class; - } - - - private void deleteRecursively(File directory) { - File[] files = directory.listFiles(); - if (files != null) { - for (File file : files) { - if (file.isDirectory()) { - deleteRecursively(file); - } else { - file.delete(); - } - } - - directory.delete(); - } - } - - private void cleanOldCacheIfNecessary(String oldLocalPrefix, String localPrefix) { - File newCache = new File(localPrefix); - if (!newCache.exists()) { - { - File oldPluginsCache = new File(oldLocalPrefix + "plugins/"); - if (oldPluginsCache.exists() && oldPluginsCache.isDirectory()) { - deleteRecursively(oldPluginsCache); - } - } - - { - File oldImportsCache = new File(oldLocalPrefix + "imports/"); - if (oldImportsCache.exists() && oldImportsCache.isDirectory()) { - deleteRecursively(oldImportsCache); - } - } - - { - File oldQmlCache = new File(oldLocalPrefix + "qml/"); - if (oldQmlCache.exists() && oldQmlCache.isDirectory()) { - deleteRecursively(oldQmlCache); - } - } - } - } - - static private void copyFile(InputStream inputStream, OutputStream outputStream) - throws IOException { - byte[] buffer = new byte[BUFFER_SIZE]; - - int count; - while ((count = inputStream.read(buffer)) > 0) { - outputStream.write(buffer, 0, count); - } - } - - private void copyAsset(String source, String destination) - throws IOException { - // Already exists, we don't have to do anything - File destinationFile = new File(destination); - if (destinationFile.exists()) { - return; - } - - File parentDirectory = destinationFile.getParentFile(); - if (!parentDirectory.exists()) { - parentDirectory.mkdirs(); - } - - destinationFile.createNewFile(); - - AssetManager assetsManager = m_context.getAssets(); - InputStream inputStream = assetsManager.open(source); - OutputStream outputStream = new FileOutputStream(destinationFile); - copyFile(inputStream, outputStream); - - inputStream.close(); - outputStream.close(); - } - - private static void createBundledBinary(String source, String destination) - throws IOException { - // Already exists, we don't have to do anything - File destinationFile = new File(destination); - if (destinationFile.exists()) { - return; - } - - File parentDirectory = destinationFile.getParentFile(); - if (!parentDirectory.exists()) { - parentDirectory.mkdirs(); - } - - destinationFile.createNewFile(); - - InputStream inputStream = new FileInputStream(source); - OutputStream outputStream = new FileOutputStream(destinationFile); - copyFile(inputStream, outputStream); - - inputStream.close(); - outputStream.close(); - } - - private boolean cleanCacheIfNecessary(String pluginsPrefix, long packageVersion) { - File versionFile = new File(pluginsPrefix + "cache.version"); - - long cacheVersion = 0; - if (versionFile.exists() && versionFile.canRead()) { - try { - DataInputStream inputStream = new DataInputStream(new FileInputStream(versionFile)); - cacheVersion = inputStream.readLong(); - inputStream.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - if (cacheVersion != packageVersion) { - deleteRecursively(new File(pluginsPrefix)); - return true; - } else { - return false; - } - } - - private void extractBundledPluginsAndImports(String pluginsPrefix) throws IOException { - String libsDir = m_context.getApplicationInfo().nativeLibraryDir + "/"; - long packageVersion = -1; - try { - PackageInfo packageInfo = m_context.getPackageManager().getPackageInfo(m_context.getPackageName(), 0); - packageVersion = packageInfo.lastUpdateTime; - } catch (Exception e) { - e.printStackTrace(); - } - - - if (!cleanCacheIfNecessary(pluginsPrefix, packageVersion)) { - return; - } - - { - File versionFile = new File(pluginsPrefix + "cache.version"); - - File parentDirectory = versionFile.getParentFile(); - if (!parentDirectory.exists()) { - parentDirectory.mkdirs(); - } - - versionFile.createNewFile(); - - DataOutputStream outputStream = new DataOutputStream(new FileOutputStream(versionFile)); - outputStream.writeLong(packageVersion); - outputStream.close(); - } - - { - String key = BUNDLED_IN_LIB_RESOURCE_ID_KEY; - if (m_contextInfo.metaData.containsKey(key)) { - String[] list = m_context.getResources().getStringArray(m_contextInfo.metaData.getInt(key)); - - for (String bundledImportBinary : list) { - String[] split = bundledImportBinary.split(":"); - String sourceFileName = libsDir + split[0]; - String destinationFileName = pluginsPrefix + split[1]; - createBundledBinary(sourceFileName, destinationFileName); - } - } - } - - { - String key = BUNDLED_IN_ASSETS_RESOURCE_ID_KEY; - if (m_contextInfo.metaData.containsKey(key)) { - String[] list = m_context.getResources().getStringArray(m_contextInfo.metaData.getInt(key)); - - for (String fileName : list) { - String[] split = fileName.split(":"); - String sourceFileName = split[0]; - String destinationFileName = pluginsPrefix + split[1]; - copyAsset(sourceFileName, destinationFileName); - } - } - - } - } -} diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/SplashActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/SplashActivity.java new file mode 100644 index 0000000000..b663a3e396 --- /dev/null +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/SplashActivity.java @@ -0,0 +1,32 @@ +package io.highfidelity.hifiinterface; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; + +public class SplashActivity extends Activity { + + private native void registerLoadCompleteListener(); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_splash); + registerLoadCompleteListener(); + } + + @Override + protected void onStart() { + super.onStart(); + } + + @Override + protected void onStop() { + super.onStop(); + } + + public void onAppLoadedComplete() { + startActivity(new Intent(this, HomeActivity.class)); + finish(); + } +} diff --git a/android/app/src/main/java/org/qtproject/qt5/android/bindings/QtActivity.java b/android/app/src/main/java/org/qtproject/qt5/android/bindings/QtActivity.java index ed55c16cde..887d27dba4 100644 --- a/android/app/src/main/java/org/qtproject/qt5/android/bindings/QtActivity.java +++ b/android/app/src/main/java/org/qtproject/qt5/android/bindings/QtActivity.java @@ -68,6 +68,8 @@ public class QtActivity extends Activity { public final String QT_ANDROID_DEFAULT_THEME = QT_ANDROID_THEMES[0]; // sets the default theme. private QtActivityLoader m_loader = new QtActivityLoader(this); + public boolean isLoading; + public QtActivity() { } @@ -499,7 +501,11 @@ public class QtActivity extends Activity { @Override protected void onPause() { super.onPause(); - QtApplication.invokeDelegate(); + // GC: this trick allow us to show a splash activity until Qt app finishes + // loading + if (!isLoading) { + QtApplication.invokeDelegate(); + } } //--------------------------------------------------------------------------- diff --git a/android/app/src/main/res/drawable/hifi_header.xml b/android/app/src/main/res/drawable/hifi_header.xml new file mode 100644 index 0000000000..9f7c85297a --- /dev/null +++ b/android/app/src/main/res/drawable/hifi_header.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/drawable/rounded_button.xml b/android/app/src/main/res/drawable/rounded_button.xml new file mode 100644 index 0000000000..11a9f90c8b --- /dev/null +++ b/android/app/src/main/res/drawable/rounded_button.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/drawable/rounded_edit.xml b/android/app/src/main/res/drawable/rounded_edit.xml new file mode 100644 index 0000000000..3c1cac4d1d --- /dev/null +++ b/android/app/src/main/res/drawable/rounded_edit.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/layout/activity_goto.xml b/android/app/src/main/res/layout/activity_goto.xml index 7f4e7d5fcf..2d5943e15d 100644 --- a/android/app/src/main/res/layout/activity_goto.xml +++ b/android/app/src/main/res/layout/activity_goto.xml @@ -3,8 +3,8 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/root_activity_goto" - android:layout_width="match_parent" - android:layout_height="match_parent" + android:layout_width="wrap_content" + android:layout_height="wrap_content" tools:context="io.highfidelity.hifiinterface.GotoActivity"> + > + + + + + diff --git a/android/app/src/main/res/layout/activity_login.xml b/android/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000000..ecf72b94bf --- /dev/null +++ b/android/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,106 @@ + + + + + + + + + + + +