Merge pull request #6050 from ZappoMan/newControllerInterface

Expose Controller.Hardware.* constants to JavaScript
This commit is contained in:
Brad Davis 2015-10-10 12:43:43 -07:00
commit 700c11563c
9 changed files with 111 additions and 13 deletions

View file

@ -11,6 +11,16 @@
// Assumes you only have the default keyboard connected
Object.keys(Controller.Hardware).forEach(function (deviceName) {
Object.keys(Controller.Hardware[deviceName]).forEach(function (input) {
print(deviceName + "." + input + ":" + Controller.Hardware[deviceName][input]);
});
});
Object.keys(Controller.Actions).forEach(function (actionName) {
print(actionName + ":" + Controller.Actions[actionName]);
});
// Resets every device to its default key bindings:
Controller.resetAllDeviceBindings();

View file

@ -91,6 +91,9 @@ public:
/// Get the name assigned to the Device when registered after creation, or "Unknown" if it hasn't been registered which should not happen.
const Name& getName() const { return _name; }
typedef std::map< Name, ID > Map;
static const Map& getDevices() { return Singleton::get()->_devicesMap; }
protected:
DeviceTracker();
virtual ~DeviceTracker();
@ -103,7 +106,6 @@ private:
void assignIDAndName( const ID id, const Name& name ) { _ID = id; _name = name; }
typedef std::vector< DeviceTracker* > Vector;
typedef std::map< Name, ID > Map;
struct SingletonData {
Map _devicesMap;
Vector _devicesVector;

View file

@ -111,7 +111,7 @@ void inputPairFromScriptValue(const QScriptValue& object, UserInputMapper::Input
inputPair.second = QString(object.property("inputName").toVariant().toString());
}
void ControllerScriptingInterface::registerControllerTypes(QScriptEngine* engine) {
void ControllerScriptingInterface::registerControllerTypes(ScriptEngine* engine) {
qScriptRegisterSequenceMetaType<QVector<UserInputMapper::Action> >(engine);
qScriptRegisterSequenceMetaType<QVector<UserInputMapper::InputChannel> >(engine);
qScriptRegisterSequenceMetaType<QVector<UserInputMapper::InputPair> >(engine);
@ -119,6 +119,8 @@ void ControllerScriptingInterface::registerControllerTypes(QScriptEngine* engine
qScriptRegisterMetaType(engine, inputChannelToScriptValue, inputChannelFromScriptValue);
qScriptRegisterMetaType(engine, inputToScriptValue, inputFromScriptValue);
qScriptRegisterMetaType(engine, inputPairToScriptValue, inputPairFromScriptValue);
wireUpControllers(engine);
}
void ControllerScriptingInterface::handleMetaEvent(HFMetaEvent* event) {
@ -381,6 +383,38 @@ 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.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) {
// This is where we retreive the Device Tracker category and then the sub tracker within it
//TODO C++11 auto icIt = _inputControllers.find(0);

View file

@ -56,7 +56,7 @@ class ControllerScriptingInterface : public AbstractControllerScriptingInterface
public:
ControllerScriptingInterface();
virtual void registerControllerTypes(QScriptEngine* engine);
virtual void registerControllerTypes(ScriptEngine* engine);
void emitKeyPressEvent(QKeyEvent* event) { emit keyPressEvent(KeyEvent(*event)); }
void emitKeyReleaseEvent(QKeyEvent* event) { emit keyReleaseEvent(KeyEvent(*event)); }
@ -150,6 +150,8 @@ public slots:
virtual void releaseInputController(AbstractInputController* input);
private:
QString sanatizeName(const QString& name); /// makes a name clean for inclusing in JavaScript
const PalmData* getPrimaryPalm() const;
const PalmData* getPalm(int palmIndex) const;
int getNumberOfActivePalms() const;
@ -164,6 +166,9 @@ private:
typedef std::map< AbstractInputController::Key, AbstractInputController* > InputControllerMap;
InputControllerMap _inputControllers;
void wireUpControllers(ScriptEngine* engine);
};
const int NUMBER_OF_SPATIALCONTROLS_PER_PALM = 2; // the hand and the tip

View file

@ -319,4 +319,6 @@ void UserInputMapper::createActionNames() {
_actionNames[SHIFT] = "SHIFT";
_actionNames[ACTION1] = "ACTION1";
_actionNames[ACTION2] = "ACTION2";
_actionNames[CONTEXT_MENU] = "CONTEXT_MENU";
_actionNames[TOGGLE_MUTE] = "TOGGLE_MUTE";
}

View file

@ -109,7 +109,8 @@ public:
class DeviceProxy {
public:
DeviceProxy(QString name) { _name = name; }
const QString& getName() const { return _name; }
QString _name;
ButtonGetter getButton = [] (const Input& input, int timestamp) -> bool { return false; };
AxisGetter getAxis = [] (const Input& input, int timestamp) -> float { return 0.0f; };
@ -234,12 +235,14 @@ public:
UserInputMapper();
typedef std::map<int, DeviceProxy::Pointer> DevicesMap;
DevicesMap getDevices() { return _registeredDevices; }
signals:
void actionEvent(int action, float state);
protected:
typedef std::map<int, DeviceProxy::Pointer> DevicesMap;
DevicesMap _registeredDevices;
uint16 _nextFreeDeviceID = 1;

View file

@ -24,6 +24,8 @@
#include "TouchEvent.h"
#include "WheelEvent.h"
class ScriptEngine;
class AbstractInputController : public QObject {
Q_OBJECT
@ -52,7 +54,7 @@ class AbstractControllerScriptingInterface : public QObject {
Q_OBJECT
public slots:
virtual void registerControllerTypes(QScriptEngine* engine) = 0;
virtual void registerControllerTypes(ScriptEngine* engine) = 0;
virtual bool isPrimaryButtonPressed() const = 0;
virtual glm::vec2 getPrimaryJoystickPosition() const = 0;

View file

@ -277,10 +277,6 @@ void ScriptEngine::init() {
registerAvatarTypes(this);
registerAudioMetaTypes(this);
if (_controllerScriptingInterface) {
_controllerScriptingInterface->registerControllerTypes(this);
}
qScriptRegisterMetaType(this, EntityPropertyFlagsToScriptValue, EntityPropertyFlagsFromScriptValue);
qScriptRegisterMetaType(this, EntityItemPropertiesToScriptValue, EntityItemPropertiesFromScriptValueHonorReadOnly);
qScriptRegisterMetaType(this, EntityItemIDtoScriptValue, EntityItemIDfromScriptValue);
@ -323,6 +319,43 @@ void ScriptEngine::init() {
// constants
globalObject().setProperty("TREE_SCALE", newVariant(QVariant(TREE_SCALE)));
if (_controllerScriptingInterface) {
_controllerScriptingInterface->registerControllerTypes(this);
}
}
void ScriptEngine::registerValue(const QString& valueName, QScriptValue value) {
if (QThread::currentThread() != thread()) {
#ifdef THREAD_DEBUGGING
qDebug() << "*** WARNING *** ScriptEngine::registerValue() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] name:" << name;
#endif
QMetaObject::invokeMethod(this, "registerValue",
Q_ARG(const QString&, valueName),
Q_ARG(QScriptValue, value));
return;
}
QStringList pathToValue = valueName.split(".");
int partsToGo = pathToValue.length();
QScriptValue partObject = globalObject();
for (const auto& pathPart : pathToValue) {
partsToGo--;
if (!partObject.property(pathPart).isValid()) {
if (partsToGo > 0) {
//QObject *object = new QObject;
QScriptValue partValue = newArray(); //newQObject(object, QScriptEngine::ScriptOwnership);
qDebug() << "partValue[" << pathPart<<"].isArray() :" << partValue.isArray();
partObject.setProperty(pathPart, partValue);
} else {
partObject.setProperty(pathPart, value);
}
}
partObject = partObject.property(pathPart);
}
}
void ScriptEngine::registerGlobalObject(const QString& name, QObject* object) {
@ -339,9 +372,13 @@ void ScriptEngine::registerGlobalObject(const QString& name, QObject* object) {
qDebug() << "ScriptEngine::registerGlobalObject() called on thread [" << QThread::currentThread() << "] name:" << name;
#endif
if (object) {
QScriptValue value = newQObject(object);
globalObject().setProperty(name, value);
if (!globalObject().property(name).isValid()) {
if (object) {
QScriptValue value = newQObject(object);
globalObject().setProperty(name, value);
} else {
globalObject().setProperty(name, QScriptValue());
}
}
}

View file

@ -84,6 +84,9 @@ public:
Q_INVOKABLE void registerFunction(const QString& parent, const QString& name, QScriptEngine::FunctionSignature fun,
int numArguments = -1);
/// registers a global object by name
Q_INVOKABLE void registerValue(const QString& valueName, QScriptValue value);
/// evaluate some code in the context of the ScriptEngine and return the result
Q_INVOKABLE QScriptValue evaluate(const QString& program, const QString& fileName = QString(), int lineNumber = 1); // this is also used by the script tool widget