diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index efe2193629..24cdabe772 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4450,7 +4450,8 @@ void Application::loadScript() { bool wantMenuItems = true; // tells the ScriptEngine object to add menu items for itself - ScriptEngine* scriptEngine = new ScriptEngine(script, wantMenuItems, fileName, Menu::getInstance()); + ScriptEngine* scriptEngine = new ScriptEngine(script, wantMenuItems, fileName, Menu::getInstance(), + &_controllerScriptingInterface); scriptEngine->setupMenuItems(); // setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so diff --git a/interface/src/Application.h b/interface/src/Application.h index 7680388e9f..e917f6d63d 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -71,6 +71,8 @@ #include "ui/LogDialog.h" #include "ParticleTreeRenderer.h" #include "ParticleEditHandle.h" +#include "ControllerScriptingInterface.h" + class QAction; class QActionGroup; @@ -505,7 +507,7 @@ private: std::vector _voxelFades; std::vector _avatarFades; - + ControllerScriptingInterface _controllerScriptingInterface; QPointer _logDialog; }; diff --git a/interface/src/ControllerScriptingInterface.cpp b/interface/src/ControllerScriptingInterface.cpp new file mode 100644 index 0000000000..fd27eb2428 --- /dev/null +++ b/interface/src/ControllerScriptingInterface.cpp @@ -0,0 +1,183 @@ +// +// ControllerScriptingInterface.h +// hifi +// +// Created by Brad Hefta-Gaub on 12/17/13 +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// + +#include +#include "Application.h" +#include "ControllerScriptingInterface.h" + +const PalmData* ControllerScriptingInterface::getPrimaryPalm() const { + int leftPalmIndex, rightPalmIndex; + + const HandData* handData = Application::getInstance()->getAvatar()->getHandData(); + handData->getLeftRightPalmIndices(leftPalmIndex, rightPalmIndex); + + if (rightPalmIndex != -1) { + return &handData->getPalms()[rightPalmIndex]; + } + + return NULL; +} + +int ControllerScriptingInterface::getNumberOfActivePalms() const { + const HandData* handData = Application::getInstance()->getAvatar()->getHandData(); + int numberOfPalms = handData->getNumPalms(); + int numberOfActivePalms = 0; + for (int i = 0; i < numberOfPalms; i++) { + if (getPalm(i)->isActive()) { + numberOfActivePalms++; + } + } + return numberOfActivePalms; +} + +const PalmData* ControllerScriptingInterface::getPalm(int palmIndex) const { + const HandData* handData = Application::getInstance()->getAvatar()->getHandData(); + return &handData->getPalms()[palmIndex]; +} + +const PalmData* ControllerScriptingInterface::getActivePalm(int palmIndex) const { + const HandData* handData = Application::getInstance()->getAvatar()->getHandData(); + int numberOfPalms = handData->getNumPalms(); + int numberOfActivePalms = 0; + for (int i = 0; i < numberOfPalms; i++) { + if (getPalm(i)->isActive()) { + if (numberOfActivePalms == palmIndex) { + return &handData->getPalms()[i]; + } + numberOfActivePalms++; + } + } + return NULL; +} + +bool ControllerScriptingInterface::isPrimaryButtonPressed() const { + const PalmData* primaryPalm = getPrimaryPalm(); + if (primaryPalm) { + if (primaryPalm->getControllerButtons() & BUTTON_FWD) { + return true; + } + } + + return false; +} + +glm::vec2 ControllerScriptingInterface::getPrimaryJoystickPosition() const { + const PalmData* primaryPalm = getPrimaryPalm(); + if (primaryPalm) { + return glm::vec2(primaryPalm->getJoystickX(), primaryPalm->getJoystickY()); + } + + return glm::vec2(0); +} + +int ControllerScriptingInterface::getNumberOfButtons() const { + return getNumberOfActivePalms() * NUMBER_OF_BUTTONS_PER_PALM; +} + +bool ControllerScriptingInterface::isButtonPressed(int buttonIndex) const { + int palmIndex = buttonIndex / NUMBER_OF_BUTTONS_PER_PALM; + int buttonOnPalm = buttonIndex % NUMBER_OF_BUTTONS_PER_PALM; + const PalmData* palmData = getActivePalm(palmIndex); + if (palmData) { + switch (buttonOnPalm) { + case 0: + return palmData->getControllerButtons() & BUTTON_0; + case 1: + return palmData->getControllerButtons() & BUTTON_1; + case 2: + return palmData->getControllerButtons() & BUTTON_2; + case 3: + return palmData->getControllerButtons() & BUTTON_3; + case 4: + return palmData->getControllerButtons() & BUTTON_4; + case 5: + return palmData->getControllerButtons() & BUTTON_FWD; + } + } + return false; +} + +int ControllerScriptingInterface::getNumberOfTriggers() const { + return getNumberOfActivePalms() * NUMBER_OF_TRIGGERS_PER_PALM; +} + +float ControllerScriptingInterface::getTriggerValue(int triggerIndex) const { + // we know there's one trigger per palm, so the triggerIndex is the palm Index + int palmIndex = triggerIndex; + const PalmData* palmData = getActivePalm(palmIndex); + if (palmData) { + return palmData->getTrigger(); + } + return 0.0f; +} + +int ControllerScriptingInterface::getNumberOfJoysticks() const { + return getNumberOfActivePalms() * NUMBER_OF_JOYSTICKS_PER_PALM; +} + +glm::vec2 ControllerScriptingInterface::getJoystickPosition(int joystickIndex) const { + // we know there's one joystick per palm, so the joystickIndex is the palm Index + int palmIndex = joystickIndex; + const PalmData* palmData = getActivePalm(palmIndex); + if (palmData) { + return glm::vec2(palmData->getJoystickX(), palmData->getJoystickY()); + } + return glm::vec2(0); +} + +int ControllerScriptingInterface::getNumberOfSpatialControls() const { + return getNumberOfActivePalms() * NUMBER_OF_SPATIALCONTROLS_PER_PALM; +} + +glm::vec3 ControllerScriptingInterface::getSpatialControlPosition(int controlIndex) const { + int palmIndex = controlIndex / NUMBER_OF_SPATIALCONTROLS_PER_PALM; + int controlOfPalm = controlIndex % NUMBER_OF_SPATIALCONTROLS_PER_PALM; + const PalmData* palmData = getActivePalm(palmIndex); + if (palmData) { + switch (controlOfPalm) { + case PALM_SPATIALCONTROL: + return palmData->getPosition(); + case TIP_SPATIALCONTROL: + return palmData->getTipPosition(); + } + } + return glm::vec3(0); // bad index +} + +glm::vec3 ControllerScriptingInterface::getSpatialControlVelocity(int controlIndex) const { + int palmIndex = controlIndex / NUMBER_OF_SPATIALCONTROLS_PER_PALM; + int controlOfPalm = controlIndex % NUMBER_OF_SPATIALCONTROLS_PER_PALM; + const PalmData* palmData = getActivePalm(palmIndex); + if (palmData) { + switch (controlOfPalm) { + case PALM_SPATIALCONTROL: + return palmData->getVelocity(); + case TIP_SPATIALCONTROL: + return palmData->getTipVelocity(); + } + } + return glm::vec3(0); // bad index +} + +glm::vec3 ControllerScriptingInterface::getSpatialControlNormal(int controlIndex) const { + int palmIndex = controlIndex / NUMBER_OF_SPATIALCONTROLS_PER_PALM; + int controlOfPalm = controlIndex % NUMBER_OF_SPATIALCONTROLS_PER_PALM; + const PalmData* palmData = getActivePalm(palmIndex); + if (palmData) { + switch (controlOfPalm) { + case PALM_SPATIALCONTROL: + return palmData->getNormal(); + case TIP_SPATIALCONTROL: + return palmData->getNormal(); // currently the tip doesn't have a unique normal, use the palm normal + } + } + return glm::vec3(0); // bad index +} + + + diff --git a/interface/src/ControllerScriptingInterface.h b/interface/src/ControllerScriptingInterface.h new file mode 100644 index 0000000000..d0e032d52f --- /dev/null +++ b/interface/src/ControllerScriptingInterface.h @@ -0,0 +1,52 @@ +// +// ControllerScriptingInterface.h +// hifi +// +// Created by Brad Hefta-Gaub on 12/17/13 +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// + +#ifndef __hifi__ControllerScriptingInterface__ +#define __hifi__ControllerScriptingInterface__ + +#include + +#include + +/// handles scripting of input controller commands from JS +class ControllerScriptingInterface : public AbstractControllerScriptingInterface { + Q_OBJECT + +public slots: + 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; + +private: + const PalmData* getPrimaryPalm() const; + const PalmData* getPalm(int palmIndex) const; + int getNumberOfActivePalms() const; + const PalmData* getActivePalm(int palmIndex) const; +}; + +const int NUMBER_OF_SPATIALCONTROLS_PER_PALM = 2; // the hand and the tip +const int NUMBER_OF_JOYSTICKS_PER_PALM = 1; +const int NUMBER_OF_TRIGGERS_PER_PALM = 1; +const int NUMBER_OF_BUTTONS_PER_PALM = 6; +const int PALM_SPATIALCONTROL = 0; +const int TIP_SPATIALCONTROL = 1; + +#endif /* defined(__hifi__ControllerScriptingInterface__) */ diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index abeb7f9686..a0c8fed980 100755 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -53,9 +53,10 @@ public: glm::vec3 worldPositionToLeapPosition(const glm::vec3& worldPosition) const; glm::vec3 worldVectorToLeapVector(const glm::vec3& worldVector) const; - std::vector& getPalms() { return _palms; } - size_t getNumPalms() { return _palms.size(); } - PalmData& addNewPalm(); + std::vector& getPalms() { return _palms; } + const std::vector& getPalms() const { return _palms; } + size_t getNumPalms() const { return _palms.size(); } + PalmData& addNewPalm(); /// Finds the indices of the left and right palms according to their locations, or -1 if either or /// both is not found. @@ -137,17 +138,18 @@ public: const glm::vec3& getRawPosition() const { return _rawPosition; } const glm::vec3& getRawNormal() const { return _rawNormal; } - bool isActive() const { return _isActive; } - int getLeapID() const { return _leapID; } - int getSixenseID() const { return _sixenseID; } + bool isActive() const { return _isActive; } + int getLeapID() const { return _leapID; } + int getSixenseID() const { return _sixenseID; } - std::vector& getFingers() { return _fingers; } - size_t getNumFingers() { return _fingers.size(); } + std::vector& getFingers() { return _fingers; } + const std::vector& getFingers() const { return _fingers; } + size_t getNumFingers() const { return _fingers.size(); } - void setActive(bool active) { _isActive = active; } - void setLeapID(int id) { _leapID = id; } - void setSixenseID(int id) { _sixenseID = id; } + void setActive(bool active) { _isActive = active; } + void setLeapID(int id) { _leapID = id; } + void setSixenseID(int id) { _sixenseID = id; } void setRawRotation(const glm::quat rawRotation) { _rawRotation = rawRotation; }; glm::quat getRawRotation() const { return _rawRotation; } @@ -164,27 +166,27 @@ public: const glm::vec3& getTipVelocity() const { return _tipVelocity; } void setTipVelocity(const glm::vec3& velocity) { _tipVelocity = velocity; } - void incrementFramesWithoutData() { _numFramesWithoutData++; } - void resetFramesWithoutData() { _numFramesWithoutData = 0; } - int getFramesWithoutData() const { return _numFramesWithoutData; } + void incrementFramesWithoutData() { _numFramesWithoutData++; } + void resetFramesWithoutData() { _numFramesWithoutData = 0; } + int getFramesWithoutData() const { return _numFramesWithoutData; } // Controller buttons void setControllerButtons(int controllerButtons) { _controllerButtons = controllerButtons; } void setLastControllerButtons(int controllerButtons) { _lastControllerButtons = controllerButtons; } - int getControllerButtons() { return _controllerButtons; } - int getLastControllerButtons() { return _lastControllerButtons; } + int getControllerButtons() const { return _controllerButtons; } + int getLastControllerButtons() const { return _lastControllerButtons; } void setTrigger(float trigger) { _trigger = trigger; } - float getTrigger() { return _trigger; } + float getTrigger() const { return _trigger; } void setJoystick(float joystickX, float joystickY) { _joystickX = joystickX; _joystickY = joystickY; } - float getJoystickX() { return _joystickX; } - float getJoystickY() { return _joystickY; } + float getJoystickX() const { return _joystickX; } + float getJoystickY() const { return _joystickY; } - bool getIsCollidingWithVoxel() { return _isCollidingWithVoxel; } + bool getIsCollidingWithVoxel() const { return _isCollidingWithVoxel; } void setIsCollidingWithVoxel(bool isCollidingWithVoxel) { _isCollidingWithVoxel = isCollidingWithVoxel; } - bool getIsCollidingWithPalm() { return _isCollidingWithPalm; } + bool getIsCollidingWithPalm() const { return _isCollidingWithPalm; } void setIsCollidingWithPalm(bool isCollidingWithPalm) { _isCollidingWithPalm = isCollidingWithPalm; } private: diff --git a/libraries/script-engine/src/AbstractControllerScriptingInterface.h b/libraries/script-engine/src/AbstractControllerScriptingInterface.h new file mode 100644 index 0000000000..5c791af0a4 --- /dev/null +++ b/libraries/script-engine/src/AbstractControllerScriptingInterface.h @@ -0,0 +1,38 @@ +// +// AbstractControllerScriptingInterface.h +// hifi +// +// Created by Brad Hefta-Gaub on 12/17/13 +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// + +#ifndef __hifi__AbstractControllerScriptingInterface__ +#define __hifi__AbstractControllerScriptingInterface__ + +#include +#include + +/// handles scripting of input controller commands from JS +class AbstractControllerScriptingInterface : public QObject { + Q_OBJECT + +public slots: + 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; +}; + +#endif /* defined(__hifi__AbstractControllerScriptingInterface__) */ diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 35585ad6ef..24c4fcf1d9 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -25,7 +25,8 @@ int ScriptEngine::_scriptNumber = 1; ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems, - const char* scriptMenuName, AbstractMenuInterface* menu) { + const char* scriptMenuName, AbstractMenuInterface* menu, + AbstractControllerScriptingInterface* controllerScriptingInterface) { _scriptContents = scriptContents; _isFinished = false; _isRunning = false; @@ -41,6 +42,7 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems, _scriptMenuName.append(_scriptNumber); } _menu = menu; + _controllerScriptingInterface = controllerScriptingInterface; } ScriptEngine::~ScriptEngine() { @@ -87,6 +89,11 @@ void ScriptEngine::run() { QScriptValue particleScripterValue = engine.newQObject(&_particleScriptingInterface); engine.globalObject().setProperty("Particles", particleScripterValue); + if (_controllerScriptingInterface) { + QScriptValue controllerScripterValue = engine.newQObject(_controllerScriptingInterface); + engine.globalObject().setProperty("Controller", controllerScripterValue); + } + QScriptValue treeScaleValue = engine.newVariant(QVariant(TREE_SCALE)); engine.globalObject().setProperty("TREE_SCALE", treeScaleValue); diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 2e0d7fcc40..c5172a5772 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -18,6 +18,7 @@ #include #include #include +#include "AbstractControllerScriptingInterface.h" const QString NO_SCRIPT(""); @@ -25,7 +26,8 @@ class ScriptEngine : public QObject { Q_OBJECT public: ScriptEngine(const QString& scriptContents = NO_SCRIPT, bool wantMenuItems = false, - const char* scriptMenuName = NULL, AbstractMenuInterface* menu = NULL); + const char* scriptMenuName = NULL, AbstractMenuInterface* menu = NULL, + AbstractControllerScriptingInterface* controllerScriptingInterface = NULL); ~ScriptEngine(); @@ -58,6 +60,7 @@ protected: private: VoxelScriptingInterface _voxelScriptingInterface; ParticleScriptingInterface _particleScriptingInterface; + AbstractControllerScriptingInterface* _controllerScriptingInterface; bool _wantMenuItems; QString _scriptMenuName; AbstractMenuInterface* _menu; diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index de9fcae781..9a099b4171 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -12,6 +12,7 @@ void registerMetaTypes(QScriptEngine* engine) { qScriptRegisterMetaType(engine, vec3toScriptValue, vec3FromScriptValue); + qScriptRegisterMetaType(engine, vec2toScriptValue, vec2FromScriptValue); qScriptRegisterMetaType(engine, xColorToScriptValue, xColorFromScriptValue); } @@ -29,6 +30,19 @@ void vec3FromScriptValue(const QScriptValue &object, glm::vec3 &vec3) { vec3.z = object.property("z").toVariant().toFloat(); } +QScriptValue vec2toScriptValue(QScriptEngine* engine, const glm::vec2 &vec2) { + QScriptValue obj = engine->newObject(); + obj.setProperty("x", vec2.x); + obj.setProperty("y", vec2.y); + return obj; +} + +void vec2FromScriptValue(const QScriptValue &object, glm::vec2 &vec2) { + vec2.x = object.property("x").toVariant().toFloat(); + vec2.y = object.property("y").toVariant().toFloat(); +} + + QScriptValue xColorToScriptValue(QScriptEngine *engine, const xColor& color) { QScriptValue obj = engine->newObject(); obj.setProperty("red", color.red); diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 51a4562c87..b5d3d80e2f 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -17,11 +17,17 @@ #include "SharedUtil.h" Q_DECLARE_METATYPE(glm::vec3) +Q_DECLARE_METATYPE(glm::vec2) Q_DECLARE_METATYPE(xColor) void registerMetaTypes(QScriptEngine* engine); + QScriptValue vec3toScriptValue(QScriptEngine* engine, const glm::vec3 &vec3); void vec3FromScriptValue(const QScriptValue &object, glm::vec3 &vec3); + +QScriptValue vec2toScriptValue(QScriptEngine* engine, const glm::vec2 &vec2); +void vec2FromScriptValue(const QScriptValue &object, glm::vec2 &vec2); + QScriptValue xColorToScriptValue(QScriptEngine* engine, const xColor& color); void xColorFromScriptValue(const QScriptValue &object, xColor& color);