diff --git a/interface/resources/qml/TabletBrowser.qml b/interface/resources/qml/TabletBrowser.qml index 85fff59207..2650102b27 100644 --- a/interface/resources/qml/TabletBrowser.qml +++ b/interface/resources/qml/TabletBrowser.qml @@ -1,5 +1,5 @@ import QtQuick 2.5 -import QtQuick.Controls 1.2 +import QtQuick.Controls 1.4 import QtWebChannel 1.0 import QtWebEngine 1.2 @@ -7,7 +7,7 @@ import "controls" import "styles" as HifiStyles import "styles-uit" import "windows" -import HFWebEngineProfile 1.0 +import HFTabletWebEngineProfile 1.0 Item { id: root @@ -27,138 +27,103 @@ Item { x: 0 y: 0 - - function goBack() { - webview.goBack(); - } - - function goForward() { - webview.goForward(); - } - - function gotoPage(url) { - webview.url = url; - } function setProfile(profile) { webview.profile = profile; } - function reloadPage() { - webview.reloadAndBypassCache(); - webview.setActiveFocusOnPress(true); - webview.setEnabled(true); + QtObject { + id: eventBridgeWrapper + WebChannel.id: "eventBridgeWrapper" + property var eventBridge; } - Item { - id:item + WebEngineView { + id: webview + objectName: "webEngineView" + x: 0 + y: 0 width: parent.width - implicitHeight: parent.height + height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height - - QtObject { - id: eventBridgeWrapper - WebChannel.id: "eventBridgeWrapper" - property var eventBridge; + profile: HFTabletWebEngineProfile { + id: webviewTabletProfile + storageName: "qmlTabletWebEngine" } - WebEngineView { - id: webview - objectName: "webEngineView" - x: 0 - y: 0 - width: parent.width - height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height - - profile: HFWebEngineProfile { - id: webviewProfile - storageName: "qmlWebEngine" - } + property string userScriptUrl: "" - property string userScriptUrl: "" - - // creates a global EventBridge object. - WebEngineScript { - id: createGlobalEventBridge - sourceCode: eventBridgeJavaScriptToInject - injectionPoint: WebEngineScript.DocumentCreation - worldId: WebEngineScript.MainWorld - } - - // detects when to raise and lower virtual keyboard - WebEngineScript { - id: raiseAndLowerKeyboard - injectionPoint: WebEngineScript.Deferred - sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js" - worldId: WebEngineScript.MainWorld - } - - // User script. - WebEngineScript { - id: userScript - sourceUrl: webview.userScriptUrl - injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished. - worldId: WebEngineScript.MainWorld - } + // creates a global EventBridge object. + WebEngineScript { + id: createGlobalEventBridge + sourceCode: eventBridgeJavaScriptToInject + injectionPoint: WebEngineScript.DocumentCreation + worldId: WebEngineScript.MainWorld + } - userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ] - - property string newUrl: "" - - webChannel.registeredObjects: [eventBridgeWrapper] + // detects when to raise and lower virtual keyboard + WebEngineScript { + id: raiseAndLowerKeyboard + injectionPoint: WebEngineScript.Deferred + sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js" + worldId: WebEngineScript.MainWorld + } - Component.onCompleted: { - // Ensure the JS from the web-engine makes it to our logging - webview.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) { - console.log("Web Entity JS message: " + sourceID + " " + lineNumber + " " + message); - }); - - webview.profile.httpUserAgent = "Mozilla/5.0 Chrome (HighFidelityInterface"; - web.address = url; - } - - onFeaturePermissionRequested: { - grantFeaturePermission(securityOrigin, feature, true); - } + // User script. + WebEngineScript { + id: userScript + sourceUrl: webview.userScriptUrl + injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished. + worldId: WebEngineScript.MainWorld + } - onLoadingChanged: { - keyboardRaised = false; - punctuationMode = false; - keyboard.resetShiftMode(false); - - // Required to support clicking on "hifi://" links - if (WebEngineView.LoadStartedStatus == loadRequest.status) { - var url = loadRequest.url.toString(); - if (urlHandler.canHandleUrl(url)) { - if (urlHandler.handleUrl(url)) { - root.stop(); - } + userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ] + + property string newUrl: "" + + webChannel.registeredObjects: [eventBridgeWrapper] + + Component.onCompleted: { + // Ensure the JS from the web-engine makes it to our logging + webview.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) { + console.log("Web Entity JS message: " + sourceID + " " + lineNumber + " " + message); + }); + + webview.profile.httpUserAgent = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36"; + web.address = url; + } + + onFeaturePermissionRequested: { + grantFeaturePermission(securityOrigin, feature, true); + } + + onLoadingChanged: { + keyboardRaised = false; + punctuationMode = false; + keyboard.resetShiftMode(false); + + // Required to support clicking on "hifi://" links + if (WebEngineView.LoadStartedStatus == loadRequest.status) { + var url = loadRequest.url.toString(); + if (urlHandler.canHandleUrl(url)) { + if (urlHandler.handleUrl(url)) { + root.stop(); } } } + } - onNewViewRequested: { - var component = Qt.createComponent("./TabletBrowser.qml"); - - if (component.status != Component.Ready) { - if (component.status == Component.Error) { - console.log("Error: " + component.errorString()); - } - return; - } - var newWindow = component.createObject(); - newWindow.setProfile(webview.profile); - request.openIn(newWindow.webView); - newWindow.eventBridge = web.eventBridge; - stackRoot.push(newWindow); - newWindow.webView.forceActiveFocus(); - + onNavigationRequested: { + if (request.navigationType == WebEngineNavigationRequest.LinkClickedNavigation) { + pagesModel.append({webUrl: request.url.toString()}) } } - - } // item - - + + onNewViewRequested: { + request.openIn(webView); + } + } + Keys.onPressed: { switch(event.key) { case Qt.Key_L: @@ -171,4 +136,4 @@ Item { } } - } // dialog +} diff --git a/interface/resources/qml/controls/TabletWebView.qml b/interface/resources/qml/controls/TabletWebView.qml index 742ab2d333..50d6e1c504 100644 --- a/interface/resources/qml/controls/TabletWebView.qml +++ b/interface/resources/qml/controls/TabletWebView.qml @@ -1,6 +1,6 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 -import QtWebEngine 1.1 +import QtWebEngine 1.2 import QtWebChannel 1.0 import "../controls-uit" as HiFiControls import "../styles" as HifiStyles @@ -14,17 +14,20 @@ Item { height: parent.height property var parentStackItem: null property int headerHeight: 38 - property alias url: root.url - property string address: url - property alias scriptURL: root.userScriptUrl + property string url + property string address: url //for compatibility + property string scriptURL property alias eventBridge: eventBridgeWrapper.eventBridge property bool keyboardEnabled: HMD.active property bool keyboardRaised: false property bool punctuationMode: false property bool isDesktop: false - property WebEngineView view: root + property WebEngineView view: loader.currentView + property int currentPage: -1 // used as a model for repeater + property alias pagesModel: pagesModel + Row { id: buttons HifiConstants { id: hifi } @@ -37,29 +40,29 @@ Item { anchors.leftMargin: 8 HiFiGlyphs { id: back; - enabled: true; + enabled: currentPage > 0 text: hifi.glyphs.backward color: enabled ? hifistyles.colors.text : hifistyles.colors.disabledText size: 48 - MouseArea { anchors.fill: parent; onClicked: stackRoot.goBack() } + MouseArea { anchors.fill: parent; onClicked: goBack() } } HiFiGlyphs { id: forward; - enabled: stackRoot.currentItem.canGoForward; + enabled: currentPage < pagesModel.count - 1 text: hifi.glyphs.forward color: enabled ? hifistyles.colors.text : hifistyles.colors.disabledText size: 48 - MouseArea { anchors.fill: parent; onClicked: stackRoot.currentItem.goForward() } + MouseArea { anchors.fill: parent; onClicked: goForward() } } HiFiGlyphs { id: reload; - enabled: true; - text: webview.loading ? hifi.glyphs.close : hifi.glyphs.reload + enabled: view != null; + text: (view !== null && view.loading) ? hifi.glyphs.close : hifi.glyphs.reload color: enabled ? hifistyles.colors.text : hifistyles.colors.disabledText size: 48 - MouseArea { anchors.fill: parent; onClicked: stackRoot.currentItem.reloadPage(); } + MouseArea { anchors.fill: parent; onClicked: reloadPage(); } } } @@ -86,7 +89,7 @@ Item { } //root.hidePermissionsBar(); web.keyboardRaised = false; - stackRoot.currentItem.gotoPage(text); + gotoPage(text); break; @@ -94,157 +97,78 @@ Item { } } + ListModel { + id: pagesModel + onCountChanged: { + currentPage = count - 1 + } + } + function goBack() { + if (currentPage > 0) { + currentPage--; + } + } + + function goForward() { + if (currentPage < pagesModel.count - 1) { + currentPage++; + } + } + + function gotoPage(url) { + pagesModel.append({webUrl: url}) + } + + function reloadPage() { + view.reloadAndBypassCache() + view.setActiveFocusOnPress(true); + view.setEnabled(true); + } + + onCurrentPageChanged: { + if (currentPage >= 0 && currentPage < pagesModel.count && loader.item !== null) { + loader.item.url = pagesModel.get(currentPage).webUrl + } + } + + onUrlChanged: { + gotoPage(url) + } + + QtObject { + id: eventBridgeWrapper + WebChannel.id: "eventBridgeWrapper" + property var eventBridge; + } + + Loader { + id: loader + + property WebEngineView currentView: null - StackView { - id: stackRoot width: parent.width height: parent.height - web.headerHeight + asynchronous: true anchors.top: buttons.bottom - //property var goBack: currentItem.goBack(); - property WebEngineView view: root - - initialItem: root; - - function goBack() { - if (depth > 1 ) { - if (currentItem.canGoBack) { - currentItem.goBack(); - } else { - stackRoot.pop(); - currentItem.webView.focus = true; - currentItem.webView.forceActiveFocus(); - web.address = currentItem.webView.url; - } - } else { - if (currentItem.canGoBack) { - currentItem.goBack(); - } else if (parentStackItem) { - web.parentStackItem.pop(); + active: false + source: "../TabletBrowser.qml" + onStatusChanged: { + if (loader.status === Loader.Ready) { + currentView = item.webView + item.webView.userScriptUrl = web.scriptURL + if (currentPage >= 0) { + //we got something to load already + item.url = pagesModel.get(currentPage).webUrl } } } - - QtObject { - id: eventBridgeWrapper - WebChannel.id: "eventBridgeWrapper" - property var eventBridge; - } - - WebEngineView { - id: root - objectName: "webEngineView" - x: 0 - y: 0 - width: parent.width - height: keyboardEnabled && keyboardRaised ? (parent.height - keyboard.height) : parent.height - profile: HFTabletWebEngineProfile { - id: webviewTabletProfile - storageName: "qmlTabletWebEngine" - } - - property WebEngineView webView: root - function reloadPage() { - root.reload(); - } - - function gotoPage(url) { - root.url = url; - } - - property string userScriptUrl: "" - - // creates a global EventBridge object. - WebEngineScript { - id: createGlobalEventBridge - sourceCode: eventBridgeJavaScriptToInject - injectionPoint: WebEngineScript.DocumentCreation - worldId: WebEngineScript.MainWorld - } - - // detects when to raise and lower virtual keyboard - WebEngineScript { - id: raiseAndLowerKeyboard - injectionPoint: WebEngineScript.Deferred - sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js" - worldId: WebEngineScript.MainWorld - } - - // User script. - WebEngineScript { - id: userScript - sourceUrl: root.userScriptUrl - injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished. - worldId: WebEngineScript.MainWorld - } - - userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ] - - property string newUrl: "" - - webChannel.registeredObjects: [eventBridgeWrapper] - - Component.onCompleted: { - // Ensure the JS from the web-engine makes it to our logging - root.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) { - console.log("Web Entity JS message: " + sourceID + " " + lineNumber + " " + message); - }); - - root.profile.httpUserAgent = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36" - - } - - onFeaturePermissionRequested: { - grantFeaturePermission(securityOrigin, feature, true); - } - - onLoadingChanged: { - keyboardRaised = false; - punctuationMode = false; - keyboard.resetShiftMode(false); - // Required to support clicking on "hifi://" links - if (WebEngineView.LoadStartedStatus == loadRequest.status) { - var url = loadRequest.url.toString(); - if (urlHandler.canHandleUrl(url)) { - if (urlHandler.handleUrl(url)) { - root.stop(); - } - } - } - } - - onNewViewRequested:{ - var component = Qt.createComponent("../TabletBrowser.qml"); - if (component.status != Component.Ready) { - if (component.status == Component.Error) { - console.log("Error: " + component.errorString()); - } - return; - } - var newWindow = component.createObject(); - newWindow.setProfile(root.profile); - request.openIn(newWindow.webView); - newWindow.eventBridge = web.eventBridge; - stackRoot.push(newWindow); - } - } - - HiFiControls.Keyboard { - id: keyboard - raised: web.keyboardEnabled && web.keyboardRaised - numeric: web.punctuationMode - anchors { - left: parent.left - right: parent.right - bottom: parent.bottom - } - } - } Component.onCompleted: { web.isDesktop = (typeof desktop !== "undefined"); address = url; + loader.active = true } Keys.onPressed: { diff --git a/libraries/controllers/src/controllers/StandardControls.h b/libraries/controllers/src/controllers/StandardControls.h index c21d8a2f6e..f521ab81cf 100644 --- a/libraries/controllers/src/controllers/StandardControls.h +++ b/libraries/controllers/src/controllers/StandardControls.h @@ -158,6 +158,22 @@ namespace controller { LEFT_HAND_PINKY2, LEFT_HAND_PINKY3, LEFT_HAND_PINKY4, + TRACKED_OBJECT_00, + TRACKED_OBJECT_01, + TRACKED_OBJECT_02, + TRACKED_OBJECT_03, + TRACKED_OBJECT_04, + TRACKED_OBJECT_05, + TRACKED_OBJECT_06, + TRACKED_OBJECT_07, + TRACKED_OBJECT_08, + TRACKED_OBJECT_09, + TRACKED_OBJECT_10, + TRACKED_OBJECT_11, + TRACKED_OBJECT_12, + TRACKED_OBJECT_13, + TRACKED_OBJECT_14, + TRACKED_OBJECT_15, NUM_STANDARD_POSES }; diff --git a/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp b/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp index c8a7b61aa7..9c29e87f16 100644 --- a/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp +++ b/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp @@ -61,6 +61,16 @@ void UserActivityLoggerScriptingInterface::palOpened(float secondsOpened) { }); } +void UserActivityLoggerScriptingInterface::makeUserConnection(QString otherID, bool success, QString detailsString) { + QJsonObject payload; + payload["otherUser"] = otherID; + payload["success"] = success; + if (detailsString.length() > 0) { + payload["details"] = detailsString; + } + logAction("makeUserConnection", payload); +} + void UserActivityLoggerScriptingInterface::logAction(QString action, QJsonObject details) { QMetaObject::invokeMethod(&UserActivityLogger::getInstance(), "logAction", Q_ARG(QString, action), diff --git a/libraries/networking/src/UserActivityLoggerScriptingInterface.h b/libraries/networking/src/UserActivityLoggerScriptingInterface.h index cf38450891..b68c7beb95 100644 --- a/libraries/networking/src/UserActivityLoggerScriptingInterface.h +++ b/libraries/networking/src/UserActivityLoggerScriptingInterface.h @@ -29,6 +29,7 @@ public: float tutorialElapsedTime, QString tutorialRunID = "", int tutorialVersion = 0, QString controllerType = ""); Q_INVOKABLE void palAction(QString action, QString target); Q_INVOKABLE void palOpened(float secondsOpen); + Q_INVOKABLE void makeUserConnection(QString otherUser, bool success, QString details=""); private: void logAction(QString action, QJsonObject details = {}); }; diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index d6e816346a..8cedee2d8f 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -63,59 +63,6 @@ bool ViveControllerManager::activate() { enableOpenVrKeyboard(_container); - // OpenVR provides 3d mesh representations of the controllers - // Disabled controller rendering code - /* - auto renderModels = vr::VRRenderModels(); - - vr::RenderModel_t model; - if (!_system->LoadRenderModel(CONTROLLER_MODEL_STRING, &model)) { - qDebug() << QString("Unable to load render model %1\n").arg(CONTROLLER_MODEL_STRING); - } else { - model::Mesh* mesh = new model::Mesh(); - model::MeshPointer meshPtr(mesh); - _modelGeometry.setMesh(meshPtr); - - auto indexBuffer = new gpu::Buffer(3 * model.unTriangleCount * sizeof(uint16_t), (gpu::Byte*)model.rIndexData); - auto indexBufferPtr = gpu::BufferPointer(indexBuffer); - auto indexBufferView = new gpu::BufferView(indexBufferPtr, gpu::Element(gpu::SCALAR, gpu::UINT16, gpu::RAW)); - mesh->setIndexBuffer(*indexBufferView); - - auto vertexBuffer = new gpu::Buffer(model.unVertexCount * sizeof(vr::RenderModel_Vertex_t), - (gpu::Byte*)model.rVertexData); - auto vertexBufferPtr = gpu::BufferPointer(vertexBuffer); - auto vertexBufferView = new gpu::BufferView(vertexBufferPtr, - 0, - vertexBufferPtr->getSize() - sizeof(float) * 3, - sizeof(vr::RenderModel_Vertex_t), - gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RAW)); - mesh->setVertexBuffer(*vertexBufferView); - mesh->addAttribute(gpu::Stream::NORMAL, - gpu::BufferView(vertexBufferPtr, - sizeof(float) * 3, - vertexBufferPtr->getSize() - sizeof(float) * 3, - sizeof(vr::RenderModel_Vertex_t), - gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RAW))); - //mesh->addAttribute(gpu::Stream::TEXCOORD, - // gpu::BufferView(vertexBufferPtr, - // 2 * sizeof(float) * 3, - // vertexBufferPtr->getSize() - sizeof(float) * 2, - // sizeof(vr::RenderModel_Vertex_t), - // gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::RAW))); - - gpu::Element formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); - gpu::Element formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); - _texture = gpu::TexturePointer( - gpu::Texture::create2D(formatGPU, model.diffuseTexture.unWidth, model.diffuseTexture.unHeight, - gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); - _texture->assignStoredMip(0, formatMip, model.diffuseTexture.unWidth * model.diffuseTexture.unHeight * 4 * sizeof(uint8_t), model.diffuseTexture.rubTextureMapData); - _texture->autoGenerateMips(-1); - - _modelLoaded = true; - _renderControllers = true; - } - */ - // register with UserInputMapper auto userInputMapper = DependencyManager::get(); userInputMapper->registerDevice(_inputDevice); @@ -145,70 +92,6 @@ void ViveControllerManager::deactivate() { _registeredWithInputMapper = false; } -void ViveControllerManager::updateRendering(RenderArgs* args, render::ScenePointer scene, render::Transaction transaction) { - PerformanceTimer perfTimer("ViveControllerManager::updateRendering"); - - /* - if (_modelLoaded) { - //auto controllerPayload = new render::Payload(this); - //auto controllerPayloadPointer = ViveControllerManager::PayloadPointer(controllerPayload); - //if (_leftHandRenderID == 0) { - // _leftHandRenderID = scene->allocateID(); - // transaction.resetItem(_leftHandRenderID, controllerPayloadPointer); - //} - //transaction.updateItem(_leftHandRenderID, ); - - - controller::Pose leftHand = _inputDevice->_poseStateMap[controller::StandardPoseChannel::LEFT_HAND]; - controller::Pose rightHand = _inputDevice->_poseStateMap[controller::StandardPoseChannel::RIGHT_HAND]; - - gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { - auto geometryCache = DependencyManager::get(); - geometryCache->useSimpleDrawPipeline(batch); - DependencyManager::get()->bindSimpleProgram(batch, true); - - auto mesh = _modelGeometry.getMesh(); - batch.setInputFormat(mesh->getVertexFormat()); - //batch._glBindTexture(GL_TEXTURE_2D, _uexture); - - if (leftHand.isValid()) { - renderHand(leftHand, batch, 1); - } - if (rightHand.isValid()) { - renderHand(rightHand, batch, -1); - } - }); - } - */ -} - -void ViveControllerManager::renderHand(const controller::Pose& pose, gpu::Batch& batch, int sign) { - /* - auto userInputMapper = DependencyManager::get(); - Transform transform(userInputMapper->getSensorToWorldMat()); - transform.postTranslate(pose.getTranslation() + pose.getRotation() * glm::vec3(0, 0, CONTROLLER_LENGTH_OFFSET)); - - glm::quat rotation = pose.getRotation() * glm::angleAxis(PI, glm::vec3(1.0f, 0.0f, 0.0f)) * glm::angleAxis(sign * PI_OVER_TWO, glm::vec3(0.0f, 0.0f, 1.0f)); - transform.postRotate(rotation); - - batch.setModelTransform(transform); - - auto mesh = _modelGeometry.getMesh(); - batch.setInputBuffer(gpu::Stream::POSITION, mesh->getVertexBuffer()); - batch.setInputBuffer(gpu::Stream::NORMAL, - mesh->getVertexBuffer()._buffer, - sizeof(float) * 3, - mesh->getVertexBuffer()._stride); - //batch.setInputBuffer(gpu::Stream::TEXCOORD, - // mesh->getVertexBuffer()._buffer, - // 2 * 3 * sizeof(float), - // mesh->getVertexBuffer()._stride); - batch.setIndexBuffer(gpu::UINT16, mesh->getIndexBuffer()._buffer, 0); - batch.drawIndexed(gpu::TRIANGLES, mesh->getNumIndices(), 0); - */ -} - - void ViveControllerManager::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { if (!_system) { @@ -257,6 +140,11 @@ void ViveControllerManager::InputDevice::update(float deltaTime, const controlle handleHandController(deltaTime, leftHandDeviceIndex, inputCalibrationData, true); handleHandController(deltaTime, rightHandDeviceIndex, inputCalibrationData, false); + // collect raw poses + for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) { + handleTrackedObject(i, inputCalibrationData); + } + // handle haptics { Locker locker(_lock); @@ -278,6 +166,30 @@ void ViveControllerManager::InputDevice::update(float deltaTime, const controlle _trackedControllers = numTrackedControllers; } +void ViveControllerManager::InputDevice::handleTrackedObject(uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData) { + + uint32_t poseIndex = controller::TRACKED_OBJECT_00 + deviceIndex; + + if (_system->IsTrackedDeviceConnected(deviceIndex) && + _nextSimPoseData.vrPoses[deviceIndex].bPoseIsValid && + poseIndex <= controller::TRACKED_OBJECT_15) { + + // process pose + const mat4& mat = _nextSimPoseData.poses[deviceIndex]; + const vec3 linearVelocity = _nextSimPoseData.linearVelocities[deviceIndex]; + const vec3 angularVelocity = _nextSimPoseData.angularVelocities[deviceIndex]; + + controller::Pose pose(extractTranslation(mat), glmExtractRotation(mat), linearVelocity, angularVelocity); + + // transform into avatar frame + glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat; + _poseStateMap[poseIndex] = pose.transform(controllerToAvatar); + } else { + controller::Pose invalidPose; + _poseStateMap[poseIndex] = invalidPose; + } +} + void ViveControllerManager::InputDevice::handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand) { if (_system->IsTrackedDeviceConnected(deviceIndex) && @@ -492,6 +404,24 @@ controller::Input::NamedVector ViveControllerManager::InputDevice::getAvailableI makePair(LEFT_HAND, "LeftHand"), makePair(RIGHT_HAND, "RightHand"), + // 16 tracked poses + makePair(TRACKED_OBJECT_00, "TrackedObject00"), + makePair(TRACKED_OBJECT_01, "TrackedObject01"), + makePair(TRACKED_OBJECT_02, "TrackedObject02"), + makePair(TRACKED_OBJECT_03, "TrackedObject03"), + makePair(TRACKED_OBJECT_04, "TrackedObject04"), + makePair(TRACKED_OBJECT_05, "TrackedObject05"), + makePair(TRACKED_OBJECT_06, "TrackedObject06"), + makePair(TRACKED_OBJECT_07, "TrackedObject07"), + makePair(TRACKED_OBJECT_08, "TrackedObject08"), + makePair(TRACKED_OBJECT_09, "TrackedObject09"), + makePair(TRACKED_OBJECT_10, "TrackedObject10"), + makePair(TRACKED_OBJECT_11, "TrackedObject11"), + makePair(TRACKED_OBJECT_12, "TrackedObject12"), + makePair(TRACKED_OBJECT_13, "TrackedObject13"), + makePair(TRACKED_OBJECT_14, "TrackedObject14"), + makePair(TRACKED_OBJECT_15, "TrackedObject15"), + // app button above trackpad. Input::NamedPair(Input(_deviceID, LEFT_APP_MENU, ChannelType::BUTTON), "LeftApplicationMenu"), Input::NamedPair(Input(_deviceID, RIGHT_APP_MENU, ChannelType::BUTTON), "RightApplicationMenu"), diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 9b34f987ab..dc1883d5e4 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -43,8 +43,6 @@ public: void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); } void pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; - void updateRendering(RenderArgs* args, render::ScenePointer scene, render::Transaction transaction); - void setRenderControllers(bool renderControllers) { _renderControllers = renderControllers; } private: @@ -62,6 +60,7 @@ private: void hapticsHelper(float deltaTime, bool leftHand); void handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand); + void handleTrackedObject(uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData); void handleButtonEvent(float deltaTime, uint32_t button, bool pressed, bool touched, bool isLeftHand); void handleAxisEvent(float deltaTime, uint32_t axis, float x, float y, bool isLeftHand); void handlePoseEvent(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, const mat4& mat, diff --git a/scripts/developer/tests/viveTrackedObjects.js b/scripts/developer/tests/viveTrackedObjects.js new file mode 100644 index 0000000000..78911538e4 --- /dev/null +++ b/scripts/developer/tests/viveTrackedObjects.js @@ -0,0 +1,36 @@ + +var TRACKED_OBJECT_POSES = [ + "TrackedObject00", "TrackedObject01", "TrackedObject02", "TrackedObject03", + "TrackedObject04", "TrackedObject05", "TrackedObject06", "TrackedObject07", + "TrackedObject08", "TrackedObject09", "TrackedObject10", "TrackedObject11", + "TrackedObject12", "TrackedObject13", "TrackedObject14", "TrackedObject15" +]; + +function init() { + Script.update.connect(update); +} + +function shutdown() { + Script.update.disconnect(update); + + TRACKED_OBJECT_POSES.forEach(function (key) { + DebugDraw.removeMyAvatarMarker(key); + }); +} + +var WHITE = {x: 1, y: 1, z: 1, w: 1}; + +function update(dt) { + if (Controller.Hardware.Vive) { + TRACKED_OBJECT_POSES.forEach(function (key) { + var pose = Controller.getPoseValue(Controller.Hardware.Vive[key]); + if (pose.valid) { + DebugDraw.addMyAvatarMarker(key, pose.rotation, pose.translation, WHITE); + } else { + DebugDraw.removeMyAvatarMarker(key); + } + }); + } +} + +init(); diff --git a/scripts/system/controllers/teleport.js b/scripts/system/controllers/teleport.js index 90f8ccb368..33c0b3116e 100644 --- a/scripts/system/controllers/teleport.js +++ b/scripts/system/controllers/teleport.js @@ -297,8 +297,9 @@ function Teleporter() { } else if (teleportLocationType === TARGET.SURFACE) { var offset = getAvatarFootOffset(); intersection.intersection.y += offset; - MyAvatar.position = intersection.intersection; + MyAvatar.goToLocation(intersection.intersection, false, {x: 0, y: 0, z: 0, w: 1}, false); HMD.centerUI(); + MyAvatar.centerBody(); } } }; diff --git a/scripts/system/makeUserConnection.js b/scripts/system/makeUserConnection.js index e70e0a2ea2..0a781a5bb8 100644 --- a/scripts/system/makeUserConnection.js +++ b/scripts/system/makeUserConnection.js @@ -543,12 +543,14 @@ function connectionRequestCompleted() { // Final result is in. Do effects. // don't change state (so animation continues while gripped) // but do send a notification, by calling the slot that emits the signal for it Window.makeConnection(true, result.connection.new_connection ? "You and " + result.connection.username + " are now connected!" : result.connection.username); + UserActivityLogger.makeUserConnection(connectingId, true, result.connection.new_connection ? "new connection" : "already connected"); return; } // failed endHandshake(); debug("failing with result data", result); // IWBNI we also did some fail sound/visual effect. Window.makeConnection(false, result.connection); + UserActivityLogger.makeUserConnection(connectingId, false, result.connection); } var POLL_INTERVAL_MS = 200, POLL_LIMIT = 5; function handleConnectionResponseAndMaybeRepeat(error, response) { @@ -573,6 +575,7 @@ function handleConnectionResponseAndMaybeRepeat(error, response) { } else if (error || (response.status !== 'success')) { debug('server fail', error, response.status); result = error ? {status: 'error', connection: error} : response; + UserActivityLogger.makeUserConnection(connectingId, false, error || response); connectionRequestCompleted(); } else { debug('server success', result);