diff --git a/interface/resources/qml/hifi/tablet/Tablet.qml b/interface/resources/qml/hifi/tablet/Tablet.qml index 8203b9f972..3e0a9d8c14 100644 --- a/interface/resources/qml/hifi/tablet/Tablet.qml +++ b/interface/resources/qml/hifi/tablet/Tablet.qml @@ -171,7 +171,7 @@ Item { console.log("Tablet.onCompleted!"); var component = Qt.createComponent("TabletButton.qml"); var buttons = []; - for (var i = 0; i < 5; i++) { + for (var i = 0; i < 6; i++) { var button = component.createObject(flowMain); button.inDebugMode = true; buttons.push(button); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cd985de339..252d5b9ba7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1592,7 +1592,15 @@ void Application::toggleMenuUnderReticle() const { offscreenUi->toggleMenu(QPoint(reticlePosition.x - X_LEFT_SHIFT, reticlePosition.y)); } +uint64_t lastTabletUIToggle { 0 }; +const uint64_t toggleTabletUILockout { 500000 }; void Application::toggleTabletUI() const { + uint64_t now = usecTimestampNow(); + if (now - lastTabletUIToggle < toggleTabletUILockout) { + return; + } + lastTabletUIToggle = now; + auto HMD = DependencyManager::get(); HMD->toggleShouldShowTablet(); } diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index ee1a0f5256..cd9f60aa82 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -18,16 +18,16 @@ #include #include +#include +#include #include #include #include -#include -#include -#include -#include -#include - #include +#include +#include +#include +#include static const float DPI = 30.47f; static const float INCHES_TO_METERS = 1.0f / 39.3701f; @@ -36,7 +36,7 @@ static const float OPAQUE_ALPHA_THRESHOLD = 0.99f; QString const Web3DOverlay::TYPE = "web3d"; -Web3DOverlay::Web3DOverlay() : _dpi(DPI) { +Web3DOverlay::Web3DOverlay() : _dpi(DPI) { _touchDevice.setCapabilities(QTouchDevice::Position); _touchDevice.setType(QTouchDevice::TouchScreen); _touchDevice.setName("RenderableWebEntityItemTouchDevice"); @@ -57,6 +57,24 @@ Web3DOverlay::Web3DOverlay(const Web3DOverlay* Web3DOverlay) : Web3DOverlay::~Web3DOverlay() { if (_webSurface) { + QQuickItem* rootItem = _webSurface->getRootItem(); + + // TABLET_UI_HACK: TODO: update this with rootTablet + if (rootItem && rootItem->objectName() == "tablet") { + auto tabletScriptingInterface = DependencyManager::get(); + tabletScriptingInterface->setQmlTablet("com.highfidelity.interface.tablet.system", nullptr); + } + + // Fix for crash in QtWebEngineCore when rapidly switching domains + // Call stop on the QWebEngineView before destroying OffscreenQMLSurface. + if (rootItem) { + QObject* obj = rootItem->findChild("webEngineView"); + if (obj) { + // stop loading + QMetaObject::invokeMethod(obj, "stop"); + } + } + _webSurface->pause(); _webSurface->disconnect(_connection); @@ -101,6 +119,32 @@ void Web3DOverlay::update(float deltatime) { */ } +void Web3DOverlay::loadSourceURL() { + + QUrl sourceUrl(_url); + if (sourceUrl.scheme() == "http" || sourceUrl.scheme() == "https" || + _url.toLower().endsWith(".htm") || _url.toLower().endsWith(".html")) { + + _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/")); + _webSurface->load("Web3DOverlay.qml"); + _webSurface->resume(); + _webSurface->getRootItem()->setProperty("url", _url); + _webSurface->getRootItem()->setProperty("scriptURL", _scriptURL); + _webSurface->getRootContext()->setContextProperty("ApplicationInterface", qApp); + + } else { + _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath())); + _webSurface->load(_url, [&](QQmlContext* context, QObject* obj) {}); + _webSurface->resume(); + + // TABLET_UI_HACK: TODO: update this to use rootTablet. + if (_webSurface->getRootItem() && _webSurface->getRootItem()->objectName() == "tablet") { + auto tabletScriptingInterface = DependencyManager::get(); + tabletScriptingInterface->setQmlTablet("com.highfidelity.interface.tablet.system", _webSurface->getRootItem()); + } + } +} + void Web3DOverlay::render(RenderArgs* args) { if (!_visible || !getParentVisible()) { return; @@ -119,12 +163,9 @@ void Web3DOverlay::render(RenderArgs* args) { // and the current rendering load) _webSurface->setMaxFps(10); _webSurface->create(currentContext); - _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/")); - _webSurface->load("Web3DOverlay.qml"); - _webSurface->resume(); - _webSurface->getRootItem()->setProperty("url", _url); - _webSurface->getRootItem()->setProperty("scriptURL", _scriptURL); - _webSurface->getRootContext()->setContextProperty("ApplicationInterface", qApp); + + loadSourceURL(); + _webSurface->resize(QSize(_resolution.x, _resolution.y)); currentContext->makeCurrent(currentSurface); @@ -150,7 +191,7 @@ void Web3DOverlay::render(RenderArgs* args) { point.setPos(windowPoint); QList touchPoints; touchPoints.push_back(point); - QTouchEvent* touchEvent = new QTouchEvent(QEvent::TouchEnd, nullptr, Qt::NoModifier, Qt::TouchPointReleased, + QTouchEvent* touchEvent = new QTouchEvent(QEvent::TouchEnd, nullptr, Qt::NoModifier, Qt::TouchPointReleased, touchPoints); touchEvent->setWindow(_webSurface->getWindow()); touchEvent->setDevice(&_touchDevice); @@ -167,7 +208,7 @@ void Web3DOverlay::render(RenderArgs* args) { vec4 color(toGlm(getColor()), getAlpha()); Transform transform = getTransform(); - + // FIXME: applyTransformTo causes tablet overlay to detach from tablet entity. // Perhaps rather than deleting the following code it should be run only if isFacingAvatar() is true? /* @@ -237,7 +278,7 @@ void Web3DOverlay::handlePointerEvent(const PointerEvent& event) { if (event.getType() == PointerEvent::Move) { // Forward a mouse move event to the Web surface. - QMouseEvent* mouseEvent = new QMouseEvent(QEvent::MouseMove, windowPoint, windowPoint, windowPoint, Qt::NoButton, + QMouseEvent* mouseEvent = new QMouseEvent(QEvent::MouseMove, windowPoint, windowPoint, windowPoint, Qt::NoButton, Qt::NoButton, Qt::NoModifier); QCoreApplication::postEvent(_webSurface->getWindow(), mouseEvent); } @@ -338,7 +379,7 @@ void Web3DOverlay::setURL(const QString& url) { _url = url; if (_webSurface) { AbstractViewStateInterface::instance()->postLambdaEvent([this, url] { - _webSurface->getRootItem()->setProperty("url", url); + loadSourceURL(); }); } } diff --git a/interface/src/ui/overlays/Web3DOverlay.h b/interface/src/ui/overlays/Web3DOverlay.h index 45ec9fbc50..db45b073e2 100644 --- a/interface/src/ui/overlays/Web3DOverlay.h +++ b/interface/src/ui/overlays/Web3DOverlay.h @@ -28,6 +28,7 @@ public: Web3DOverlay(const Web3DOverlay* Web3DOverlay); virtual ~Web3DOverlay(); + void loadSourceURL(); virtual void render(RenderArgs* args) override; virtual const render::ShapeKey getShapeKey() override; @@ -46,7 +47,7 @@ public: glm::vec2 getSize(); - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, + virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face, glm::vec3& surfaceNormal) override; virtual Web3DOverlay* createClone() const override; diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 7e51249830..34e3fa87b7 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -366,6 +366,8 @@ void RenderableWebEntityItem::destroyWebSurface() { tabletScriptingInterface->setQmlTablet("com.highfidelity.interface.tablet.system", nullptr); } + // Fix for crash in QtWebEngineCore when rapidly switching domains + // Call stop on the QWebEngineView before destroying OffscreenQMLSurface. if (rootItem) { QObject* obj = rootItem->findChild("webEngineView"); if (obj) { diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 3055473666..384e0e24a6 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -13,7 +13,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html /* global setEntityCustomData, getEntityCustomData, flatten, Xform, Script, Quat, Vec3, MyAvatar, Entities, Overlays, Settings, - Reticle, Controller, Camera, Messages, Mat4, getControllerWorldLocation, getGrabPointSphereOffset, setGrabCommunications */ + Reticle, Controller, Camera, Messages, Mat4, getControllerWorldLocation, getGrabPointSphereOffset, setGrabCommunications, + Menu */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ (function() { // BEGIN LOCAL_SCOPE @@ -61,6 +62,12 @@ var PICK_WITH_HAND_RAY = true; var EQUIP_SPHERE_SCALE_FACTOR = 0.65; +var WEB_TOUCH_SPHERE_RADIUS = 0.017; +var WEB_STYLUS_COLOR = { red: 0, green: 240, blue: 0 }; +var WEB_STYLUS_TIP_COLOR = { red: 0, green: 0, blue: 240 }; +var WEB_STYLUS_ALPHA = 1.0; +var WEB_DISPLAY_STYLUS_DISTANCE = 1.0; +var WEB_TOUCH_DISTANCE = 0.2; // // distant manipulation @@ -747,6 +754,7 @@ function MyController(hand) { this.hand = hand; this.autoUnequipCounter = 0; this.grabPointIntersectsEntity = false; + this.stylus = null; this.shouldScale = false; @@ -946,6 +954,62 @@ function MyController(hand) { } }; + this.showStylus = function() { + if (this.stylus) { + return; + } + if (!MyAvatar.sessionUUID) { + return; + } + print("SHOW"); + var stylusTipProperties = { + localPosition: Vec3.sum({ x: 0, y: WEB_TOUCH_DISTANCE - (WEB_TOUCH_SPHERE_RADIUS / 2.0), z: 0 }, + getGrabPointSphereOffset(this.handToController())), + localRotation: { x: 0, y: 0, z: 0, w: 1 }, + dimensions: WEB_TOUCH_SPHERE_RADIUS, + color: WEB_STYLUS_TIP_COLOR, + alpha: WEB_STYLUS_ALPHA, + solid: true, + visible: true, + ignoreRayIntersection: true, + drawInFront: false, + parentID: MyAvatar.sessionUUID, + parentJointIndex: MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? + "_CONTROLLER_RIGHTHAND" : + "_CONTROLLER_LEFTHAND") + }; + this.stylusTip = Overlays.addOverlay("sphere", stylusTipProperties); + + var stylusProperties = { + localPosition: Vec3.sum({ x: 0.0, y: WEB_TOUCH_DISTANCE / 2.0, z: 0.0 }, + getGrabPointSphereOffset(this.handToController())), + localRotation: { x: 0, y: 0, z: 0, w: 1 }, + dimensions: { x: 0.01, y: WEB_TOUCH_DISTANCE - WEB_TOUCH_SPHERE_RADIUS, z: 0.01 }, + color: WEB_STYLUS_COLOR, + alpha: WEB_STYLUS_ALPHA, + solid: true, + visible: true, + ignoreRayIntersection: true, + drawInFront: false, + parentID: MyAvatar.sessionUUID, + parentJointIndex: MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? + "_CONTROLLER_RIGHTHAND" : + "_CONTROLLER_LEFTHAND") + }; + this.stylus = Overlays.addOverlay("cube", stylusProperties); + }; + + this.hideStylus = function() { + if (!this.stylus) { + return; + } + print("HIDE"); + Overlays.deleteOverlay(this.stylus); + this.stylus = null; + Overlays.deleteOverlay(this.stylusTip); + this.stylusTip = null; + }; + this.overlayLineOn = function(closePoint, farPoint, color) { if (this.overlayLine === null) { var lineProperties = { @@ -1064,7 +1128,6 @@ function MyController(hand) { _this.rawSecondaryValue = value; // The value to check if we will allow the release function to be called - var allowReleaseValue = 0.1; if (value > 0 && _this.state == STATE_HOLD) { _this.release(); } @@ -1162,6 +1225,142 @@ function MyController(hand) { this.grabPointIntersectsEntity = false; this.grabPointSphereOff(); } + + var rayPickInfo = this.calcRayPickInfo(this.hand); + if (rayPickInfo.overlayID && rayPickInfo.distance < WEB_DISPLAY_STYLUS_DISTANCE) { + this.showStylus(); + this.hideStylusCounter = 0; + } else if (rayPickInfo.entityID && + rayPickInfo.properties.type == "Web" && + rayPickInfo.distance < WEB_DISPLAY_STYLUS_DISTANCE) { + this.showStylus(); + this.hideStylusCounter = 0; + } else { + this.hideStylusCounter++; + if (this.hideStylusCounter > 10) { + this.hideStylus(); + } + return; + } + + if (rayPickInfo.distance < WEB_TOUCH_DISTANCE) { + Controller.triggerHapticPulse(1, 20, this.hand); + var pointerEvent; + + if (rayPickInfo.entityID && Entities.wantsHandControllerPointerEvents(rayPickInfo.entityID)) { + var entity = rayPickInfo.entityID; + var name = entityPropertiesCache.getProps(entity).name; + + if (Entities.keyboardFocusEntity != entity) { + Overlays.keyboardFocusOverlay = 0; + Entities.keyboardFocusEntity = entity; + + pointerEvent = { + type: "Move", + id: this.hand + 1, // 0 is reserved for hardware mouse + pos2D: projectOntoEntityXYPlane(entity, rayPickInfo.intersection), + pos3D: rayPickInfo.intersection, + normal: rayPickInfo.normal, + direction: rayPickInfo.searchRay.direction, + button: "None" + }; + + this.hoverEntity = entity; + Entities.sendHoverEnterEntity(entity, pointerEvent); + } + + // send mouse events for button highlights and tooltips. + if (this.hand == mostRecentSearchingHand || (this.hand !== mostRecentSearchingHand && + this.getOtherHandController().state !== STATE_SEARCHING && + this.getOtherHandController().state !== STATE_ENTITY_TOUCHING && + this.getOtherHandController().state !== STATE_OVERLAY_TOUCHING)) { + + // most recently searching hand has priority over other hand, for the purposes of button highlighting. + pointerEvent = { + type: "Move", + id: this.hand + 1, // 0 is reserved for hardware mouse + pos2D: projectOntoEntityXYPlane(entity, rayPickInfo.intersection), + pos3D: rayPickInfo.intersection, + normal: rayPickInfo.normal, + direction: rayPickInfo.searchRay.direction, + button: "None" + }; + + Entities.sendMouseMoveOnEntity(entity, pointerEvent); + Entities.sendHoverOverEntity(entity, pointerEvent); + } + + if (!isEditing()) { + this.grabbedEntity = entity; + this.setState(STATE_ENTITY_TOUCHING, "begin touching entity '" + name + "'"); + return; + } + } else if (this.hoverEntity) { + pointerEvent = { + type: "Move", + id: this.hand + 1 + }; + Entities.sendHoverLeaveEntity(this.hoverEntity, pointerEvent); + this.hoverEntity = null; + } + + if (rayPickInfo.overlayID) { + var overlay = rayPickInfo.overlayID; + + if (Overlays.keyboardFocusOverlay != overlay) { + Entities.keyboardFocusEntity = null; + Overlays.keyboardFocusOverlay = overlay; + + pointerEvent = { + type: "Move", + id: HARDWARE_MOUSE_ID, + pos2D: projectOntoOverlayXYPlane(overlay, rayPickInfo.intersection), + pos3D: rayPickInfo.intersection, + normal: rayPickInfo.normal, + direction: rayPickInfo.searchRay.direction, + button: "None" + }; + + this.hoverOverlay = overlay; + Overlays.sendHoverEnterOverlay(overlay, pointerEvent); + } + + // Send mouse events for button highlights and tooltips. + if (this.hand == mostRecentSearchingHand || (this.hand !== mostRecentSearchingHand && + this.getOtherHandController().state !== STATE_SEARCHING && + this.getOtherHandController().state !== STATE_ENTITY_TOUCHING && + this.getOtherHandController().state !== STATE_OVERLAY_TOUCHING)) { + + // most recently searching hand has priority over other hand, for the purposes of button highlighting. + pointerEvent = { + type: "Move", + id: HARDWARE_MOUSE_ID, + pos2D: projectOntoOverlayXYPlane(overlay, rayPickInfo.intersection), + pos3D: rayPickInfo.intersection, + normal: rayPickInfo.normal, + direction: rayPickInfo.searchRay.direction, + button: "None" + }; + + Overlays.sendMouseMoveOnOverlay(overlay, pointerEvent); + Overlays.sendHoverOverOverlay(overlay, pointerEvent); + } + + if (!isEditing()) { + this.grabbedOverlay = overlay; + this.setState(STATE_OVERLAY_TOUCHING, "begin touching overlay '" + overlay + "'"); + return; + } + + } else if (this.hoverOverlay) { + pointerEvent = { + type: "Move", + id: HARDWARE_MOUSE_ID + }; + Overlays.sendHoverLeaveOverlay(this.hoverOverlay, pointerEvent); + this.hoverOverlay = null; + } + } }; this.clearEquipHaptics = function() { @@ -1230,7 +1429,8 @@ function MyController(hand) { searchRay: pickRay, distance: Vec3.distance(pickRay.origin, intersection.intersection), intersection: intersection.intersection, - normal: intersection.surfaceNormal + normal: intersection.surfaceNormal, + properties: intersection.properties }; } else { return result; @@ -1562,63 +1762,7 @@ function MyController(hand) { } } - var pointerEvent; - if (rayPickInfo.entityID && Entities.wantsHandControllerPointerEvents(rayPickInfo.entityID)) { - entity = rayPickInfo.entityID; - name = entityPropertiesCache.getProps(entity).name; - - if (Entities.keyboardFocusEntity != entity) { - Overlays.keyboardFocusOverlay = 0; - Entities.keyboardFocusEntity = entity; - - pointerEvent = { - type: "Move", - id: this.hand + 1, // 0 is reserved for hardware mouse - pos2D: projectOntoEntityXYPlane(entity, rayPickInfo.intersection), - pos3D: rayPickInfo.intersection, - normal: rayPickInfo.normal, - direction: rayPickInfo.searchRay.direction, - button: "None" - }; - - this.hoverEntity = entity; - Entities.sendHoverEnterEntity(entity, pointerEvent); - } - - // send mouse events for button highlights and tooltips. - if (this.hand == mostRecentSearchingHand || (this.hand !== mostRecentSearchingHand && - this.getOtherHandController().state !== STATE_SEARCHING && - this.getOtherHandController().state !== STATE_ENTITY_TOUCHING && - this.getOtherHandController().state !== STATE_OVERLAY_TOUCHING)) { - - // most recently searching hand has priority over other hand, for the purposes of button highlighting. - pointerEvent = { - type: "Move", - id: this.hand + 1, // 0 is reserved for hardware mouse - pos2D: projectOntoEntityXYPlane(entity, rayPickInfo.intersection), - pos3D: rayPickInfo.intersection, - normal: rayPickInfo.normal, - direction: rayPickInfo.searchRay.direction, - button: "None" - }; - - Entities.sendMouseMoveOnEntity(entity, pointerEvent); - Entities.sendHoverOverEntity(entity, pointerEvent); - } - - if (this.triggerSmoothedGrab() && (!isEditing() || name == "WebTablet Web")) { - this.grabbedEntity = entity; - this.setState(STATE_ENTITY_TOUCHING, "begin touching entity '" + name + "'"); - return; - } - } else if (this.hoverEntity) { - pointerEvent = { - type: "Move", - id: this.hand + 1 - }; - Entities.sendHoverLeaveEntity(this.hoverEntity, pointerEvent); - this.hoverEntity = null; - } + // web-entity mouse event stuff was here if (rayPickInfo.entityID) { entity = rayPickInfo.entityID; @@ -1642,64 +1786,7 @@ function MyController(hand) { } } - var overlay; - - if (rayPickInfo.overlayID) { - overlay = rayPickInfo.overlayID; - - if (Overlays.keyboardFocusOverlay != overlay) { - Entities.keyboardFocusEntity = null; - Overlays.keyboardFocusOverlay = overlay; - - pointerEvent = { - type: "Move", - id: HARDWARE_MOUSE_ID, - pos2D: projectOntoOverlayXYPlane(overlay, rayPickInfo.intersection), - pos3D: rayPickInfo.intersection, - normal: rayPickInfo.normal, - direction: rayPickInfo.searchRay.direction, - button: "None" - }; - - this.hoverOverlay = overlay; - Overlays.sendHoverEnterOverlay(overlay, pointerEvent); - } - - // Send mouse events for button highlights and tooltips. - if (this.hand == mostRecentSearchingHand || (this.hand !== mostRecentSearchingHand && - this.getOtherHandController().state !== STATE_SEARCHING && - this.getOtherHandController().state !== STATE_ENTITY_TOUCHING && - this.getOtherHandController().state !== STATE_OVERLAY_TOUCHING)) { - - // most recently searching hand has priority over other hand, for the purposes of button highlighting. - pointerEvent = { - type: "Move", - id: HARDWARE_MOUSE_ID, - pos2D: projectOntoOverlayXYPlane(overlay, rayPickInfo.intersection), - pos3D: rayPickInfo.intersection, - normal: rayPickInfo.normal, - direction: rayPickInfo.searchRay.direction, - button: "None" - }; - - Overlays.sendMouseMoveOnOverlay(overlay, pointerEvent); - Overlays.sendHoverOverOverlay(overlay, pointerEvent); - } - - if (this.triggerSmoothedGrab() && !isEditing()) { - this.grabbedOverlay = overlay; - this.setState(STATE_OVERLAY_TOUCHING, "begin touching overlay '" + overlay + "'"); - return; - } - - } else if (this.hoverOverlay) { - pointerEvent = { - type: "Move", - id: HARDWARE_MOUSE_ID - }; - Overlays.sendHoverLeaveOverlay(this.hoverOverlay, pointerEvent); - this.hoverOverlay = null; - } + // overlay mouse event stuff was here this.updateEquipHaptics(potentialEquipHotspot, handPosition); @@ -2459,16 +2546,16 @@ function MyController(hand) { entityPropertiesCache.addEntity(this.grabbedEntity); - if (!this.triggerSmoothedGrab()) { - this.setState(STATE_OFF, "released trigger"); - return; - } - // test for intersection between controller laser and web entity plane. var intersectInfo = handLaserIntersectEntity(this.grabbedEntity, getControllerWorldLocation(this.handToController(), true)); if (intersectInfo) { + if (intersectInfo.distance > WEB_TOUCH_DISTANCE) { + this.setState(STATE_OFF, "pulled away from web entity"); + return; + } + if (Entities.keyboardFocusEntity != this.grabbedEntity) { Overlays.keyboardFocusOverlay = 0; Entities.keyboardFocusEntity = this.grabbedEntity; @@ -2495,9 +2582,6 @@ function MyController(hand) { } this.intersectionDistance = intersectInfo.distance; - if (farGrabEnabled) { - this.searchIndicatorOn(intersectInfo.searchRay); - } Reticle.setVisible(false); } else { this.setState(STATE_OFF, "grabbed entity was destroyed"); @@ -2562,16 +2646,16 @@ function MyController(hand) { this.overlayTouching = function (dt) { this.touchingEnterTimer += dt; - if (!this.triggerSmoothedGrab()) { - this.setState(STATE_OFF, "released trigger"); - return; - } - // Test for intersection between controller laser and Web overlay plane. var intersectInfo = handLaserIntersectOverlay(this.grabbedOverlay, getControllerWorldLocation(this.handToController(), true)); if (intersectInfo) { + if (intersectInfo.distance > WEB_TOUCH_DISTANCE) { + this.setState(STATE_OFF, "pulled away from overlay"); + return; + } + if (Overlays.keyboardFocusOverlay != this.grabbedOverlay) { Entities.keyboardFocusEntity = null; Overlays.keyboardFocusOverlay = this.grabbedOverlay; @@ -2591,15 +2675,13 @@ function MyController(hand) { var POINTER_PRESS_TO_MOVE_DELAY = 0.15; // seconds var POINTER_PRESS_TO_MOVE_DEADSPOT_ANGLE = 0.05; // radians ~ 3 degrees if (this.deadspotExpired || this.touchingEnterTimer > POINTER_PRESS_TO_MOVE_DELAY || - angleBetween(pointerEvent.direction, this.touchingEnterPointerEvent.direction) > POINTER_PRESS_TO_MOVE_DEADSPOT_ANGLE) { + angleBetween(pointerEvent.direction, + this.touchingEnterPointerEvent.direction) > POINTER_PRESS_TO_MOVE_DEADSPOT_ANGLE) { Overlays.sendMouseMoveOnOverlay(this.grabbedOverlay, pointerEvent); this.deadspotExpired = true; } this.intersectionDistance = intersectInfo.distance; - if (farGrabEnabled) { - this.searchIndicatorOn(intersectInfo.searchRay); - } Reticle.setVisible(false); } else { this.setState(STATE_OFF, "grabbed overlay was destroyed"); diff --git a/scripts/system/help.js b/scripts/system/help.js index d1be9f6e79..c8e14a80a6 100644 --- a/scripts/system/help.js +++ b/scripts/system/help.js @@ -27,7 +27,6 @@ Script.scriptEnding.connect(function () { tablet.removeButton(button); - button.clicked.disconnect(onClicked); }); }()); // END LOCAL_SCOPE