Merge pull request #8000 from Atlante45/feat/plugins

Select/Disable plugins via command line args
This commit is contained in:
Brad Hefta-Gaub 2016-06-07 18:17:29 -07:00
commit 80100b1d34
16 changed files with 184 additions and 131 deletions

View file

@ -19,6 +19,7 @@
#include <glm/gtc/type_ptr.hpp>
#include <QtCore/QAbstractNativeEventFilter>
#include <QtCore/QCommandLineParser>
#include <QtCore/QMimeData>
#include <QtCore/QThreadPool>
@ -197,7 +198,6 @@ static const float PHYSICS_READY_RANGE = 3.0f; // how far from avatar to check f
static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
static const QString INPUT_DEVICE_MENU_PREFIX = "Device: ";
Setting::Handle<int> maxOctreePacketsPerSecond("maxOctreePPS", DEFAULT_MAX_OCTREE_PPS);
const QHash<QString, Application::AcceptURLMethod> Application::_acceptedExtensions {
@ -999,7 +999,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
RenderableWebEntityItem* webEntity = dynamic_cast<RenderableWebEntityItem*>(entity.get());
if (webEntity) {
webEntity->setProxyWindow(_window->windowHandle());
if (Menu::getInstance()->isOptionChecked(INPUT_DEVICE_MENU_PREFIX + KeyboardMouseDevice::NAME)) {
if (_keyboardMouseDevice->isActive()) {
_keyboardMouseDevice->pluginFocusOutEvent();
}
_keyboardFocusedItem = entityItemID;
@ -1152,9 +1152,7 @@ void Application::aboutToQuit() {
emit beforeAboutToQuit();
foreach(auto inputPlugin, PluginManager::getInstance()->getInputPlugins()) {
QString name = INPUT_DEVICE_MENU_PREFIX + inputPlugin->getName();
QAction* action = Menu::getInstance()->getActionForOption(name);
if (action->isChecked()) {
if (inputPlugin->isActive()) {
inputPlugin->deactivate();
}
}
@ -1476,7 +1474,6 @@ void Application::initializeUi() {
}
}
_window->setMenuBar(new Menu());
updateInputModes();
auto compositorHelper = DependencyManager::get<CompositorHelper>();
connect(compositorHelper.data(), &CompositorHelper::allowMouseCaptureChanged, [=] {
@ -2024,7 +2021,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
}
if (hasFocus()) {
if (Menu::getInstance()->isOptionChecked(INPUT_DEVICE_MENU_PREFIX + KeyboardMouseDevice::NAME)) {
if (_keyboardMouseDevice->isActive()) {
_keyboardMouseDevice->keyPressEvent(event);
}
@ -2358,7 +2355,7 @@ void Application::keyReleaseEvent(QKeyEvent* event) {
return;
}
if (Menu::getInstance()->isOptionChecked(INPUT_DEVICE_MENU_PREFIX + KeyboardMouseDevice::NAME)) {
if (_keyboardMouseDevice->isActive()) {
_keyboardMouseDevice->keyReleaseEvent(event);
}
@ -2390,9 +2387,7 @@ void Application::keyReleaseEvent(QKeyEvent* event) {
void Application::focusOutEvent(QFocusEvent* event) {
auto inputPlugins = PluginManager::getInstance()->getInputPlugins();
foreach(auto inputPlugin, inputPlugins) {
QString name = INPUT_DEVICE_MENU_PREFIX + inputPlugin->getName();
QAction* action = Menu::getInstance()->getActionForOption(name);
if (action && action->isChecked()) {
if (inputPlugin->isActive()) {
inputPlugin->pluginFocusOutEvent();
}
}
@ -2477,7 +2472,7 @@ void Application::mouseMoveEvent(QMouseEvent* event) {
return;
}
if (Menu::getInstance()->isOptionChecked(INPUT_DEVICE_MENU_PREFIX + KeyboardMouseDevice::NAME)) {
if (_keyboardMouseDevice->isActive()) {
_keyboardMouseDevice->mouseMoveEvent(event);
}
@ -2514,7 +2509,7 @@ void Application::mousePressEvent(QMouseEvent* event) {
if (hasFocus()) {
if (Menu::getInstance()->isOptionChecked(INPUT_DEVICE_MENU_PREFIX + KeyboardMouseDevice::NAME)) {
if (_keyboardMouseDevice->isActive()) {
_keyboardMouseDevice->mousePressEvent(event);
}
@ -2559,7 +2554,7 @@ void Application::mouseReleaseEvent(QMouseEvent* event) {
}
if (hasFocus()) {
if (Menu::getInstance()->isOptionChecked(INPUT_DEVICE_MENU_PREFIX + KeyboardMouseDevice::NAME)) {
if (_keyboardMouseDevice->isActive()) {
_keyboardMouseDevice->mouseReleaseEvent(event);
}
@ -2586,7 +2581,7 @@ void Application::touchUpdateEvent(QTouchEvent* event) {
return;
}
if (Menu::getInstance()->isOptionChecked(INPUT_DEVICE_MENU_PREFIX + KeyboardMouseDevice::NAME)) {
if (_keyboardMouseDevice->isActive()) {
_keyboardMouseDevice->touchUpdateEvent(event);
}
}
@ -2604,7 +2599,7 @@ void Application::touchBeginEvent(QTouchEvent* event) {
return;
}
if (Menu::getInstance()->isOptionChecked(INPUT_DEVICE_MENU_PREFIX + KeyboardMouseDevice::NAME)) {
if (_keyboardMouseDevice->isActive()) {
_keyboardMouseDevice->touchBeginEvent(event);
}
@ -2621,7 +2616,7 @@ void Application::touchEndEvent(QTouchEvent* event) {
return;
}
if (Menu::getInstance()->isOptionChecked(INPUT_DEVICE_MENU_PREFIX + KeyboardMouseDevice::NAME)) {
if (_keyboardMouseDevice->isActive()) {
_keyboardMouseDevice->touchEndEvent(event);
}
@ -2637,7 +2632,7 @@ void Application::wheelEvent(QWheelEvent* event) const {
return;
}
if (Menu::getInstance()->isOptionChecked(INPUT_DEVICE_MENU_PREFIX + KeyboardMouseDevice::NAME)) {
if (_keyboardMouseDevice->isActive()) {
_keyboardMouseDevice->wheelEvent(event);
}
}
@ -2770,9 +2765,7 @@ void Application::idle(float nsecsElapsed) {
getActiveDisplayPlugin()->idle();
auto inputPlugins = PluginManager::getInstance()->getInputPlugins();
foreach(auto inputPlugin, inputPlugins) {
QString name = INPUT_DEVICE_MENU_PREFIX + inputPlugin->getName();
QAction* action = Menu::getInstance()->getActionForOption(name);
if (action && action->isChecked()) {
if (inputPlugin->isActive()) {
inputPlugin->idle();
}
}
@ -2956,6 +2949,27 @@ void Application::loadSettings() {
//DependencyManager::get<LODManager>()->setAutomaticLODAdjust(false);
Menu::getInstance()->loadSettings();
// If there is a preferred plugin, we probably messed it up with the menu settings, so fix it.
auto pluginManager = PluginManager::getInstance();
auto plugins = pluginManager->getPreferredDisplayPlugins();
for (auto plugin : plugins) {
auto menu = Menu::getInstance();
if (auto action = menu->getActionForOption(plugin->getName())) {
action->setChecked(true);
action->trigger();
// Find and activated highest priority plugin, bail for the rest
break;
}
}
auto inputs = pluginManager->getInputPlugins();
for (auto plugin : inputs) {
if (!plugin->isActive()) {
plugin->activate();
}
}
getMyAvatar()->loadData();
_settingsLoaded = true;
@ -4936,7 +4950,34 @@ void Application::postLambdaEvent(std::function<void()> f) {
}
}
void Application::initPlugins() {
void Application::initPlugins(const QStringList& arguments) {
QCommandLineOption display("display", "Preferred displays", "displays");
QCommandLineOption disableDisplays("disable-displays", "Displays to disable", "displays");
QCommandLineOption disableInputs("disable-inputs", "Inputs to disable", "inputs");
QCommandLineParser parser;
parser.addOption(display);
parser.addOption(disableDisplays);
parser.addOption(disableInputs);
parser.parse(arguments);
if (parser.isSet(display)) {
auto preferredDisplays = parser.value(display).split(',', QString::SkipEmptyParts);
qInfo() << "Setting prefered display plugins:" << preferredDisplays;
PluginManager::getInstance()->setPreferredDisplayPlugins(preferredDisplays);
}
if (parser.isSet(disableDisplays)) {
auto disabledDisplays = parser.value(disableDisplays).split(',', QString::SkipEmptyParts);
qInfo() << "Disabling following display plugins:" << disabledDisplays;
PluginManager::getInstance()->disableDisplays(disabledDisplays);
}
if (parser.isSet(disableInputs)) {
auto disabledInputs = parser.value(disableInputs).split(',', QString::SkipEmptyParts);
qInfo() << "Disabling following input plugins:" << disabledInputs;
PluginManager::getInstance()->disableInputs(disabledInputs);
}
}
void Application::shutdownPlugins() {
@ -5206,81 +5247,6 @@ void Application::updateDisplayMode() {
Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin");
}
static void addInputPluginToMenu(InputPluginPointer inputPlugin) {
auto menu = Menu::getInstance();
QString name = INPUT_DEVICE_MENU_PREFIX + inputPlugin->getName();
Q_ASSERT(!menu->menuItemExists(MenuOption::InputMenu, name));
static QActionGroup* inputPluginGroup = nullptr;
if (!inputPluginGroup) {
inputPluginGroup = new QActionGroup(menu);
inputPluginGroup->setExclusive(false);
}
auto parent = menu->getMenu(MenuOption::InputMenu);
auto action = menu->addCheckableActionToQMenuAndActionHash(parent,
name, 0, true, qApp,
SLOT(updateInputModes()));
inputPluginGroup->addAction(action);
Q_ASSERT(menu->menuItemExists(MenuOption::InputMenu, name));
}
void Application::updateInputModes() {
auto menu = Menu::getInstance();
auto inputPlugins = PluginManager::getInstance()->getInputPlugins();
static std::once_flag once;
std::call_once(once, [&] {
foreach(auto inputPlugin, inputPlugins) {
addInputPluginToMenu(inputPlugin);
}
});
auto offscreenUi = DependencyManager::get<OffscreenUi>();
InputPluginList newInputPlugins;
InputPluginList removedInputPlugins;
foreach(auto inputPlugin, inputPlugins) {
QString name = INPUT_DEVICE_MENU_PREFIX + inputPlugin->getName();
QAction* action = menu->getActionForOption(name);
auto it = std::find(std::begin(_activeInputPlugins), std::end(_activeInputPlugins), inputPlugin);
if (action->isChecked() && it == std::end(_activeInputPlugins)) {
_activeInputPlugins.push_back(inputPlugin);
newInputPlugins.push_back(inputPlugin);
} else if (!action->isChecked() && it != std::end(_activeInputPlugins)) {
_activeInputPlugins.erase(it);
removedInputPlugins.push_back(inputPlugin);
}
}
// A plugin was checked
if (newInputPlugins.size() > 0) {
foreach(auto newInputPlugin, newInputPlugins) {
newInputPlugin->activate();
//newInputPlugin->installEventFilter(qApp);
//newInputPlugin->installEventFilter(offscreenUi.data());
}
}
if (removedInputPlugins.size() > 0) { // A plugin was unchecked
foreach(auto removedInputPlugin, removedInputPlugins) {
removedInputPlugin->deactivate();
//removedInputPlugin->removeEventFilter(qApp);
//removedInputPlugin->removeEventFilter(offscreenUi.data());
}
}
//if (newInputPlugins.size() > 0 || removedInputPlugins.size() > 0) {
// if (!_currentInputPluginActions.isEmpty()) {
// auto menu = Menu::getInstance();
// foreach(auto itemInfo, _currentInputPluginActions) {
// menu->removeMenuItem(itemInfo.first, itemInfo.second);
// }
// _currentInputPluginActions.clear();
// }
//}
}
mat4 Application::getEyeProjection(int eye) const {
QMutexLocker viewLocker(&_viewMutex);
if (isHMDMode()) {

View file

@ -101,7 +101,7 @@ public:
};
// FIXME? Empty methods, do we still need them?
static void initPlugins();
static void initPlugins(const QStringList& arguments);
static void shutdownPlugins();
Application(int& argc, char** argv, QElapsedTimer& startup_time);
@ -327,7 +327,6 @@ private slots:
void nodeKilled(SharedNodePointer node);
static void packetSent(quint64 length);
void updateDisplayMode();
void updateInputModes();
void domainConnectionRefused(const QString& reasonMessage, int reason);
private:

View file

@ -403,12 +403,6 @@ Menu::Menu() {
// Developer > Avatar >>>
MenuWrapper* avatarDebugMenu = developerMenu->addMenu("Avatar");
// Settings > Input Devices
MenuWrapper* inputModeMenu = addMenu(MenuOption::InputMenu, "Advanced");
QActionGroup* inputModeGroup = new QActionGroup(inputModeMenu);
inputModeGroup->setExclusive(false);
// Developer > Avatar > Face Tracking
MenuWrapper* faceTrackingMenu = avatarDebugMenu->addMenu("Face Tracking");
{

View file

@ -113,7 +113,6 @@ namespace MenuOption {
const QString Help = "Help...";
const QString IncreaseAvatarSize = "Increase Avatar Size";
const QString IndependentMode = "Independent Mode";
const QString InputMenu = "Developer>Avatar>Input Devices";
const QString ActionMotorControl = "Enable Default Motor Control";
const QString LeapMotionOnHMD = "Leap Motion on HMD";
const QString LoadScript = "Open and Run Script File...";

View file

@ -46,6 +46,12 @@ int main(int argc, const char* argv[]) {
bool instanceMightBeRunning = true;
QStringList arguments;
for (int i = 0; i < argc; ++i) {
arguments << argv[i];
}
#ifdef Q_OS_WIN
// Try to create a shared memory block - if it can't be created, there is an instance of
// interface already running. We only do this on Windows for now because of the potential
@ -64,12 +70,6 @@ int main(int argc, const char* argv[]) {
// Try to connect - if we can't connect, interface has probably just gone down
if (socket.waitForConnected(LOCAL_SERVER_TIMEOUT_MS)) {
QStringList arguments;
for (int i = 0; i < argc; ++i) {
arguments << argv[i];
}
QCommandLineParser parser;
QCommandLineOption urlOption("url", "", "value");
parser.addOption(urlOption);
@ -135,7 +135,7 @@ int main(int argc, const char* argv[]) {
// Oculus initialization MUST PRECEDE OpenGL context creation.
// The nature of the Application constructor means this has to be either here,
// or in the main window ctor, before GL startup.
Application::initPlugins();
Application::initPlugins(arguments);
int exitCode;
{

View file

@ -25,7 +25,6 @@ InputPluginList getInputPlugins() {
for (int i = 0; PLUGIN_POOL[i]; ++i) {
InputPlugin* plugin = PLUGIN_POOL[i];
if (plugin->isSupported()) {
plugin->init();
result.push_back(InputPluginPointer(plugin));
}
}

View file

@ -25,6 +25,50 @@ PluginManager* PluginManager::getInstance() {
return &_manager;
}
QString getPluginNameFromMetaData(QJsonObject object) {
static const char* METADATA_KEY = "MetaData";
static const char* NAME_KEY = "name";
if (!object.contains(METADATA_KEY) || !object[METADATA_KEY].isObject()) {
return QString();
}
auto metaDataObject = object[METADATA_KEY].toObject();
if (!metaDataObject.contains(NAME_KEY) || !metaDataObject[NAME_KEY].isString()) {
return QString();
}
return metaDataObject[NAME_KEY].toString();
}
QString getPluginIIDFromMetaData(QJsonObject object) {
static const char* IID_KEY = "IID";
if (!object.contains(IID_KEY) || !object[IID_KEY].isString()) {
return QString();
}
return object[IID_KEY].toString();
}
QStringList preferredDisplayPlugins;
QStringList disabledDisplays;
QStringList disabledInputs;
bool isDisabled(QJsonObject metaData) {
auto name = getPluginNameFromMetaData(metaData);
auto iid = getPluginIIDFromMetaData(metaData);
if (iid == DisplayProvider_iid) {
return disabledDisplays.contains(name);
} else if (iid == InputProvider_iid) {
return disabledInputs.contains(name);
}
return false;
}
using Loader = QSharedPointer<QPluginLoader>;
using LoaderList = QList<Loader>;
@ -43,11 +87,21 @@ const LoaderList& getLoadedPlugins() {
qDebug() << "Loading runtime plugins from " << pluginPath;
auto candidates = pluginDir.entryList();
for (auto plugin : candidates) {
qDebug() << "Attempting plugins " << plugin;
qDebug() << "Attempting plugin" << qPrintable(plugin);
QSharedPointer<QPluginLoader> loader(new QPluginLoader(pluginPath + plugin));
if (isDisabled(loader->metaData())) {
qWarning() << "Plugin" << qPrintable(plugin) << "is disabled";
// Skip this one, it's disabled
continue;
}
if (loader->load()) {
qDebug() << "Plugins " << plugin << " success";
qDebug() << "Plugin" << qPrintable(plugin) << "loaded successfully";
loadedPlugins.push_back(loader);
} else {
qDebug() << "Plugin" << qPrintable(plugin) << "failed to load:";
qDebug() << " " << qPrintable(loader->errorString());
}
}
}
@ -110,7 +164,9 @@ const InputPluginList& PluginManager::getInputPlugins() {
InputProvider* inputProvider = qobject_cast<InputProvider*>(loader->instance());
if (inputProvider) {
for (auto inputPlugin : inputProvider->getInputPlugins()) {
inputPlugins.push_back(inputPlugin);
if (inputPlugin->isSupported()) {
inputPlugins.push_back(inputPlugin);
}
}
}
}
@ -124,6 +180,40 @@ const InputPluginList& PluginManager::getInputPlugins() {
return inputPlugins;
}
void PluginManager::setPreferredDisplayPlugins(const QStringList& displays) {
preferredDisplayPlugins = displays;
}
DisplayPluginList PluginManager::getPreferredDisplayPlugins() {
static DisplayPluginList displayPlugins;
static std::once_flag once;
std::call_once(once, [&] {
// Grab the built in plugins
auto plugins = getDisplayPlugins();
for (auto pluginName : preferredDisplayPlugins) {
auto it = std::find_if(plugins.begin(), plugins.end(), [&](DisplayPluginPointer plugin) {
return plugin->getName() == pluginName;
});
if (it != plugins.end()) {
displayPlugins.push_back(*it);
}
}
});
return displayPlugins;
}
void PluginManager::disableDisplays(const QStringList& displays) {
disabledDisplays << displays;
}
void PluginManager::disableInputs(const QStringList& inputs) {
disabledInputs << inputs;
}
void PluginManager::saveSettings() {
saveInputPluginSettings(getInputPlugins());
}

View file

@ -13,11 +13,17 @@
class PluginManager : public QObject {
public:
static PluginManager* getInstance();
PluginManager();
static PluginManager* getInstance();
PluginManager();
const DisplayPluginList& getDisplayPlugins();
void disableDisplayPlugin(const QString& name);
const InputPluginList& getInputPlugins();
void saveSettings();
const DisplayPluginList& getDisplayPlugins();
const InputPluginList& getInputPlugins();
DisplayPluginList getPreferredDisplayPlugins();
void setPreferredDisplayPlugins(const QStringList& displays);
void disableDisplayPlugin(const QString& name);
void disableDisplays(const QStringList& displays);
void disableInputs(const QStringList& inputs);
void saveSettings();
};

View file

@ -1 +1 @@
{}
{"name":"Neuron"}

View file

@ -1 +1 @@
{}
{"name":"SDL2"}

View file

@ -1 +1 @@
{}
{"name":"Sixense"}

View file

@ -1 +1 @@
{}
{"name":"Spacemouse"}

View file

@ -1 +1 @@
{}
{"name":"Oculus Rift"}

View file

@ -31,7 +31,7 @@
using namespace oglplus;
const QString OculusLegacyDisplayPlugin::NAME("Oculus Rift (0.5) (Legacy)");
const QString OculusLegacyDisplayPlugin::NAME("Oculus Rift");
OculusLegacyDisplayPlugin::OculusLegacyDisplayPlugin() {
}

View file

@ -1 +1 @@
{}
{"name":"Oculus Rift"}

View file

@ -1 +1 @@
{}
{"name":"OpenVR (Vive)"}