mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-08 19:23:28 +02:00
first cut at simulating mouse/reticle behavior with input contorllers
This commit is contained in:
parent
205bc1b790
commit
3dcdfbc0f1
13 changed files with 123 additions and 353 deletions
39
examples/controllers/reticleTests.js
Normal file
39
examples/controllers/reticleTests.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// reticleTest.js
|
||||
// examples/controllers
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 2015/12/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
|
||||
//
|
||||
|
||||
var mappingJSON = {
|
||||
"name": "com.highfidelity.testing.reticleWithJoystick",
|
||||
"channels": [
|
||||
{ "from": "Standard.RT", "to": "Actions.ReticleClick", "filters": "constrainToInteger" },
|
||||
|
||||
{ "from": "Standard.RX", "to": "Actions.ReticleX",
|
||||
"filters":
|
||||
[
|
||||
{ "type": "pulse", "interval": 0.05 },
|
||||
{ "type": "scale", "scale": 20 }
|
||||
]
|
||||
},
|
||||
{ "from": "Standard.RY", "to": "Actions.ReticleY",
|
||||
"filters":
|
||||
[
|
||||
{ "type": "pulse", "interval": 0.05 },
|
||||
{ "type": "scale", "scale": 20 }
|
||||
]
|
||||
},
|
||||
]
|
||||
};
|
||||
|
||||
mapping = Controller.parseMapping(JSON.stringify(mappingJSON));
|
||||
mapping.enable();
|
||||
|
||||
Script.scriptEnding.connect(function(){
|
||||
mapping.disable();
|
||||
});
|
|
@ -11,7 +11,7 @@
|
|||
{ "from": "Keyboard.S", "when": "Keyboard.Shift", "to": "Actions.PITCH_DOWN" },
|
||||
{ "from": "Keyboard.W", "when": "Keyboard.Shift", "to": "Actions.PITCH_UP" },
|
||||
|
||||
|
||||
|
||||
{ "comment" : "Mouse turn need to be small continuous increments",
|
||||
"from": { "makeAxis" : [
|
||||
[ "Keyboard.MouseMoveLeft" ],
|
||||
|
@ -75,7 +75,6 @@
|
|||
{ "from": "Keyboard.S", "to": "Actions.LONGITUDINAL_BACKWARD" },
|
||||
{ "from": "Keyboard.C", "to": "Actions.VERTICAL_DOWN" },
|
||||
{ "from": "Keyboard.E", "to": "Actions.VERTICAL_UP" },
|
||||
|
||||
{ "from": "Keyboard.Left", "when": "Keyboard.RightMouseButton", "to": "Actions.LATERAL_LEFT" },
|
||||
{ "from": "Keyboard.Right", "when": "Keyboard.RightMouseButton", "to": "Actions.LATERAL_RIGHT" },
|
||||
{ "from": "Keyboard.Left", "when": "Keyboard.Shift", "to": "Actions.LATERAL_LEFT" },
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
{ "type": "scale", "scale": 22.5 }
|
||||
]
|
||||
},
|
||||
{ "from": "Standard.RX", "to": "Actions.Yaw" },
|
||||
|
||||
{ "from": "Standard.RX", "to": "Actions.Yaw" },
|
||||
{ "from": "Standard.RY",
|
||||
"when": "Application.Grounded",
|
||||
"to": "Actions.Up",
|
||||
|
@ -24,6 +24,7 @@
|
|||
"invert"
|
||||
]
|
||||
},
|
||||
|
||||
{ "from": "Standard.RY", "to": "Actions.Up", "filters": "invert"},
|
||||
|
||||
{ "from": [ "Standard.DU", "Standard.DL", "Standard.DR", "Standard.DD" ], "to": "Standard.LeftPrimaryThumb" },
|
||||
|
|
|
@ -382,7 +382,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
_scaleMirror(1.0f),
|
||||
_rotateMirror(0.0f),
|
||||
_raiseMirror(0.0f),
|
||||
_lastMouseMoveWasSimulated(false),
|
||||
_enableProcessOctreeThread(true),
|
||||
_runningScriptsWidget(NULL),
|
||||
_runningScriptsWidgetWasVisible(false),
|
||||
|
@ -664,6 +663,21 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
// Setup the userInputMapper with the actions
|
||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
connect(userInputMapper.data(), &UserInputMapper::actionEvent, [this](int action, float state) {
|
||||
if (action == controller::toInt(controller::Action::RETICLE_CLICK)) {
|
||||
auto globalPos = getReticlePosition();
|
||||
auto localPos = _glWidget->mapFromGlobal(globalPos);
|
||||
if (state) {
|
||||
QMouseEvent mousePress(QEvent::MouseButtonPress, localPos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
|
||||
sendEvent(_glWidget, &mousePress);
|
||||
_reticleClickPressed = true;
|
||||
} else {
|
||||
QMouseEvent mouseRelease(QEvent::MouseButtonRelease, localPos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
|
||||
sendEvent(_glWidget, &mouseRelease);
|
||||
_reticleClickPressed = false;
|
||||
}
|
||||
return; // nothing else to do
|
||||
}
|
||||
|
||||
if (state) {
|
||||
if (action == controller::toInt(controller::Action::TOGGLE_MUTE)) {
|
||||
DependencyManager::get<AudioClient>()->toggleMute();
|
||||
|
@ -671,6 +685,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
cycleCamera();
|
||||
} else if (action == controller::toInt(controller::Action::CONTEXT_MENU)) {
|
||||
VrMenu::toggle(); // show context menu even on non-stereo displays
|
||||
} else if (action == controller::toInt(controller::Action::RETICLE_X)) {
|
||||
auto reticlePos = getReticlePosition();
|
||||
reticlePos.setX(reticlePos.x() + state);
|
||||
setReticlePosition(reticlePos);
|
||||
} else if (action == controller::toInt(controller::Action::RETICLE_Y)) {
|
||||
auto reticlePos = getReticlePosition();
|
||||
reticlePos.setY(reticlePos.y() + state);
|
||||
setReticlePosition(reticlePos);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -692,8 +714,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
|
||||
// Setup the keyboardMouseDevice and the user input mapper with the default bindings
|
||||
userInputMapper->registerDevice(_keyboardMouseDevice->getInputDevice());
|
||||
|
||||
|
||||
userInputMapper->loadDefaultMapping(userInputMapper->getStandardDeviceID());
|
||||
|
||||
// check first run...
|
||||
|
@ -745,15 +765,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
setActiveEyeTracker();
|
||||
#endif
|
||||
|
||||
_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);
|
||||
applicationUpdater->checkForUpdate();
|
||||
|
@ -1940,8 +1951,6 @@ void Application::focusOutEvent(QFocusEvent* event) {
|
|||
|
||||
void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) {
|
||||
PROFILE_RANGE(__FUNCTION__);
|
||||
// Used by application overlay to determine how to draw cursor(s)
|
||||
_lastMouseMoveWasSimulated = deviceID > 0;
|
||||
|
||||
if (_aboutToQuit) {
|
||||
return;
|
||||
|
@ -1969,11 +1978,20 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) {
|
|||
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
QPointF transformedPos = offscreenUi->mapToVirtualScreen(event->localPos(), _glWidget);
|
||||
auto button = event->button();
|
||||
auto buttons = event->buttons();
|
||||
// Determine if the ReticleClick Action is 1 and if so, fake include the LeftMouseButton
|
||||
if (_reticleClickPressed) {
|
||||
if (button == Qt::NoButton) {
|
||||
button = Qt::LeftButton;
|
||||
}
|
||||
buttons |= Qt::LeftButton;
|
||||
}
|
||||
|
||||
QMouseEvent mappedEvent(event->type(),
|
||||
transformedPos,
|
||||
event->screenPos(), event->button(),
|
||||
event->buttons(), event->modifiers());
|
||||
|
||||
event->screenPos(), button,
|
||||
buttons, event->modifiers());
|
||||
|
||||
getEntities()->mouseMoveEvent(&mappedEvent, deviceID);
|
||||
_controllerScriptingInterface->emitMouseMoveEvent(&mappedEvent, deviceID); // send events to any registered scripts
|
||||
|
@ -2877,13 +2895,6 @@ void Application::update(float deltaTime) {
|
|||
Hand* hand = DependencyManager::get<AvatarManager>()->getMyAvatar()->getHand();
|
||||
setPalmData(hand, leftHand, deltaTime, HandData::LeftHand, userInputMapper->getActionState(controller::Action::LEFT_HAND_CLICK));
|
||||
setPalmData(hand, rightHand, deltaTime, HandData::RightHand, userInputMapper->getActionState(controller::Action::RIGHT_HAND_CLICK));
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::EnableHandMouseInput)) {
|
||||
emulateMouse(hand, userInputMapper->getActionState(controller::Action::LEFT_HAND_CLICK),
|
||||
userInputMapper->getActionState(controller::Action::SHIFT), HandData::LeftHand);
|
||||
emulateMouse(hand, userInputMapper->getActionState(controller::Action::RIGHT_HAND_CLICK),
|
||||
userInputMapper->getActionState(controller::Action::SHIFT), HandData::RightHand);
|
||||
}
|
||||
|
||||
updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process...
|
||||
updateDialogs(deltaTime); // update various stats dialogs if present
|
||||
|
||||
|
@ -4742,6 +4753,14 @@ bool Application::isThrottleRendering() const {
|
|||
return getActiveDisplayPlugin()->isThrottled();
|
||||
}
|
||||
|
||||
QPoint Application::getReticlePosition() const {
|
||||
return QCursor::pos();
|
||||
}
|
||||
|
||||
void Application::setReticlePosition(QPoint position) {
|
||||
QCursor::setPos(position);
|
||||
}
|
||||
|
||||
ivec2 Application::getTrueMouse() const {
|
||||
return toGlm(_glWidget->mapFromGlobal(QCursor::pos()));
|
||||
}
|
||||
|
@ -5062,125 +5081,6 @@ void Application::setPalmData(Hand* hand, const controller::Pose& pose, float de
|
|||
});
|
||||
}
|
||||
|
||||
void Application::emulateMouse(Hand* hand, float click, float shift, HandData::Hand whichHand) {
|
||||
auto palms = hand->getCopyOfPalms();
|
||||
|
||||
// Locate the palm, if it exists and is active
|
||||
PalmData* palm;
|
||||
bool foundHand = false;
|
||||
for (size_t j = 0; j < palms.size(); j++) {
|
||||
if (palms[j].whichHand() == whichHand) {
|
||||
palm = &(palms[j]);
|
||||
foundHand = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundHand || !palm->isActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Process the mouse events
|
||||
QPoint pos;
|
||||
|
||||
|
||||
// FIXME - this mouse emulation stuff needs to be reworked for new controller input plugins
|
||||
unsigned int deviceID = whichHand == HandData::LeftHand ? CONTROLLER_0_EVENT : CONTROLLER_1_EVENT;
|
||||
int index = (int)whichHand; // FIXME - hack attack
|
||||
|
||||
if (isHMDMode()) {
|
||||
pos = getApplicationCompositor().getPalmClickLocation(palm);
|
||||
} else {
|
||||
// Get directon relative to avatar orientation
|
||||
glm::vec3 direction = glm::inverse(getMyAvatar()->getOrientation()) * palm->getFingerDirection();
|
||||
|
||||
// Get the angles, scaled between (-0.5,0.5)
|
||||
float xAngle = (atan2f(direction.z, direction.x) + (float)M_PI_2);
|
||||
float yAngle = 0.5f - ((atan2f(direction.z, direction.y) + (float)M_PI_2));
|
||||
auto canvasSize = getCanvasSize();
|
||||
// Get the pixel range over which the xAngle and yAngle are scaled
|
||||
float cursorRange = canvasSize.x * controller::InputDevice::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);
|
||||
|
||||
mouseReleaseEvent(&mouseEvent, deviceID);
|
||||
|
||||
_oldHandLeftClick[index] = false;
|
||||
}
|
||||
if (_oldHandRightClick[index]) {
|
||||
QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, Qt::RightButton, Qt::RightButton, 0);
|
||||
|
||||
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)]) {
|
||||
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);
|
||||
|
||||
mousePressEvent(&mouseEvent, deviceID);
|
||||
}
|
||||
} else if (_oldHandRightClick[index]) {
|
||||
QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, Qt::RightButton, Qt::RightButton, 0);
|
||||
|
||||
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);
|
||||
|
||||
mousePressEvent(&mouseEvent, deviceID);
|
||||
}
|
||||
} else if (_oldHandLeftClick[index]) {
|
||||
QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, Qt::LeftButton, Qt::LeftButton, 0);
|
||||
|
||||
mouseReleaseEvent(&mouseEvent, deviceID);
|
||||
|
||||
_oldHandLeftClick[index] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Application::crashApplication() {
|
||||
qCDebug(interfaceapp) << "Intentionally crashed Interface";
|
||||
QObject* object = nullptr;
|
||||
|
|
|
@ -143,9 +143,11 @@ public:
|
|||
EntityTreeRenderer* getEntityClipboardRenderer() { return &_entityClipboardRenderer; }
|
||||
EntityEditPacketSender* getEntityEditPacketSender() { return &_entityEditSender; }
|
||||
|
||||
QPoint getReticlePosition() const;
|
||||
void setReticlePosition(QPoint position);
|
||||
|
||||
ivec2 getMouse() const;
|
||||
ivec2 getTrueMouse() const;
|
||||
bool getLastMouseMoveWasSimulated() const { return _lastMouseMoveWasSimulated; }
|
||||
|
||||
FaceTracker* getActiveFaceTracker();
|
||||
FaceTracker* getSelectedFaceTracker();
|
||||
|
@ -361,7 +363,6 @@ private:
|
|||
void update(float deltaTime);
|
||||
|
||||
void setPalmData(Hand* hand, const controller::Pose& pose, float deltaTime, HandData::Hand whichHand, float triggerValue);
|
||||
void emulateMouse(Hand* hand, float click, float shift, HandData::Hand whichHand);
|
||||
|
||||
// Various helper functions called during update()
|
||||
void updateLOD();
|
||||
|
@ -476,8 +477,6 @@ private:
|
|||
|
||||
Environment _environment;
|
||||
|
||||
bool _lastMouseMoveWasSimulated;
|
||||
|
||||
QSet<int> _keysPressed;
|
||||
|
||||
bool _enableProcessOctreeThread;
|
||||
|
@ -537,14 +536,6 @@ private:
|
|||
ApplicationCompositor _compositor;
|
||||
OverlayConductor _overlayConductor;
|
||||
|
||||
|
||||
// FIXME - Hand Controller to mouse emulation helpers. This is crufty and should be moved
|
||||
// into the input plugins or something.
|
||||
int _oldHandMouseX[(int)HandData::NUMBER_OF_HANDS];
|
||||
int _oldHandMouseY[(int)HandData::NUMBER_OF_HANDS];
|
||||
bool _oldHandLeftClick[(int)HandData::NUMBER_OF_HANDS];
|
||||
bool _oldHandRightClick[(int)HandData::NUMBER_OF_HANDS];
|
||||
|
||||
DialogsManagerScriptingInterface* _dialogsManagerScriptingInterface = new DialogsManagerScriptingInterface();
|
||||
|
||||
EntityItemID _keyboardFocusedItem;
|
||||
|
@ -559,6 +550,8 @@ private:
|
|||
bool _inPaint = false;
|
||||
bool _isGLInitialized { false };
|
||||
bool _physicsEnabled { false };
|
||||
|
||||
bool _reticleClickPressed { false };
|
||||
};
|
||||
|
||||
#endif // hifi_Application_h
|
||||
|
|
|
@ -477,7 +477,6 @@ Menu::Menu() {
|
|||
|
||||
MenuWrapper* handOptionsMenu = developerMenu->addMenu("Hands");
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false);
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::EnableHandMouseInput, 0, false);
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::LowVelocityFilter, 0, true,
|
||||
qApp, SLOT(setLowVelocityFilter(bool)));
|
||||
|
||||
|
|
|
@ -219,7 +219,6 @@ namespace MenuOption {
|
|||
const QString FrameTimer = "Show Timer";
|
||||
const QString FullscreenMirror = "Fullscreen Mirror";
|
||||
const QString GlowWhenSpeaking = "Glow When Speaking";
|
||||
const QString EnableHandMouseInput = "Enable Hand Controller Mouse Input";
|
||||
const QString IncreaseAvatarSize = "Increase Avatar Size";
|
||||
const QString IndependentMode = "Independent Mode";
|
||||
const QString InputMenu = "Avatar>Input Devices";
|
||||
|
|
|
@ -115,10 +115,6 @@ bool raySphereIntersect(const glm::vec3 &dir, const glm::vec3 &origin, float r,
|
|||
ApplicationCompositor::ApplicationCompositor() :
|
||||
_alphaPropertyAnimation(new QPropertyAnimation(this, "alpha"))
|
||||
{
|
||||
memset(_reticleActive, 0, sizeof(_reticleActive));
|
||||
memset(_magActive, 0, sizeof(_reticleActive));
|
||||
memset(_magSizeMult, 0, sizeof(_magSizeMult));
|
||||
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
|
||||
_reticleQuad = geometryCache->allocateID();
|
||||
|
@ -219,9 +215,6 @@ void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) {
|
|||
batch.setResourceTexture(0, overlayFramebuffer->getRenderBuffer(0));
|
||||
geometryCache->renderUnitQuad(batch, vec4(vec3(1), _alpha));
|
||||
|
||||
// Doesn't actually render
|
||||
renderPointers(batch);
|
||||
|
||||
//draw the mouse pointer
|
||||
// Get the mouse coordinates and convert to NDC [-1, 1]
|
||||
vec2 canvasSize = qApp->getCanvasSize();
|
||||
|
@ -306,8 +299,7 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int
|
|||
}
|
||||
#endif
|
||||
|
||||
// Doesn't actually render
|
||||
renderPointers(batch);
|
||||
|
||||
vec3 reticleScale = vec3(Cursor::Manager::instance().getScale() * reticleSize);
|
||||
|
||||
bindCursorTexture(batch);
|
||||
|
@ -316,34 +308,13 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int
|
|||
glm::mat4 overlayXfm;
|
||||
_modelTransform.getMatrix(overlayXfm);
|
||||
|
||||
// Only render the hand pointers if the EnableHandMouseInput is enabled
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::EnableHandMouseInput)) {
|
||||
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
auto palms = myAvatar->getHand()->getCopyOfPalms();
|
||||
for (const auto& palm : palms) {
|
||||
if (palm.isActive()) {
|
||||
glm::vec2 polar = getPolarCoordinates(palm);
|
||||
// Convert to quaternion
|
||||
mat4 pointerXfm = glm::mat4_cast(quat(vec3(polar.y, -polar.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1));
|
||||
mat4 reticleXfm = overlayXfm * pointerXfm;
|
||||
reticleXfm = glm::scale(reticleXfm, reticleScale);
|
||||
batch.setModelTransform(reticleXfm);
|
||||
// Render reticle at location
|
||||
geometryCache->renderUnitQuad(batch, glm::vec4(1), _reticleQuad);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Mouse Pointer
|
||||
if (_reticleActive[MOUSE]) {
|
||||
glm::vec2 projection = screenToSpherical(glm::vec2(_reticlePosition[MOUSE].x(),
|
||||
_reticlePosition[MOUSE].y()));
|
||||
mat4 pointerXfm = glm::mat4_cast(quat(vec3(-projection.y, projection.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1));
|
||||
mat4 reticleXfm = overlayXfm * pointerXfm;
|
||||
reticleXfm = glm::scale(reticleXfm, reticleScale);
|
||||
batch.setModelTransform(reticleXfm);
|
||||
geometryCache->renderUnitQuad(batch, glm::vec4(1), _reticleQuad);
|
||||
}
|
||||
glm::vec2 projection = screenToSpherical(qApp->getTrueMouse());
|
||||
mat4 pointerXfm = glm::mat4_cast(quat(vec3(-projection.y, projection.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1));
|
||||
mat4 reticleXfm = overlayXfm * pointerXfm;
|
||||
reticleXfm = glm::scale(reticleXfm, reticleScale);
|
||||
batch.setModelTransform(reticleXfm);
|
||||
geometryCache->renderUnitQuad(batch, glm::vec4(1), _reticleQuad);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -423,124 +394,6 @@ bool ApplicationCompositor::calculateRayUICollisionPoint(const glm::vec3& positi
|
|||
return false;
|
||||
}
|
||||
|
||||
//Renders optional pointers
|
||||
void ApplicationCompositor::renderPointers(gpu::Batch& batch) {
|
||||
if (qApp->isHMDMode() && !qApp->getLastMouseMoveWasSimulated()) {
|
||||
//If we are in oculus, render reticle later
|
||||
auto trueMouse = qApp->getTrueMouse();
|
||||
trueMouse /= qApp->getCanvasSize();
|
||||
QPoint position = QPoint(qApp->getTrueMouse().x, qApp->getTrueMouse().y);
|
||||
_reticlePosition[MOUSE] = position;
|
||||
_reticleActive[MOUSE] = true;
|
||||
_magActive[MOUSE] = _magnifier;
|
||||
_reticleActive[LEFT_CONTROLLER] = false;
|
||||
_reticleActive[RIGHT_CONTROLLER] = false;
|
||||
} else if (qApp->getLastMouseMoveWasSimulated()
|
||||
&& Menu::getInstance()->isOptionChecked(MenuOption::EnableHandMouseInput)) {
|
||||
//only render controller pointer if we aren't already rendering a mouse pointer
|
||||
_reticleActive[MOUSE] = false;
|
||||
_magActive[MOUSE] = false;
|
||||
renderControllerPointers(batch);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// FIXME - this is old code that likely needs to be removed and/or reworked to support the new input control model
|
||||
void ApplicationCompositor::renderControllerPointers(gpu::Batch& batch) {
|
||||
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
|
||||
//Static variables used for storing controller state
|
||||
static quint64 pressedTime[NUMBER_OF_RETICLES] = { 0ULL, 0ULL, 0ULL };
|
||||
static bool isPressed[NUMBER_OF_RETICLES] = { false, false, false };
|
||||
static bool stateWhenPressed[NUMBER_OF_RETICLES] = { false, false, false };
|
||||
|
||||
const HandData* handData = DependencyManager::get<AvatarManager>()->getMyAvatar()->getHandData();
|
||||
auto palms = handData->getCopyOfPalms();
|
||||
|
||||
for (unsigned int palmIndex = 2; palmIndex < 4; palmIndex++) {
|
||||
const int index = palmIndex - 1;
|
||||
|
||||
const PalmData* palmData = NULL;
|
||||
|
||||
if (palmIndex >= palms.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (palms[palmIndex].isActive()) {
|
||||
palmData = &palms[palmIndex];
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isPressed[index]) {
|
||||
isPressed[index] = false;
|
||||
//If the button was only pressed for < 250 ms
|
||||
//then disable it.
|
||||
|
||||
const int MAX_BUTTON_PRESS_TIME = 250 * MSECS_TO_USECS;
|
||||
if (usecTimestampNow() < pressedTime[index] + MAX_BUTTON_PRESS_TIME) {
|
||||
_magActive[index] = !stateWhenPressed[index];
|
||||
}
|
||||
}
|
||||
|
||||
//if we have the oculus, we should make the cursor smaller since it will be
|
||||
//magnified
|
||||
if (qApp->isHMDMode()) {
|
||||
|
||||
QPoint point = getPalmClickLocation(palmData);
|
||||
|
||||
_reticlePosition[index] = point;
|
||||
|
||||
//When button 2 is pressed we drag the mag window
|
||||
if (isPressed[index]) {
|
||||
_magActive[index] = true;
|
||||
}
|
||||
|
||||
// If oculus is enabled, we draw the crosshairs later
|
||||
continue;
|
||||
}
|
||||
|
||||
auto canvasSize = qApp->getCanvasSize();
|
||||
int mouseX, mouseY;
|
||||
|
||||
// Get directon relative to avatar orientation
|
||||
glm::vec3 direction = glm::inverse(myAvatar->getOrientation()) * palmData->getFingerDirection();
|
||||
|
||||
// Get the angles, scaled between (-0.5,0.5)
|
||||
float xAngle = (atan2f(direction.z, direction.x) + PI_OVER_TWO);
|
||||
float yAngle = 0.5f - ((atan2f(direction.z, direction.y) + (float)PI_OVER_TWO));
|
||||
|
||||
// Get the pixel range over which the xAngle and yAngle are scaled
|
||||
float cursorRange = canvasSize.x * controller::InputDevice::getCursorPixelRangeMult();
|
||||
|
||||
mouseX = (canvasSize.x / 2.0f + cursorRange * xAngle);
|
||||
mouseY = (canvasSize.y / 2.0f + cursorRange * yAngle);
|
||||
|
||||
//If the cursor is out of the screen then don't render it
|
||||
if (mouseX < 0 || mouseX >= (int)canvasSize.x || mouseY < 0 || mouseY >= (int)canvasSize.y) {
|
||||
_reticleActive[index] = false;
|
||||
continue;
|
||||
}
|
||||
_reticleActive[index] = true;
|
||||
|
||||
|
||||
const float reticleSize = 40.0f;
|
||||
|
||||
mouseX -= reticleSize / 2.0f;
|
||||
mouseY += reticleSize / 2.0f;
|
||||
|
||||
|
||||
glm::vec2 topLeft(mouseX, mouseY);
|
||||
glm::vec2 bottomRight(mouseX + reticleSize, mouseY - reticleSize);
|
||||
glm::vec2 texCoordTopLeft(0.0f, 0.0f);
|
||||
glm::vec2 texCoordBottomRight(1.0f, 1.0f);
|
||||
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
|
||||
glm::vec4(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], 1.0f));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void ApplicationCompositor::buildHemiVertices(
|
||||
const float fov, const float aspectRatio, const int slices, const int stacks) {
|
||||
static float textureFOV = 0.0f, textureAspectRatio = 1.0f;
|
||||
|
|
|
@ -92,9 +92,6 @@ private:
|
|||
void drawSphereSection(gpu::Batch& batch);
|
||||
void updateTooltips();
|
||||
|
||||
void renderPointers(gpu::Batch& batch);
|
||||
void renderControllerPointers(gpu::Batch& batch);
|
||||
|
||||
vec2 getPolarCoordinates(const PalmData& palm) const;
|
||||
|
||||
// Support for hovering and tooltips
|
||||
|
@ -109,11 +106,6 @@ private:
|
|||
float _textureAspectRatio{ 1.0f };
|
||||
int _hemiVerticesID{ GeometryCache::UNKNOWN_ID };
|
||||
|
||||
enum Reticles { MOUSE, LEFT_CONTROLLER, RIGHT_CONTROLLER, NUMBER_OF_RETICLES };
|
||||
bool _reticleActive[NUMBER_OF_RETICLES];
|
||||
QPoint _reticlePosition[NUMBER_OF_RETICLES];
|
||||
bool _magActive[NUMBER_OF_RETICLES];
|
||||
float _magSizeMult[NUMBER_OF_RETICLES];
|
||||
bool _magnifier{ true };
|
||||
|
||||
float _alpha{ 1.0f };
|
||||
|
|
|
@ -62,6 +62,14 @@ namespace controller {
|
|||
makeButtonPair(Action::TOGGLE_MUTE, "ToggleMute"),
|
||||
makeButtonPair(Action::CYCLE_CAMERA, "CycleCamera"),
|
||||
|
||||
makeAxisPair(Action::RETICLE_CLICK, "ReticleClick"),
|
||||
makeAxisPair(Action::RETICLE_X, "ReticleX"),
|
||||
makeAxisPair(Action::RETICLE_Y, "ReticleY"),
|
||||
makeAxisPair(Action::RETICLE_LEFT, "ReticleLeft"),
|
||||
makeAxisPair(Action::RETICLE_RIGHT, "ReticleRight"),
|
||||
makeAxisPair(Action::RETICLE_UP, "ReticleUp"),
|
||||
makeAxisPair(Action::RETICLE_DOWN, "ReticleDown"),
|
||||
|
||||
// Aliases and bisected versions
|
||||
makeAxisPair(Action::LONGITUDINAL_BACKWARD, "Backward"),
|
||||
makeAxisPair(Action::LONGITUDINAL_FORWARD, "Forward"),
|
||||
|
|
|
@ -55,6 +55,17 @@ enum class Action {
|
|||
|
||||
SHIFT,
|
||||
|
||||
// Pointer/Reticle control
|
||||
RETICLE_CLICK,
|
||||
RETICLE_X,
|
||||
RETICLE_Y,
|
||||
|
||||
// Biseced aliases for RETICLE_X/RETICLE_Y
|
||||
RETICLE_LEFT,
|
||||
RETICLE_RIGHT,
|
||||
RETICLE_UP,
|
||||
RETICLE_DOWN,
|
||||
|
||||
// Biseced aliases for TRANSLATE_Z
|
||||
LONGITUDINAL_BACKWARD,
|
||||
LONGITUDINAL_FORWARD,
|
||||
|
@ -78,7 +89,7 @@ enum class Action {
|
|||
// Biseced aliases for TRANSLATE_CAMERA_Z
|
||||
BOOM_IN,
|
||||
BOOM_OUT,
|
||||
|
||||
|
||||
NUM_ACTIONS,
|
||||
};
|
||||
|
||||
|
|
|
@ -255,6 +255,9 @@ void UserInputMapper::update(float deltaTime) {
|
|||
fixBisectedAxis(_actionStates[toInt(Action::ROTATE_Y)], _actionStates[toInt(Action::YAW_LEFT)], _actionStates[toInt(Action::YAW_RIGHT)]);
|
||||
fixBisectedAxis(_actionStates[toInt(Action::ROTATE_X)], _actionStates[toInt(Action::PITCH_UP)], _actionStates[toInt(Action::PITCH_DOWN)]);
|
||||
|
||||
fixBisectedAxis(_actionStates[toInt(Action::RETICLE_X)], _actionStates[toInt(Action::RETICLE_LEFT)], _actionStates[toInt(Action::RETICLE_RIGHT)]);
|
||||
fixBisectedAxis(_actionStates[toInt(Action::RETICLE_Y)], _actionStates[toInt(Action::RETICLE_UP)], _actionStates[toInt(Action::RETICLE_DOWN)]);
|
||||
|
||||
static const float EPSILON = 0.01f;
|
||||
for (auto i = 0; i < toInt(Action::NUM_ACTIONS); i++) {
|
||||
_actionStates[i] *= _actionScales[i];
|
||||
|
@ -319,42 +322,12 @@ QVector<QString> UserInputMapper::getActionNames() const {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
/*
|
||||
void UserInputMapper::assignDefaulActionScales() {
|
||||
_actionScales[toInt(Action::LONGITUDINAL_BACKWARD)] = 1.0f; // 1m per unit
|
||||
_actionScales[toInt(Action::LONGITUDINAL_FORWARD)] = 1.0f; // 1m per unit
|
||||
_actionScales[toInt(Action::LATERAL_LEFT)] = 1.0f; // 1m per unit
|
||||
_actionScales[toInt(Action::LATERAL_RIGHT)] = 1.0f; // 1m per unit
|
||||
_actionScales[toInt(Action::VERTICAL_DOWN)] = 1.0f; // 1m per unit
|
||||
_actionScales[toInt(Action::VERTICAL_UP)] = 1.0f; // 1m per unit
|
||||
_actionScales[toInt(Action::YAW_LEFT)] = 1.0f; // 1 degree per unit
|
||||
_actionScales[toInt(Action::YAW_RIGHT)] = 1.0f; // 1 degree per unit
|
||||
_actionScales[toInt(Action::PITCH_DOWN)] = 1.0f; // 1 degree per unit
|
||||
_actionScales[toInt(Action::PITCH_UP)] = 1.0f; // 1 degree per unit
|
||||
_actionScales[toInt(Action::BOOM_IN)] = 0.5f; // .5m per unit
|
||||
_actionScales[toInt(Action::BOOM_OUT)] = 0.5f; // .5m per unit
|
||||
_actionScales[toInt(Action::LEFT_HAND)] = 1.0f; // default
|
||||
_actionScales[toInt(Action::RIGHT_HAND)] = 1.0f; // default
|
||||
_actionScales[toInt(Action::LEFT_HAND_CLICK)] = 1.0f; // on
|
||||
_actionScales[toInt(Action::RIGHT_HAND_CLICK)] = 1.0f; // on
|
||||
_actionScales[toInt(Action::SHIFT)] = 1.0f; // on
|
||||
_actionScales[toInt(Action::ACTION1)] = 1.0f; // default
|
||||
_actionScales[toInt(Action::ACTION2)] = 1.0f; // default
|
||||
_actionScales[toInt(Action::TRANSLATE_X)] = 1.0f; // default
|
||||
_actionScales[toInt(Action::TRANSLATE_Y)] = 1.0f; // default
|
||||
_actionScales[toInt(Action::TRANSLATE_Z)] = 1.0f; // default
|
||||
_actionScales[toInt(Action::ROLL)] = 1.0f; // default
|
||||
_actionScales[toInt(Action::PITCH)] = 1.0f; // default
|
||||
_actionScales[toInt(Action::YAW)] = 1.0f; // default
|
||||
}
|
||||
*/
|
||||
|
||||
static int actionMetaTypeId = qRegisterMetaType<Action>();
|
||||
static int inputMetaTypeId = qRegisterMetaType<Input>();
|
||||
static int inputPairMetaTypeId = qRegisterMetaType<Input::NamedPair>();
|
||||
static int poseMetaTypeId = qRegisterMetaType<controller::Pose>("Pose");
|
||||
|
||||
|
||||
QScriptValue inputToScriptValue(QScriptEngine* engine, const Input& input);
|
||||
void inputFromScriptValue(const QScriptValue& object, Input& input);
|
||||
QScriptValue actionToScriptValue(QScriptEngine* engine, const Action& action);
|
||||
|
|
|
@ -99,6 +99,9 @@ void KeyboardMouseDevice::mouseMoveEvent(QMouseEvent* event, unsigned int device
|
|||
_inputDevice->_axisStateMap[MOUSE_AXIS_Y_POS] = (currentMove.y() < 0 ? -currentMove.y() : 0.0f);
|
||||
_inputDevice->_axisStateMap[MOUSE_AXIS_Y_NEG] = (currentMove.y() > 0 ? currentMove.y() : 0.0f);
|
||||
|
||||
// FIXME - this has the characteristic that it will show large jumps when you move the cursor
|
||||
// outside of the application window, because we don't get MouseEvents when the cursor is outside
|
||||
// of the application window.
|
||||
_lastCursor = currentPos;
|
||||
_mouseMoved = true;
|
||||
|
||||
|
|
Loading…
Reference in a new issue