diff --git a/interface/src/raypick/PathPointer.cpp b/interface/src/raypick/PathPointer.cpp index d0f66cd240..7e8ec74549 100644 --- a/interface/src/raypick/PathPointer.cpp +++ b/interface/src/raypick/PathPointer.cpp @@ -366,3 +366,17 @@ QVector PathPointer::getOverlayIDs() { } return result; } + +QUuid PathPointer::getStartOverlayID(const QString& state) { + if (_renderStates.find(_currentRenderState) != _renderStates.end()) { + return _renderStates[_currentRenderState]->getStartID(); + } + return QUuid(); +} + +QUuid PathPointer::getEndOverlayID(const QString& state) { + if (_renderStates.find(_currentRenderState) != _renderStates.end()) { + return _renderStates[_currentRenderState]->getEndID(); + } + return QUuid(); +} diff --git a/interface/src/raypick/PathPointer.h b/interface/src/raypick/PathPointer.h index 92d221aeb9..49db9ba95a 100644 --- a/interface/src/raypick/PathPointer.h +++ b/interface/src/raypick/PathPointer.h @@ -77,6 +77,8 @@ public: void editRenderState(const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) override; QVector getOverlayIDs() override; + QUuid getStartOverlayID(const QString& state) override; + QUuid getEndOverlayID(const QString& state) override; void setLength(float length) override; void setLockEndUUID(const QUuid& objectID, bool isOverlay, const glm::mat4& offsetMat = glm::mat4()) override; diff --git a/interface/src/raypick/PointerScriptingInterface.cpp b/interface/src/raypick/PointerScriptingInterface.cpp index 34f9841fe9..fd37efcdac 100644 --- a/interface/src/raypick/PointerScriptingInterface.cpp +++ b/interface/src/raypick/PointerScriptingInterface.cpp @@ -379,4 +379,12 @@ QVariantMap PointerScriptingInterface::getPrevPickResult(unsigned int uid) const QVector PointerScriptingInterface::getOverlayIDs(unsigned int uid) { return DependencyManager::get()->getOverlayIDs(uid); -} \ No newline at end of file +} + +QUuid PointerScriptingInterface::getStartOverlayID(unsigned int uid, const QString& state) { + return DependencyManager::get()->getStartOverlayID(uid, state); +} + +QUuid PointerScriptingInterface::getEndOverlayID(unsigned int uid, const QString& state) { + return DependencyManager::get()->getEndOverlayID(uid, state); +} diff --git a/interface/src/raypick/PointerScriptingInterface.h b/interface/src/raypick/PointerScriptingInterface.h index 65036c3104..830111f770 100644 --- a/interface/src/raypick/PointerScriptingInterface.h +++ b/interface/src/raypick/PointerScriptingInterface.h @@ -207,9 +207,29 @@ public: * Get the IDs of the overlays used by a Pointer. * @function Pointers.getOverlayIDs * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. - * @returns {Uuid[]} The overlay IDs used by the Pointer. + * @returns {Uuid[]} The overlay IDs used by the Pointer if a {@link PickType|Parabola}, otherwise null. */ Q_INVOKABLE QVector getOverlayIDs(unsigned int uid); + + /**jsdoc + * Get the ID of the start overlay for a particular state used by a {@link PickType|Path} or {@link PickType|Parabola} + * Pointer. + * @function Pointers.getStartOverlayID + * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. + * @returns {Uuid} The ID of the start overlay used by the Pointer if a {@link PickType|Path} or {@link PickType|Parabola}, + * otherwise Uuid.NULL. + */ + Q_INVOKABLE QUuid getStartOverlayID(unsigned int uid, const QString& state); + + /**jsdoc + * Get the ID of the end overlay for a particular state used by a {@link PickType|Path} or {@link PickType|Parabola} + * Pointer. + * @function Pointers.getEndOverlayID + * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. + * @returns {Uuid} The ID of the end overlay used by the Pointer if a {@link PickType|Path} or {@link PickType|Parabola}, + * otherwise Uuid.NULL. + */ + Q_INVOKABLE QUuid getEndOverlayID(unsigned int uid, const QString& state); }; #endif // hifi_PointerScriptingInterface_h diff --git a/interface/src/raypick/StylusPointer.h b/interface/src/raypick/StylusPointer.h index a4778ffd97..4957943652 100644 --- a/interface/src/raypick/StylusPointer.h +++ b/interface/src/raypick/StylusPointer.h @@ -34,6 +34,8 @@ public: void editRenderState(const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) override {} QVector getOverlayIDs() override; + QUuid getStartOverlayID(const QString& state) override { return QUuid(); }; + QUuid getEndOverlayID(const QString& state) override { return QUuid(); };; static OverlayID buildStylusOverlay(const QVariantMap& properties); diff --git a/libraries/pointers/src/Pointer.h b/libraries/pointers/src/Pointer.h index 96b43e317b..2b3c1477ae 100644 --- a/libraries/pointers/src/Pointer.h +++ b/libraries/pointers/src/Pointer.h @@ -51,6 +51,8 @@ public: virtual void editRenderState(const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) = 0; virtual QVector getOverlayIDs() = 0; + virtual QUuid getStartOverlayID(const QString& state) = 0; + virtual QUuid getEndOverlayID(const QString& state) = 0; virtual void setPrecisionPicking(bool precisionPicking); virtual void setIgnoreItems(const QVector& ignoreItems) const; diff --git a/libraries/pointers/src/PointerManager.cpp b/libraries/pointers/src/PointerManager.cpp index 6a395ecac2..484f946f2d 100644 --- a/libraries/pointers/src/PointerManager.cpp +++ b/libraries/pointers/src/PointerManager.cpp @@ -154,3 +154,19 @@ QVector PointerManager::getOverlayIDs(unsigned int uid) { QVector empty; return empty; } + +QUuid PointerManager::getStartOverlayID(unsigned int uid, const QString& state) { + auto pointer = find(uid); + if (pointer) { + return pointer->getStartOverlayID(state); + } + return QUuid(); +} + +QUuid PointerManager::getEndOverlayID(unsigned int uid, const QString& state) { + auto pointer = find(uid); + if (pointer) { + return pointer->getEndOverlayID(state); + } + return QUuid(); +} diff --git a/libraries/pointers/src/PointerManager.h b/libraries/pointers/src/PointerManager.h index 0b6dcd6eae..10482a74a7 100644 --- a/libraries/pointers/src/PointerManager.h +++ b/libraries/pointers/src/PointerManager.h @@ -45,6 +45,8 @@ public: bool isMouse(unsigned int uid); QVector getOverlayIDs(unsigned int uid); + QUuid getStartOverlayID(unsigned int uid, const QString& state); + QUuid getEndOverlayID(unsigned int uid, const QString& state); static const unsigned int MOUSE_POINTER_ID { PointerEvent::INVALID_POINTER_ID + 1 }; diff --git a/scripts/system/controllers/controllerModules/teleport.js b/scripts/system/controllers/controllerModules/teleport.js index 2325f72d2a..6d08a9d51c 100644 --- a/scripts/system/controllers/controllerModules/teleport.js +++ b/scripts/system/controllers/controllerModules/teleport.js @@ -221,6 +221,7 @@ Script.include("/~/system/libraries/controllers.js"); this.playAreaCenterOffset = this.PLAY_AREA_OVERLAY_OFFSET; this.isPlayAreaVisible = false; this.isPlayAreaAvailable = false; + this.targetOverlayID = null; this.TELEPORT_SCALE_DURATION = 500; this.TELEPORT_SCALE_TIMEOUT = 20; @@ -296,14 +297,17 @@ Script.include("/~/system/libraries/controllers.js"); } }; - this.setPlayAreaVisible = function (visible) { + this.setPlayAreaVisible = function (visible, targetOverlayID) { if (!this.isPlayAreaAvailable || this.isPlayAreaVisible === visible) { return; } + this.isPlayAreaVisible = visible; + this.targetOverlayID = targetOverlayID; + Overlays.editOverlay(this.playAreaOverlay, { - visible: visible, - dimensions: Vec3.ZERO + dimensions: Vec3.ZERO, + visible: visible }); for (var i = 0; i < this.playAreaSensorPositionOverlays.length; i++) { Overlays.editOverlay(this.playAreaSensorPositionOverlays[i], { @@ -349,12 +353,31 @@ Script.include("/~/system/libraries/controllers.js"); var avatarSensorPosition = Mat4.transformPoint(worldToSensorMatrix, MyAvatar.position); avatarSensorPosition.y = 0; - Overlays.editOverlay(this.playAreaOverlay, { - position: Vec3.sum(position, - Vec3.multiplyQbyV(sensorToWorldRotation, - Vec3.multiply(MyAvatar.scale, Vec3.subtract(this.playAreaCenterOffset, avatarSensorPosition)))), - rotation: sensorToWorldRotation - }); + var targetXZPosition = { x: position.x, y: 0, z: position.z }; + var avatarXZPosition = MyAvatar.position; + avatarXZPosition.y = 0; + var MIN_PARENTING_DISTANCE = 0.2; // Parenting under this distance results in the play area's rotation jittering. + if (Vec3.distance(targetXZPosition, avatarXZPosition) < MIN_PARENTING_DISTANCE) { + // Set play area position and rotation in world coordinates with no parenting. + Overlays.editOverlay(this.playAreaOverlay, { + parentID: Uuid.NULL, + position: Vec3.sum(position, + Vec3.multiplyQbyV(sensorToWorldRotation, + Vec3.multiply(MyAvatar.scale, Vec3.subtract(this.playAreaCenterOffset, avatarSensorPosition)))), + rotation: sensorToWorldRotation + }); + } else { + // Set play area position and rotation in local coordinates with parenting. + var targetRotation = Overlays.getProperty(this.targetOverlayID, "rotation"); + var sensorToTargetRotation = Quat.multiply(Quat.inverse(targetRotation), sensorToWorldRotation); + Overlays.editOverlay(this.playAreaOverlay, { + parentID: this.targetOverlayID, + localPosition: Vec3.multiplyQbyV(Quat.inverse(targetRotation), + Vec3.multiplyQbyV(sensorToWorldRotation, + Vec3.multiply(MyAvatar.scale, Vec3.subtract(this.playAreaCenterOffset, avatarSensorPosition)))), + localRotation: sensorToTargetRotation + }); + } }; @@ -538,14 +561,17 @@ Script.include("/~/system/libraries/controllers.js"); } else { Selection.disableListHighlight(this.teleporterSelectionName); } + var pointerID; if (mode === 'head') { Pointers.setRenderState(_this.teleportParabolaHeadVisible, visibleState); Pointers.setRenderState(_this.teleportParabolaHeadInvisible, invisibleState); + pointerID = _this.teleportParabolaHeadVisible; } else { Pointers.setRenderState(_this.teleportParabolaHandVisible, visibleState); Pointers.setRenderState(_this.teleportParabolaHandInvisible, invisibleState); + pointerID = _this.teleportParabolaHandVisible; } - this.setPlayAreaVisible(visible); + this.setPlayAreaVisible(visible, Pointers.getEndOverlayID(pointerID, "teleport")); this.setTeleportVisible(visible); };