added left/right hand click actions, vive controller should be able to emulate mouse events

This commit is contained in:
Anthony J. Thibault 2015-07-07 14:35:55 -07:00
parent 5293effc2e
commit d75353eeb2
10 changed files with 168 additions and 17 deletions

View file

@ -671,6 +671,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
#endif
ViveControllerManager::getInstance().activate();
_oldHandMouseX[0] = -1;
_oldHandMouseY[0] = -1;
_oldHandMouseX[1] = -1;
_oldHandMouseY[1] = -1;
_oldHandLeftClick[0] = false;
_oldHandRightClick[0] = false;
_oldHandLeftClick[1] = false;
_oldHandRightClick[1] = false;
auto applicationUpdater = DependencyManager::get<AutoUpdater>();
connect(applicationUpdater.data(), &AutoUpdater::newVersionIsAvailable, dialogsManager.data(), &DialogsManager::showUpdateDialog);
@ -2622,6 +2631,12 @@ void Application::update(float deltaTime) {
Hand* hand = DependencyManager::get<AvatarManager>()->getMyAvatar()->getHand();
setPalmData(hand, leftHand, LEFT_HAND_INDEX);
setPalmData(hand, rightHand, RIGHT_HAND_INDEX);
if (Menu::getInstance()->isOptionChecked(MenuOption::HandMouseInput)) {
emulateMouse(hand, userInputMapper->getActionState(UserInputMapper::LEFT_HAND_CLICK),
userInputMapper->getActionState(UserInputMapper::SHIFT), LEFT_HAND_INDEX);
emulateMouse(hand, userInputMapper->getActionState(UserInputMapper::RIGHT_HAND_CLICK),
userInputMapper->getActionState(UserInputMapper::SHIFT), RIGHT_HAND_INDEX);
}
}
_myAvatar->setDriveKeys(BOOM_IN, userInputMapper->getActionState(UserInputMapper::BOOM_IN));
_myAvatar->setDriveKeys(BOOM_OUT, userInputMapper->getActionState(UserInputMapper::BOOM_OUT));
@ -2802,6 +2817,121 @@ void Application::setPalmData(Hand* hand, UserInputMapper::PoseValue pose, int i
palm->setRawRotation(pose.getRotation());
}
void Application::emulateMouse(Hand* hand, float click, float shift, int index) {
// Locate the palm, if it exists and is active
PalmData* palm;
bool foundHand = false;
for (size_t j = 0; j < hand->getNumPalms(); j++) {
if (hand->getPalms()[j].getSixenseID() == index) {
palm = &(hand->getPalms()[j]);
foundHand = true;
}
}
if (!foundHand || !palm->isActive()) {
return;
}
// Process the mouse events
QPoint pos;
unsigned int deviceID = index == 0 ? CONTROLLER_0_EVENT : CONTROLLER_1_EVENT;
if (Menu::getInstance()->isOptionChecked(MenuOption::HandLasers) || qApp->isHMDMode()) {
pos = qApp->getApplicationCompositor().getPalmClickLocation(palm);
}
else {
// Get directon relative to avatar orientation
glm::vec3 direction = glm::inverse(_myAvatar->getOrientation()) * palm->getFingerDirection();
// Get the angles, scaled between (-0.5,0.5)
float xAngle = (atan2(direction.z, direction.x) + M_PI_2);
float yAngle = 0.5f - ((atan2f(direction.z, direction.y) + (float)M_PI_2));
auto canvasSize = qApp->getCanvasSize();
// Get the pixel range over which the xAngle and yAngle are scaled
// TODO: move this from SixenseManager
float cursorRange = canvasSize.x * SixenseManager::getInstance().getCursorPixelRangeMult();
pos.setX(canvasSize.x / 2.0f + cursorRange * xAngle);
pos.setY(canvasSize.y / 2.0f + cursorRange * yAngle);
}
//If we are off screen then we should stop processing, and if a trigger or bumper is pressed,
//we should unpress them.
if (pos.x() == INT_MAX) {
if (_oldHandLeftClick[index]) {
QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, Qt::LeftButton, Qt::LeftButton, 0);
qApp->mouseReleaseEvent(&mouseEvent, deviceID);
_oldHandLeftClick[index] = false;
}
if (_oldHandRightClick[index]) {
QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, Qt::RightButton, Qt::RightButton, 0);
qApp->mouseReleaseEvent(&mouseEvent, deviceID);
_oldHandRightClick[index] = false;
}
return;
}
//If position has changed, emit a mouse move to the application
if (pos.x() != _oldHandMouseX[index] || pos.y() != _oldHandMouseY[index]) {
QMouseEvent mouseEvent(QEvent::MouseMove, pos, Qt::NoButton, Qt::NoButton, 0);
// Only send the mouse event if the opposite left button isnt held down.
// Is this check necessary?
if (!_oldHandLeftClick[(int)(!index)]) {
qApp->mouseMoveEvent(&mouseEvent, deviceID);
}
}
_oldHandMouseX[index] = pos.x();
_oldHandMouseY[index] = pos.y();
//We need separate coordinates for clicks, since we need to check if
//a magnification window was clicked on
int clickX = pos.x();
int clickY = pos.y();
//Set pos to the new click location, which may be the same if no magnification window is open
pos.setX(clickX);
pos.setY(clickY);
// Right click
if (shift == 1.0f && click == 1.0f) {
if (!_oldHandRightClick[index]) {
_oldHandRightClick[index] = true;
QMouseEvent mouseEvent(QEvent::MouseButtonPress, pos, Qt::RightButton, Qt::RightButton, 0);
qApp->mousePressEvent(&mouseEvent, deviceID);
}
} else if (_oldHandRightClick[index]) {
QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, Qt::RightButton, Qt::RightButton, 0);
qApp->mouseReleaseEvent(&mouseEvent, deviceID);
_oldHandRightClick[index] = false;
}
// Left click
if (shift != 1.0f && click == 1.0f) {
if (!_oldHandLeftClick[index]) {
_oldHandLeftClick[index] = true;
QMouseEvent mouseEvent(QEvent::MouseButtonPress, pos, Qt::LeftButton, Qt::LeftButton, 0);
qApp->mousePressEvent(&mouseEvent, deviceID);
}
} else if (_oldHandLeftClick[index]) {
QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, Qt::LeftButton, Qt::LeftButton, 0);
qApp->mouseReleaseEvent(&mouseEvent, deviceID);
_oldHandLeftClick[index] = false;
}
}
int Application::sendNackPackets() {
if (Menu::getInstance()->isOptionChecked(MenuOption::DisableNackPackets)) {
@ -3683,7 +3813,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
sceneInterface->setEngineDrawnOverlay3DItems(engineRC->_numDrawnOverlay3DItems);
}
//Render the sixense lasers
if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers)) {
if (Menu::getInstance()->isOptionChecked(MenuOption::HandLasers)) {
_myAvatar->renderLaserPointers(*renderArgs->_batch);
}

View file

@ -482,8 +482,9 @@ private:
void cleanupBeforeQuit();
void update(float deltaTime);
void setPalmData(Hand* hand, UserInputMapper::PoseValue pose, int index);
void emulateMouse(Hand* hand, float click, float shift, int index);
// Various helper functions called during update()
void updateLOD();
@ -671,6 +672,11 @@ private:
glm::vec3 _headPosition;
glm::quat _headOrientation;
int _oldHandMouseX[2];
int _oldHandMouseY[2];
bool _oldHandLeftClick[2];
bool _oldHandRightClick[2];
};
#endif // hifi_Application_h

