mirror of
https://github.com/Armored-Dragon/overte.git
synced 2025-03-11 16:13:16 +01:00
added options for both hands (default), all devices, short pulse, and fixed touch timing mechanism
This commit is contained in:
parent
afca0ec2c9
commit
e7743cd8e2
11 changed files with 105 additions and 41 deletions
|
@ -31,6 +31,12 @@ namespace controller {
|
|||
class Endpoint;
|
||||
using EndpointPointer = std::shared_ptr<Endpoint>;
|
||||
|
||||
enum Hand {
|
||||
LEFT = 0,
|
||||
RIGHT,
|
||||
BOTH
|
||||
};
|
||||
|
||||
// NOTE: If something inherits from both InputDevice and InputPlugin, InputPlugin must go first.
|
||||
// e.g. class Example : public InputPlugin, public InputDevice
|
||||
// instead of class Example : public InputDevice, public InputPlugin
|
||||
|
@ -56,7 +62,7 @@ public:
|
|||
const QString& getName() const { return _name; }
|
||||
|
||||
// By default, Input Devices do not support haptics
|
||||
virtual bool triggerHapticPulse(float strength, float duration, bool leftHand) { return false; }
|
||||
virtual bool triggerHapticPulse(float strength, float duration, controller::Hand hand) { return false; }
|
||||
|
||||
// Update call MUST be called once per simulation loop
|
||||
// It takes care of updating the action states and deltas
|
||||
|
|
|
@ -140,8 +140,22 @@ namespace controller {
|
|||
return DependencyManager::get<UserInputMapper>()->getActionNames();
|
||||
}
|
||||
|
||||
bool ScriptingInterface::triggerHapticPulse(unsigned int device, float strength, float duration, bool leftHand) const {
|
||||
return DependencyManager::get<UserInputMapper>()->triggerHapticPulse(device, strength, duration, leftHand);
|
||||
bool ScriptingInterface::triggerHapticPulse(float strength, float duration, controller::Hand hand) const {
|
||||
return DependencyManager::get<UserInputMapper>()->triggerHapticPulse(strength, duration, hand);
|
||||
}
|
||||
|
||||
bool ScriptingInterface::triggerShortHapticPulse(float strength, controller::Hand hand) const {
|
||||
const float SHORT_HAPTIC_DURATION_MS = 250.0f;
|
||||
return DependencyManager::get<UserInputMapper>()->triggerHapticPulse(strength, SHORT_HAPTIC_DURATION_MS, hand);
|
||||
}
|
||||
|
||||
bool ScriptingInterface::triggerHapticPulseOnDevice(unsigned int device, float strength, float duration, controller::Hand hand) const {
|
||||
return DependencyManager::get<UserInputMapper>()->triggerHapticPulseOnDevice(device, strength, duration, hand);
|
||||
}
|
||||
|
||||
bool ScriptingInterface::triggerShortHapticPulseOnDevice(unsigned int device, float strength, controller::Hand hand) const {
|
||||
const float SHORT_HAPTIC_DURATION_MS = 250.0f;
|
||||
return DependencyManager::get<UserInputMapper>()->triggerHapticPulseOnDevice(device, strength, SHORT_HAPTIC_DURATION_MS, hand);
|
||||
}
|
||||
|
||||
void ScriptingInterface::updateMaps() {
|
||||
|
|
|
@ -84,7 +84,10 @@ namespace controller {
|
|||
Q_INVOKABLE Pose getPoseValue(const int& source) const;
|
||||
Q_INVOKABLE Pose getPoseValue(StandardPoseChannel source, uint16_t device = 0) const;
|
||||
|
||||
Q_INVOKABLE bool triggerHapticPulse(unsigned int device, float strength, float duration, bool leftHand = true) const;
|
||||
Q_INVOKABLE bool triggerHapticPulse(float strength, float duration, controller::Hand hand = BOTH) const;
|
||||
Q_INVOKABLE bool triggerShortHapticPulse(float strength, controller::Hand hand = BOTH) const;
|
||||
Q_INVOKABLE bool triggerHapticPulseOnDevice(unsigned int device, float strength, float duration, controller::Hand hand = BOTH) const;
|
||||
Q_INVOKABLE bool triggerShortHapticPulseOnDevice(unsigned int device, float strength, controller::Hand hand = BOTH) const;
|
||||
|
||||
Q_INVOKABLE QObject* newMapping(const QString& mappingName = QUuid::createUuid().toString());
|
||||
Q_INVOKABLE void enableMapping(const QString& mappingName, bool enable = true);
|
||||
|
|
|
@ -336,10 +336,19 @@ QVector<QString> UserInputMapper::getActionNames() const {
|
|||
return result;
|
||||
}
|
||||
|
||||
bool UserInputMapper::triggerHapticPulse(uint16 deviceID, float strength, float duration, bool leftHand) {
|
||||
bool UserInputMapper::triggerHapticPulse(float strength, float duration, controller::Hand hand) {
|
||||
Locker locker(_lock);
|
||||
bool toReturn = false;
|
||||
for (auto device : _registeredDevices) {
|
||||
toReturn = toReturn || device.second->triggerHapticPulse(strength, duration, hand);
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
bool UserInputMapper::triggerHapticPulseOnDevice(uint16 deviceID, float strength, float duration, controller::Hand hand) {
|
||||
Locker locker(_lock);
|
||||
if (_registeredDevices.find(deviceID) != _registeredDevices.end()) {
|
||||
return _registeredDevices[deviceID]->triggerHapticPulse(strength, duration, leftHand);
|
||||
return _registeredDevices[deviceID]->triggerHapticPulse(strength, duration, hand);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -348,6 +357,7 @@ int actionMetaTypeId = qRegisterMetaType<Action>();
|
|||
int inputMetaTypeId = qRegisterMetaType<Input>();
|
||||
int inputPairMetaTypeId = qRegisterMetaType<Input::NamedPair>();
|
||||
int poseMetaTypeId = qRegisterMetaType<controller::Pose>("Pose");
|
||||
int handMetaTypeId = qRegisterMetaType<controller::Hand>();
|
||||
|
||||
QScriptValue inputToScriptValue(QScriptEngine* engine, const Input& input);
|
||||
void inputFromScriptValue(const QScriptValue& object, Input& input);
|
||||
|
@ -355,6 +365,8 @@ QScriptValue actionToScriptValue(QScriptEngine* engine, const Action& action);
|
|||
void actionFromScriptValue(const QScriptValue& object, Action& action);
|
||||
QScriptValue inputPairToScriptValue(QScriptEngine* engine, const Input::NamedPair& inputPair);
|
||||
void inputPairFromScriptValue(const QScriptValue& object, Input::NamedPair& inputPair);
|
||||
QScriptValue handToScriptValue(QScriptEngine* engine, const controller::Hand& hand);
|
||||
void handFromScriptValue(const QScriptValue& object, controller::Hand& hand);
|
||||
|
||||
QScriptValue inputToScriptValue(QScriptEngine* engine, const Input& input) {
|
||||
QScriptValue obj = engine->newObject();
|
||||
|
@ -393,12 +405,21 @@ void inputPairFromScriptValue(const QScriptValue& object, Input::NamedPair& inpu
|
|||
inputPair.second = QString(object.property("inputName").toVariant().toString());
|
||||
}
|
||||
|
||||
QScriptValue handToScriptValue(QScriptEngine* engine, const controller::Hand& hand) {
|
||||
return engine->newVariant((int)hand);
|
||||
}
|
||||
|
||||
void handFromScriptValue(const QScriptValue& object, controller::Hand& hand) {
|
||||
hand = Hand(object.toVariant().toInt());
|
||||
}
|
||||
|
||||
void UserInputMapper::registerControllerTypes(QScriptEngine* engine) {
|
||||
qScriptRegisterSequenceMetaType<QVector<Action> >(engine);
|
||||
qScriptRegisterSequenceMetaType<Input::NamedVector>(engine);
|
||||
qScriptRegisterMetaType(engine, actionToScriptValue, actionFromScriptValue);
|
||||
qScriptRegisterMetaType(engine, inputToScriptValue, inputFromScriptValue);
|
||||
qScriptRegisterMetaType(engine, inputPairToScriptValue, inputPairFromScriptValue);
|
||||
qScriptRegisterMetaType(engine, handToScriptValue, handFromScriptValue);
|
||||
|
||||
qScriptRegisterMetaType(engine, Pose::toScriptValue, Pose::fromScriptValue);
|
||||
}
|
||||
|
|
|
@ -89,7 +89,8 @@ namespace controller {
|
|||
void setActionState(Action action, float value) { _actionStates[toInt(action)] = value; }
|
||||
void deltaActionState(Action action, float delta) { _actionStates[toInt(action)] += delta; }
|
||||
void setActionState(Action action, const Pose& value) { _poseStates[toInt(action)] = value; }
|
||||
bool triggerHapticPulse(uint16 deviceID, float strength, float duration, bool leftHand);
|
||||
bool triggerHapticPulse(float strength, float duration, controller::Hand hand);
|
||||
bool triggerHapticPulseOnDevice(uint16 deviceID, float strength, float duration, controller::Hand hand);
|
||||
|
||||
static Input makeStandardInput(controller::StandardButtonChannel button);
|
||||
static Input makeStandardInput(controller::StandardAxisChannel axis);
|
||||
|
@ -200,6 +201,7 @@ Q_DECLARE_METATYPE(QVector<controller::Input::NamedPair>)
|
|||
Q_DECLARE_METATYPE(controller::Input)
|
||||
Q_DECLARE_METATYPE(controller::Action)
|
||||
Q_DECLARE_METATYPE(QVector<controller::Action>)
|
||||
Q_DECLARE_METATYPE(controller::Hand)
|
||||
|
||||
// Cheating.
|
||||
using UserInputMapper = controller::UserInputMapper;
|
||||
|
|
|
@ -67,7 +67,7 @@ void Joystick::handleButtonEvent(const SDL_ControllerButtonEvent& event) {
|
|||
}
|
||||
}
|
||||
|
||||
bool Joystick::triggerHapticPulse(float strength, float duration, bool leftHand) {
|
||||
bool Joystick::triggerHapticPulse(float strength, float duration, controller::Hand hand) {
|
||||
if (SDL_HapticRumblePlay(_sdlHaptic, strength, duration) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ public:
|
|||
virtual void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override;
|
||||
virtual void focusOutEvent() override;
|
||||
|
||||
bool triggerHapticPulse(float strength, float duration, bool leftHand) override;
|
||||
bool triggerHapticPulse(float strength, float duration, controller::Hand hand) override;
|
||||
|
||||
Joystick() : InputDevice("GamePad") {}
|
||||
~Joystick();
|
||||
|
|
|
@ -55,11 +55,6 @@ bool OculusControllerManager::activate() {
|
|||
userInputMapper->registerDevice(_touch);
|
||||
}
|
||||
|
||||
_leftHapticTimer.setSingleShot(true);
|
||||
_rightHapticTimer.setSingleShot(true);
|
||||
connect(&_leftHapticTimer, SIGNAL(timeout()), this, SLOT(stopHapticPulse(true)));
|
||||
connect(&_rightHapticTimer, SIGNAL(timeout()), this, SLOT(stopHapticPulse(false)));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -221,6 +216,21 @@ void OculusControllerManager::TouchDevice::update(float deltaTime, const control
|
|||
_buttonPressedMap.insert(pair.second);
|
||||
}
|
||||
}
|
||||
|
||||
// Haptics
|
||||
{
|
||||
Locker locker(_lock);
|
||||
if (_leftHapticDuration > 0.0f) {
|
||||
_leftHapticDuration -= deltaTime;
|
||||
} else {
|
||||
stopHapticPulse(true);
|
||||
}
|
||||
if (_rightHapticDuration > 0.0f) {
|
||||
_rightHapticDuration -= deltaTime;
|
||||
} else {
|
||||
stopHapticPulse(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OculusControllerManager::TouchDevice::focusOutEvent() {
|
||||
|
@ -239,19 +249,22 @@ void OculusControllerManager::TouchDevice::handlePose(float deltaTime,
|
|||
pose.velocity = toGlm(handPose.LinearVelocity);
|
||||
}
|
||||
|
||||
bool OculusControllerManager::TouchDevice::triggerHapticPulse(float strength, float duration, bool leftHand) {
|
||||
auto handType = (leftHand ? ovrControllerType_LTouch : ovrControllerType_RTouch);
|
||||
if (ovr_SetControllerVibration(_parent._session, handType, 1.0f, strength) != ovrSuccess) {
|
||||
return false;
|
||||
bool OculusControllerManager::TouchDevice::triggerHapticPulse(float strength, float duration, controller::Hand hand) {
|
||||
Locker locker(_lock);
|
||||
bool toReturn = true;
|
||||
if (hand == controller::BOTH || hand == controller::LEFT) {
|
||||
if (ovr_SetControllerVibration(_parent._session, ovrControllerType_LTouch, 1.0f, strength) != ovrSuccess) {
|
||||
toReturn = false;
|
||||
}
|
||||
_leftHapticDuration = duration;
|
||||
}
|
||||
|
||||
if (leftHand) {
|
||||
_parent._leftHapticTimer.start(duration);
|
||||
} else {
|
||||
_parent._rightHapticTimer.start(duration);
|
||||
if (hand == controller::BOTH || hand == controller::RIGHT) {
|
||||
if (ovr_SetControllerVibration(_parent._session, ovrControllerType_RTouch, 1.0f, strength) != ovrSuccess) {
|
||||
toReturn = false;
|
||||
}
|
||||
_rightHapticDuration = duration;
|
||||
}
|
||||
|
||||
return true;
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
void OculusControllerManager::TouchDevice::stopHapticPulse(bool leftHand) {
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#define hifi__OculusControllerManager
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <GLMHelpers.h>
|
||||
|
@ -68,20 +67,28 @@ private:
|
|||
void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override;
|
||||
void focusOutEvent() override;
|
||||
|
||||
bool triggerHapticPulse(float strength, float duration, bool leftHand) override;
|
||||
bool triggerHapticPulse(float strength, float duration, controller::Hand hand) override;
|
||||
|
||||
private:
|
||||
void stopHapticPulse(bool leftHand);
|
||||
void handlePose(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, ovrHandType hand, const ovrPoseStatef& handPose);
|
||||
int _trackedControllers { 0 };
|
||||
|
||||
// perform an action when the TouchDevice mutex is acquired.
|
||||
using Locker = std::unique_lock<std::recursive_mutex>;
|
||||
template <typename F>
|
||||
void withLock(F&& f) { Locker locker(_lock); f(); }
|
||||
|
||||
float _leftHapticDuration { 0.0f };
|
||||
float _rightHapticDuration { 0.0f };
|
||||
mutable std::recursive_mutex _lock;
|
||||
|
||||
friend class OculusControllerManager;
|
||||
};
|
||||
|
||||
ovrSession _session { nullptr };
|
||||
ovrInputState _inputState {};
|
||||
RemoteDevice::Pointer _remote;
|
||||
QTimer _leftHapticTimer;
|
||||
QTimer _rightHapticTimer;
|
||||
TouchDevice::Pointer _touch;
|
||||
static const QString NAME;
|
||||
};
|
||||
|
|
|
@ -452,12 +452,13 @@ void ViveControllerManager::InputDevice::handlePoseEvent(float deltaTime, const
|
|||
_poseStateMap[isLeftHand ? controller::LEFT_HAND : controller::RIGHT_HAND] = avatarPose.transform(controllerToAvatar);
|
||||
}
|
||||
|
||||
bool ViveControllerManager::InputDevice::triggerHapticPulse(float strength, float duration, bool leftHand) {
|
||||
bool ViveControllerManager::InputDevice::triggerHapticPulse(float strength, float duration, controller::Hand hand) {
|
||||
Locker locker(_lock);
|
||||
if (leftHand) {
|
||||
if (hand == controller::BOTH || hand == controller::LEFT) {
|
||||
_leftHapticStrength = strength;
|
||||
_leftHapticDuration = duration;
|
||||
} else {
|
||||
}
|
||||
if (hand == controller::BOTH || hand == controller::RIGHT) {
|
||||
_rightHapticStrength = strength;
|
||||
_rightHapticDuration = duration;
|
||||
}
|
||||
|
@ -481,9 +482,6 @@ void ViveControllerManager::InputDevice::hapticsHelper(float deltaTime, bool lef
|
|||
_system->TriggerHapticPulse(deviceIndex, 0, hapticTime);
|
||||
}
|
||||
|
||||
// Must wait 5 ms before triggering another pulse on this controller
|
||||
// https://github.com/ValveSoftware/openvr/wiki/IVRSystem::TriggerHapticPulse
|
||||
const float HAPTIC_RESET_TIME = 5.0f;
|
||||
float remainingHapticTime = duration - (hapticTime / 1000.0f + deltaTime * 1000.0f); // in milliseconds
|
||||
if (leftHand) {
|
||||
_leftHapticDuration = remainingHapticTime;
|
||||
|
|
|
@ -48,7 +48,7 @@ public:
|
|||
private:
|
||||
class InputDevice : public controller::InputDevice {
|
||||
public:
|
||||
InputDevice(vr::IVRSystem*& system) : controller::InputDevice("Vive"), _system(system), _leftHapticDuration(0.0f), _rightHapticDuration(0.0f) {}
|
||||
InputDevice(vr::IVRSystem*& system) : controller::InputDevice("Vive"), _system(system) {}
|
||||
private:
|
||||
// Device functions
|
||||
controller::Input::NamedVector getAvailableInputs() const override;
|
||||
|
@ -56,7 +56,7 @@ private:
|
|||
void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override;
|
||||
void focusOutEvent() override;
|
||||
|
||||
bool triggerHapticPulse(float strength, float duration, bool leftHand) override;
|
||||
bool triggerHapticPulse(float strength, float duration, controller::Hand hand) override;
|
||||
void hapticsHelper(float deltaTime, bool leftHand);
|
||||
|
||||
void handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand);
|
||||
|
@ -100,10 +100,10 @@ private:
|
|||
|
||||
int _trackedControllers { 0 };
|
||||
vr::IVRSystem*& _system;
|
||||
float _leftHapticStrength;
|
||||
float _leftHapticDuration;
|
||||
float _rightHapticStrength;
|
||||
float _rightHapticDuration;
|
||||
float _leftHapticStrength { 0.0f };
|
||||
float _leftHapticDuration { 0.0f };
|
||||
float _rightHapticStrength { 0.0f };
|
||||
float _rightHapticDuration { 0.0f };
|
||||
mutable std::recursive_mutex _lock;
|
||||
|
||||
friend class ViveControllerManager;
|
||||
|
|
Loading…
Reference in a new issue