diff --git a/Engine/source/gui/controls/guiTextEditCtrl.h b/Engine/source/gui/controls/guiTextEditCtrl.h index 9d29038f7..15021ea5e 100644 --- a/Engine/source/gui/controls/guiTextEditCtrl.h +++ b/Engine/source/gui/controls/guiTextEditCtrl.h @@ -124,6 +124,7 @@ public: void invalidText(bool playSound = true); void validText(); bool isValidText(); + inline bool isPasswordText() { return mPasswordText; } bool isAllTextSelected(); void selectAllText(); diff --git a/Engine/source/gui/core/guiControl.h b/Engine/source/gui/core/guiControl.h index ca873878d..fa3a327dd 100644 --- a/Engine/source/gui/core/guiControl.h +++ b/Engine/source/gui/core/guiControl.h @@ -286,6 +286,8 @@ class GuiControl : public SimGroup const char * getConsoleCommand(); ///< Returns the name of the function bound to this GuiControl LangTable *getGUILangTable(void); const UTF8 *getGUIString(S32 id); + + inline String& getTooltip() { return mTooltip; } ///< Returns the tooltip /// @} diff --git a/Engine/source/platform/input/openVR/openVROverlay.cpp b/Engine/source/platform/input/openVR/openVROverlay.cpp index 24bede00b..25c345153 100644 --- a/Engine/source/platform/input/openVR/openVROverlay.cpp +++ b/Engine/source/platform/input/openVR/openVROverlay.cpp @@ -12,6 +12,7 @@ #endif #include "postFx/postEffectCommon.h" +#include "gui/controls/guiTextEditCtrl.h" ImplementEnumType(OpenVROverlayType, "Desired overlay type for OpenVROverlay. .\n\n" @@ -32,6 +33,9 @@ OpenVROverlay::OpenVROverlay() mTrackingOrigin = vr::TrackingUniverseSeated; mTargetFormat = GFXFormatR8G8B8A8_LINEAR_FORCE; // needed for openvr! + mManualMouseHandling = true; + + mMouseScale = Point2F(1, 1); } OpenVROverlay::~OpenVROverlay() @@ -75,7 +79,7 @@ void OpenVROverlay::initPersistFields() addProtectedField("transformDeviceComponent", TypeString, Offset(mTransformDeviceComponent, OpenVROverlay), &setProtectedOverlayDirty, &defaultProtectedGetFn, "Rotation of overlay."); - addProtectedField("inputMethod", TypeOpenVROverlayInputMethod, Offset(mTransformDeviceComponent, OpenVROverlay), &setProtectedOverlayDirty, &defaultProtectedGetFn, + addProtectedField("inputMethod", TypeOpenVROverlayInputMethod, Offset(mInputMethod, OpenVROverlay), &setProtectedOverlayDirty, &defaultProtectedGetFn, "Type of input method."); addProtectedField("mouseScale", TypePoint2F, Offset(mMouseScale, OpenVROverlay), &setProtectedOverlayDirty, &defaultProtectedGetFn, "Scale of mouse input."); @@ -86,6 +90,8 @@ void OpenVROverlay::initPersistFields() addProtectedField("controllerDevice", TypeS32, Offset(mControllerDeviceIndex, OpenVROverlay), &setProtectedOverlayDirty, &defaultProtectedGetFn, "Index of controller to attach overlay to."); + addField("manualMouseHandling", TypeBool, Offset(mManualMouseHandling, OpenVROverlay), "Forces openvr to create mouse events for overlay"); + Parent::initPersistFields(); } @@ -95,6 +101,12 @@ bool OpenVROverlay::onAdd() { mOverlayTypeDirty = true; mOverlayDirty = true; + + if (OPENVR) + { + OPENVR->registerOverlay(this); + } + return true; } @@ -114,6 +126,11 @@ void OpenVROverlay::onRemove() vr::VROverlay()->DestroyOverlay(mThumbOverlayHandle); mThumbOverlayHandle = NULL; } + + if (OPENVR) + { + OPENVR->unregisterOverlay(this); + } } void OpenVROverlay::resetOverlay() @@ -202,10 +219,10 @@ void OpenVROverlay::updateOverlay() overlay->SetOverlayWidthInMeters(mOverlayHandle, mOverlayWidth); // NOTE: if flags in openvr change, double check this - /*for (U32 i = vr::VROverlayFlags_None; i <= vr::VROverlayFlags_ShowTouchPadScrollWheel; i++) + for (U32 i = vr::VROverlayFlags_None; i <= vr::VROverlayFlags_ShowTouchPadScrollWheel; i++) { overlay->SetOverlayFlag(mOverlayHandle, (vr::VROverlayFlags)i, mOverlayFlags & (1 << i)); - }*/ + } mOverlayDirty = false; } @@ -216,11 +233,14 @@ void OpenVROverlay::showOverlay() if (mOverlayHandle == NULL) return; - vr::EVROverlayError err = vr::VROverlay()->ShowOverlay(mOverlayHandle); - if (err != vr::VROverlayError_None) - { - Con::errorf("VR Overlay error!"); - } + if (mOverlayType != OVERLAYTYPE_DASHBOARD) + { + vr::EVROverlayError err = vr::VROverlay()->ShowOverlay(mOverlayHandle); + if (err != vr::VROverlayError_None) + { + Con::errorf("VR Overlay error!"); + } + } if (!mStagingTexture) { @@ -233,7 +253,10 @@ void OpenVROverlay::hideOverlay() if (mOverlayHandle == NULL) return; - vr::VROverlay()->HideOverlay(mOverlayHandle); + if (mOverlayType != OVERLAYTYPE_DASHBOARD) + { + vr::VROverlay()->HideOverlay(mOverlayHandle); + } } @@ -294,21 +317,24 @@ bool OpenVROverlay::castRay(const Point3F &origin, const Point3F &direction, Ray vr::VROverlayIntersectionParams_t params; vr::VROverlayIntersectionResults_t result; + Point3F ovrOrigin = OpenVRUtil::convertPointToOVR(origin); + Point3F ovrDirection = OpenVRUtil::convertPointToOVR(direction); + params.eOrigin = mTrackingOrigin; - params.vSource.v[0] = origin.x; - params.vSource.v[1] = origin.y; - params.vSource.v[2] = origin.z; - params.vDirection.v[0] = direction.x; // TODO: need to transform this to vr-space - params.vDirection.v[1] = direction.y; - params.vDirection.v[2] = direction.z; + params.vSource.v[0] = ovrOrigin.x; + params.vSource.v[1] = ovrOrigin.y; + params.vSource.v[2] = ovrOrigin.z; + params.vDirection.v[0] = ovrDirection.x; + params.vDirection.v[1] = ovrDirection.y; + params.vDirection.v[2] = ovrDirection.z; bool rayHit = vr::VROverlay()->ComputeOverlayIntersection(mOverlayHandle, ¶ms, &result); if (rayHit && info) { info->t = result.fDistance; - info->point = Point3F(result.vPoint.v[0], result.vPoint.v[1], result.vPoint.v[2]); // TODO: need to transform this FROM vr-space - info->normal = Point3F(result.vNormal.v[0], result.vNormal.v[1], result.vNormal.v[2]); + info->point = OpenVRUtil::convertPointFromOVR(result.vPoint); // TODO: need to transform this FROM vr-space + info->normal = OpenVRUtil::convertPointFromOVR(result.vNormal); info->texCoord = Point2F(result.vUVs.v[0], result.vUVs.v[1]); info->object = NULL; info->userData = this; @@ -324,6 +350,19 @@ void OpenVROverlay::moveGamepadFocusToNeighbour() void OpenVROverlay::handleOpenVREvents() { + if (mManualMouseHandling) + { + // tell OpenVR to make some events for us + for (vr::TrackedDeviceIndex_t unDeviceId = 1; unDeviceId < vr::k_unControllerStateAxisCount; unDeviceId++) + { + if (vr::VROverlay()->HandleControllerOverlayInteractionAsMouse(mOverlayHandle, unDeviceId)) + { + break; + } + } + } + + vr::VREvent_t vrEvent; while (vr::VROverlay()->PollNextOverlayEvent(mOverlayHandle, &vrEvent, sizeof(vrEvent))) { @@ -334,20 +373,23 @@ void OpenVROverlay::handleOpenVREvents() eventInfo.modifier = (InputModifiers)0; eventInfo.ascii = 0; + Con::printf("Overlay event %i", vrEvent.eventType); + switch (vrEvent.eventType) { case vr::VREvent_MouseMove: { + Con::printf("mousemove %f,%f", vrEvent.data.mouse.x, vrEvent.data.mouse.y); eventInfo.objType = SI_AXIS; eventInfo.objInst = SI_XAXIS; eventInfo.action = SI_MAKE; - eventInfo.fValue = vrEvent.data.mouse.x; + eventInfo.fValue = getExtent().x * vrEvent.data.mouse.x; processMouseEvent(eventInfo); eventInfo.objType = SI_AXIS; eventInfo.objInst = SI_YAXIS; eventInfo.action = SI_MAKE; - eventInfo.fValue = vrEvent.data.mouse.y; + eventInfo.fValue = getExtent().y * (1.0 - vrEvent.data.mouse.y); processMouseEvent(eventInfo); } break; @@ -381,7 +423,13 @@ void OpenVROverlay::handleOpenVREvents() case vr::VREvent_Quit: AssertFatal(false, "WTF is going on here"); break; - } + + case vr::VREvent_KeyboardCharInput: + case vr::VREvent_KeyboardDone: + updateTextControl((GuiControl*)vrEvent.data.keyboard.uUserValue); + break; + } + } if (mThumbOverlayHandle != vr::k_ulOverlayHandleInvalid) @@ -400,6 +448,20 @@ void OpenVROverlay::handleOpenVREvents() } } +void OpenVROverlay::updateTextControl(GuiControl* ctrl) +{ + if (!ctrl) + return; + + GuiTextCtrl* textCtrl = dynamic_cast(ctrl); + if (textCtrl) + { + char text[GuiTextCtrl::MAX_STRING_LENGTH]; + vr::VROverlay()->GetKeyboardText(text, GuiTextCtrl::MAX_STRING_LENGTH); + textCtrl->setText(text); + } +} + void OpenVROverlay::onFrameRendered() { vr::IVROverlay *overlay = vr::VROverlay(); @@ -444,6 +506,34 @@ void OpenVROverlay::onFrameRendered() //Con::printf("Overlay visible ? %s", vr::VROverlay()->IsOverlayVisible(mOverlayHandle) ? "YES" : "NO"); } +void OpenVROverlay::enableKeyboardTranslation() +{ + vr::IVROverlay *overlay = vr::VROverlay(); + if (!overlay || !mOverlayHandle) + return; + + GuiTextEditCtrl* ctrl = dynamic_cast(getFirstResponder()); + if (ctrl) + { + vr::EGamepadTextInputMode inputMode = ctrl->isPasswordText() ? vr::k_EGamepadTextInputModePassword : vr::k_EGamepadTextInputModeNormal; + char text[GuiTextCtrl::MAX_STRING_LENGTH + 1]; + ctrl->getText(text); + overlay->ShowKeyboardForOverlay(mOverlayHandle, inputMode, vr::k_EGamepadTextInputLineModeSingleLine, ctrl->getTooltip().c_str(), GuiTextCtrl::MAX_STRING_LENGTH, text, false, (uint64_t)ctrl); + } +} + +void OpenVROverlay::disableKeyboardTranslation() +{ + vr::IVROverlay *overlay = vr::VROverlay(); + if (!overlay || !mOverlayHandle) + return; + + overlay->HideKeyboard(); +} + +void OpenVROverlay::setNativeAcceleratorsEnabled(bool enabled) +{ +} DefineEngineMethod(OpenVROverlay, showOverlay, void, (), , "") { diff --git a/Engine/source/platform/input/openVR/openVROverlay.h b/Engine/source/platform/input/openVR/openVROverlay.h index 6998f3423..faee66b83 100644 --- a/Engine/source/platform/input/openVR/openVROverlay.h +++ b/Engine/source/platform/input/openVR/openVROverlay.h @@ -57,6 +57,7 @@ public: bool mOverlayTypeDirty; ///< Overlay type is dirty bool mOverlayDirty; ///< Overlay properties are dirty + bool mManualMouseHandling; OverlayType mOverlayType; // @@ -89,7 +90,12 @@ public: void moveGamepadFocusToNeighbour(); void handleOpenVREvents(); + void updateTextControl(GuiControl* ctrl); void onFrameRendered(); + + virtual void enableKeyboardTranslation(); + virtual void disableKeyboardTranslation(); + virtual void setNativeAcceleratorsEnabled(bool enabled); }; typedef OpenVROverlay::OverlayType OpenVROverlayType; diff --git a/Engine/source/platform/input/openVR/openVRProvider.cpp b/Engine/source/platform/input/openVR/openVRProvider.cpp index 79fed71a8..2061403e7 100644 --- a/Engine/source/platform/input/openVR/openVRProvider.cpp +++ b/Engine/source/platform/input/openVR/openVRProvider.cpp @@ -1,4 +1,5 @@ #include "platform/input/openVR/openVRProvider.h" +#include "platform/input/openVR/openVROverlay.h" #include "platform/platformInput.h" #include "core/module.h" #include "console/engineAPI.h" @@ -547,7 +548,7 @@ void OpenVRProvider::buildInputCodeTable() bool OpenVRProvider::process() { if (!mHMD) - return true; + return true; if (!vr::VRCompositor()) return true; @@ -559,6 +560,12 @@ bool OpenVRProvider::process() processVREvent(event); } + // process overlay events + for (U32 i = 0; i < mOverlays.size(); i++) + { + mOverlays[i]->handleOpenVREvents(); + } + // Process SteamVR controller state for (vr::TrackedDeviceIndex_t unDevice = 0; unDevice < vr::k_unMaxTrackedDeviceCount; unDevice++) { @@ -1014,6 +1021,20 @@ void OpenVRProvider::resetSensors() } } +void OpenVRProvider::registerOverlay(OpenVROverlay* overlay) +{ + mOverlays.push_back(overlay); +} + +void OpenVRProvider::unregisterOverlay(OpenVROverlay* overlay) +{ + S32 index = mOverlays.find_next(overlay); + if (index != -1) + { + mOverlays.erase(index); + } +} + OpenVROverlay *OpenVRProvider::getGamepadFocusOverlay() { return NULL; diff --git a/Engine/source/platform/input/openVR/openVRProvider.h b/Engine/source/platform/input/openVR/openVRProvider.h index de3a73e89..b690b0941 100644 --- a/Engine/source/platform/input/openVR/openVRProvider.h +++ b/Engine/source/platform/input/openVR/openVRProvider.h @@ -54,6 +54,24 @@ namespace OpenVRUtil void convertMatrixFPlainToSteamVRAffineMatrix(const MatrixF &inMat, vr::HmdMatrix34_t &outMat); U32 convertOpenVRButtonToTorqueButton(uint32_t vrButton); + + /// Converts a point to OVR coords + inline Point3F convertPointToOVR(const Point3F &point) + { + return Point3F(-point.x, -point.z, point.y); + } + + /// Converts a point from OVR coords + inline Point3F convertPointFromOVR(const Point3F &point) + { + return Point3F(-point.x, point.z, -point.y); + } + + // Converts a point from OVR coords, from an input float array + inline Point3F convertPointFromOVR(const vr::HmdVector3_t& v) + { + return Point3F(-v.v[0], v.v[2], -v.v[1]); + } }; template class VRTextureSet @@ -199,6 +217,12 @@ public: void resetSensors(); /// } + /// @name Overlay registration + /// { + void registerOverlay(OpenVROverlay* overlay); + void unregisterOverlay(OpenVROverlay* overlay); + /// } + /// @name Console API /// { @@ -231,6 +255,8 @@ public: GFXAdapterLUID mLUID; vr::ETrackingUniverseOrigin mTrackingSpace; + + Vector mOverlays; /// } GuiCanvas* mDrawCanvas;