// // Overlays.h // interface/src/ui/overlays // // Modified by Zander Otavka on 7/15/15 // Copyright 2014 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 // // Exposes methods to scripts for managing `Overlay`s and `OverlayPanel`s. // // YOU SHOULD NOT USE `Overlays` DIRECTLY, unless you like pain and deprecation. Instead, use // the object oriented API replacement found in `examples/libraries/overlayManager.js`. See // that file for docs and usage. // #ifndef hifi_Overlays_h #define hifi_Overlays_h #include #include #include #include #include "Overlay.h" #include "PanelAttachable.h" class PickRay; class OverlayPropertyResult { public: OverlayPropertyResult(); QVariant value; }; Q_DECLARE_METATYPE(OverlayPropertyResult); QScriptValue OverlayPropertyResultToScriptValue(QScriptEngine* engine, const OverlayPropertyResult& value); void OverlayPropertyResultFromScriptValue(const QScriptValue& object, OverlayPropertyResult& value); const OverlayID UNKNOWN_OVERLAY_ID = OverlayID(); /**jsdoc * @typedef {object} Overlays.RayToOverlayIntersectionResult * @property {boolean} intersects - true if the {@link PickRay} intersected with a 3D overlay, otherwise * false. * @property {Uuid} overlayID - The UUID of the overlay that was intersected. * @property {number} distance - The distance from the {@link PickRay} origin to the intersection point. * @property {Vec3} surfaceNormal - The normal of the overlay surface at the intersection point. * @property {Vec3} intersection - The position of the intersection point. * @property {Object} extraInfo Additional intersection details, if available. */ class RayToOverlayIntersectionResult { public: bool intersects { false }; OverlayID overlayID { UNKNOWN_OVERLAY_ID }; float distance { 0 }; BoxFace face; glm::vec3 surfaceNormal; glm::vec3 intersection; QVariantMap extraInfo; }; Q_DECLARE_METATYPE(RayToOverlayIntersectionResult); QScriptValue RayToOverlayIntersectionResultToScriptValue(QScriptEngine* engine, const RayToOverlayIntersectionResult& value); void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& object, RayToOverlayIntersectionResult& value); /**jsdoc * The Overlays API provides facilities to create and interact with overlays. Overlays are 2D and 3D objects visible only to * yourself and that aren't persisted to the domain. They are used for UI. * @namespace Overlays * @property {Uuid} keyboardFocusOverlay - Get or set the {@link Overlays.OverlayType|web3d} overlay that has keyboard focus. * If no overlay is set, get returns null; set to null to clear keyboard focus. */ class Overlays : public QObject { Q_OBJECT Q_PROPERTY(OverlayID keyboardFocusOverlay READ getKeyboardFocusOverlay WRITE setKeyboardFocusOverlay) public: Overlays(); void init(); void update(float deltatime); void renderHUD(RenderArgs* renderArgs); void disable(); void enable(); Overlay::Pointer getOverlay(OverlayID id) const; /// adds an overlay that's already been created OverlayID addOverlay(Overlay* overlay) { return addOverlay(Overlay::Pointer(overlay)); } OverlayID addOverlay(const Overlay::Pointer& overlay); bool mousePressEvent(QMouseEvent* event); bool mouseDoublePressEvent(QMouseEvent* event); bool mouseReleaseEvent(QMouseEvent* event); bool mouseMoveEvent(QMouseEvent* event); void cleanupAllOverlays(); public slots: /**jsdoc * Add an overlay to the scene. * @function Overlays.addOverlay * @param {Overlays.OverlayType} type - The type of the overlay to add. * @param {Overlays.OverlayProperties} properties - The properties of the overlay to add. * @returns {Uuid} The ID of the newly created overlay. * @example Add a cube overlay in front of your avatar. * var overlay = Overlays.addOverlay("cube", { * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -3 })), * rotation: MyAvatar.orientation, * dimensions: { x: 0.3, y: 0.3, z: 0.3 }, * solid: true * }); */ OverlayID addOverlay(const QString& type, const QVariant& properties); /**jsdoc * Create a clone of an existing overlay. * @function Overlays.cloneOverlay * @param {Uuid} overlayID - The ID of the overlay to clone. * @returns {Uuid} The ID of the new overlay. * @example Add an overlay in front of your avatar, clone it, and move the clone to be above the * original. * var position = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -3 })); * var original = Overlays.addOverlay("cube", { * position: position, * rotation: MyAvatar.orientation, * dimensions: { x: 0.3, y: 0.3, z: 0.3 }, * solid: true * }); * * var clone = Overlays.cloneOverlay(original); * Overlays.editOverlay(clone, { * position: Vec3.sum({ x: 0, y: 0.5, z: 0}, position) * }); */ OverlayID cloneOverlay(OverlayID id); /**jsdoc * Edit an overlay's properties. * @function Overlays.editOverlay * @param {Uuid} overlayID - The ID of the overlay to edit. * @param {Overlays.OverlayProperties} properties - The properties changes to make. * @returns {boolean} true if the overlay was found and edited, otherwise false. * @example Add an overlay in front of your avatar then change its color. * var overlay = Overlays.addOverlay("cube", { * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -3 })), * rotation: MyAvatar.orientation, * dimensions: { x: 0.3, y: 0.3, z: 0.3 }, * solid: true * }); * * var success = Overlays.editOverlay(overlay, { * color: { red: 255, green: 0, blue: 0 } * }); * print("Success: " + success); */ bool editOverlay(OverlayID id, const QVariant& properties); /**jsdoc * Edit multiple overlays' properties. * @function Overlays.editOverlays * @param propertiesById {object.} - An object with overlay IDs as keys and * {@link Overlays.OverlayProperties|OverlayProperties} edits to make as values. * @returns {boolean} true if all overlays were found and edited, otherwise false (some may have * been found and edited). * @example Create two overlays in front of your avatar then change their colors. * var overlayA = Overlays.addOverlay("cube", { * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: -0.3, y: 0, z: -3 })), * rotation: MyAvatar.orientation, * dimensions: { x: 0.3, y: 0.3, z: 0.3 }, * solid: true * }); * var overlayB = Overlays.addOverlay("cube", { * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0.3, y: 0, z: -3 })), * rotation: MyAvatar.orientation, * dimensions: { x: 0.3, y: 0.3, z: 0.3 }, * solid: true * }); * * var overlayEdits = {}; * overlayEdits[overlayA] = { color: { red: 255, green: 0, blue: 0 } }; * overlayEdits[overlayB] = { color: { red: 0, green: 255, blue: 0 } }; * var success = Overlays.editOverlays(overlayEdits); * print("Success: " + success); */ bool editOverlays(const QVariant& propertiesById); /**jsdoc * Delete an overlay. * @function Overlays.deleteOverlay * @param {Uuid} overlayID - The ID of the overlay to delete. * @example Create an overlay in front of your avatar then delete it. * var overlay = Overlays.addOverlay("cube", { * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -3 })), * rotation: MyAvatar.orientation, * dimensions: { x: 0.3, y: 0.3, z: 0.3 }, * solid: true * }); * print("Overlay: " + overlay); * Overlays.deleteOverlay(overlay); */ void deleteOverlay(OverlayID id); /**jsdoc * Get the type of an overlay. * @function Overlays.getOverlayType * @param {Uuid} overlayID - The ID of the overlay to get the type of. * @returns {Overlays.OverlayType} The type of the overlay if found, otherwise an empty string. * @example Create an overlay in front of your avatar then get and report its type. * var overlay = Overlays.addOverlay("cube", { * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -3 })), * rotation: MyAvatar.orientation, * dimensions: { x: 0.3, y: 0.3, z: 0.3 }, * solid: true * }); * var type = Overlays.getOverlayType(overlay); * print("Type: " + type); */ QString getOverlayType(OverlayID overlayId); /**jsdoc * Get the overlay script object. * @function Overlays.getOverlayObject * @deprecated This function is deprecated and will soon be removed. * @param {Uuid} overlayID - The ID of the overlay to get the script object of. * @returns {object} The script object for the overlay if found. */ QObject* getOverlayObject(OverlayID id); /**jsdoc * Get the ID of the 2D overlay at a particular point on the screen or HUD. * @function Overlays.getOverlayAtPoint * @param {Vec2} point - The point to check for an overlay. * @returns {Uuid} The ID of the 2D overlay at the specified point if found, otherwise null. * @example Create a 2D overlay and add an event function that reports the overlay clicked on, if any. * var overlay = Overlays.addOverlay("rectangle", { * bounds: { x: 100, y: 100, width: 200, height: 100 }, * color: { red: 255, green: 255, blue: 255 } * }); * print("Created: " + overlay); * * Controller.mousePressEvent.connect(function (event) { * var overlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); * print("Clicked: " + overlay); * }); */ OverlayID getOverlayAtPoint(const glm::vec2& point); /**jsdoc * Get the value of a 3D overlay's property. * @function Overlays.getProperty * @param {Uuid} overlayID - The ID of the overlay. Must be for a 3D {@link Overlays.OverlayType|OverlayType}. * @param {string} property - The name of the property value to get. * @returns {object} The value of the property if the 3D overlay and property can be found, otherwise * undefined. * @example Create an overlay in front of your avatar then report its alpha property value. * var overlay = Overlays.addOverlay("cube", { * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -3 })), * rotation: MyAvatar.orientation, * dimensions: { x: 0.3, y: 0.3, z: 0.3 }, * solid: true * }); * var alpha = Overlays.getProperty(overlay, "alpha"); * print("Overlay alpha: " + alpha); */ OverlayPropertyResult getProperty(OverlayID id, const QString& property); /**jsdoc * Get the values of an overlay's properties. * @function Overlays.getProperties * @param {Uuid} overlayID - The ID of the overlay. * @param {Array.} properties - An array of names of properties to get the values of. * @returns {Overlays.OverlayProperties} The values of valid properties if the overlay can be found, otherwise * undefined. * @example Create an overlay in front of your avatar then report some of its properties. * var overlay = Overlays.addOverlay("cube", { * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -3 })), * rotation: MyAvatar.orientation, * dimensions: { x: 0.3, y: 0.3, z: 0.3 }, * solid: true * }); * var properties = Overlays.getProperties(overlay, ["color", "alpha", "grabbable"]); * print("Overlay properties: " + JSON.stringify(properties)); */ OverlayPropertyResult getProperties(const OverlayID& id, const QStringList& properties); /**jsdoc * Get the values of multiple overlays' properties. * @function Overlays.getOverlaysProperties * @param propertiesById {object.>} - An object with overlay IDs as keys and arrays of the names of * properties to get for each as values. * @returns {object.} An object with overlay IDs as keys and * {@link Overlays.OverlayProperties|OverlayProperties} as values. * @example Create two cube overlays in front of your avatar then get some of their properties. * var overlayA = Overlays.addOverlay("cube", { * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: -0.3, y: 0, z: -3 })), * rotation: MyAvatar.orientation, * dimensions: { x: 0.3, y: 0.3, z: 0.3 }, * solid: true * }); * var overlayB = Overlays.addOverlay("cube", { * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0.3, y: 0, z: -3 })), * rotation: MyAvatar.orientation, * dimensions: { x: 0.3, y: 0.3, z: 0.3 }, * solid: true * }); * var propertiesToGet = {}; * propertiesToGet[overlayA] = ["color", "alpha"]; * propertiesToGet[overlayB] = ["dimensions"]; * var properties = Overlays.getOverlaysProperties(propertiesToGet); * print("Overlays properties: " + JSON.stringify(properties)); */ OverlayPropertyResult getOverlaysProperties(const QVariant& overlaysProperties); /**jsdoc * Find the closest 3D overlay intersected by a {@link PickRay}. * @function Overlays.findRayIntersection * @param {PickRay} pickRay - The PickRay to use for finding overlays. * @param {boolean} [precisionPicking=false] - Unused; exists to match Entity API. * @param {Array.} [overlayIDsToInclude=[]] - Whitelist for intersection test. If empty then the result isn't limited * to overlays in the list. * @param {Array.} [overlayIDsToExclude=[]] - Blacklist for intersection test. If empty then the result doesn't * exclude overlays in the list. * @param {boolean} [visibleOnly=false] - Unused; exists to match Entity API. * @param {boolean} [collidableOnly=false] - Unused; exists to match Entity API. * @returns {Overlays.RayToOverlayIntersectionResult} The closest 3D overlay intersected by pickRay, taking * into account overlayIDsToInclude and overlayIDsToExclude if they're not empty. * @example Create a cube overlay in front of your avatar. Report 3D overlay intersection details for mouse * clicks. * var overlay = Overlays.addOverlay("cube", { * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -3 })), * rotation: MyAvatar.orientation, * dimensions: { x: 0.3, y: 0.3, z: 0.3 }, * solid: true * }); * * Controller.mousePressEvent.connect(function (event) { * var pickRay = Camera.computePickRay(event.x, event.y); * var intersection = Overlays.findRayIntersection(pickRay); * print("Intersection: " + JSON.stringify(intersection)); * }); */ RayToOverlayIntersectionResult findRayIntersection(const PickRay& ray, bool precisionPicking = false, const QScriptValue& overlayIDsToInclude = QScriptValue(), const QScriptValue& overlayIDsToDiscard = QScriptValue(), bool visibleOnly = false, bool collidableOnly = false); // TODO: Apart from the name, this function signature on JavaScript is identical to that of findRayIntersection() and should // probably be removed from the JavaScript API so as not to cause confusion. /**jsdoc * Find the closest 3D overlay intersected by a {@link PickRay}. * @function Overlays.findRayIntersectionVector * @deprecated Use {@link Overlays.findRayIntersection} instead; it has identical parameters and results. * @param {PickRay} pickRay - The PickRay to use for finding overlays. * @param {boolean} [precisionPicking=false] - Unused; exists to match Entity API. * @param {Array.} [overlayIDsToInclude=[]] - Whitelist for intersection test. If empty then the result isn't limited * to overlays in the list. * @param {Array.} [overlayIDsToExclude=[]] - Blacklist for intersection test. If empty then the result doesn't * exclude overlays in the list. * @param {boolean} [visibleOnly=false] - Unused; exists to match Entity API. * @param {boolean} [collidableOnly=false] - Unused; exists to match Entity API. * @returns {Overlays.RayToOverlayIntersectionResult} The closest 3D overlay intersected by pickRay, taking * into account overlayIDsToInclude and overlayIDsToExclude if they're not empty. */ RayToOverlayIntersectionResult findRayIntersectionVector(const PickRay& ray, bool precisionPicking, const QVector& overlaysToInclude, const QVector& overlaysToDiscard, bool visibleOnly = false, bool collidableOnly = false); /**jsdoc * Return a list of 3D overlays with bounding boxes that touch a search sphere. * @function Overlays.findOverlays * @param {Vec3} center - The center of the search sphere. * @param {number} radius - The radius of the search sphere. * @returns {Uuid[]} An array of overlay IDs with bounding boxes that touch a search sphere. * @example Create two cube overlays in front of your avatar then search for overlays near your avatar. * var overlayA = Overlays.addOverlay("cube", { * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: -0.3, y: 0, z: -3 })), * rotation: MyAvatar.orientation, * dimensions: { x: 0.3, y: 0.3, z: 0.3 }, * solid: true * }); * print("Overlay A: " + overlayA); * var overlayB = Overlays.addOverlay("cube", { * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0.3, y: 0, z: -3 })), * rotation: MyAvatar.orientation, * dimensions: { x: 0.3, y: 0.3, z: 0.3 }, * solid: true * }); * print("Overlay B: " + overlayB); * * var overlaysFound = Overlays.findOverlays(MyAvatar.position, 5.0); * print("Overlays found: " + JSON.stringify(overlaysFound)); */ QVector findOverlays(const glm::vec3& center, float radius); /**jsdoc * Check whether an overlay's assets have been loaded. For example, for an image overlay the result indicates * whether its image has been loaded. * @function Overlays.isLoaded * @param {Uuid} overlayID - The ID of the overlay to check. * @returns {boolean} true if the overlay's assets have been loaded, otherwise false. * @example Create an image overlay and report whether its image is loaded after 1s. * var overlay = Overlays.addOverlay("image", { * bounds: { x: 100, y: 100, width: 200, height: 200 }, * imageURL: "https://content.highfidelity.com/DomainContent/production/Particles/wispy-smoke.png" * }); * Script.setTimeout(function () { * var isLoaded = Overlays.isLoaded(overlay); * print("Image loaded: " + isLoaded); * }, 1000); */ bool isLoaded(OverlayID id); /**jsdoc * Calculates the size of the given text in the specified overlay if it is a text overlay. * @function Overlays.textSize * @param {Uuid} overlayID - The ID of the overlay to use for calculation. * @param {string} text - The string to calculate the size of. * @returns {Size} The size of the text if the overlay is a text overlay, otherwise * { height: 0, width : 0 }. If the overlay is a 2D overlay, the size is in pixels; if the overlay is a 3D * overlay, the size is in meters. * @example Calculate the size of "hello" in a 3D text overlay. * var overlay = Overlays.addOverlay("text3d", { * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -2 })), * rotation: MyAvatar.orientation, * text: "hello", * lineHeight: 0.2 * }); * var textSize = Overlays.textSize(overlay, "hello"); * print("Size of \"hello\": " + JSON.stringify(textSize)); */ QSizeF textSize(OverlayID id, const QString& text); /**jsdoc * Get the width of the window or HUD. * @function Overlays.width * @returns {number} The width, in pixels, of the Interface window if in desktop mode or the HUD if in HMD mode. */ float width(); /**jsdoc * Get the height of the window or HUD. * @function Overlays.height * @returns {number} The height, in pixels, of the Interface window if in desktop mode or the HUD if in HMD mode. */ float height(); /**jsdoc * Check if there is an overlay of a given ID. * @function Overlays.isAddedOverly * @param {Uuid} overlayID - The ID to check. * @returns {boolean} true if an overlay with the given ID exists, false otherwise. */ bool isAddedOverlay(OverlayID id); /**jsdoc * Generate a mouse press event on an overlay. * @function Overlays.sendMousePressOnOverlay * @param {Uuid} overlayID - The ID of the overlay to generate a mouse press event on. * @param {PointerEvent} event - The mouse press event details. * @example Create a 2D rectangle overlay plus a 3D cube overlay and generate mousePressOnOverlay events for the 2D * overlay. * var overlay = Overlays.addOverlay("cube", { * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -3 })), * rotation: MyAvatar.orientation, * dimensions: { x: 0.3, y: 0.3, z: 0.3 }, * solid: true * }); * print("3D overlay: " + overlay); * * var overlay = Overlays.addOverlay("rectangle", { * bounds: { x: 100, y: 100, width: 200, height: 100 }, * color: { red: 255, green: 255, blue: 255 } * }); * print("2D overlay: " + overlay); * * // Overlays.mousePressOnOverlay by default applies only to 3D overlays. * Overlays.mousePressOnOverlay.connect(function(overlayID, event) { * print("Clicked: " + overlayID); * }); * * Controller.mousePressEvent.connect(function (event) { * // Overlays.getOverlayAtPoint applies only to 2D overlays. * var overlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); * if (overlay) { * Overlays.sendMousePressOnOverlay(overlay, { * type: "press", * id: 0, * pos2D: event * }); * } * }); */ void sendMousePressOnOverlay(const OverlayID& overlayID, const PointerEvent& event); /**jsdoc * Generate a mouse release event on an overlay. * @function Overlays.sendMouseReleaseOnOverlay * @param {Uuid} overlayID - The ID of the overlay to generate a mouse release event on. * @param {PointerEvent} event - The mouse release event details. */ void sendMouseReleaseOnOverlay(const OverlayID& overlayID, const PointerEvent& event); /**jsdoc * Generate a mouse move event on an overlay. * @function Overlays.sendMouseMoveOnOverlay * @param {Uuid} overlayID - The ID of the overlay to generate a mouse move event on. * @param {PointerEvent} event - The mouse move event details. */ void sendMouseMoveOnOverlay(const OverlayID& overlayID, const PointerEvent& event); /**jsdoc * Generate a hover enter event on an overlay. * @function Overlays.sendHoverEnterOverlay * @param {Uuid} id - The ID of the overlay to generate a hover enter event on. * @param {PointerEvent} event - The hover enter event details. */ void sendHoverEnterOverlay(const OverlayID& overlayID, const PointerEvent& event); /**jsdoc * Generate a hover over event on an overlay. * @function Overlays.sendHoverOverOverlay * @param {Uuid} overlayID - The ID of the overlay to generate a hover over event on. * @param {PointerEvent} event - The hover over event details. */ void sendHoverOverOverlay(const OverlayID& overlayID, const PointerEvent& event); /**jsdoc * Generate a hover leave event on an overlay. * @function Overlays.sendHoverLeaveOverlay * @param {Uuid} overlayID - The ID of the overlay to generate a hover leave event on. * @param {PointerEvent} event - The hover leave event details. */ void sendHoverLeaveOverlay(const OverlayID& overlayID, const PointerEvent& event); /**jsdoc * Get the ID of the Web3D overlay that has keyboard focus. * @function Overlays.getKeyboardFocusOverlay * @returns {Uuid} The ID of the {@link Overlays.OverlayType|web3d} overlay that has focus, if any, otherwise * null. */ OverlayID getKeyboardFocusOverlay(); /**jsdoc * Set the Web3D overlay that has keyboard focus. * @function Overlays.setKeyboardFocusOverlay * @param {Uuid} overlayID - The ID of the {@link Overlays.OverlayType|web3d} overlay to set keyboard focus to. Use * {@link Uuid|Uuid.NULL} or null to unset keyboard focus from an overlay. */ void setKeyboardFocusOverlay(const OverlayID& id); signals: /**jsdoc * Triggered when an overlay is deleted. * @function Overlays.overlayDeleted * @param {Uuid} overlayID - The ID of the overlay that was deleted. * @returns {Signal} * @example Create an overlay then delete it after 1s. * var overlay = Overlays.addOverlay("cube", { * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -3 })), * rotation: MyAvatar.orientation, * dimensions: { x: 0.3, y: 0.3, z: 0.3 }, * solid: true * }); * print("Overlay: " + overlay); * * Overlays.overlayDeleted.connect(function(overlayID) { * print("Deleted: " + overlayID); * }); * Script.setTimeout(function () { * Overlays.deleteOverlay(overlay); * }, 1000); */ void overlayDeleted(OverlayID id); /**jsdoc * Triggered when a mouse press event occurs on an overlay. Only occurs for 3D overlays (unless you use * {@link Overlays.sendMousePressOnOverlay|sendMousePressOnOverlay} for a 2D overlay). * @function Overlays.mousePressOnOverlay * @param {Uuid} overlayID - The ID of the overlay the mouse press event occurred on. * @param {PointerEvent} event - The mouse press event details. * @returns {Signal} * @example Create a cube overlay in front of your avatar and report mouse clicks on it. * var overlay = Overlays.addOverlay("cube", { * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -3 })), * rotation: MyAvatar.orientation, * dimensions: { x: 0.3, y: 0.3, z: 0.3 }, * solid: true * }); * print("My overlay: " + overlay); * * Overlays.mousePressOnOverlay.connect(function(overlayID, event) { * if (overlayID === overlay) { * print("Clicked on my overlay"); * } * }); */ void mousePressOnOverlay(OverlayID overlayID, const PointerEvent& event); /**jsdoc * Triggered when a mouse double press event occurs on an overlay. Only occurs for 3D overlays. * @function Overlays.mouseDoublePressOnOverlay * @param {Uuid} overlayID - The ID of the overlay the mouse double press event occurred on. * @param {PointerEvent} event - The mouse double press event details. * @returns {Signal} */ void mouseDoublePressOnOverlay(OverlayID overlayID, const PointerEvent& event); /**jsdoc * Triggered when a mouse release event occurs on an overlay. Only occurs for 3D overlays (unless you use * {@link Overlays.sendMouseReleaseOnOverlay|sendMouseReleaseOnOverlay} for a 2D overlay). * @function Overlays.mouseReleaseOnOverlay * @param {Uuid} overlayID - The ID of the overlay the mouse release event occurred on. * @param {PointerEvent} event - The mouse release event details. * @returns {Signal} */ void mouseReleaseOnOverlay(OverlayID overlayID, const PointerEvent& event); /**jsdoc * Triggered when a mouse move event occurs on an overlay. Only occurs for 3D overlays (unless you use * {@link Overlays.sendMouseMoveOnOverlay|sendMouseMoveOnOverlay} for a 2D overlay). * @function Overlays.mouseMoveOnOverlay * @param {Uuid} overlayID - The ID of the overlay the mouse moved event occurred on. * @param {PointerEvent} event - The mouse move event details. * @returns {Signal} */ void mouseMoveOnOverlay(OverlayID overlayID, const PointerEvent& event); /**jsdoc * Triggered when a mouse press event occurs on something other than a 3D overlay. * @function Overlays.mousePressOffOverlay * @returns {Signal} */ void mousePressOffOverlay(); /**jsdoc * Triggered when a mouse double press event occurs on something other than a 3D overlay. * @function Overlays.mouseDoublePressOffOverlay * @returns {Signal} */ void mouseDoublePressOffOverlay(); /**jsdoc * Triggered when a mouse cursor starts hovering over an overlay. Only occurs for 3D overlays (unless you use * {@link Overlays.sendHoverEnterOverlay|sendHoverEnterOverlay} for a 2D overlay). * @function Overlays.hoverEnterOverlay * @param {Uuid} overlayID - The ID of the overlay the mouse moved event occurred on. * @param {PointerEvent} event - The mouse move event details. * @returns {Signal} * @example Create a cube overlay in front of your avatar and report when you start hovering your mouse over * it. * var overlay = Overlays.addOverlay("cube", { * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -3 })), * rotation: MyAvatar.orientation, * dimensions: { x: 0.3, y: 0.3, z: 0.3 }, * solid: true * }); * print("Overlay: " + overlay); * Overlays.hoverEnterOverlay.connect(function(overlayID, event) { * print("Hover enter: " + overlayID); * }); */ void hoverEnterOverlay(OverlayID overlayID, const PointerEvent& event); /**jsdoc * Triggered when a mouse cursor continues hovering over an overlay. Only occurs for 3D overlays (unless you use * {@link Overlays.sendHoverOverOverlay|sendHoverOverOverlay} for a 2D overlay). * @function Overlays.hoverOverOverlay * @param {Uuid} overlayID - The ID of the overlay the hover over event occurred on. * @param {PointerEvent} event - The hover over event details. * @returns {Signal} */ void hoverOverOverlay(OverlayID overlayID, const PointerEvent& event); /**jsdoc * Triggered when a mouse cursor finishes hovering over an overlay. Only occurs for 3D overlays (unless you use * {@link Overlays.sendHoverLeaveOverlay|sendHoverLeaveOverlay} for a 2D overlay). * @function Overlays.hoverLeaveOverlay * @param {Uuid} overlayID - The ID of the overlay the hover leave event occurred on. * @param {PointerEvent} event - The hover leave event details. * @returns {Signal} */ void hoverLeaveOverlay(OverlayID overlayID, const PointerEvent& event); private: void cleanupOverlaysToDelete(); mutable QMutex _mutex { QMutex::Recursive }; QMap _overlaysHUD; QMap _overlaysWorld; QList _overlaysToDelete; unsigned int _stackOrder { 1 }; bool _enabled = true; PointerEvent calculateOverlayPointerEvent(OverlayID overlayID, PickRay ray, RayToOverlayIntersectionResult rayPickResult, QMouseEvent* event, PointerEvent::EventType eventType); OverlayID _currentClickingOnOverlayID { UNKNOWN_OVERLAY_ID }; OverlayID _currentHoverOverOverlayID { UNKNOWN_OVERLAY_ID }; RayToOverlayIntersectionResult findRayIntersectionForMouseEvent(PickRay ray); private slots: void mousePressPointerEvent(const OverlayID& overlayID, const PointerEvent& event); void mouseMovePointerEvent(const OverlayID& overlayID, const PointerEvent& event); void mouseReleasePointerEvent(const OverlayID& overlayID, const PointerEvent& event); void hoverEnterPointerEvent(const OverlayID& overlayID, const PointerEvent& event); void hoverOverPointerEvent(const OverlayID& overlayID, const PointerEvent& event); void hoverLeavePointerEvent(const OverlayID& overlayID, const PointerEvent& event); }; #endif // hifi_Overlays_h