View file

@ -466,6 +466,8 @@ Menu::Menu() {
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::AlternateIK, 0, false);
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHands, 0, true);
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false);
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::HandMouseInput, 0, true);
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::HandLasers, 0, false);
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::ShowIKConstraints, 0, false);
#if 0
@ -489,8 +491,6 @@ Menu::Menu() {
true,
qApp,
SLOT(setLowVelocityFilter(bool)));
addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, MenuOption::SixenseMouseInput, 0, true);
addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, MenuOption::SixenseLasers, 0, false);
#endif
MenuWrapper* leapOptionsMenu = handOptionsMenu->addMenu("Leap Motion");

View file

@ -199,6 +199,8 @@ namespace MenuOption {
const QString FrameTimer = "Show Timer";
const QString FullscreenMirror = "Fullscreen Mirror";
const QString GlowWhenSpeaking = "Glow When Speaking";
const QString HandMouseInput = "Enable Hand Mouse Input";
const QString HandLasers = "Enable Hand UI Lasers";
const QString IncreaseAvatarSize = "Increase Avatar Size";
const QString IndependentMode = "Independent Mode";
const QString KeyboardMotorControl = "Enable Keyboard Motor Control";
@ -270,8 +272,6 @@ namespace MenuOption {
const QString ShowRealtimeEntityStats = "Show Realtime Entity Stats";
const QString SimpleShadows = "Simple";
const QString SixenseEnabled = "Enable Hydra Support";
const QString SixenseMouseInput = "Enable Sixense Mouse Input";
const QString SixenseLasers = "Enable Sixense UI Lasers";
const QString ShiftHipsForIdleAnimations = "Shift hips for idle animations";
const QString Stars = "Stars";
const QString Stats = "Stats";

View file

@ -248,7 +248,7 @@ void SixenseManager::update(float deltaTime) {
handleAxisEvent(data->joystick_x, data->joystick_y, data->trigger, numActiveControllers - 1);
// Emulate the mouse so we can use scripts
if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseMouseInput) && !_controllersAtBase) {
if (Menu::getInstance()->isOptionChecked(MenuOption::HandMouseInput) && !_controllersAtBase) {
emulateMouse(palm, numActiveControllers - 1);
}
@ -518,7 +518,7 @@ void SixenseManager::emulateMouse(PalmData* palm, int index) {
triggerButton = Qt::LeftButton;
}
if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers) || qApp->isHMDMode()) {
if (Menu::getInstance()->isOptionChecked(MenuOption::HandLasers) || qApp->isHMDMode()) {
pos = qApp->getApplicationCompositor().getPalmClickLocation(palm);
} else {
// Get directon relative to avatar orientation

View file

@ -415,7 +415,7 @@ void ApplicationCompositor::renderPointers(gpu::Batch& batch) {
_magActive[MOUSE] = _magnifier;
_reticleActive[LEFT_CONTROLLER] = false;
_reticleActive[RIGHT_CONTROLLER] = false;
} else if (qApp->getLastMouseMoveWasSimulated() && Menu::getInstance()->isOptionChecked(MenuOption::SixenseMouseInput)) {
} else if (qApp->getLastMouseMoveWasSimulated() && Menu::getInstance()->isOptionChecked(MenuOption::HandMouseInput)) {
//only render controller pointer if we aren't already rendering a mouse pointer
_reticleActive[MOUSE] = false;
_magActive[MOUSE] = false;
@ -490,7 +490,7 @@ void ApplicationCompositor::renderControllerPointers(gpu::Batch& batch) {
auto canvasSize = qApp->getCanvasSize();
int mouseX, mouseY;
if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers)) {
if (Menu::getInstance()->isOptionChecked(MenuOption::HandLasers)) {
QPoint res = getPalmClickLocation(palmData);
mouseX = res.x();
mouseY = res.y();

View file

@ -248,6 +248,8 @@ void UserInputMapper::assignDefaulActionScales() {
_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
@ -270,6 +272,8 @@ void UserInputMapper::createActionNames() {
_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";

View file

@ -152,7 +152,10 @@ public:
LEFT_HAND,
RIGHT_HAND,
LEFT_HAND_CLICK,
RIGHT_HAND_CLICK,
SHIFT,
ACTION1,

View file

@ -31,10 +31,12 @@ const unsigned int RIGHT_MASK = 1U;
const uint64_t VR_BUTTON_A = 1U << 1;
const uint64_t VR_GRIP_BUTTON = 1U << 2;
const uint64_t VR_TRACKPAD_BUTTON = 1ULL << 32;
const uint64_t VR_TRIGGER_BUTTON = 1ULL << 33;
const unsigned int BUTTON_A = 1U << 1;
const unsigned int GRIP_BUTTON = 1U << 2;
const unsigned int TRACKPAD_BUTTON = 1U << 3;
const unsigned int TRIGGER_BUTTON = 1U << 4;
ViveControllerManager& ViveControllerManager::getInstance() {
static ViveControllerManager sharedInstance;
@ -111,11 +113,9 @@ void ViveControllerManager::update() {
if (_deviceID != 0) {
userInputMapper->removeDevice(_deviceID);
_deviceID = 0;
_poseStateMap[makeInput(LEFT_HAND).getChannel()] = UserInputMapper::PoseValue();
_poseStateMap[makeInput(RIGHT_HAND).getChannel()] = UserInputMapper::PoseValue();
//_poseStateMap[makeInput(LEFT_HAND).getChannel()] = UserInputMapper::PoseValue();
//_poseStateMap[makeInput(RIGHT_HAND).getChannel()] = UserInputMapper::PoseValue();
}
_trackedControllers = numTrackedControllers;
return;
}
if (_trackedControllers == 0 && numTrackedControllers > 0) {
@ -154,6 +154,9 @@ void ViveControllerManager::handleButtonEvent(uint64_t buttons, int index) {
if (buttons & VR_TRACKPAD_BUTTON) {
_buttonPressedMap.insert(makeInput(TRACKPAD_BUTTON, index).getChannel());
}
if (buttons & VR_TRIGGER_BUTTON) {
_buttonPressedMap.insert(makeInput(TRIGGER_BUTTON, index).getChannel());
}
}
void ViveControllerManager::handlePoseEvent(const mat4& mat, int index) {
@ -186,6 +189,7 @@ void ViveControllerManager::registerToUserInputMapper(UserInputMapper& mapper) {
availableInputs.append(UserInputMapper::InputPair(makeInput(BUTTON_A, 0), "Left Button A"));
availableInputs.append(UserInputMapper::InputPair(makeInput(GRIP_BUTTON, 0), "Left Grip Button"));
availableInputs.append(UserInputMapper::InputPair(makeInput(TRACKPAD_BUTTON, 0), "Left Trackpad Button"));
availableInputs.append(UserInputMapper::InputPair(makeInput(TRIGGER_BUTTON, 0), "Left Trigger Button"));
availableInputs.append(UserInputMapper::InputPair(makeInput(AXIS_Y_POS, 0), "Left Trackpad Up"));
availableInputs.append(UserInputMapper::InputPair(makeInput(AXIS_Y_NEG, 0), "Left Trackpad Down"));
@ -196,6 +200,7 @@ void ViveControllerManager::registerToUserInputMapper(UserInputMapper& mapper) {
availableInputs.append(UserInputMapper::InputPair(makeInput(BUTTON_A, 1), "Right Button A"));
availableInputs.append(UserInputMapper::InputPair(makeInput(GRIP_BUTTON, 1), "Right Grip Button"));
availableInputs.append(UserInputMapper::InputPair(makeInput(TRACKPAD_BUTTON, 1), "Right Trackpad Button"));
availableInputs.append(UserInputMapper::InputPair(makeInput(TRIGGER_BUTTON, 1), "Right Trigger Button"));
availableInputs.append(UserInputMapper::InputPair(makeInput(AXIS_Y_POS, 1), "Right Trackpad Up"));
availableInputs.append(UserInputMapper::InputPair(makeInput(AXIS_Y_NEG, 1), "Right Trackpad Down"));
@ -235,6 +240,9 @@ void ViveControllerManager::assignDefaultInputMapping(UserInputMapper& mapper) {
mapper.addInputChannel(UserInputMapper::ACTION1, makeInput(BUTTON_A, 0));
mapper.addInputChannel(UserInputMapper::ACTION2, makeInput(BUTTON_A, 1));
mapper.addInputChannel(UserInputMapper::LEFT_HAND_CLICK, makeInput(TRIGGER_BUTTON, 0));
mapper.addInputChannel(UserInputMapper::RIGHT_HAND_CLICK, makeInput(TRIGGER_BUTTON, 1));
// Hands
mapper.addInputChannel(UserInputMapper::LEFT_HAND, makeInput(LEFT_HAND));

View file

@ -148,6 +148,8 @@ public:
GlowWhenSpeaking,
NamesAboveHeads,
GoToUser,
HandMouseInput,
HandLasers,
HMDTools,
IncreaseAvatarSize,
KeyboardMotorControl,
@ -214,8 +216,6 @@ public:
ShowIKConstraints,
SimpleShadows,
SixenseEnabled,
SixenseMouseInput,
SixenseLasers,
ShiftHipsForIdleAnimations,
Stars,
Stats,