mirror of
https://github.com/lubosz/overte.git
synced 2025-04-09 15:33:14 +02:00
Merging old and new controller interfaces
This commit is contained in:
parent
619fce0d7f
commit
0063f9ae1d
43 changed files with 1086 additions and 1101 deletions
|
@ -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()
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
#include <InfoView.h>
|
||||
#include <input-plugins/InputPlugin.h>
|
||||
#include <input-plugins/Joystick.h> // this should probably be removed
|
||||
#include <input-plugins/UserInputMapper.h>
|
||||
#include <controllers/UserInputMapper.h>
|
||||
#include <LogHandler.h>
|
||||
#include <MainWindow.h>
|
||||
#include <MessageDialog.h>
|
||||
|
@ -614,7 +614,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
|
||||
// Setup the userInputMapper with the actions
|
||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include <QObject>
|
||||
#include <QLibrary>
|
||||
#include <input-plugins/UserInputMapper.h>
|
||||
#include <controllers/UserInputMapper.h>
|
||||
|
||||
#include "InterfaceLogging.h"
|
||||
|
||||
|
|
|
@ -9,21 +9,19 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "ControllerScriptingInterface.h"
|
||||
|
||||
#include <avatar/AvatarManager.h>
|
||||
#include <avatar/MyAvatar.h>
|
||||
#include <HandData.h>
|
||||
#include <HFBackEvent.h>
|
||||
|
||||
#include <controllers/NewControllerScriptingInterface.h>
|
||||
|
||||
#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 <input-plugins/SixenseManager.h>
|
||||
|
||||
|
||||
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<UserInputMapper>()->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<UserInputMapper>()->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<UserInputMapper>()->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<InputController>(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<QString> 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); }
|
||||
|
||||
|
|
|
@ -14,15 +14,20 @@
|
|||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <input-plugins/UserInputMapper.h>
|
||||
#include <controllers/UserInputMapper.h>
|
||||
#include <controllers/ScriptingInterface.h>
|
||||
|
||||
#include <HFActionEvent.h>
|
||||
#include <KeyEvent.h>
|
||||
#include <MouseEvent.h>
|
||||
#include <SpatialEvent.h>
|
||||
#include <TouchEvent.h>
|
||||
#include <WheelEvent.h>
|
||||
class ScriptEngine;
|
||||
|
||||
#include <AbstractControllerScriptingInterface.h>
|
||||
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<UserInputMapper::Action> getAllActions();
|
||||
|
||||
Q_INVOKABLE bool addInputChannel(UserInputMapper::InputChannel inputChannel);
|
||||
Q_INVOKABLE bool removeInputChannel(UserInputMapper::InputChannel inputChannel);
|
||||
Q_INVOKABLE QVector<UserInputMapper::InputChannel> getInputChannelsForAction(UserInputMapper::Action action);
|
||||
|
||||
Q_INVOKABLE QVector<UserInputMapper::InputPair> getAvailableInputs(unsigned int device);
|
||||
Q_INVOKABLE QVector<UserInputMapper::InputChannel> 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<QString> getDeviceNames();
|
||||
|
||||
Q_INVOKABLE int findAction(QString actionName);
|
||||
Q_INVOKABLE QVector<QString> 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<UserInputMapper::Action> getAllActions();
|
||||
|
||||
Q_INVOKABLE virtual bool addInputChannel(UserInputMapper::InputChannel inputChannel);
|
||||
Q_INVOKABLE virtual bool removeInputChannel(UserInputMapper::InputChannel inputChannel);
|
||||
Q_INVOKABLE virtual QVector<UserInputMapper::InputChannel> getInputChannelsForAction(UserInputMapper::Action action);
|
||||
|
||||
Q_INVOKABLE virtual QVector<UserInputMapper::InputPair> getAvailableInputs(unsigned int device);
|
||||
Q_INVOKABLE virtual QVector<UserInputMapper::InputChannel> 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<QString> getDeviceNames();
|
||||
|
||||
Q_INVOKABLE virtual int findAction(QString actionName);
|
||||
Q_INVOKABLE virtual QVector<QString> 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<int,KeyEvent> _capturedKeys;
|
||||
QSet<int> _capturedJoysticks;
|
||||
|
||||
typedef std::map< AbstractInputController::Key, AbstractInputController* > InputControllerMap;
|
||||
using InputKey = controller::InputController::Key;
|
||||
using InputControllerMap = std::map<InputKey, controller::InputController::Pointer>;
|
||||
InputControllerMap _inputControllers;
|
||||
|
||||
void wireUpControllers(ScriptEngine* engine);
|
||||
|
||||
controller::NewControllerScriptingInterface* _newControllerScriptingInterface = nullptr;
|
||||
};
|
||||
|
||||
const int NUMBER_OF_SPATIALCONTROLS_PER_PALM = 2; // the hand and the tip
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
#include "Application.h"
|
||||
#include <input-plugins/SixenseManager.h> // TODO: any references to sixense should be removed here
|
||||
#include <input-plugins/InputDevice.h>
|
||||
#include <controllers/InputDevice.h>
|
||||
|
||||
|
||||
// Used to animate the magnification windows
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
#include <input-plugins/UserInputMapper.h>
|
||||
#include "UserInputMapper.h"
|
||||
|
||||
class QScriptValue;
|
||||
|
||||
|
|
|
@ -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 <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
#include <QtQml/QJSValue>
|
||||
#include <QtScript/QScriptValue>
|
||||
|
||||
#include <input-plugins/UserInputMapper.h>
|
||||
|
||||
#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<QString, Mapping::Pointer>;
|
||||
using MappingStack = std::list<Mapping::Pointer>;
|
||||
using InputToEndpointMap = std::map<UserInputMapper::Input, Endpoint::Pointer>;
|
||||
using EndpointSet = std::unordered_set<Endpoint::Pointer>;
|
||||
using ValueMap = std::map<Endpoint::Pointer, float>;
|
||||
using EndpointPair = std::pair<Endpoint::Pointer, Endpoint::Pointer>;
|
||||
using EndpointPairMap = std::map<EndpointPair, Endpoint::Pointer>;
|
||||
|
||||
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
|
|
@ -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 <mutex>
|
||||
#include <set>
|
||||
|
@ -14,19 +14,15 @@
|
|||
|
||||
#include <GLMHelpers.h>
|
||||
#include <DependencyManager.h>
|
||||
#include <input-plugins/UserInputMapper.h>
|
||||
#include <input-plugins/InputPlugin.h>
|
||||
#include <input-plugins/KeyboardMouseDevice.h>
|
||||
#include <plugins/PluginManager.h>
|
||||
|
||||
#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<UserInputMapper>();
|
||||
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<UserInputMapper>();
|
||||
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>();
|
||||
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();
|
138
libraries/controllers/src/controllers/ScriptingInterface.h
Normal file
138
libraries/controllers/src/controllers/ScriptingInterface.h
Normal file
|
@ -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 <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
#include <QtQml/QJSValue>
|
||||
#include <QtScript/QScriptValue>
|
||||
|
||||
#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<InputController>;
|
||||
|
||||
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<QString, Mapping::Pointer>;
|
||||
using MappingStack = std::list<Mapping::Pointer>;
|
||||
using InputToEndpointMap = std::map<UserInputMapper::Input, Endpoint::Pointer>;
|
||||
using EndpointSet = std::unordered_set<Endpoint::Pointer>;
|
||||
using ValueMap = std::map<Endpoint::Pointer, float>;
|
||||
using EndpointPair = std::pair<Endpoint::Pointer, Endpoint::Pointer>;
|
||||
using EndpointPairMap = std::map<EndpointPair, Endpoint::Pointer>;
|
||||
|
||||
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
|
|
@ -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 <limits>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#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<UserInputMapper::DeviceProxy>(_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<UserInputMapper::InputPair> {
|
||||
QVector<UserInputMapper::InputPair> 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 <limits>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#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<UserInputMapper::DeviceProxy>(_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<UserInputMapper::InputPair> {
|
||||
QVector<UserInputMapper::InputPair> 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);
|
||||
}
|
|
@ -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 <qobject.h>
|
||||
#include <qvector.h>
|
||||
|
||||
#include "InputDevice.h"
|
||||
|
||||
#include "StandardControls.h"
|
||||
|
||||
typedef std::shared_ptr<StandardController> 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 <qobject.h>
|
||||
#include <qvector.h>
|
||||
|
||||
#include "InputDevice.h"
|
||||
|
||||
#include "StandardControls.h"
|
||||
|
||||
typedef std::shared_ptr<StandardController> 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
|
|
@ -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
|
||||
};
|
||||
|
||||
}
|
736
libraries/input-plugins/src/input-plugins/UserInputMapper.cpp → libraries/controllers/src/controllers/UserInputMapper.cpp
Executable file → Normal file
736
libraries/input-plugins/src/input-plugins/UserInputMapper.cpp → libraries/controllers/src/controllers/UserInputMapper.cpp
Executable file → Normal file
|
@ -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<QString> UserInputMapper::getDeviceNames() {
|
||||
QVector<QString> 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<ActionToInputsMap::iterator, ActionToInputsMap::iterator> 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<InputChannel> 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::InputChannel> UserInputMapper::getAllInputsForDevice(uint16 device) {
|
||||
InputChannels allChannels;
|
||||
getInputChannels(allChannels);
|
||||
|
||||
QVector<InputChannel> 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::Action> UserInputMapper::getAllActions() const {
|
||||
QVector<Action> actions;
|
||||
for (auto i = 0; i < NUM_ACTIONS; i++) {
|
||||
actions.append(Action(i));
|
||||
}
|
||||
return actions;
|
||||
}
|
||||
|
||||
QVector<UserInputMapper::InputChannel> UserInputMapper::getInputChannelsForAction(UserInputMapper::Action action) {
|
||||
QVector<InputChannel> inputChannels;
|
||||
std::pair <ActionToInputsMap::iterator, ActionToInputsMap::iterator> 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<QString> UserInputMapper::getActionNames() const {
|
||||
QVector<QString> 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>();
|
||||
_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<QString> UserInputMapper::getDeviceNames() {
|
||||
QVector<QString> 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<ActionToInputsMap::iterator, ActionToInputsMap::iterator> 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<InputChannel> 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::InputChannel> UserInputMapper::getAllInputsForDevice(uint16 device) {
|
||||
InputChannels allChannels;
|
||||
getInputChannels(allChannels);
|
||||
|
||||
QVector<InputChannel> 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::Action> UserInputMapper::getAllActions() const {
|
||||
QVector<Action> actions;
|
||||
for (auto i = 0; i < NUM_ACTIONS; i++) {
|
||||
actions.append(Action(i));
|
||||
}
|
||||
return actions;
|
||||
}
|
||||
|
||||
QVector<UserInputMapper::InputChannel> UserInputMapper::getInputChannelsForAction(UserInputMapper::Action action) {
|
||||
QVector<InputChannel> inputChannels;
|
||||
std::pair <ActionToInputsMap::iterator, ActionToInputsMap::iterator> 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<QString> UserInputMapper::getActionNames() const {
|
||||
QVector<QString> 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>();
|
||||
_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;
|
||||
}
|
||||
}
|
56
libraries/input-plugins/src/input-plugins/UserInputMapper.h → libraries/controllers/src/controllers/UserInputMapper.h
Executable file → Normal file
56
libraries/input-plugins/src/input-plugins/UserInputMapper.h → libraries/controllers/src/controllers/UserInputMapper.h
Executable file → Normal file
|
@ -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,
|
||||
};
|
|
@ -12,7 +12,7 @@
|
|||
#include <QtCore/QDebug>
|
||||
|
||||
#include "RouteBuilderProxy.h"
|
||||
#include "../NewControllerScriptingInterface.h"
|
||||
#include "../ScriptingInterface.h"
|
||||
#include "../Logging.h"
|
||||
|
||||
namespace controller {
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include <GLMHelpers.h>
|
||||
|
||||
#include "MappingBuilderProxy.h"
|
||||
#include "../NewControllerScriptingInterface.h"
|
||||
#include "../ScriptingInterface.h"
|
||||
#include "../Logging.h"
|
||||
|
||||
namespace controller {
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ InputPluginList getInputPlugins() {
|
|||
InputPlugin* PLUGIN_POOL[] = {
|
||||
new KeyboardMouseDevice(),
|
||||
new SDL2Manager(),
|
||||
new SixenseManager(),
|
||||
//new SixenseManager(),
|
||||
//new ViveControllerManager(),
|
||||
nullptr
|
||||
};
|
||||
|
|
|
@ -9,13 +9,10 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "Joystick.h"
|
||||
|
||||
#include "StandardControls.h"
|
||||
#include <limits>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
const float CONTROLLER_THRESHOLD = 0.3f;
|
||||
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
#undef main
|
||||
#endif
|
||||
|
||||
#include "InputDevice.h"
|
||||
#include "StandardControls.h"
|
||||
#include <controllers/InputDevice.h>
|
||||
#include <controllers/StandardControls.h>
|
||||
|
||||
class Joystick : public QObject, public InputDevice {
|
||||
Q_OBJECT
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#include <QtCore/QPoint>
|
||||
|
||||
#include "InputDevice.h"
|
||||
#include <controllers/InputDevice.h>
|
||||
#include "InputPlugin.h"
|
||||
|
||||
class QTouchEvent;
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
#include <SDL.h>
|
||||
#endif
|
||||
|
||||
#include "InputPlugin.h"
|
||||
#include "UserInputMapper.h"
|
||||
#include <controllers/UserInputMapper.h>
|
||||
|
||||
#include "InputPlugin.h"
|
||||
#include "Joystick.h"
|
||||
|
||||
class SDL2Manager : public InputPlugin {
|
||||
|
|
|
@ -24,8 +24,9 @@
|
|||
|
||||
#endif
|
||||
|
||||
#include <controllers/InputDevice.h>
|
||||
|
||||
#include "InputPlugin.h"
|
||||
#include "InputDevice.h"
|
||||
|
||||
class QLibrary;
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include <model/Geometry.h>
|
||||
#include <gpu/Texture.h>
|
||||
#include "InputDevice.h"
|
||||
#include <controllers/InputDevice.h>
|
||||
#include "InputPlugin.h"
|
||||
#include <RenderArgs.h>
|
||||
#include <render/Scene.h>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 <QtCore/QObject>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
#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
|
|
@ -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;
|
||||
|
|
|
@ -76,16 +76,16 @@ void avatarDataFromScriptValue(const QScriptValue &object, AvatarData* &out) {
|
|||
out = qobject_cast<AvatarData*>(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<AbstractInputController*>(object.toQObject());
|
||||
void inputControllerFromScriptValue(const QScriptValue &object, controller::InputController* &out) {
|
||||
out = qobject_cast<controller::InputController*>(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);
|
||||
//}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -26,8 +26,10 @@
|
|||
#include <LimitedNodeList.h>
|
||||
#include <EntityItemID.h>
|
||||
#include <EntitiesScriptEngineProvider.h>
|
||||
#include <controllers/ScriptingInterface.h>
|
||||
|
||||
#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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -13,7 +13,7 @@ Item {
|
|||
property color color: 'black'
|
||||
|
||||
function update() {
|
||||
value = NewControllers.getValue(controlId);
|
||||
value = Controllers.getValue(controlId);
|
||||
canvas.requestPaint();
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ Item {
|
|||
property string label: ""
|
||||
|
||||
function update() {
|
||||
value = NewControllers.getValue(controlId);
|
||||
value = Controllers.getValue(controlId);
|
||||
canvas.requestPaint();
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,10 +38,10 @@
|
|||
#include <plugins/PluginManager.h>
|
||||
#include <input-plugins/InputPlugin.h>
|
||||
#include <input-plugins/KeyboardMouseDevice.h>
|
||||
#include <controllers/NewControllerScriptingInterface.h>
|
||||
#include <controllers/ScriptingInterface.h>
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <input-plugins/UserInputMapper.h>
|
||||
#include <controllers/UserInputMapper.h>
|
||||
|
||||
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>();
|
||||
userInputMapper->update(delta);
|
||||
});
|
||||
timer.start(50);
|
||||
|
||||
{
|
||||
DependencyManager::set<UserInputMapper>();
|
||||
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();
|
||||
|
|
Loading…
Reference in a new issue