diff --git a/interface/resources/html/help.html b/interface/resources/html/help.html index 6cc4dab6af..422f5c6b46 100644 --- a/interface/resources/html/help.html +++ b/interface/resources/html/help.html @@ -50,21 +50,33 @@ function showKbm() { document.getElementById("main_image").setAttribute("src", "img/controls-help-keyboard.png"); } - function showHandControllers() { + function showViveControllers() { document.getElementById("main_image").setAttribute("src", "img/controls-help-vive.png"); } - function showGameController() { + function showXboxController() { document.getElementById("main_image").setAttribute("src", "img/controls-help-gamepad.png"); } + function load() { + console.log("In help.html: ", window.location.href); + parts = window.location.href.split("?"); + if (parts.length > 0) { + var defaultTab = parts[1]; + if (defaultTab == "xbox") { + showXboxController(); + } else if (defaultTab == "vive") { + showViveControllers(); + } + } + } </script> </head> - <body> + <body onload="load()"> <div id="image_area"> <img id="main_image" src="img/controls-help-keyboard.png" width="1024px" height="720px"></img> <a href="#" id="kbm_button" onmousedown="showKbm()"></a> - <a href="#" id="hand_controllers_button" onmousedown="showHandControllers()"></a> - <a href="#" id="game_controller_button" onmousedown="showGameController()"></a> + <a href="#" id="hand_controllers_button" onmousedown="showViveControllers()"></a> + <a href="#" id="game_controller_button" onmousedown="showXboxController()"></a> </div> </body> diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index bbf97ad60c..867761e012 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2161,7 +2161,17 @@ void Application::aboutApp() { } void Application::showHelp() { - InfoView::show(INFO_HELP_PATH); + static const QString QUERY_STRING_XBOX = "xbox"; + static const QString QUERY_STRING_VIVE = "vive"; + + QString queryString = ""; + if (PluginUtils::isViveControllerAvailable()) { + queryString = QUERY_STRING_VIVE; + } else if (PluginUtils::isXboxControllerAvailable()) { + queryString = QUERY_STRING_XBOX; + } + + InfoView::show(INFO_HELP_PATH, false, queryString); } void Application::resizeEvent(QResizeEvent* event) { diff --git a/libraries/plugins/src/plugins/InputPlugin.h b/libraries/plugins/src/plugins/InputPlugin.h index f68be3edf6..0db0b24420 100644 --- a/libraries/plugins/src/plugins/InputPlugin.h +++ b/libraries/plugins/src/plugins/InputPlugin.h @@ -21,6 +21,9 @@ public: virtual void pluginFocusOutEvent() = 0; virtual void pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) = 0; + // Some input plugins are comprised of multiple subdevices (SDL2, for instance). + // If an input plugin is only a single device, it will only return it's primary name. + virtual QStringList getSubdeviceNames() { return { getName() }; }; virtual bool isHandController() const = 0; }; diff --git a/libraries/plugins/src/plugins/PluginUtils.cpp b/libraries/plugins/src/plugins/PluginUtils.cpp index bc53e8166a..48530bfe8c 100644 --- a/libraries/plugins/src/plugins/PluginUtils.cpp +++ b/libraries/plugins/src/plugins/PluginUtils.cpp @@ -32,3 +32,26 @@ bool PluginUtils::isHandControllerAvailable() { } return false; }; + +bool isSubdeviceContainingNameAvailable(QString name) { + for (auto& inputPlugin : PluginManager::getInstance()->getInputPlugins()) { + if (inputPlugin->isActive()) { + auto subdeviceNames = inputPlugin->getSubdeviceNames(); + for (auto& subdeviceName : subdeviceNames) { + if (subdeviceName.contains(name)) { + return true; + } + } + } + } + return false; +}; + +bool PluginUtils::isViveControllerAvailable() { + return isSubdeviceContainingNameAvailable("OpenVR"); +}; + +bool PluginUtils::isXboxControllerAvailable() { + return isSubdeviceContainingNameAvailable("X360 Controller"); +}; + diff --git a/libraries/plugins/src/plugins/PluginUtils.h b/libraries/plugins/src/plugins/PluginUtils.h index 727677ccd3..f1449bc3af 100644 --- a/libraries/plugins/src/plugins/PluginUtils.h +++ b/libraries/plugins/src/plugins/PluginUtils.h @@ -16,4 +16,6 @@ class PluginUtils { public: static bool isHMDAvailable(const QString& pluginName = ""); static bool isHandControllerAvailable(); + static bool isViveControllerAvailable(); + static bool isXboxControllerAvailable(); }; diff --git a/libraries/ui/src/InfoView.cpp b/libraries/ui/src/InfoView.cpp index 6b6d6645f5..d2c72bf5f2 100644 --- a/libraries/ui/src/InfoView.cpp +++ b/libraries/ui/src/InfoView.cpp @@ -37,7 +37,7 @@ QString fetchVersion(const QUrl& url) { return r.trimmed(); } -void InfoView::show(const QString& path, bool firstOrChangedOnly) { +void InfoView::show(const QString& path, bool firstOrChangedOnly, QString urlQuery) { static bool registered{ false }; if (!registered) { registerType(); @@ -49,6 +49,8 @@ void InfoView::show(const QString& path, bool firstOrChangedOnly) { } else { url = QUrl::fromLocalFile(path); } + url.setQuery(urlQuery); + if (firstOrChangedOnly) { const QString lastVersion = infoVersion.get(); const QString version = fetchVersion(url); diff --git a/libraries/ui/src/InfoView.h b/libraries/ui/src/InfoView.h index 275effbfa5..ea6150a4d8 100644 --- a/libraries/ui/src/InfoView.h +++ b/libraries/ui/src/InfoView.h @@ -22,7 +22,7 @@ class InfoView : public QQuickItem { static const QString NAME; public: static void registerType(); - static void show(const QString& path, bool firstOrChangedOnly = false); + static void show(const QString& path, bool firstOrChangedOnly = false, QString urlQuery = ""); InfoView(QQuickItem* parent = nullptr); QUrl url(); diff --git a/plugins/hifiSdl2/src/Joystick.h b/plugins/hifiSdl2/src/Joystick.h index 25381d545a..a10e02d325 100644 --- a/plugins/hifiSdl2/src/Joystick.h +++ b/plugins/hifiSdl2/src/Joystick.h @@ -31,6 +31,8 @@ public: const QString& getName() const { return _name; } + SDL_GameController* getGameController() { return _sdlGameController; } + // Device functions virtual controller::Input::NamedVector getAvailableInputs() const override; virtual QString getDefaultMappingConfig() const override; diff --git a/plugins/hifiSdl2/src/SDL2Manager.cpp b/plugins/hifiSdl2/src/SDL2Manager.cpp index b9a19658e2..b6fa567aee 100644 --- a/plugins/hifiSdl2/src/SDL2Manager.cpp +++ b/plugins/hifiSdl2/src/SDL2Manager.cpp @@ -65,8 +65,10 @@ void SDL2Manager::init() { _openJoysticks[id] = joystick; auto userInputMapper = DependencyManager::get<controller::UserInputMapper>(); userInputMapper->registerDevice(joystick); + auto name = SDL_GameControllerName(controller); + _subdeviceNames << name; emit joystickAdded(joystick.get()); - emit subdeviceConnected(getName(), SDL_GameControllerName(controller)); + emit subdeviceConnected(getName(), name); } } } @@ -78,6 +80,10 @@ void SDL2Manager::init() { } } +QStringList SDL2Manager::getSubdeviceNames() { + return _subdeviceNames; +} + void SDL2Manager::deinit() { _openJoysticks.clear(); @@ -157,15 +163,19 @@ void SDL2Manager::pluginUpdate(float deltaTime, const controller::InputCalibrati Joystick::Pointer joystick = std::make_shared<Joystick>(id, controller); _openJoysticks[id] = joystick; userInputMapper->registerDevice(joystick); + QString name = SDL_GameControllerName(controller); emit joystickAdded(joystick.get()); - emit subdeviceConnected(getName(), SDL_GameControllerName(controller)); + emit subdeviceConnected(getName(), name); + _subdeviceNames << name; } } else if (event.type == SDL_CONTROLLERDEVICEREMOVED) { if (_openJoysticks.contains(event.cdevice.which)) { Joystick::Pointer joystick = _openJoysticks[event.cdevice.which]; _openJoysticks.remove(event.cdevice.which); userInputMapper->removeDevice(joystick->getDeviceID()); + QString name = SDL_GameControllerName(joystick->getGameController()); emit joystickRemoved(joystick.get()); + _subdeviceNames.removeOne(name); } } } diff --git a/plugins/hifiSdl2/src/SDL2Manager.h b/plugins/hifiSdl2/src/SDL2Manager.h index 44b75abd2f..fc1654bce1 100644 --- a/plugins/hifiSdl2/src/SDL2Manager.h +++ b/plugins/hifiSdl2/src/SDL2Manager.h @@ -26,6 +26,7 @@ public: bool isSupported() const override; const QString& getName() const override { return NAME; } + QStringList getSubdeviceNames() override; bool isHandController() const override { return false; } void init() override; @@ -79,6 +80,7 @@ private: QMap<SDL_JoystickID, Joystick::Pointer> _openJoysticks; bool _isInitialized { false } ; static const QString NAME; + QStringList _subdeviceNames; }; #endif // hifi__SDL2Manager_h diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index 5d493f4c9d..f0edc5a465 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -117,6 +117,17 @@ void OculusControllerManager::stopHapticPulse(bool leftHand) { } } +QStringList OculusControllerManager::getSubdeviceNames() { + QStringList devices; + if (_touch) { + devices << _touch->getName(); + } + if (_remote) { + devices << _remote->getName(); + } + return devices; +} + using namespace controller; static const std::vector<std::pair<ovrButton, StandardButtonChannel>> BUTTON_MAP { { diff --git a/plugins/oculus/src/OculusControllerManager.h b/plugins/oculus/src/OculusControllerManager.h index 234acd7db2..1ca9e0f47e 100644 --- a/plugins/oculus/src/OculusControllerManager.h +++ b/plugins/oculus/src/OculusControllerManager.h @@ -27,6 +27,7 @@ public: const QString& getName() const override { return NAME; } bool isHandController() const override { return _touch != nullptr; } + QStringList getSubdeviceNames() override; bool activate() override; void deactivate() override;