diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 95de0649ad..43db834c3c 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -98,9 +98,8 @@ endif() # link required hifi libraries link_hifi_libraries(shared octree environment gpu procedural model render fbx networking model-networking entities avatars audio audio-client animation script-engine physics - render-utils entities-renderer ui auto-updater - plugins display-plugins input-plugins - controllers) + render-utils entities-renderer ui auto-updater + controllers plugins display-plugins input-plugins ) target_bullet() target_glew() diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e0e5003830..77f353a3ff 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -60,7 +60,7 @@ #include #include #include // this should probably be removed -#include +#include #include #include #include @@ -614,7 +614,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : // Setup the userInputMapper with the actions auto userInputMapper = DependencyManager::get(); - connect(userInputMapper.data(), &UserInputMapper::actionEvent, &_controllerScriptingInterface, &AbstractControllerScriptingInterface::actionEvent); + connect(userInputMapper.data(), &UserInputMapper::actionEvent, &_controllerScriptingInterface, &ControllerScriptingInterface::actionEvent); connect(userInputMapper.data(), &UserInputMapper::actionEvent, [this](int action, float state) { if (state) { switch (action) { @@ -2708,7 +2708,7 @@ void Application::update(float deltaTime) { } // Dispatch input events - _controllerScriptingInterface.updateInputControllers(); + _controllerScriptingInterface.update(); // Transfer the user inputs to the driveKeys myAvatar->clearDriveKeys(); diff --git a/interface/src/Application.h b/interface/src/Application.h index dc714ad82a..61421c34d6 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -161,7 +161,7 @@ public: ToolWindow* getToolWindow() { return _toolWindow ; } - virtual AbstractControllerScriptingInterface* getControllerScriptingInterface() { return &_controllerScriptingInterface; } + virtual controller::ScriptingInterface* getControllerScriptingInterface() { return &_controllerScriptingInterface; } virtual void registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine); QImage renderAvatarBillboard(RenderArgs* renderArgs); diff --git a/interface/src/devices/3DConnexionClient.h b/interface/src/devices/3DConnexionClient.h index cdf8e1e2a1..bddb86a857 100755 --- a/interface/src/devices/3DConnexionClient.h +++ b/interface/src/devices/3DConnexionClient.h @@ -13,7 +13,7 @@ #include #include -#include +#include #include "InterfaceLogging.h" diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 54aa72da6b..1a212fbea9 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -9,21 +9,19 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ControllerScriptingInterface.h" + #include #include #include #include -#include - #include "Application.h" #include "devices/MotionTracker.h" -#include "ControllerScriptingInterface.h" // TODO: this needs to be removed, as well as any related controller-specific information #include - ControllerScriptingInterface::ControllerScriptingInterface() : _mouseCaptured(false), _touchCaptured(false), @@ -34,7 +32,6 @@ ControllerScriptingInterface::ControllerScriptingInterface() : } ControllerScriptingInterface::~ControllerScriptingInterface() { - delete _newControllerScriptingInterface; } @@ -126,13 +123,6 @@ void ControllerScriptingInterface::registerControllerTypes(ScriptEngine* engine) qScriptRegisterMetaType(engine, inputChannelToScriptValue, inputChannelFromScriptValue); qScriptRegisterMetaType(engine, inputToScriptValue, inputFromScriptValue); qScriptRegisterMetaType(engine, inputPairToScriptValue, inputPairFromScriptValue); - - wireUpControllers(engine); - - // hack in the new controller scripting interface... - _newControllerScriptingInterface = new controller::NewControllerScriptingInterface(); - engine->registerGlobalObject("NewControllers", _newControllerScriptingInterface); - } void ControllerScriptingInterface::handleMetaEvent(HFMetaEvent* event) { @@ -192,6 +182,7 @@ const PalmData* ControllerScriptingInterface::getActivePalm(int palmIndex) const return NULL; } +/* bool ControllerScriptingInterface::isPrimaryButtonPressed() const { const PalmData* primaryPalm = getPrimaryPalm(); if (primaryPalm) { @@ -345,6 +336,7 @@ glm::vec3 ControllerScriptingInterface::getSpatialControlNormal(int controlIndex } return glm::vec3(0); // bad index } +*/ bool ControllerScriptingInterface::isKeyCaptured(QKeyEvent* event) const { return isKeyCaptured(KeyEvent(*event)); @@ -395,96 +387,49 @@ glm::vec2 ControllerScriptingInterface::getViewportDimensions() const { return qApp->getUiSize(); } -QString ControllerScriptingInterface::sanatizeName(const QString& name) { - QString cleanName { name }; - cleanName.remove(QRegularExpression{"[\\(\\)\\.\\s]"}); - return cleanName; -} - -void ControllerScriptingInterface::wireUpControllers(ScriptEngine* engine) { - - // Controller.Standard.* - auto standardDevice = DependencyManager::get()->getStandardDevice(); - if (standardDevice) { - auto deviceName = sanatizeName(standardDevice->getName()); - auto deviceInputs = standardDevice->getAvailabeInputs(); - for (const auto& inputMapping : deviceInputs) { - auto input = inputMapping.first; - auto inputName = sanatizeName(inputMapping.second); - QString deviceInputName{ "Controller." + deviceName + "." + inputName }; - engine->registerValue(deviceInputName, input.getID()); - } - } - - // Controller.Hardware.* - auto devices = DependencyManager::get()->getDevices(); - for(const auto& deviceMapping : devices) { - auto device = deviceMapping.second.get(); - auto deviceName = sanatizeName(device->getName()); - auto deviceInputs = device->getAvailabeInputs(); - for (const auto& inputMapping : deviceInputs) { - auto input = inputMapping.first; - auto inputName = sanatizeName(inputMapping.second); - QString deviceInputName { "Controller.Hardware." + deviceName + "." + inputName }; - engine->registerValue(deviceInputName, input.getID()); - } - } - - // Controller.Actions.* - auto actionNames = DependencyManager::get()->getActionNames(); - int actionNumber = 0; - for (const auto& actionName : actionNames) { - QString safeActionName { "Controller.Actions." + sanatizeName(actionName) }; - engine->registerValue(safeActionName, actionNumber); - actionNumber++; - } -} - -AbstractInputController* ControllerScriptingInterface::createInputController(const QString& deviceName, const QString& tracker) { +controller::InputController::Pointer ControllerScriptingInterface::createInputController(const QString& deviceName, const QString& tracker) { // This is where we retreive the Device Tracker category and then the sub tracker within it - //TODO C++11 auto icIt = _inputControllers.find(0); - InputControllerMap::iterator icIt = _inputControllers.find(0); - + auto icIt = _inputControllers.find(0); if (icIt != _inputControllers.end()) { return (*icIt).second; - } else { + } - // Look for device - DeviceTracker::ID deviceID = DeviceTracker::getDeviceID(deviceName.toStdString()); - if (deviceID < 0) { - deviceID = 0; - } - // TODO in this current implementation, we just pick the device assuming there is one (normally the Leapmotion) - // in the near future we need to change that to a real mapping between the devices and the deviceName - // ALso we need to expand the spec so we can fall back on the "default" controller per categories - if (deviceID >= 0) { - // TODO here again the assumption it's the LeapMotion and so it's a MOtionTracker, this would need to be changed to support different types of devices - MotionTracker* motionTracker = dynamic_cast< MotionTracker* > (DeviceTracker::getDevice(deviceID)); - if (motionTracker) { - MotionTracker::Index trackerID = motionTracker->findJointIndex(tracker.toStdString()); - if (trackerID >= 0) { - AbstractInputController* inputController = new InputController(deviceID, trackerID, this); + // Look for device + DeviceTracker::ID deviceID = DeviceTracker::getDeviceID(deviceName.toStdString()); + if (deviceID < 0) { + deviceID = 0; + } + // TODO in this current implementation, we just pick the device assuming there is one (normally the Leapmotion) + // in the near future we need to change that to a real mapping between the devices and the deviceName + // ALso we need to expand the spec so we can fall back on the "default" controller per categories - _inputControllers.insert(InputControllerMap::value_type(inputController->getKey(), inputController)); - - return inputController; - } + if (deviceID >= 0) { + // TODO here again the assumption it's the LeapMotion and so it's a MOtionTracker, this would need to be changed to support different types of devices + MotionTracker* motionTracker = dynamic_cast< MotionTracker* > (DeviceTracker::getDevice(deviceID)); + if (motionTracker) { + MotionTracker::Index trackerID = motionTracker->findJointIndex(tracker.toStdString()); + if (trackerID >= 0) { + controller::InputController::Pointer inputController = std::make_shared(deviceID, trackerID, this); + controller::InputController::Key key = inputController->getKey(); + _inputControllers.insert(InputControllerMap::value_type(inputController->getKey(), inputController)); + return inputController; } } - - return 0; } + + return controller::InputController::Pointer(); } -void ControllerScriptingInterface::releaseInputController(AbstractInputController* input) { +void ControllerScriptingInterface::releaseInputController(controller::InputController::Pointer input) { _inputControllers.erase(input->getKey()); } -void ControllerScriptingInterface::updateInputControllers() { - //TODO C++11 for (auto it = _inputControllers.begin(); it != _inputControllers.end(); it++) { - for (InputControllerMap::iterator it = _inputControllers.begin(); it != _inputControllers.end(); it++) { - (*it).second->update(); +void ControllerScriptingInterface::update() { + controller::ScriptingInterface::update(); + + for (auto entry : _inputControllers) { + entry.second->update(); } } @@ -545,7 +490,6 @@ QVector ControllerScriptingInterface::getActionNames() const { } InputController::InputController(int deviceTrackerId, int subTrackerId, QObject* parent) : - AbstractInputController(), _deviceTrackerId(deviceTrackerId), _subTrackerId(subTrackerId), _isActive(false) @@ -568,7 +512,7 @@ void InputController::update() { joint->getLocFrame().getRotation(_eventCache.locRotation); _isActive = true; - emit spatialEvent(_eventCache); + //emit spatialEvent(_eventCache); } } } @@ -580,3 +524,19 @@ const unsigned int INPUTCONTROLLER_KEY_DEVICE_MASK = 16; InputController::Key InputController::getKey() const { return (((_deviceTrackerId & INPUTCONTROLLER_KEY_DEVICE_MASK) << INPUTCONTROLLER_KEY_DEVICE_OFFSET) | _subTrackerId); } + + +void ControllerScriptingInterface::emitKeyPressEvent(QKeyEvent* event) { emit keyPressEvent(KeyEvent(*event)); } +void ControllerScriptingInterface::emitKeyReleaseEvent(QKeyEvent* event) { emit keyReleaseEvent(KeyEvent(*event)); } + +void ControllerScriptingInterface::emitMouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { emit mouseMoveEvent(MouseEvent(*event, deviceID)); } +void ControllerScriptingInterface::emitMousePressEvent(QMouseEvent* event, unsigned int deviceID) { emit mousePressEvent(MouseEvent(*event, deviceID)); } +void ControllerScriptingInterface::emitMouseDoublePressEvent(QMouseEvent* event, unsigned int deviceID) { emit mouseDoublePressEvent(MouseEvent(*event, deviceID)); } +void ControllerScriptingInterface::emitMouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { emit mouseReleaseEvent(MouseEvent(*event, deviceID)); } + +void ControllerScriptingInterface::emitTouchBeginEvent(const TouchEvent& event) { emit touchBeginEvent(event); } +void ControllerScriptingInterface::emitTouchEndEvent(const TouchEvent& event) { emit touchEndEvent(event); } +void ControllerScriptingInterface::emitTouchUpdateEvent(const TouchEvent& event) { emit touchUpdateEvent(event); } + +void ControllerScriptingInterface::emitWheelEvent(QWheelEvent* event) { emit wheelEvent(*event); } + diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h index dfe87043cd..652bd640b1 100644 --- a/interface/src/scripting/ControllerScriptingInterface.h +++ b/interface/src/scripting/ControllerScriptingInterface.h @@ -14,15 +14,20 @@ #include -#include +#include +#include + +#include +#include +#include +#include +#include +#include +class ScriptEngine; -#include class PalmData; -namespace controller { - class NewControllerScriptingInterface; -} -class InputController : public AbstractInputController { +class InputController : public controller::InputController { Q_OBJECT public: @@ -53,30 +58,53 @@ signals: /// handles scripting of input controller commands from JS -class ControllerScriptingInterface : public AbstractControllerScriptingInterface { +class ControllerScriptingInterface : public controller::ScriptingInterface { Q_OBJECT + public: ControllerScriptingInterface(); ~ControllerScriptingInterface(); + Q_INVOKABLE QVector getAllActions(); + + Q_INVOKABLE bool addInputChannel(UserInputMapper::InputChannel inputChannel); + Q_INVOKABLE bool removeInputChannel(UserInputMapper::InputChannel inputChannel); + Q_INVOKABLE QVector getInputChannelsForAction(UserInputMapper::Action action); + + Q_INVOKABLE QVector getAvailableInputs(unsigned int device); + Q_INVOKABLE QVector getAllInputsForDevice(unsigned int device); + + Q_INVOKABLE QString getDeviceName(unsigned int device); + + Q_INVOKABLE float getActionValue(int action); + + Q_INVOKABLE void resetDevice(unsigned int device); + Q_INVOKABLE void resetAllDeviceBindings(); + Q_INVOKABLE int findDevice(QString name); + Q_INVOKABLE QVector getDeviceNames(); + + Q_INVOKABLE int findAction(QString actionName); + Q_INVOKABLE QVector getActionNames() const; + + virtual void registerControllerTypes(ScriptEngine* engine); - void emitKeyPressEvent(QKeyEvent* event) { emit keyPressEvent(KeyEvent(*event)); } - void emitKeyReleaseEvent(QKeyEvent* event) { emit keyReleaseEvent(KeyEvent(*event)); } + void emitKeyPressEvent(QKeyEvent* event); + void emitKeyReleaseEvent(QKeyEvent* event); void handleMetaEvent(HFMetaEvent* event); - void emitMouseMoveEvent(QMouseEvent* event, unsigned int deviceID = 0) { emit mouseMoveEvent(MouseEvent(*event, deviceID)); } - void emitMousePressEvent(QMouseEvent* event, unsigned int deviceID = 0) { emit mousePressEvent(MouseEvent(*event, deviceID)); } - void emitMouseDoublePressEvent(QMouseEvent* event, unsigned int deviceID = 0) { emit mouseDoublePressEvent(MouseEvent(*event, deviceID)); } - void emitMouseReleaseEvent(QMouseEvent* event, unsigned int deviceID = 0) { emit mouseReleaseEvent(MouseEvent(*event, deviceID)); } + void emitMouseMoveEvent(QMouseEvent* event, unsigned int deviceID = 0); + void emitMousePressEvent(QMouseEvent* event, unsigned int deviceID = 0); + void emitMouseDoublePressEvent(QMouseEvent* event, unsigned int deviceID = 0); + void emitMouseReleaseEvent(QMouseEvent* event, unsigned int deviceID = 0); - void emitTouchBeginEvent(const TouchEvent& event) { emit touchBeginEvent(event); } - void emitTouchEndEvent(const TouchEvent& event) { emit touchEndEvent(event); } - void emitTouchUpdateEvent(const TouchEvent& event) { emit touchUpdateEvent(event); } + void emitTouchBeginEvent(const TouchEvent& event); + void emitTouchEndEvent(const TouchEvent& event); + void emitTouchUpdateEvent(const TouchEvent& event); - void emitWheelEvent(QWheelEvent* event) { emit wheelEvent(*event); } + void emitWheelEvent(QWheelEvent* event); bool isKeyCaptured(QKeyEvent* event) const; bool isKeyCaptured(const KeyEvent& event) const; @@ -86,48 +114,10 @@ public: bool areActionsCaptured() const { return _actionsCaptured; } bool isJoystickCaptured(int joystickIndex) const; - void updateInputControllers(); + virtual void update() override; public slots: - Q_INVOKABLE virtual QVector getAllActions(); - - Q_INVOKABLE virtual bool addInputChannel(UserInputMapper::InputChannel inputChannel); - Q_INVOKABLE virtual bool removeInputChannel(UserInputMapper::InputChannel inputChannel); - Q_INVOKABLE virtual QVector getInputChannelsForAction(UserInputMapper::Action action); - - Q_INVOKABLE virtual QVector getAvailableInputs(unsigned int device); - Q_INVOKABLE virtual QVector getAllInputsForDevice(unsigned int device); - - Q_INVOKABLE virtual QString getDeviceName(unsigned int device); - - Q_INVOKABLE virtual float getActionValue(int action); - Q_INVOKABLE virtual void resetDevice(unsigned int device); - Q_INVOKABLE virtual void resetAllDeviceBindings(); - Q_INVOKABLE virtual int findDevice(QString name); - Q_INVOKABLE virtual QVector getDeviceNames(); - - Q_INVOKABLE virtual int findAction(QString actionName); - Q_INVOKABLE virtual QVector getActionNames() const; - - virtual bool isPrimaryButtonPressed() const; - virtual glm::vec2 getPrimaryJoystickPosition() const; - - virtual int getNumberOfButtons() const; - virtual bool isButtonPressed(int buttonIndex) const; - - virtual int getNumberOfTriggers() const; - virtual float getTriggerValue(int triggerIndex) const; - - virtual int getNumberOfJoysticks() const; - virtual glm::vec2 getJoystickPosition(int joystickIndex) const; - - virtual int getNumberOfSpatialControls() const; - virtual glm::vec3 getSpatialControlPosition(int controlIndex) const; - virtual glm::vec3 getSpatialControlVelocity(int controlIndex) const; - virtual glm::vec3 getSpatialControlNormal(int controlIndex) const; - virtual glm::quat getSpatialControlRawRotation(int controlIndex) const; - virtual glm::vec3 getSpatialControlRawAngularVelocity(int controlIndex) const; virtual void captureKeyEvents(const KeyEvent& event); virtual void releaseKeyEvents(const KeyEvent& event); @@ -149,9 +139,31 @@ public slots: virtual glm::vec2 getViewportDimensions() const; /// Factory to create an InputController - virtual AbstractInputController* createInputController(const QString& deviceName, const QString& tracker); + virtual controller::InputController::Pointer createInputController(const QString& deviceName, const QString& tracker); + virtual void releaseInputController(controller::InputController::Pointer input); - virtual void releaseInputController(AbstractInputController* input); +signals: + void keyPressEvent(const KeyEvent& event); + void keyReleaseEvent(const KeyEvent& event); + + void actionStartEvent(const HFActionEvent& event); + void actionEndEvent(const HFActionEvent& event); + + void backStartEvent(); + void backEndEvent(); + + void mouseMoveEvent(const MouseEvent& event, unsigned int deviceID = 0); + void mousePressEvent(const MouseEvent& event, unsigned int deviceID = 0); + void mouseDoublePressEvent(const MouseEvent& event, unsigned int deviceID = 0); + void mouseReleaseEvent(const MouseEvent& event, unsigned int deviceID = 0); + + void touchBeginEvent(const TouchEvent& event); + void touchEndEvent(const TouchEvent& event); + void touchUpdateEvent(const TouchEvent& event); + + void wheelEvent(const WheelEvent& event); + + void actionEvent(int action, float state); private: QString sanatizeName(const QString& name); /// makes a name clean for inclusing in JavaScript @@ -168,12 +180,9 @@ private: QMultiMap _capturedKeys; QSet _capturedJoysticks; - typedef std::map< AbstractInputController::Key, AbstractInputController* > InputControllerMap; + using InputKey = controller::InputController::Key; + using InputControllerMap = std::map; InputControllerMap _inputControllers; - - void wireUpControllers(ScriptEngine* engine); - - controller::NewControllerScriptingInterface* _newControllerScriptingInterface = nullptr; }; const int NUMBER_OF_SPATIALCONTROLS_PER_PALM = 2; // the hand and the tip diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 4e5dd0da0c..4fc2f3ddb4 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -27,7 +27,7 @@ #include "Application.h" #include // TODO: any references to sixense should be removed here -#include +#include // Used to animate the magnification windows diff --git a/libraries/controllers/CMakeLists.txt b/libraries/controllers/CMakeLists.txt index fbabbe1463..5beffce461 100644 --- a/libraries/controllers/CMakeLists.txt +++ b/libraries/controllers/CMakeLists.txt @@ -4,7 +4,7 @@ set(TARGET_NAME controllers) setup_hifi_library(Script) # use setup_hifi_library macro to setup our project and link appropriate Qt modules -link_hifi_libraries(shared plugins input-plugins) +link_hifi_libraries(shared) GroupSources("src/controllers") diff --git a/libraries/controllers/src/controllers/Endpoint.h b/libraries/controllers/src/controllers/Endpoint.h index bea33517f5..5c6e6c028b 100644 --- a/libraries/controllers/src/controllers/Endpoint.h +++ b/libraries/controllers/src/controllers/Endpoint.h @@ -14,7 +14,7 @@ #include #include -#include +#include "UserInputMapper.h" class QScriptValue; diff --git a/libraries/input-plugins/src/input-plugins/InputDevice.cpp b/libraries/controllers/src/controllers/InputDevice.cpp similarity index 100% rename from libraries/input-plugins/src/input-plugins/InputDevice.cpp rename to libraries/controllers/src/controllers/InputDevice.cpp diff --git a/libraries/input-plugins/src/input-plugins/InputDevice.h b/libraries/controllers/src/controllers/InputDevice.h similarity index 100% rename from libraries/input-plugins/src/input-plugins/InputDevice.h rename to libraries/controllers/src/controllers/InputDevice.h diff --git a/libraries/controllers/src/controllers/NewControllerScriptingInterface.h b/libraries/controllers/src/controllers/NewControllerScriptingInterface.h deleted file mode 100644 index 659c8bfd05..0000000000 --- a/libraries/controllers/src/controllers/NewControllerScriptingInterface.h +++ /dev/null @@ -1,89 +0,0 @@ -// -// Created by Bradley Austin Davis 2015/10/09 -// Copyright 2015 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 -// - -#pragma once -#ifndef hifi_Controllers_NewControllerScriptingInterface_h -#define hifi_Controllers_NewControllerScriptingInterface_h - -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include - -#include "Mapping.h" - -class QScriptValue; - -namespace controller { - class NewControllerScriptingInterface : public QObject { - Q_OBJECT - Q_PROPERTY(QVariantMap Hardware READ getHardware CONSTANT FINAL) - Q_PROPERTY(QVariantMap Actions READ getActions CONSTANT FINAL) - Q_PROPERTY(QVariantMap Standard READ getStandard CONSTANT FINAL) - - public: - NewControllerScriptingInterface(); - Q_INVOKABLE float getValue(const int& source); - - Q_INVOKABLE void update(); - Q_INVOKABLE QObject* newMapping(const QString& mappingName = QUuid::createUuid().toString()); - Q_INVOKABLE void enableMapping(const QString& mappingName, bool enable = true); - Q_INVOKABLE void disableMapping(const QString& mappingName) { - enableMapping(mappingName, false); - } - - - const QVariantMap& getHardware() { return _hardware; } - const QVariantMap& getActions() { return _actions; } - const QVariantMap& getStandard() { return _standard; } - - private: - - // FIXME move to unordered set / map - using MappingMap = std::map; - using MappingStack = std::list; - using InputToEndpointMap = std::map; - using EndpointSet = std::unordered_set; - using ValueMap = std::map; - using EndpointPair = std::pair; - using EndpointPairMap = std::map; - - void update(Mapping::Pointer& mapping, EndpointSet& consumed); - float getValue(const Endpoint::Pointer& endpoint); - Endpoint::Pointer endpointFor(const QJSValue& endpoint); - Endpoint::Pointer endpointFor(const QScriptValue& endpoint); - Endpoint::Pointer endpointFor(const UserInputMapper::Input& endpoint); - Endpoint::Pointer compositeEndpointFor(Endpoint::Pointer first, Endpoint::Pointer second); - - friend class MappingBuilderProxy; - friend class RouteBuilderProxy; - private: - uint16_t _nextFunctionId; - InputToEndpointMap _endpoints; - EndpointPairMap _compositeEndpoints; - - ValueMap _overrideValues; - MappingMap _mappingsByName; - MappingStack _activeMappings; - - QVariantMap _hardware; - QVariantMap _actions; - QVariantMap _standard; - }; -} - - -#endif diff --git a/libraries/controllers/src/controllers/NewControllerScriptingInterface.cpp b/libraries/controllers/src/controllers/ScriptingInterface.cpp similarity index 77% rename from libraries/controllers/src/controllers/NewControllerScriptingInterface.cpp rename to libraries/controllers/src/controllers/ScriptingInterface.cpp index 4bc5b9eeb5..9d2cdfd2de 100644 --- a/libraries/controllers/src/controllers/NewControllerScriptingInterface.cpp +++ b/libraries/controllers/src/controllers/ScriptingInterface.cpp @@ -5,7 +5,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "NewControllerScriptingInterface.h" +#include "ScriptingInterface.h" #include #include @@ -14,19 +14,15 @@ #include #include -#include -#include -#include -#include #include "impl/MappingBuilderProxy.h" #include "Logging.h" +#include "InputDevice.h" static const uint16_t ACTIONS_DEVICE = UserInputMapper::Input::INVALID_DEVICE - (uint16_t)1; namespace controller { - class VirtualEndpoint : public Endpoint { public: VirtualEndpoint(const UserInputMapper::Input& id = UserInputMapper::Input(-1)) @@ -97,18 +93,15 @@ namespace controller { Endpoint::Pointer _second; }; - QString sanatizeName(const QString& name) { - QString cleanName{ name }; - cleanName.remove(QRegularExpression{ "[\\(\\)\\.\\s]" }); - return cleanName; - } + + QRegularExpression ScriptingInterface::SANITIZE_NAME_EXPRESSION{ "[\\(\\)\\.\\s]" }; QVariantMap createDeviceMap(const UserInputMapper::DeviceProxy* device) { auto userInputMapper = DependencyManager::get(); QVariantMap deviceMap; for (const auto& inputMapping : device->getAvailabeInputs()) { const auto& input = inputMapping.first; - const auto inputName = sanatizeName(inputMapping.second); + const auto inputName = QString(inputMapping.second).remove(ScriptingInterface::SANITIZE_NAME_EXPRESSION); qCDebug(controllers) << "\tInput " << input.getChannel() << (int)input.getType() << QString::number(input.getID(), 16) << ": " << inputName; deviceMap.insert(inputName, input.getID()); @@ -116,12 +109,12 @@ namespace controller { return deviceMap; } - NewControllerScriptingInterface::NewControllerScriptingInterface() { + ScriptingInterface::ScriptingInterface() { auto userInputMapper = DependencyManager::get(); auto devices = userInputMapper->getDevices(); for (const auto& deviceMapping : devices) { auto device = deviceMapping.second.get(); - auto deviceName = sanatizeName(device->getName()); + auto deviceName = QString(device->getName()).remove(ScriptingInterface::SANITIZE_NAME_EXPRESSION); qCDebug(controllers) << "Device" << deviceMapping.first << ":" << deviceName; // Expose the IDs to JS _hardware.insert(deviceName, createDeviceMap(device)); @@ -164,7 +157,8 @@ namespace controller { UserInputMapper::Input actionInput(ACTIONS_DEVICE, actionNumber++, UserInputMapper::ChannelType::AXIS); qCDebug(controllers) << "\tAction: " << actionName << " " << QString::number(actionInput.getID(), 16); // Expose the IDs to JS - _actions.insert(sanatizeName(actionName), actionInput.getID()); + QString cleanActionName = QString(actionName).remove(ScriptingInterface::SANITIZE_NAME_EXPRESSION); + _actions.insert(cleanActionName, actionInput.getID()); // Create the endpoints // FIXME action endpoints need to accumulate values, and have them cleared at each frame @@ -172,7 +166,7 @@ namespace controller { } } - QObject* NewControllerScriptingInterface::newMapping(const QString& mappingName) { + QObject* ScriptingInterface::newMapping(const QString& mappingName) { if (_mappingsByName.count(mappingName)) { qCWarning(controllers) << "Refusing to recreate mapping named " << mappingName; } @@ -182,7 +176,7 @@ namespace controller { return new MappingBuilderProxy(*this, mapping); } - void NewControllerScriptingInterface::enableMapping(const QString& mappingName, bool enable) { + void ScriptingInterface::enableMapping(const QString& mappingName, bool enable) { auto iterator = _mappingsByName.find(mappingName); if (_mappingsByName.end() == iterator) { qCWarning(controllers) << "Request to enable / disable unknown mapping " << mappingName; @@ -202,7 +196,7 @@ namespace controller { } } - float NewControllerScriptingInterface::getValue(const int& source) { + float ScriptingInterface::getValue(const int& source) const { // return (sin(secTimestampNow()) + 1.0f) / 2.0f; UserInputMapper::Input input(source); auto iterator = _endpoints.find(input); @@ -214,7 +208,7 @@ namespace controller { return getValue(endpoint); } - float NewControllerScriptingInterface::getValue(const Endpoint::Pointer& endpoint) { + float ScriptingInterface::getValue(const Endpoint::Pointer& endpoint) const { auto valuesIterator = _overrideValues.find(endpoint); if (_overrideValues.end() != valuesIterator) { return valuesIterator->second; @@ -223,19 +217,20 @@ namespace controller { return endpoint->value(); } - - void NewControllerScriptingInterface::update() { - static float last = secTimestampNow(); - float now = secTimestampNow(); - float delta = now - last; - last = now; + float ScriptingInterface::getButtonValue(StandardButtonChannel source, uint16_t device) const { + return getValue(UserInputMapper::Input(device, source, UserInputMapper::ChannelType::BUTTON).getID()); + } - foreach(auto inputPlugin, PluginManager::getInstance()->getInputPlugins()) { - inputPlugin->pluginUpdate(delta, false); - } + float ScriptingInterface::getAxisValue(StandardAxisChannel source, uint16_t device) const { + return getValue(UserInputMapper::Input(device, source, UserInputMapper::ChannelType::AXIS).getID()); + } + glm::mat4 ScriptingInterface::getPoseValue(StandardPoseChannel source, uint16_t device) const { + return glm::mat4(); + } + + void ScriptingInterface::update() { auto userInputMapper = DependencyManager::get(); - userInputMapper->update(delta); _overrideValues.clear(); EndpointSet readEndpoints; @@ -295,9 +290,7 @@ namespace controller { } } - - - Endpoint::Pointer NewControllerScriptingInterface::endpointFor(const QJSValue& endpoint) { + Endpoint::Pointer ScriptingInterface::endpointFor(const QJSValue& endpoint) { if (endpoint.isNumber()) { return endpointFor(UserInputMapper::Input(endpoint.toInt())); } @@ -311,7 +304,7 @@ namespace controller { return Endpoint::Pointer(); } - Endpoint::Pointer NewControllerScriptingInterface::endpointFor(const QScriptValue& endpoint) { + Endpoint::Pointer ScriptingInterface::endpointFor(const QScriptValue& endpoint) { if (endpoint.isNumber()) { return endpointFor(UserInputMapper::Input(endpoint.toInt32())); } @@ -325,7 +318,7 @@ namespace controller { return Endpoint::Pointer(); } - Endpoint::Pointer NewControllerScriptingInterface::endpointFor(const UserInputMapper::Input& inputId) { + Endpoint::Pointer ScriptingInterface::endpointFor(const UserInputMapper::Input& inputId) { auto iterator = _endpoints.find(inputId); if (_endpoints.end() == iterator) { qWarning() << "Unknown input: " << QString::number(inputId.getID(), 16); @@ -334,7 +327,7 @@ namespace controller { return iterator->second; } - Endpoint::Pointer NewControllerScriptingInterface::compositeEndpointFor(Endpoint::Pointer first, Endpoint::Pointer second) { + Endpoint::Pointer ScriptingInterface::compositeEndpointFor(Endpoint::Pointer first, Endpoint::Pointer second) { EndpointPair pair(first, second); Endpoint::Pointer result; auto iterator = _compositeEndpoints.find(pair); @@ -347,6 +340,66 @@ namespace controller { return result; } + bool ScriptingInterface::isPrimaryButtonPressed() const { + return isButtonPressed(StandardButtonChannel::A); + } + + glm::vec2 ScriptingInterface::getPrimaryJoystickPosition() const { + return getJoystickPosition(0); + } + + int ScriptingInterface::getNumberOfButtons() const { + return StandardButtonChannel::NUM_STANDARD_BUTTONS; + } + + bool ScriptingInterface::isButtonPressed(int buttonIndex) const { + return getButtonValue((StandardButtonChannel)buttonIndex) == 0.0 ? false : true; + } + + int ScriptingInterface::getNumberOfTriggers() const { + return 2; + } + + float ScriptingInterface::getTriggerValue(int triggerIndex) const { + return getAxisValue(triggerIndex == 0 ? StandardAxisChannel::LT : StandardAxisChannel::RT); + } + + int ScriptingInterface::getNumberOfJoysticks() const { + return 2; + } + + glm::vec2 ScriptingInterface::getJoystickPosition(int joystickIndex) const { + StandardAxisChannel xid = StandardAxisChannel::LX; + StandardAxisChannel yid = StandardAxisChannel::LY; + if (joystickIndex != 0) { + xid = StandardAxisChannel::RX; + yid = StandardAxisChannel::RY; + } + vec2 result; + result.x = getAxisValue(xid); + result.y = getAxisValue(yid); + return result; + } + + int ScriptingInterface::getNumberOfSpatialControls() const { + return 2; + } + + glm::vec3 ScriptingInterface::getSpatialControlPosition(int controlIndex) const { + return vec3(); + } + + glm::vec3 ScriptingInterface::getSpatialControlVelocity(int controlIndex) const { + return vec3(); + } + + glm::vec3 ScriptingInterface::getSpatialControlNormal(int controlIndex) const { + return vec3(); + } + + glm::quat ScriptingInterface::getSpatialControlRawRotation(int controlIndex) const { + return quat(); + } } // namespace controllers //var mapping = Controller.newMapping(); diff --git a/libraries/controllers/src/controllers/ScriptingInterface.h b/libraries/controllers/src/controllers/ScriptingInterface.h new file mode 100644 index 0000000000..043e06a67f --- /dev/null +++ b/libraries/controllers/src/controllers/ScriptingInterface.h @@ -0,0 +1,138 @@ +// +// AbstractControllerScriptingInterface.h +// libraries/script-engine/src +// +// Created by Brad Hefta-Gaub on 12/17/13. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#pragma once +#ifndef hifi_AbstractControllerScriptingInterface_h +#define hifi_AbstractControllerScriptingInterface_h + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include "UserInputMapper.h" +#include "StandardControls.h" +#include "Mapping.h" + +namespace controller { + class InputController : public QObject { + Q_OBJECT + + public: + using Key = unsigned int; + using Pointer = std::shared_ptr; + + virtual void update() = 0; + virtual Key getKey() const = 0; + + public slots: + virtual bool isActive() const = 0; + virtual glm::vec3 getAbsTranslation() const = 0; + virtual glm::quat getAbsRotation() const = 0; + virtual glm::vec3 getLocTranslation() const = 0; + virtual glm::quat getLocRotation() const = 0; + + signals: + //void spatialEvent(const SpatialEvent& event); + }; + + /// handles scripting of input controller commands from JS + class ScriptingInterface : public QObject { + Q_OBJECT + Q_PROPERTY(QVariantMap Hardware READ getHardware CONSTANT FINAL) + Q_PROPERTY(QVariantMap Actions READ getActions CONSTANT FINAL) + Q_PROPERTY(QVariantMap Standard READ getStandard CONSTANT FINAL) + + public: + ScriptingInterface(); + + Q_INVOKABLE float getValue(const int& source) const; + Q_INVOKABLE float getButtonValue(StandardButtonChannel source, uint16_t device = 0) const; + Q_INVOKABLE float getAxisValue(StandardAxisChannel source, uint16_t device = 0) const; + Q_INVOKABLE glm::mat4 getPoseValue(StandardPoseChannel source, uint16_t device = 0) const; + Q_INVOKABLE QObject* newMapping(const QString& mappingName = QUuid::createUuid().toString()); + Q_INVOKABLE void enableMapping(const QString& mappingName, bool enable = true); + Q_INVOKABLE void disableMapping(const QString& mappingName) { + enableMapping(mappingName, false); + } + + Q_INVOKABLE bool isPrimaryButtonPressed() const; + Q_INVOKABLE glm::vec2 getPrimaryJoystickPosition() const; + + Q_INVOKABLE int getNumberOfButtons() const; + Q_INVOKABLE bool isButtonPressed(int buttonIndex) const; + + Q_INVOKABLE int getNumberOfTriggers() const; + Q_INVOKABLE float getTriggerValue(int triggerIndex) const; + + Q_INVOKABLE int getNumberOfJoysticks() const; + Q_INVOKABLE glm::vec2 getJoystickPosition(int joystickIndex) const; + + Q_INVOKABLE int getNumberOfSpatialControls() const; + Q_INVOKABLE glm::vec3 getSpatialControlPosition(int controlIndex) const; + Q_INVOKABLE glm::vec3 getSpatialControlVelocity(int controlIndex) const; + Q_INVOKABLE glm::vec3 getSpatialControlNormal(int controlIndex) const; + Q_INVOKABLE glm::quat getSpatialControlRawRotation(int controlIndex) const; + + Q_INVOKABLE const QVariantMap& getHardware() { return _hardware; } + Q_INVOKABLE const QVariantMap& getActions() { return _actions; } + Q_INVOKABLE const QVariantMap& getStandard() { return _standard; } + + static QRegularExpression SANITIZE_NAME_EXPRESSION; + + public slots: + virtual void update(); + //virtual void registerControllerTypes(ScriptEngine* engine) = 0; + + private: + friend class MappingBuilderProxy; + friend class RouteBuilderProxy; + + // FIXME move to unordered set / map + using MappingMap = std::map; + using MappingStack = std::list; + using InputToEndpointMap = std::map; + using EndpointSet = std::unordered_set; + using ValueMap = std::map; + using EndpointPair = std::pair; + using EndpointPairMap = std::map; + + void update(Mapping::Pointer& mapping, EndpointSet& consumed); + float getValue(const Endpoint::Pointer& endpoint) const; + Endpoint::Pointer endpointFor(const QJSValue& endpoint); + Endpoint::Pointer endpointFor(const QScriptValue& endpoint); + Endpoint::Pointer endpointFor(const UserInputMapper::Input& endpoint); + Endpoint::Pointer compositeEndpointFor(Endpoint::Pointer first, Endpoint::Pointer second); + + QVariantMap _hardware; + QVariantMap _actions; + QVariantMap _standard; + + InputToEndpointMap _endpoints; + EndpointPairMap _compositeEndpoints; + + ValueMap _overrideValues; + MappingMap _mappingsByName; + MappingStack _activeMappings; + }; +} + + +#endif // hifi_AbstractControllerScriptingInterface_h diff --git a/libraries/input-plugins/src/input-plugins/StandardController.cpp b/libraries/controllers/src/controllers/StandardController.cpp similarity index 98% rename from libraries/input-plugins/src/input-plugins/StandardController.cpp rename to libraries/controllers/src/controllers/StandardController.cpp index 5460e22c96..9c423eded2 100644 --- a/libraries/input-plugins/src/input-plugins/StandardController.cpp +++ b/libraries/controllers/src/controllers/StandardController.cpp @@ -1,121 +1,121 @@ -// -// StandardController.cpp -// input-plugins/src/input-plugins -// -// Created by Brad Hefta-Gaub on 2015-10-11. -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - -#include - -#include "StandardController.h" - -const float CONTROLLER_THRESHOLD = 0.3f; - -StandardController::~StandardController() { -} - -void StandardController::update(float deltaTime, bool jointsCaptured) { -} - -void StandardController::focusOutEvent() { - _axisStateMap.clear(); - _buttonPressedMap.clear(); -}; - -void StandardController::registerToUserInputMapper(UserInputMapper& mapper) { - // Grab the current free device ID - _deviceID = mapper.getStandardDeviceID(); - - auto proxy = std::make_shared(_name); - proxy->getButton = [this] (const UserInputMapper::Input& input, int timestamp) -> bool { return this->getButton(input.getChannel()); }; - proxy->getAxis = [this] (const UserInputMapper::Input& input, int timestamp) -> float { return this->getAxis(input.getChannel()); }; - proxy->getAvailabeInputs = [this] () -> QVector { - QVector availableInputs; - // Buttons - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::A), "A")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::B), "B")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::X), "X")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::Y), "Y")); - - // DPad - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DU), "DU")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DD), "DD")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DL), "DL")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DR), "DR")); - - // Bumpers - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LB), "LB")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RB), "RB")); - - // Stick press - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LS), "LS")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RS), "RS")); - - // Center buttons - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::START), "Start")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::BACK), "Back")); - - // Analog sticks - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LY), "LY")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LX), "LX")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RY), "RY")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RX), "RX")); - - // Triggers - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LT), "LT")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RT), "RT")); - - // Poses - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LEFT), "LeftPose")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RIGHT), "RightPose")); - - // Aliases, PlayStation style names - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LB), "L1")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RB), "R1")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LT), "L2")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RT), "R2")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LS), "L3")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RS), "R3")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::BACK), "Select")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::A), "Cross")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::B), "Circle")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::X), "Square")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::Y), "Triangle")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DU), "Up")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DD), "Down")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DL), "Left")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DR), "Right")); - - - return availableInputs; - }; - - proxy->resetDeviceBindings = [this, &mapper] () -> bool { - mapper.removeAllInputChannelsForDevice(_deviceID); - this->assignDefaultInputMapping(mapper); - return true; - }; - - mapper.registerStandardDevice(proxy); -} - -void StandardController::assignDefaultInputMapping(UserInputMapper& mapper) { -} - -UserInputMapper::Input StandardController::makeInput(controller::StandardButtonChannel button) { - return UserInputMapper::Input(_deviceID, button, UserInputMapper::ChannelType::BUTTON); -} - -UserInputMapper::Input StandardController::makeInput(controller::StandardAxisChannel axis) { - return UserInputMapper::Input(_deviceID, axis, UserInputMapper::ChannelType::AXIS); -} - -UserInputMapper::Input StandardController::makeInput(controller::StandardPoseChannel pose) { - return UserInputMapper::Input(_deviceID, pose, UserInputMapper::ChannelType::POSE); -} +// +// StandardController.cpp +// input-plugins/src/input-plugins +// +// Created by Brad Hefta-Gaub on 2015-10-11. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include + +#include "StandardController.h" + +const float CONTROLLER_THRESHOLD = 0.3f; + +StandardController::~StandardController() { +} + +void StandardController::update(float deltaTime, bool jointsCaptured) { +} + +void StandardController::focusOutEvent() { + _axisStateMap.clear(); + _buttonPressedMap.clear(); +}; + +void StandardController::registerToUserInputMapper(UserInputMapper& mapper) { + // Grab the current free device ID + _deviceID = mapper.getStandardDeviceID(); + + auto proxy = std::make_shared(_name); + proxy->getButton = [this] (const UserInputMapper::Input& input, int timestamp) -> bool { return this->getButton(input.getChannel()); }; + proxy->getAxis = [this] (const UserInputMapper::Input& input, int timestamp) -> float { return this->getAxis(input.getChannel()); }; + proxy->getAvailabeInputs = [this] () -> QVector { + QVector availableInputs; + // Buttons + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::A), "A")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::B), "B")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::X), "X")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::Y), "Y")); + + // DPad + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DU), "DU")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DD), "DD")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DL), "DL")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DR), "DR")); + + // Bumpers + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LB), "LB")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RB), "RB")); + + // Stick press + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LS), "LS")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RS), "RS")); + + // Center buttons + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::START), "Start")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::BACK), "Back")); + + // Analog sticks + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LY), "LY")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LX), "LX")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RY), "RY")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RX), "RX")); + + // Triggers + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LT), "LT")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RT), "RT")); + + // Poses + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LEFT), "LeftPose")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RIGHT), "RightPose")); + + // Aliases, PlayStation style names + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LB), "L1")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RB), "R1")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LT), "L2")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RT), "R2")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LS), "L3")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RS), "R3")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::BACK), "Select")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::A), "Cross")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::B), "Circle")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::X), "Square")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::Y), "Triangle")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DU), "Up")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DD), "Down")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DL), "Left")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DR), "Right")); + + + return availableInputs; + }; + + proxy->resetDeviceBindings = [this, &mapper] () -> bool { + mapper.removeAllInputChannelsForDevice(_deviceID); + this->assignDefaultInputMapping(mapper); + return true; + }; + + mapper.registerStandardDevice(proxy); +} + +void StandardController::assignDefaultInputMapping(UserInputMapper& mapper) { +} + +UserInputMapper::Input StandardController::makeInput(controller::StandardButtonChannel button) { + return UserInputMapper::Input(_deviceID, button, UserInputMapper::ChannelType::BUTTON); +} + +UserInputMapper::Input StandardController::makeInput(controller::StandardAxisChannel axis) { + return UserInputMapper::Input(_deviceID, axis, UserInputMapper::ChannelType::AXIS); +} + +UserInputMapper::Input StandardController::makeInput(controller::StandardPoseChannel pose) { + return UserInputMapper::Input(_deviceID, pose, UserInputMapper::ChannelType::POSE); +} diff --git a/libraries/input-plugins/src/input-plugins/StandardController.h b/libraries/controllers/src/controllers/StandardController.h similarity index 96% rename from libraries/input-plugins/src/input-plugins/StandardController.h rename to libraries/controllers/src/controllers/StandardController.h index ad1329d5ed..c393af80f4 100644 --- a/libraries/input-plugins/src/input-plugins/StandardController.h +++ b/libraries/controllers/src/controllers/StandardController.h @@ -1,48 +1,48 @@ -// -// StandardController.h -// input-plugins/src/input-plugins -// -// Created by Brad Hefta-Gaub on 2015-10-11. -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_StandardController_h -#define hifi_StandardController_h - -#include -#include - -#include "InputDevice.h" - -#include "StandardControls.h" - -typedef std::shared_ptr StandardControllerPointer; - -class StandardController : public QObject, public InputDevice { - Q_OBJECT - Q_PROPERTY(QString name READ getName) - -public: - - const QString& getName() const { return _name; } - - // Device functions - virtual void registerToUserInputMapper(UserInputMapper& mapper) override; - virtual void assignDefaultInputMapping(UserInputMapper& mapper) override; - virtual void update(float deltaTime, bool jointsCaptured) override; - virtual void focusOutEvent() override; - - StandardController() : InputDevice("Standard") {} - ~StandardController(); - - UserInputMapper::Input makeInput(controller::StandardButtonChannel button); - UserInputMapper::Input makeInput(controller::StandardAxisChannel axis); - UserInputMapper::Input makeInput(controller::StandardPoseChannel pose); - -private: -}; - -#endif // hifi_StandardController_h +// +// StandardController.h +// input-plugins/src/input-plugins +// +// Created by Brad Hefta-Gaub on 2015-10-11. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_StandardController_h +#define hifi_StandardController_h + +#include +#include + +#include "InputDevice.h" + +#include "StandardControls.h" + +typedef std::shared_ptr StandardControllerPointer; + +class StandardController : public QObject, public InputDevice { + Q_OBJECT + Q_PROPERTY(QString name READ getName) + +public: + + const QString& getName() const { return _name; } + + // Device functions + virtual void registerToUserInputMapper(UserInputMapper& mapper) override; + virtual void assignDefaultInputMapping(UserInputMapper& mapper) override; + virtual void update(float deltaTime, bool jointsCaptured) override; + virtual void focusOutEvent() override; + + StandardController() : InputDevice("Standard") {} + ~StandardController(); + + UserInputMapper::Input makeInput(controller::StandardButtonChannel button); + UserInputMapper::Input makeInput(controller::StandardAxisChannel axis); + UserInputMapper::Input makeInput(controller::StandardPoseChannel pose); + +private: +}; + +#endif // hifi_StandardController_h diff --git a/libraries/input-plugins/src/input-plugins/StandardControls.h b/libraries/controllers/src/controllers/StandardControls.h similarity index 95% rename from libraries/input-plugins/src/input-plugins/StandardControls.h rename to libraries/controllers/src/controllers/StandardControls.h index e5943ff780..505b4f85c7 100644 --- a/libraries/input-plugins/src/input-plugins/StandardControls.h +++ b/libraries/controllers/src/controllers/StandardControls.h @@ -1,59 +1,59 @@ -// -// Created by Bradley Austin Davis 2015/10/09 -// Copyright 2015 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 -// -#pragma once - -namespace controller { - - // Needs to match order and values of SDL_GameControllerButton - enum StandardButtonChannel { - // Button quad - A = 0, - B, - X, - Y, - // Center buttons - BACK, - GUIDE, - START, - // Stick press - LS, - RS, - // Bumper press - LB, - RB, - // DPad - DU, - DD, - DL, - DR, - NUM_STANDARD_BUTTONS - }; - - // Needs to match order and values of SDL_GameControllerAxis - enum StandardAxisChannel { - // Left Analog stick - LX = 0, - LY, - // Right Analog stick - RX, - RY, - // Triggers - LT, - RT, - NUM_STANDARD_AXES - }; - - // No correlation to SDL - enum StandardPoseChannel { - LEFT = 0, - RIGHT, - HEAD, - NUM_STANDARD_POSES - }; - -} +// +// Created by Bradley Austin Davis 2015/10/09 +// Copyright 2015 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 +// +#pragma once + +namespace controller { + + // Needs to match order and values of SDL_GameControllerButton + enum StandardButtonChannel { + // Button quad + A = 0, + B, + X, + Y, + // Center buttons + BACK, + GUIDE, + START, + // Stick press + LS, + RS, + // Bumper press + LB, + RB, + // DPad + DU, + DD, + DL, + DR, + NUM_STANDARD_BUTTONS + }; + + // Needs to match order and values of SDL_GameControllerAxis + enum StandardAxisChannel { + // Left Analog stick + LX = 0, + LY, + // Right Analog stick + RX, + RY, + // Triggers + LT, + RT, + NUM_STANDARD_AXES + }; + + // No correlation to SDL + enum StandardPoseChannel { + LEFT = 0, + RIGHT, + HEAD, + NUM_STANDARD_POSES + }; + +} diff --git a/libraries/input-plugins/src/input-plugins/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp old mode 100755 new mode 100644 similarity index 93% rename from libraries/input-plugins/src/input-plugins/UserInputMapper.cpp rename to libraries/controllers/src/controllers/UserInputMapper.cpp index c29acc09af..8fc44ebf5b --- a/libraries/input-plugins/src/input-plugins/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -1,368 +1,368 @@ -// -// UserInputMapper.cpp -// input-plugins/src/input-plugins -// -// Created by Sam Gateau on 4/27/15. -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "UserInputMapper.h" -#include "StandardController.h" - -const UserInputMapper::Input UserInputMapper::Input::INVALID_INPUT = UserInputMapper::Input(UINT16_MAX); -const uint16_t UserInputMapper::Input::INVALID_DEVICE = INVALID_INPUT.getDevice(); -const uint16_t UserInputMapper::Input::INVALID_CHANNEL = INVALID_INPUT.getChannel(); -const uint16_t UserInputMapper::Input::INVALID_TYPE = (uint16_t)INVALID_INPUT.getType(); - -// Default contruct allocate the poutput size with the current hardcoded action channels -UserInputMapper::UserInputMapper() { - registerStandardDevice(); - assignDefaulActionScales(); - createActionNames(); -} - -UserInputMapper::~UserInputMapper() { -} - - -bool UserInputMapper::registerDevice(uint16 deviceID, const DeviceProxy::Pointer& proxy){ - proxy->_name += " (" + QString::number(deviceID) + ")"; - _registeredDevices[deviceID] = proxy; - return true; -} - -UserInputMapper::DeviceProxy::Pointer UserInputMapper::getDeviceProxy(const Input& input) { - auto device = _registeredDevices.find(input.getDevice()); - if (device != _registeredDevices.end()) { - return (device->second); - } else { - return DeviceProxy::Pointer(); - } -} - -QString UserInputMapper::getDeviceName(uint16 deviceID) { - if (_registeredDevices.find(deviceID) != _registeredDevices.end()) { - return _registeredDevices[deviceID]->_name; - } - return QString("unknown"); -} - - -void UserInputMapper::resetAllDeviceBindings() { - for (auto device : _registeredDevices) { - device.second->resetDeviceBindings(); - } -} - -void UserInputMapper::resetDevice(uint16 deviceID) { - auto device = _registeredDevices.find(deviceID); - if (device != _registeredDevices.end()) { - device->second->resetDeviceBindings(); - } -} - -int UserInputMapper::findDevice(QString name) { - for (auto device : _registeredDevices) { - if (device.second->_name.split(" (")[0] == name) { - return device.first; - } - } - return 0; -} - -QVector UserInputMapper::getDeviceNames() { - QVector result; - for (auto device : _registeredDevices) { - QString deviceName = device.second->_name.split(" (")[0]; - result << deviceName; - } - return result; -} - - -bool UserInputMapper::addInputChannel(Action action, const Input& input, float scale) { - return addInputChannel(action, input, Input(), scale); -} - -bool UserInputMapper::addInputChannel(Action action, const Input& input, const Input& modifier, float scale) { - // Check that the device is registered - if (!getDeviceProxy(input)) { - qDebug() << "UserInputMapper::addInputChannel: The input comes from a device #" << input.getDevice() << "is unknown. no inputChannel mapped."; - return false; - } - - auto inputChannel = InputChannel(input, modifier, action, scale); - - // Insert or replace the input to modifiers - if (inputChannel.hasModifier()) { - auto& modifiers = _inputToModifiersMap[input.getID()]; - modifiers.push_back(inputChannel._modifier); - std::sort(modifiers.begin(), modifiers.end()); - } - - // Now update the action To Inputs side of things - _actionToInputsMap.insert(ActionToInputsMap::value_type(action, inputChannel)); - - return true; -} - -int UserInputMapper::addInputChannels(const InputChannels& channels) { - int nbAdded = 0; - for (auto& channel : channels) { - nbAdded += addInputChannel(channel._action, channel._input, channel._modifier, channel._scale); - } - return nbAdded; -} - -bool UserInputMapper::removeInputChannel(InputChannel inputChannel) { - // Remove from Input to Modifiers map - if (inputChannel.hasModifier()) { - _inputToModifiersMap.erase(inputChannel._input.getID()); - } - - // Remove from Action to Inputs map - std::pair ret; - ret = _actionToInputsMap.equal_range(inputChannel._action); - for (ActionToInputsMap::iterator it=ret.first; it!=ret.second; ++it) { - if (it->second == inputChannel) { - _actionToInputsMap.erase(it); - return true; - } - } - - return false; -} - -void UserInputMapper::removeAllInputChannels() { - _inputToModifiersMap.clear(); - _actionToInputsMap.clear(); -} - -void UserInputMapper::removeAllInputChannelsForDevice(uint16 device) { - QVector channels = getAllInputsForDevice(device); - for (auto& channel : channels) { - removeInputChannel(channel); - } -} - -void UserInputMapper::removeDevice(int device) { - removeAllInputChannelsForDevice((uint16) device); - _registeredDevices.erase(device); -} - -int UserInputMapper::getInputChannels(InputChannels& channels) const { - for (auto& channel : _actionToInputsMap) { - channels.push_back(channel.second); - } - - return _actionToInputsMap.size(); -} - -QVector UserInputMapper::getAllInputsForDevice(uint16 device) { - InputChannels allChannels; - getInputChannels(allChannels); - - QVector channels; - for (InputChannel inputChannel : allChannels) { - if (inputChannel._input._device == device) { - channels.push_back(inputChannel); - } - } - - return channels; -} - -void UserInputMapper::update(float deltaTime) { - - // Reset the axis state for next loop - for (auto& channel : _actionStates) { - channel = 0.0f; - } - - for (auto& channel : _poseStates) { - channel = PoseValue(); - } - - int currentTimestamp = 0; - - for (auto& channelInput : _actionToInputsMap) { - auto& inputMapping = channelInput.second; - auto& inputID = inputMapping._input; - bool enabled = true; - - // Check if this input channel has modifiers and collect the possibilities - auto modifiersIt = _inputToModifiersMap.find(inputID.getID()); - if (modifiersIt != _inputToModifiersMap.end()) { - Modifiers validModifiers; - bool isActiveModifier = false; - for (auto& modifier : modifiersIt->second) { - auto deviceProxy = getDeviceProxy(modifier); - if (deviceProxy->getButton(modifier, currentTimestamp)) { - validModifiers.push_back(modifier); - isActiveModifier |= (modifier.getID() == inputMapping._modifier.getID()); - } - } - enabled = (validModifiers.empty() && !inputMapping.hasModifier()) || isActiveModifier; - } - - // if enabled: default input or all modifiers on - if (enabled) { - auto deviceProxy = getDeviceProxy(inputID); - switch (inputMapping._input.getType()) { - case ChannelType::BUTTON: { - _actionStates[channelInput.first] += inputMapping._scale * float(deviceProxy->getButton(inputID, currentTimestamp));// * deltaTime; // weight the impulse by the deltaTime - break; - } - case ChannelType::AXIS: { - _actionStates[channelInput.first] += inputMapping._scale * deviceProxy->getAxis(inputID, currentTimestamp); - break; - } - case ChannelType::POSE: { - if (!_poseStates[channelInput.first].isValid()) { - _poseStates[channelInput.first] = deviceProxy->getPose(inputID, currentTimestamp); - } - break; - } - default: { - break; //silence please - } - } - } else{ - // Channel input not enabled - enabled = false; - } - } - - // Scale all the channel step with the scale - static const float EPSILON = 0.01f; - for (auto i = 0; i < NUM_ACTIONS; i++) { - _actionStates[i] *= _actionScales[i]; - // Emit only on change, and emit when moving back to 0 - if (fabsf(_actionStates[i] - _lastActionStates[i]) > EPSILON) { - _lastActionStates[i] = _actionStates[i]; - emit actionEvent(i, _actionStates[i]); - } - // TODO: emit signal for pose changes - } -} - -QVector UserInputMapper::getAllActions() const { - QVector actions; - for (auto i = 0; i < NUM_ACTIONS; i++) { - actions.append(Action(i)); - } - return actions; -} - -QVector UserInputMapper::getInputChannelsForAction(UserInputMapper::Action action) { - QVector inputChannels; - std::pair ret; - ret = _actionToInputsMap.equal_range(action); - for (ActionToInputsMap::iterator it=ret.first; it!=ret.second; ++it) { - inputChannels.append(it->second); - } - return inputChannels; -} - -int UserInputMapper::findAction(const QString& actionName) const { - auto actions = getAllActions(); - for (auto action : actions) { - if (getActionName(action) == actionName) { - return action; - } - } - // If the action isn't found, return -1 - return -1; -} - -QVector UserInputMapper::getActionNames() const { - QVector result; - for (auto i = 0; i < NUM_ACTIONS; i++) { - result << _actionNames[i]; - } - return result; -} - -void UserInputMapper::assignDefaulActionScales() { - _actionScales[LONGITUDINAL_BACKWARD] = 1.0f; // 1m per unit - _actionScales[LONGITUDINAL_FORWARD] = 1.0f; // 1m per unit - _actionScales[LATERAL_LEFT] = 1.0f; // 1m per unit - _actionScales[LATERAL_RIGHT] = 1.0f; // 1m per unit - _actionScales[VERTICAL_DOWN] = 1.0f; // 1m per unit - _actionScales[VERTICAL_UP] = 1.0f; // 1m per unit - _actionScales[YAW_LEFT] = 1.0f; // 1 degree per unit - _actionScales[YAW_RIGHT] = 1.0f; // 1 degree per unit - _actionScales[PITCH_DOWN] = 1.0f; // 1 degree per unit - _actionScales[PITCH_UP] = 1.0f; // 1 degree per unit - _actionScales[BOOM_IN] = 0.5f; // .5m per unit - _actionScales[BOOM_OUT] = 0.5f; // .5m per unit - _actionScales[LEFT_HAND] = 1.0f; // default - _actionScales[RIGHT_HAND] = 1.0f; // default - _actionScales[LEFT_HAND_CLICK] = 1.0f; // on - _actionScales[RIGHT_HAND_CLICK] = 1.0f; // on - _actionStates[SHIFT] = 1.0f; // on - _actionStates[ACTION1] = 1.0f; // default - _actionStates[ACTION2] = 1.0f; // default - _actionStates[TranslateX] = 1.0f; // default - _actionStates[TranslateY] = 1.0f; // default - _actionStates[TranslateZ] = 1.0f; // default - _actionStates[Roll] = 1.0f; // default - _actionStates[Pitch] = 1.0f; // default - _actionStates[Yaw] = 1.0f; // default -} - -// This is only necessary as long as the actions are hardcoded -// Eventually you can just add the string when you add the action -void UserInputMapper::createActionNames() { - _actionNames[LONGITUDINAL_BACKWARD] = "LONGITUDINAL_BACKWARD"; - _actionNames[LONGITUDINAL_FORWARD] = "LONGITUDINAL_FORWARD"; - _actionNames[LATERAL_LEFT] = "LATERAL_LEFT"; - _actionNames[LATERAL_RIGHT] = "LATERAL_RIGHT"; - _actionNames[VERTICAL_DOWN] = "VERTICAL_DOWN"; - _actionNames[VERTICAL_UP] = "VERTICAL_UP"; - _actionNames[YAW_LEFT] = "YAW_LEFT"; - _actionNames[YAW_RIGHT] = "YAW_RIGHT"; - _actionNames[PITCH_DOWN] = "PITCH_DOWN"; - _actionNames[PITCH_UP] = "PITCH_UP"; - _actionNames[BOOM_IN] = "BOOM_IN"; - _actionNames[BOOM_OUT] = "BOOM_OUT"; - _actionNames[LEFT_HAND] = "LEFT_HAND"; - _actionNames[RIGHT_HAND] = "RIGHT_HAND"; - _actionNames[LEFT_HAND_CLICK] = "LEFT_HAND_CLICK"; - _actionNames[RIGHT_HAND_CLICK] = "RIGHT_HAND_CLICK"; - _actionNames[SHIFT] = "SHIFT"; - _actionNames[ACTION1] = "ACTION1"; - _actionNames[ACTION2] = "ACTION2"; - _actionNames[CONTEXT_MENU] = "CONTEXT_MENU"; - _actionNames[TOGGLE_MUTE] = "TOGGLE_MUTE"; - _actionNames[TranslateX] = "TranslateX"; - _actionNames[TranslateY] = "TranslateY"; - _actionNames[TranslateZ] = "TranslateZ"; - _actionNames[Roll] = "Roll"; - _actionNames[Pitch] = "Pitch"; - _actionNames[Yaw] = "Yaw"; -} - -void UserInputMapper::registerStandardDevice() { - _standardController = std::make_shared(); - _standardController->registerToUserInputMapper(*this); -} - -float UserInputMapper::DeviceProxy::getValue(const Input& input, int timestamp) const { - switch (input.getType()) { - case UserInputMapper::ChannelType::BUTTON: - return getButton(input, timestamp) ? 1.0f : 0.0f; - - case UserInputMapper::ChannelType::AXIS: - return getAxis(input, timestamp); - - case UserInputMapper::ChannelType::POSE: - return getPose(input, timestamp)._valid ? 1.0f : 0.0f; - - default: - return 0.0f; - } -} +// +// UserInputMapper.cpp +// input-plugins/src/input-plugins +// +// Created by Sam Gateau on 4/27/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "UserInputMapper.h" +#include "StandardController.h" + +const UserInputMapper::Input UserInputMapper::Input::INVALID_INPUT = UserInputMapper::Input(UINT16_MAX); +const uint16_t UserInputMapper::Input::INVALID_DEVICE = INVALID_INPUT.getDevice(); +const uint16_t UserInputMapper::Input::INVALID_CHANNEL = INVALID_INPUT.getChannel(); +const uint16_t UserInputMapper::Input::INVALID_TYPE = (uint16_t)INVALID_INPUT.getType(); + +// Default contruct allocate the poutput size with the current hardcoded action channels +UserInputMapper::UserInputMapper() { + registerStandardDevice(); + assignDefaulActionScales(); + createActionNames(); +} + +UserInputMapper::~UserInputMapper() { +} + + +bool UserInputMapper::registerDevice(uint16 deviceID, const DeviceProxy::Pointer& proxy){ + proxy->_name += " (" + QString::number(deviceID) + ")"; + _registeredDevices[deviceID] = proxy; + return true; +} + +UserInputMapper::DeviceProxy::Pointer UserInputMapper::getDeviceProxy(const Input& input) { + auto device = _registeredDevices.find(input.getDevice()); + if (device != _registeredDevices.end()) { + return (device->second); + } else { + return DeviceProxy::Pointer(); + } +} + +QString UserInputMapper::getDeviceName(uint16 deviceID) { + if (_registeredDevices.find(deviceID) != _registeredDevices.end()) { + return _registeredDevices[deviceID]->_name; + } + return QString("unknown"); +} + + +void UserInputMapper::resetAllDeviceBindings() { + for (auto device : _registeredDevices) { + device.second->resetDeviceBindings(); + } +} + +void UserInputMapper::resetDevice(uint16 deviceID) { + auto device = _registeredDevices.find(deviceID); + if (device != _registeredDevices.end()) { + device->second->resetDeviceBindings(); + } +} + +int UserInputMapper::findDevice(QString name) { + for (auto device : _registeredDevices) { + if (device.second->_name.split(" (")[0] == name) { + return device.first; + } + } + return 0; +} + +QVector UserInputMapper::getDeviceNames() { + QVector result; + for (auto device : _registeredDevices) { + QString deviceName = device.second->_name.split(" (")[0]; + result << deviceName; + } + return result; +} + + +bool UserInputMapper::addInputChannel(Action action, const Input& input, float scale) { + return addInputChannel(action, input, Input(), scale); +} + +bool UserInputMapper::addInputChannel(Action action, const Input& input, const Input& modifier, float scale) { + // Check that the device is registered + if (!getDeviceProxy(input)) { + qDebug() << "UserInputMapper::addInputChannel: The input comes from a device #" << input.getDevice() << "is unknown. no inputChannel mapped."; + return false; + } + + auto inputChannel = InputChannel(input, modifier, action, scale); + + // Insert or replace the input to modifiers + if (inputChannel.hasModifier()) { + auto& modifiers = _inputToModifiersMap[input.getID()]; + modifiers.push_back(inputChannel._modifier); + std::sort(modifiers.begin(), modifiers.end()); + } + + // Now update the action To Inputs side of things + _actionToInputsMap.insert(ActionToInputsMap::value_type(action, inputChannel)); + + return true; +} + +int UserInputMapper::addInputChannels(const InputChannels& channels) { + int nbAdded = 0; + for (auto& channel : channels) { + nbAdded += addInputChannel(channel._action, channel._input, channel._modifier, channel._scale); + } + return nbAdded; +} + +bool UserInputMapper::removeInputChannel(InputChannel inputChannel) { + // Remove from Input to Modifiers map + if (inputChannel.hasModifier()) { + _inputToModifiersMap.erase(inputChannel._input.getID()); + } + + // Remove from Action to Inputs map + std::pair ret; + ret = _actionToInputsMap.equal_range(inputChannel._action); + for (ActionToInputsMap::iterator it=ret.first; it!=ret.second; ++it) { + if (it->second == inputChannel) { + _actionToInputsMap.erase(it); + return true; + } + } + + return false; +} + +void UserInputMapper::removeAllInputChannels() { + _inputToModifiersMap.clear(); + _actionToInputsMap.clear(); +} + +void UserInputMapper::removeAllInputChannelsForDevice(uint16 device) { + QVector channels = getAllInputsForDevice(device); + for (auto& channel : channels) { + removeInputChannel(channel); + } +} + +void UserInputMapper::removeDevice(int device) { + removeAllInputChannelsForDevice((uint16) device); + _registeredDevices.erase(device); +} + +int UserInputMapper::getInputChannels(InputChannels& channels) const { + for (auto& channel : _actionToInputsMap) { + channels.push_back(channel.second); + } + + return _actionToInputsMap.size(); +} + +QVector UserInputMapper::getAllInputsForDevice(uint16 device) { + InputChannels allChannels; + getInputChannels(allChannels); + + QVector channels; + for (InputChannel inputChannel : allChannels) { + if (inputChannel._input._device == device) { + channels.push_back(inputChannel); + } + } + + return channels; +} + +void UserInputMapper::update(float deltaTime) { + + // Reset the axis state for next loop + for (auto& channel : _actionStates) { + channel = 0.0f; + } + + for (auto& channel : _poseStates) { + channel = PoseValue(); + } + + int currentTimestamp = 0; + + for (auto& channelInput : _actionToInputsMap) { + auto& inputMapping = channelInput.second; + auto& inputID = inputMapping._input; + bool enabled = true; + + // Check if this input channel has modifiers and collect the possibilities + auto modifiersIt = _inputToModifiersMap.find(inputID.getID()); + if (modifiersIt != _inputToModifiersMap.end()) { + Modifiers validModifiers; + bool isActiveModifier = false; + for (auto& modifier : modifiersIt->second) { + auto deviceProxy = getDeviceProxy(modifier); + if (deviceProxy->getButton(modifier, currentTimestamp)) { + validModifiers.push_back(modifier); + isActiveModifier |= (modifier.getID() == inputMapping._modifier.getID()); + } + } + enabled = (validModifiers.empty() && !inputMapping.hasModifier()) || isActiveModifier; + } + + // if enabled: default input or all modifiers on + if (enabled) { + auto deviceProxy = getDeviceProxy(inputID); + switch (inputMapping._input.getType()) { + case ChannelType::BUTTON: { + _actionStates[channelInput.first] += inputMapping._scale * float(deviceProxy->getButton(inputID, currentTimestamp));// * deltaTime; // weight the impulse by the deltaTime + break; + } + case ChannelType::AXIS: { + _actionStates[channelInput.first] += inputMapping._scale * deviceProxy->getAxis(inputID, currentTimestamp); + break; + } + case ChannelType::POSE: { + if (!_poseStates[channelInput.first].isValid()) { + _poseStates[channelInput.first] = deviceProxy->getPose(inputID, currentTimestamp); + } + break; + } + default: { + break; //silence please + } + } + } else{ + // Channel input not enabled + enabled = false; + } + } + + // Scale all the channel step with the scale + static const float EPSILON = 0.01f; + for (auto i = 0; i < NUM_ACTIONS; i++) { + _actionStates[i] *= _actionScales[i]; + // Emit only on change, and emit when moving back to 0 + if (fabsf(_actionStates[i] - _lastActionStates[i]) > EPSILON) { + _lastActionStates[i] = _actionStates[i]; + emit actionEvent(i, _actionStates[i]); + } + // TODO: emit signal for pose changes + } +} + +QVector UserInputMapper::getAllActions() const { + QVector actions; + for (auto i = 0; i < NUM_ACTIONS; i++) { + actions.append(Action(i)); + } + return actions; +} + +QVector UserInputMapper::getInputChannelsForAction(UserInputMapper::Action action) { + QVector inputChannels; + std::pair ret; + ret = _actionToInputsMap.equal_range(action); + for (ActionToInputsMap::iterator it=ret.first; it!=ret.second; ++it) { + inputChannels.append(it->second); + } + return inputChannels; +} + +int UserInputMapper::findAction(const QString& actionName) const { + auto actions = getAllActions(); + for (auto action : actions) { + if (getActionName(action) == actionName) { + return action; + } + } + // If the action isn't found, return -1 + return -1; +} + +QVector UserInputMapper::getActionNames() const { + QVector result; + for (auto i = 0; i < NUM_ACTIONS; i++) { + result << _actionNames[i]; + } + return result; +} + +void UserInputMapper::assignDefaulActionScales() { + _actionScales[LONGITUDINAL_BACKWARD] = 1.0f; // 1m per unit + _actionScales[LONGITUDINAL_FORWARD] = 1.0f; // 1m per unit + _actionScales[LATERAL_LEFT] = 1.0f; // 1m per unit + _actionScales[LATERAL_RIGHT] = 1.0f; // 1m per unit + _actionScales[VERTICAL_DOWN] = 1.0f; // 1m per unit + _actionScales[VERTICAL_UP] = 1.0f; // 1m per unit + _actionScales[YAW_LEFT] = 1.0f; // 1 degree per unit + _actionScales[YAW_RIGHT] = 1.0f; // 1 degree per unit + _actionScales[PITCH_DOWN] = 1.0f; // 1 degree per unit + _actionScales[PITCH_UP] = 1.0f; // 1 degree per unit + _actionScales[BOOM_IN] = 0.5f; // .5m per unit + _actionScales[BOOM_OUT] = 0.5f; // .5m per unit + _actionScales[LEFT_HAND] = 1.0f; // default + _actionScales[RIGHT_HAND] = 1.0f; // default + _actionScales[LEFT_HAND_CLICK] = 1.0f; // on + _actionScales[RIGHT_HAND_CLICK] = 1.0f; // on + _actionStates[SHIFT] = 1.0f; // on + _actionStates[ACTION1] = 1.0f; // default + _actionStates[ACTION2] = 1.0f; // default + _actionStates[TRANSLATE_X] = 1.0f; // default + _actionStates[TRANSLATE_Y] = 1.0f; // default + _actionStates[TRANSLATE_Z] = 1.0f; // default + _actionStates[ROLL] = 1.0f; // default + _actionStates[PITCH] = 1.0f; // default + _actionStates[YAW] = 1.0f; // default +} + +// This is only necessary as long as the actions are hardcoded +// Eventually you can just add the string when you add the action +void UserInputMapper::createActionNames() { + _actionNames[LONGITUDINAL_BACKWARD] = "LONGITUDINAL_BACKWARD"; + _actionNames[LONGITUDINAL_FORWARD] = "LONGITUDINAL_FORWARD"; + _actionNames[LATERAL_LEFT] = "LATERAL_LEFT"; + _actionNames[LATERAL_RIGHT] = "LATERAL_RIGHT"; + _actionNames[VERTICAL_DOWN] = "VERTICAL_DOWN"; + _actionNames[VERTICAL_UP] = "VERTICAL_UP"; + _actionNames[YAW_LEFT] = "YAW_LEFT"; + _actionNames[YAW_RIGHT] = "YAW_RIGHT"; + _actionNames[PITCH_DOWN] = "PITCH_DOWN"; + _actionNames[PITCH_UP] = "PITCH_UP"; + _actionNames[BOOM_IN] = "BOOM_IN"; + _actionNames[BOOM_OUT] = "BOOM_OUT"; + _actionNames[LEFT_HAND] = "LEFT_HAND"; + _actionNames[RIGHT_HAND] = "RIGHT_HAND"; + _actionNames[LEFT_HAND_CLICK] = "LEFT_HAND_CLICK"; + _actionNames[RIGHT_HAND_CLICK] = "RIGHT_HAND_CLICK"; + _actionNames[SHIFT] = "SHIFT"; + _actionNames[ACTION1] = "ACTION1"; + _actionNames[ACTION2] = "ACTION2"; + _actionNames[CONTEXT_MENU] = "CONTEXT_MENU"; + _actionNames[TOGGLE_MUTE] = "TOGGLE_MUTE"; + _actionNames[TRANSLATE_X] = "TranslateX"; + _actionNames[TRANSLATE_Y] = "TranslateY"; + _actionNames[TRANSLATE_Z] = "TranslateZ"; + _actionNames[ROLL] = "Roll"; + _actionNames[PITCH] = "Pitch"; + _actionNames[YAW] = "Yaw"; +} + +void UserInputMapper::registerStandardDevice() { + _standardController = std::make_shared(); + _standardController->registerToUserInputMapper(*this); +} + +float UserInputMapper::DeviceProxy::getValue(const Input& input, int timestamp) const { + switch (input.getType()) { + case UserInputMapper::ChannelType::BUTTON: + return getButton(input, timestamp) ? 1.0f : 0.0f; + + case UserInputMapper::ChannelType::AXIS: + return getAxis(input, timestamp); + + case UserInputMapper::ChannelType::POSE: + return getPose(input, timestamp)._valid ? 1.0f : 0.0f; + + default: + return 0.0f; + } +} diff --git a/libraries/input-plugins/src/input-plugins/UserInputMapper.h b/libraries/controllers/src/controllers/UserInputMapper.h old mode 100755 new mode 100644 similarity index 96% rename from libraries/input-plugins/src/input-plugins/UserInputMapper.h rename to libraries/controllers/src/controllers/UserInputMapper.h index 304e74e8cc..2a42dfa1aa --- a/libraries/input-plugins/src/input-plugins/UserInputMapper.h +++ b/libraries/controllers/src/controllers/UserInputMapper.h @@ -146,44 +146,52 @@ public: // Actions are the output channels of the Mapper, that's what the InputChannel map to // For now the Actions are hardcoded, this is bad, but we will fix that in the near future enum Action { - LONGITUDINAL_BACKWARD = 0, - LONGITUDINAL_FORWARD, + TRANSLATE_X = 0, + TRANSLATE_Y, + TRANSLATE_Z, + ROTATE_X, PITCH = ROTATE_X, + ROTATE_Y, YAW = ROTATE_Y, + ROTATE_Z, ROLL = ROTATE_Z, - LATERAL_LEFT, - LATERAL_RIGHT, + TRANSLATE_CAMERA_Z, - VERTICAL_DOWN, - VERTICAL_UP, - - YAW_LEFT, - YAW_RIGHT, - - PITCH_DOWN, - PITCH_UP, - - BOOM_IN, - BOOM_OUT, - LEFT_HAND, RIGHT_HAND, LEFT_HAND_CLICK, RIGHT_HAND_CLICK, - SHIFT, - ACTION1, ACTION2, CONTEXT_MENU, TOGGLE_MUTE, - TranslateX, - TranslateY, - TranslateZ, - Roll, - Pitch, - Yaw, + SHIFT, + + // Biseced aliases for TRANSLATE_Z + LONGITUDINAL_BACKWARD, + LONGITUDINAL_FORWARD, + + // Biseced aliases for TRANSLATE_X + LATERAL_LEFT, + LATERAL_RIGHT, + + // Biseced aliases for TRANSLATE_Y + VERTICAL_DOWN, + VERTICAL_UP, + + // Biseced aliases for ROTATE_Y + YAW_LEFT, + YAW_RIGHT, + + // Biseced aliases for ROTATE_X + PITCH_DOWN, + PITCH_UP, + + // Biseced aliases for TRANSLATE_CAMERA_Z + BOOM_IN, + BOOM_OUT, NUM_ACTIONS, }; diff --git a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.cpp b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.cpp index a826b4fd4d..1e889f2dda 100644 --- a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.cpp +++ b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.cpp @@ -12,7 +12,7 @@ #include #include "RouteBuilderProxy.h" -#include "../NewControllerScriptingInterface.h" +#include "../ScriptingInterface.h" #include "../Logging.h" namespace controller { diff --git a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h index 70495a9cfe..024faa7a4a 100644 --- a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h +++ b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h @@ -20,12 +20,14 @@ class QScriptValue; namespace controller { -class NewControllerScriptingInterface; +class ScriptingInterface; +// TODO migrate functionality to a MappingBuilder class and make the proxy defer to that +// (for easier use in both C++ and JS) class MappingBuilderProxy : public QObject { Q_OBJECT public: - MappingBuilderProxy(NewControllerScriptingInterface& parent, Mapping::Pointer mapping) + MappingBuilderProxy(ScriptingInterface& parent, Mapping::Pointer mapping) : _parent(parent), _mapping(mapping) { } Q_INVOKABLE QObject* from(const QJSValue& source); @@ -38,7 +40,7 @@ protected: QObject* from(const Endpoint::Pointer& source); friend class RouteBuilderProxy; - NewControllerScriptingInterface& _parent; + ScriptingInterface& _parent; Mapping::Pointer _mapping; }; diff --git a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp index e6b67e9ca6..50c3b534d1 100644 --- a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp +++ b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp @@ -12,7 +12,7 @@ #include #include "MappingBuilderProxy.h" -#include "../NewControllerScriptingInterface.h" +#include "../ScriptingInterface.h" #include "../Logging.h" namespace controller { diff --git a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h index 63cd106edb..d7cf024468 100644 --- a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h +++ b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h @@ -19,12 +19,14 @@ class QScriptValue; namespace controller { -class NewControllerScriptingInterface; +class ScriptingInterface; +// TODO migrate functionality to a RouteBuilder class and make the proxy defer to that +// (for easier use in both C++ and JS) class RouteBuilderProxy : public QObject { Q_OBJECT public: - RouteBuilderProxy(NewControllerScriptingInterface& parent, Mapping::Pointer mapping, Route::Pointer route) + RouteBuilderProxy(ScriptingInterface& parent, Mapping::Pointer mapping, Route::Pointer route) : _parent(parent), _mapping(mapping), _route(route) { } Q_INVOKABLE void to(const QJSValue& destination); @@ -47,7 +49,7 @@ class RouteBuilderProxy : public QObject { Mapping::Pointer _mapping; Route::Pointer _route; - NewControllerScriptingInterface& _parent; + ScriptingInterface& _parent; }; } diff --git a/libraries/entities-renderer/CMakeLists.txt b/libraries/entities-renderer/CMakeLists.txt index bb90c04c95..4f2a525f07 100644 --- a/libraries/entities-renderer/CMakeLists.txt +++ b/libraries/entities-renderer/CMakeLists.txt @@ -1,7 +1,7 @@ set(TARGET_NAME entities-renderer) AUTOSCRIBE_SHADER_LIB(gpu model render render-utils) setup_hifi_library(Widgets Network Script) -link_hifi_libraries(shared gpu procedural model model-networking script-engine render render-utils) +link_hifi_libraries(shared gpu procedural model model-networking script-engine controllers render render-utils) target_bullet() diff --git a/libraries/input-plugins/CMakeLists.txt b/libraries/input-plugins/CMakeLists.txt index 094a697012..4c33b2517a 100644 --- a/libraries/input-plugins/CMakeLists.txt +++ b/libraries/input-plugins/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME input-plugins) setup_hifi_library() -link_hifi_libraries(shared plugins gpu render-utils) +link_hifi_libraries(shared plugins controllers) GroupSources("src/input-plugins") diff --git a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp index 2b16d905f5..b52dd3f658 100644 --- a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp +++ b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp @@ -22,7 +22,7 @@ InputPluginList getInputPlugins() { InputPlugin* PLUGIN_POOL[] = { new KeyboardMouseDevice(), new SDL2Manager(), - new SixenseManager(), + //new SixenseManager(), //new ViveControllerManager(), nullptr }; diff --git a/libraries/input-plugins/src/input-plugins/Joystick.cpp b/libraries/input-plugins/src/input-plugins/Joystick.cpp index 684b9e80d5..e7a0124deb 100644 --- a/libraries/input-plugins/src/input-plugins/Joystick.cpp +++ b/libraries/input-plugins/src/input-plugins/Joystick.cpp @@ -9,13 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - -#include - #include "Joystick.h" -#include "StandardControls.h" +#include +#include const float CONTROLLER_THRESHOLD = 0.3f; diff --git a/libraries/input-plugins/src/input-plugins/Joystick.h b/libraries/input-plugins/src/input-plugins/Joystick.h index 2a7a11d230..c6537acafe 100644 --- a/libraries/input-plugins/src/input-plugins/Joystick.h +++ b/libraries/input-plugins/src/input-plugins/Joystick.h @@ -20,8 +20,8 @@ #undef main #endif -#include "InputDevice.h" -#include "StandardControls.h" +#include +#include class Joystick : public QObject, public InputDevice { Q_OBJECT diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h index e8a6131387..3c935cab26 100644 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h @@ -16,7 +16,7 @@ #include -#include "InputDevice.h" +#include #include "InputPlugin.h" class QTouchEvent; diff --git a/libraries/input-plugins/src/input-plugins/SDL2Manager.h b/libraries/input-plugins/src/input-plugins/SDL2Manager.h index 23e3ee059f..fec6972591 100644 --- a/libraries/input-plugins/src/input-plugins/SDL2Manager.h +++ b/libraries/input-plugins/src/input-plugins/SDL2Manager.h @@ -16,9 +16,9 @@ #include #endif -#include "InputPlugin.h" -#include "UserInputMapper.h" +#include +#include "InputPlugin.h" #include "Joystick.h" class SDL2Manager : public InputPlugin { diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.h b/libraries/input-plugins/src/input-plugins/SixenseManager.h index 9fa7f84a86..53ee7f3c29 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.h +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.h @@ -24,8 +24,9 @@ #endif +#include + #include "InputPlugin.h" -#include "InputDevice.h" class QLibrary; diff --git a/libraries/input-plugins/src/input-plugins/ViveControllerManager.h b/libraries/input-plugins/src/input-plugins/ViveControllerManager.h index 5cae8daaf4..bcc27d07ae 100644 --- a/libraries/input-plugins/src/input-plugins/ViveControllerManager.h +++ b/libraries/input-plugins/src/input-plugins/ViveControllerManager.h @@ -19,7 +19,7 @@ #include #include -#include "InputDevice.h" +#include #include "InputPlugin.h" #include #include diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index cfe0afd220..5e3d135034 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -1,3 +1,3 @@ set(TARGET_NAME script-engine) setup_hifi_library(Gui Network Script WebSockets Widgets) -link_hifi_libraries(shared networking octree gpu procedural model model-networking fbx entities animation audio physics) +link_hifi_libraries(shared networking octree gpu procedural model model-networking fbx entities controllers animation audio physics) diff --git a/libraries/script-engine/src/AbstractControllerScriptingInterface.h b/libraries/script-engine/src/AbstractControllerScriptingInterface.h deleted file mode 100644 index d6a6b51b62..0000000000 --- a/libraries/script-engine/src/AbstractControllerScriptingInterface.h +++ /dev/null @@ -1,125 +0,0 @@ -// -// AbstractControllerScriptingInterface.h -// libraries/script-engine/src -// -// Created by Brad Hefta-Gaub on 12/17/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_AbstractControllerScriptingInterface_h -#define hifi_AbstractControllerScriptingInterface_h - -#include - -#include -#include - -#include "HFActionEvent.h" -#include "KeyEvent.h" -#include "MouseEvent.h" -#include "SpatialEvent.h" -#include "TouchEvent.h" -#include "WheelEvent.h" - -class ScriptEngine; - -class AbstractInputController : public QObject { - Q_OBJECT - -public: - typedef unsigned int Key; - - virtual void update() = 0; - - virtual Key getKey() const = 0; - -public slots: - - virtual bool isActive() const = 0; - virtual glm::vec3 getAbsTranslation() const = 0; - virtual glm::quat getAbsRotation() const = 0; - virtual glm::vec3 getLocTranslation() const = 0; - virtual glm::quat getLocRotation() const = 0; - -signals: - void spatialEvent(const SpatialEvent& event); - -}; - -/// handles scripting of input controller commands from JS -class AbstractControllerScriptingInterface : public QObject { - Q_OBJECT - -public slots: - virtual void registerControllerTypes(ScriptEngine* engine) = 0; - - virtual bool isPrimaryButtonPressed() const = 0; - virtual glm::vec2 getPrimaryJoystickPosition() const = 0; - - virtual int getNumberOfButtons() const = 0; - virtual bool isButtonPressed(int buttonIndex) const = 0; - - virtual int getNumberOfTriggers() const = 0; - virtual float getTriggerValue(int triggerIndex) const = 0; - - virtual int getNumberOfJoysticks() const = 0; - virtual glm::vec2 getJoystickPosition(int joystickIndex) const = 0; - - virtual int getNumberOfSpatialControls() const = 0; - virtual glm::vec3 getSpatialControlPosition(int controlIndex) const = 0; - virtual glm::vec3 getSpatialControlVelocity(int controlIndex) const = 0; - virtual glm::vec3 getSpatialControlNormal(int controlIndex) const = 0; - virtual glm::quat getSpatialControlRawRotation(int controlIndex) const = 0; - - virtual void captureKeyEvents(const KeyEvent& event) = 0; - virtual void releaseKeyEvents(const KeyEvent& event) = 0; - - virtual void captureMouseEvents() = 0; - virtual void releaseMouseEvents() = 0; - - virtual void captureTouchEvents() = 0; - virtual void releaseTouchEvents() = 0; - - virtual void captureWheelEvents() = 0; - virtual void releaseWheelEvents() = 0; - - virtual void captureActionEvents() = 0; - virtual void releaseActionEvents() = 0; - - virtual void captureJoystick(int joystickIndex) = 0; - virtual void releaseJoystick(int joystickIndex) = 0; - - virtual glm::vec2 getViewportDimensions() const = 0; - - - virtual AbstractInputController* createInputController( const QString& category, const QString& tracker ) = 0; - -signals: - void keyPressEvent(const KeyEvent& event); - void keyReleaseEvent(const KeyEvent& event); - - void actionStartEvent(const HFActionEvent& event); - void actionEndEvent(const HFActionEvent& event); - - void backStartEvent(); - void backEndEvent(); - - void mouseMoveEvent(const MouseEvent& event, unsigned int deviceID = 0); - void mousePressEvent(const MouseEvent& event, unsigned int deviceID = 0); - void mouseDoublePressEvent(const MouseEvent& event, unsigned int deviceID = 0); - void mouseReleaseEvent(const MouseEvent& event, unsigned int deviceID = 0); - - void touchBeginEvent(const TouchEvent& event); - void touchEndEvent(const TouchEvent& event); - void touchUpdateEvent(const TouchEvent& event); - - void wheelEvent(const WheelEvent& event); - - void actionEvent(int action, float state); - -}; - -#endif // hifi_AbstractControllerScriptingInterface_h diff --git a/libraries/script-engine/src/AbstractScriptingServicesInterface.h b/libraries/script-engine/src/AbstractScriptingServicesInterface.h index 9d24531b60..565a415f63 100644 --- a/libraries/script-engine/src/AbstractScriptingServicesInterface.h +++ b/libraries/script-engine/src/AbstractScriptingServicesInterface.h @@ -12,7 +12,10 @@ #ifndef hifi_AbstractScriptingServicesInterface_h #define hifi_AbstractScriptingServicesInterface_h -class AbstractControllerScriptingInterface; +namespace controller { + class ScriptingInterface; +} + class Transform; class ScriptEngine; class QThread; @@ -22,7 +25,7 @@ class AbstractScriptingServicesInterface { public: /// Returns the controller interface for the application - virtual AbstractControllerScriptingInterface* getControllerScriptingInterface() = 0; + virtual controller::ScriptingInterface* getControllerScriptingInterface() = 0; /// Registers application specific services with a script engine. virtual void registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) = 0; diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 76590f266b..40d4d664ce 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -76,16 +76,16 @@ void avatarDataFromScriptValue(const QScriptValue &object, AvatarData* &out) { out = qobject_cast(object.toQObject()); } -QScriptValue inputControllerToScriptValue(QScriptEngine *engine, AbstractInputController* const &in) { + +QScriptValue inputControllerToScriptValue(QScriptEngine *engine, controller::InputController* const &in) { return engine->newQObject(in); } -void inputControllerFromScriptValue(const QScriptValue &object, AbstractInputController* &out) { - out = qobject_cast(object.toQObject()); +void inputControllerFromScriptValue(const QScriptValue &object, controller::InputController* &out) { + out = qobject_cast(object.toQObject()); } -ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNameString, - AbstractControllerScriptingInterface* controllerScriptingInterface, bool wantSignals) : +ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNameString, controller::ScriptingInterface* controllerScriptingInterface, bool wantSignals) : _scriptContents(scriptContents), _isFinished(false), @@ -93,7 +93,6 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam _isInitialized(false), _timerFunctionMap(), _wantSignals(wantSignals), - _controllerScriptingInterface(controllerScriptingInterface), _fileNameString(fileNameString), _quatLibrary(), _vec3Library(), @@ -301,7 +300,7 @@ void ScriptEngine::init() { globalObject().setProperty("AudioEffectOptions", audioEffectOptionsConstructorValue); qScriptRegisterMetaType(this, injectorToScriptValue, injectorFromScriptValue); - qScriptRegisterMetaType(this, inputControllerToScriptValue, inputControllerFromScriptValue); + //qScriptRegisterMetaType(this, inputControllerToScriptValue, inputControllerFromScriptValue); qScriptRegisterMetaType(this, avatarDataToScriptValue, avatarDataFromScriptValue); qScriptRegisterMetaType(this, animationDetailsToScriptValue, animationDetailsFromScriptValue); qScriptRegisterMetaType(this, webSocketToScriptValue, webSocketFromScriptValue); @@ -310,7 +309,7 @@ void ScriptEngine::init() { registerGlobalObject("Script", this); registerGlobalObject("Audio", &AudioScriptingInterface::getInstance()); - registerGlobalObject("Controller", _controllerScriptingInterface); +// registerGlobalObject("Controller", _controllerScriptingInterface); registerGlobalObject("Entities", entityScriptingInterface.data()); registerGlobalObject("Quat", &_quatLibrary); registerGlobalObject("Vec3", &_vec3Library); @@ -320,9 +319,9 @@ void ScriptEngine::init() { // constants globalObject().setProperty("TREE_SCALE", newVariant(QVariant(TREE_SCALE))); - if (_controllerScriptingInterface) { - _controllerScriptingInterface->registerControllerTypes(this); - } + //if (_controllerScriptingInterface) { + // _controllerScriptingInterface->registerControllerTypes(this); + //} } diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 1d3986143a..0108899571 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -26,8 +26,10 @@ #include #include #include +#include -#include "AbstractControllerScriptingInterface.h" + +#include "MouseEvent.h" #include "ArrayBufferClass.h" #include "AudioScriptingInterface.h" #include "Quat.h" @@ -53,7 +55,7 @@ class ScriptEngine : public QScriptEngine, public ScriptUser, public EntitiesScr public: ScriptEngine(const QString& scriptContents = NO_SCRIPT, const QString& fileNameString = QString(""), - AbstractControllerScriptingInterface* controllerScriptingInterface = NULL, + controller::ScriptingInterface* controllerScriptingInterface = nullptr, bool wantSignals = true); ~ScriptEngine(); @@ -182,7 +184,6 @@ private: QObject* setupTimerWithInterval(const QScriptValue& function, int intervalMS, bool isSingleShot); void stopTimer(QTimer* timer); - AbstractControllerScriptingInterface* _controllerScriptingInterface; QString _fileNameString; Quat _quatLibrary; Vec3 _vec3Library; diff --git a/tests/controllers/qml/content.qml b/tests/controllers/qml/content.qml index 41d623a389..5f9bbd455e 100644 --- a/tests/controllers/qml/content.qml +++ b/tests/controllers/qml/content.qml @@ -8,17 +8,17 @@ import "./controls" Column { id: root - property var actions: NewControllers.Actions - property var standard: NewControllers.Standard + property var actions: Controllers.Actions + property var standard: Controllers.Standard property var testMapping: null property var xbox: null Component.onCompleted: { var patt = /^X360Controller/; - for (var prop in NewControllers.Hardware) { + for (var prop in Controllers.Hardware) { if(patt.test(prop)) { - root.xbox = NewControllers.Hardware[prop] + root.xbox = Controllers.Hardware[prop] break } } @@ -29,7 +29,7 @@ Column { Timer { interval: 50; running: true; repeat: true onTriggered: { - NewControllers.update(); + Controllers.update(); } } @@ -38,7 +38,7 @@ Column { Button { text: "Default Mapping" onClicked: { - var mapping = NewControllers.newMapping("Default"); + var mapping = Controllers.newMapping("Default"); mapping.from(xbox.A).to(standard.A); mapping.from(xbox.B).to(standard.B); mapping.from(xbox.X).to(standard.X); @@ -59,7 +59,7 @@ Column { mapping.from(xbox.RX).to(standard.RX); mapping.from(xbox.LT).to(standard.LT); mapping.from(xbox.RT).to(standard.RT); - NewControllers.enableMapping("Default"); + Controllers.enableMapping("Default"); enabled = false; text = "Built" } @@ -68,16 +68,35 @@ Column { Button { text: "Build Mapping" onClicked: { - var mapping = NewControllers.newMapping(); + var mapping = Controllers.newMapping(); // Inverting a value mapping.from(xbox.RY).invert().to(standard.RY); // Assigning a value from a function mapping.from(function() { return Math.sin(Date.now() / 250); }).to(standard.RX); // Constrainting a value to -1, 0, or 1, with a deadzone mapping.from(xbox.LY).deadZone(0.5).constrainToInteger().to(standard.LY); - mapping.join(standard.LB, standard.RB).pulse(0.5).to(actions.Yaw); + // change join to makeAxis + mapping.join(standard.LB, standard.RB).to(actions.Yaw); mapping.from(actions.Yaw).clamp(0, 1).invert().to(actions.YAW_RIGHT); mapping.from(actions.Yaw).clamp(-1, 0).to(actions.YAW_LEFT); + + // mapping.modifier(keyboard.Ctrl).scale(2.0) + +// mapping.from(keyboard.A).to(actions.TranslateLeft) +// mapping.from(keyboard.A, keyboard.Shift).to(actions.TurnLeft) +// mapping.from(keyboard.A, keyboard.Shift, keyboard.Ctrl).scale(2.0).to(actions.TurnLeft) + +// // First loopbacks +// // Then non-loopbacks by constraint level (number of inputs) +// mapping.from(xbox.RX).deadZone(0.2).to(xbox.RX) + +// mapping.from(standard.RB, standard.LB, keyboard.Shift).to(actions.TurnLeft) + + +// mapping.from(keyboard.A, keyboard.Shift).to(actions.TurnLeft) + + +// mapping.from(keyboard.W).when(keyboard.Shift).to(actions.Forward) testMapping = mapping; enabled = false text = "Built" @@ -105,7 +124,7 @@ Column { Row { spacing: 8 ScrollingGraph { - controlId: NewControllers.Actions.Yaw + controlId: Controllers.Actions.Yaw label: "Yaw" min: -3.0 max: 3.0 @@ -113,7 +132,7 @@ Column { } ScrollingGraph { - controlId: NewControllers.Actions.YAW_LEFT + controlId: Controllers.Actions.YAW_LEFT label: "Yaw Left" min: -3.0 max: 3.0 @@ -121,7 +140,7 @@ Column { } ScrollingGraph { - controlId: NewControllers.Actions.YAW_RIGHT + controlId: Controllers.Actions.YAW_RIGHT label: "Yaw Right" min: -3.0 max: 3.0 diff --git a/tests/controllers/qml/controls/AnalogButton.qml b/tests/controllers/qml/controls/AnalogButton.qml index 26f91458ac..141c131063 100644 --- a/tests/controllers/qml/controls/AnalogButton.qml +++ b/tests/controllers/qml/controls/AnalogButton.qml @@ -13,7 +13,7 @@ Item { property color color: 'black' function update() { - value = NewControllers.getValue(controlId); + value = Controllers.getValue(controlId); canvas.requestPaint(); } diff --git a/tests/controllers/qml/controls/AnalogStick.qml b/tests/controllers/qml/controls/AnalogStick.qml index 8860aea49c..5d011411c9 100644 --- a/tests/controllers/qml/controls/AnalogStick.qml +++ b/tests/controllers/qml/controls/AnalogStick.qml @@ -15,8 +15,8 @@ Item { function update() { value = Qt.vector2d( - NewControllers.getValue(controlIds[0]), - NewControllers.getValue(controlIds[1]) + Controllers.getValue(controlIds[0]), + Controllers.getValue(controlIds[1]) ); canvas.requestPaint(); } diff --git a/tests/controllers/qml/controls/ScrollingGraph.qml b/tests/controllers/qml/controls/ScrollingGraph.qml index 69f919aaf1..471d142d27 100644 --- a/tests/controllers/qml/controls/ScrollingGraph.qml +++ b/tests/controllers/qml/controls/ScrollingGraph.qml @@ -22,7 +22,7 @@ Item { property string label: "" function update() { - value = NewControllers.getValue(controlId); + value = Controllers.getValue(controlId); canvas.requestPaint(); } diff --git a/tests/controllers/qml/controls/ToggleButton.qml b/tests/controllers/qml/controls/ToggleButton.qml index 9ef54f5971..46a7b4bdfd 100644 --- a/tests/controllers/qml/controls/ToggleButton.qml +++ b/tests/controllers/qml/controls/ToggleButton.qml @@ -15,7 +15,7 @@ Item { Timer { interval: 50; running: true; repeat: true onTriggered: { - root.value = NewControllers.getValue(root.controlId); + root.value = Controllers.getValue(root.controlId); canvas.requestPaint(); } } diff --git a/tests/controllers/src/main.cpp b/tests/controllers/src/main.cpp index 7182862ff1..3a45195439 100644 --- a/tests/controllers/src/main.cpp +++ b/tests/controllers/src/main.cpp @@ -38,10 +38,10 @@ #include #include #include -#include +#include #include -#include +#include const QString& getQmlDir() { static QString dir; @@ -87,6 +87,22 @@ int main(int argc, char** argv) { } + QTimer timer; + QObject::connect(&timer, &QTimer::timeout, [] { + static float last = secTimestampNow(); + float now = secTimestampNow(); + float delta = now - last; + last = now; + + foreach(auto inputPlugin, PluginManager::getInstance()->getInputPlugins()) { + inputPlugin->pluginUpdate(delta, false); + } + + auto userInputMapper = DependencyManager::get(); + userInputMapper->update(delta); + }); + timer.start(50); + { DependencyManager::set(); foreach(auto inputPlugin, PluginManager::getInstance()->getInputPlugins()) { @@ -98,17 +114,9 @@ int main(int argc, char** argv) { keyboardMouseDevice->registerToUserInputMapper(*userInputMapper); } } - - //new PluginContainerProxy(); auto rootContext = engine.rootContext(); - - auto controllers = new NewControllerScriptingInterface(); - rootContext->setContextProperty("NewControllers", controllers); - QVariantMap map; - map.insert("Hardware", controllers->property("Hardware")); - map.insert("Actions", controllers->property("Actions")); - rootContext->setContextProperty("ControllerIds", map); + rootContext->setContextProperty("Controllers", new ScriptingInterface()); } engine.load(getQmlDir() + "main.qml"); app.exec();