// // 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 class PickRay; /**jsdoc * The result of a {@link PickRay} search using {@link Overlays.findRayIntersection|findRayIntersection}. * @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 local entity 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 }; QUuid overlayID; float distance { 0.0f }; BoxFace face { UNKNOWN_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); class ParabolaToOverlayIntersectionResult { public: bool intersects { false }; QUuid overlayID; float distance { 0.0f }; float parabolicDistance { 0.0f }; BoxFace face { UNKNOWN_FACE }; glm::vec3 surfaceNormal; glm::vec3 intersection; QVariantMap extraInfo; }; /**jsdoc * (Note: 3D Overlays are deprecated. Use local entities instead.) 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 * * @hifi-interface * @hifi-client-entity * @hifi-avatar * * @property {Uuid} keyboardFocusOverlay - Get or set the {@link Entities.EntityTypes|Web} entity that has keyboard focus. * If no entity has keyboard focus, get returns null; set to null or {@link Uuid|Uuid.NULL} to * clear keyboard focus. */ class Overlays : public QObject { Q_OBJECT Q_PROPERTY(QUuid keyboardFocusOverlay READ getKeyboardFocusOverlay WRITE setKeyboardFocusOverlay) public: Overlays(); void init(); void update(float deltatime); void render(RenderArgs* renderArgs); void disable(); void enable(); Overlay::Pointer take2DOverlay(const QUuid& id); Overlay::Pointer get2DOverlay(const QUuid& id) const; /// adds an overlay that's already been created QUuid addOverlay(Overlay* overlay) { return add2DOverlay(Overlay::Pointer(overlay)); } QUuid add2DOverlay(const Overlay::Pointer& overlay); RayToOverlayIntersectionResult findRayIntersectionVector(const PickRay& ray, bool precisionPicking, const QVector& include, const QVector& discard, bool visibleOnly = false, bool collidableOnly = false); ParabolaToOverlayIntersectionResult findParabolaIntersectionVector(const PickParabola& parabola, bool precisionPicking, const QVector& include, const QVector& discard, bool visibleOnly = false, bool collidableOnly = false); std::pair mousePressEvent(QMouseEvent* event); bool mouseDoublePressEvent(QMouseEvent* event); bool mouseReleaseEvent(QMouseEvent* event); bool mouseMoveEvent(QMouseEvent* event); void cleanupAllOverlays(); mutable QScriptEngine _scriptEngine; 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 if successful, otherwise {@link Uuid|Uuid.NULL}. * @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 * }); */ QUuid addOverlay(const QString& type, const QVariant& properties); /**jsdoc * Create a clone of an existing entity (or 2D overlay). * @function Overlays.cloneOverlay * @param {Uuid} id - The ID of the entity/2D overlay to clone. * @returns {Uuid} The ID of the new object if successful, otherwise {@link Uuid|Uuid.NULL}. */ QUuid cloneOverlay(const QUuid& id); /**jsdoc * Edit an overlay's properties. * @function Overlays.editOverlay * @param {Uuid} id - 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(const QUuid& 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 entity or 2D overlay. * @function Overlays.deleteOverlay * @param {Uuid} id - The ID of the object to delete. */ void deleteOverlay(const QUuid& id); /**jsdoc * Get the type of an entity or 2D overlay. * @function Overlays.getOverlayType * @param {Uuid} id - The ID of the object to get the type of. * @returns {string} The type of the object if found, otherwise an empty string. * @example Create an object 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(const QUuid& id); /**jsdoc * Get the overlay script object. In particular, this is useful for accessing the event bridge for a web3d * overlay. * @function Overlays.getOverlayObject * @param {Uuid} overlayID - The ID of the overlay to get the script object of. * @returns {object} The script object for the overlay if found. * @example Receive "hello" messages from a web3d overlay. * // HTML file: name "web3d.html". * * * * HELLO * * *

HELLO

* * * * * // Script file. * var web3dOverlay = Overlays.addOverlay("web3d", { * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, {x: 0, y: 0.5, z: -3 })), * rotation: MyAvatar.orientation, * url: Script.resolvePath("web3d.html"), * alpha: 1.0 * }); * * function onWebEventReceived(event) { * print("onWebEventReceived() : " + JSON.stringify(event)); * } * * overlayObject = Overlays.getOverlayObject(web3dOverlay); * overlayObject.webEventReceived.connect(onWebEventReceived); * * Script.scriptEnding.connect(function () { * Overlays.deleteOverlay(web3dOverlay); * }); */ QObject* getOverlayObject(const QUuid& 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); * }); */ QUuid getOverlayAtPoint(const glm::vec2& point); /**jsdoc * Get the value of a 3D overlay's property. * @function Overlays.getProperty * @param {Uuid} id - 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); */ QVariant getProperty(const QUuid& id, const QString& property); /**jsdoc * Get the values of an overlay's properties. * @function Overlays.getProperties * @param {Uuid} id - 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)); */ QVariantMap getProperties(const QUuid& 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)); */ QVariantMap getOverlaysProperties(const QVariant& overlaysProperties); /**jsdoc * Find the closest 3D overlay intersected by a {@link PickRay}. Overlays with their drawInFront property set * to true have priority over overlays that don't, except that tablet overlays have priority over any * drawInFront overlays behind them. I.e., if a drawInFront overlay is behind one that isn't * drawInFront, the drawInFront overlay is returned, but if a tablet overlay is in front of a * drawInFront overlay, the tablet overlay is returned. * @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.} [include=[]] - If not empty then the search is restricted to these overlays. * @param {Array.} [discard=[]] - Overlays to ignore during the search. * @param {boolean} [visibleOnly=false] - If true then only entities that are * {@link Entities.EntityProperties|visible} are searched. * @param {boolean} [collideableOnly=false] - If true then only entities that are not * {@link Entities.EntityProperties|collisionless} are searched. * @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& include = QScriptValue(), const QScriptValue& discard = QScriptValue(), bool visibleOnly = false, bool collidableOnly = false); /**jsdoc * Return a list of local entities 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 entity IDs with bounding boxes that touch a search sphere. * @example Create two cube entities in front of your avatar then search for entities 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} id - 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(const QUuid& id); /**jsdoc * Calculates the size of the given text in the specified object if it is a text entity or overlay. * @function Overlays.textSize * @param {Uuid} id - The ID of the object to use for calculation. * @param {string} text - The string to calculate the size of. * @returns {Size} The size of the text if the object is a text entity or overlay, otherwise * { height: 0, width : 0 }. If the object is a 2D overlay, the size is in pixels; if the object is an entity, * the size is in meters. * @example Calculate the size of "hello" in a 3D text entity. * 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(const QUuid& 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 object of a given ID. * @function Overlays.isAddedOverlay * @param {Uuid} id - The ID to check. * @returns {boolean} true if an object with the given ID exists, false otherwise. */ bool isAddedOverlay(const QUuid& id); /**jsdoc * Generate a mouse press event on an overlay. * @function Overlays.sendMousePressOnOverlay * @param {Uuid} id - 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 QUuid& id, const PointerEvent& event); /**jsdoc * Generate a mouse release event on an overlay. * @function Overlays.sendMouseReleaseOnOverlay * @param {Uuid} id - The ID of the overlay to generate a mouse release event on. * @param {PointerEvent} event - The mouse release event details. */ void sendMouseReleaseOnOverlay(const QUuid& id, const PointerEvent& event); /**jsdoc * Generate a mouse move event on an overlay. * @function Overlays.sendMouseMoveOnOverlay * @param {Uuid} id - The ID of the overlay to generate a mouse move event on. * @param {PointerEvent} event - The mouse move event details. */ void sendMouseMoveOnOverlay(const QUuid& id, 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 QUuid& id, const PointerEvent& event); /**jsdoc * Generate a hover over event on an overlay. * @function Overlays.sendHoverOverOverlay * @param {Uuid} id - The ID of the overlay to generate a hover over event on. * @param {PointerEvent} event - The hover over event details. */ void sendHoverOverOverlay(const QUuid& id, const PointerEvent& event); /**jsdoc * Generate a hover leave event on an overlay. * @function Overlays.sendHoverLeaveOverlay * @param {Uuid} id - The ID of the overlay to generate a hover leave event on. * @param {PointerEvent} event - The hover leave event details. */ void sendHoverLeaveOverlay(const QUuid& id, const PointerEvent& event); /**jsdoc * Get the ID of the Web3D entity that has keyboard focus. * @function Overlays.getKeyboardFocusOverlay * @returns {Uuid} The ID of the {@link Entities.EntityTypes|Web} overlay that has focus, if any, otherwise * null. */ QUuid getKeyboardFocusOverlay() { return DependencyManager::get()->getKeyboardFocusEntity(); } /**jsdoc * Set the Web3D entity that has keyboard focus. * @function Overlays.setKeyboardFocusOverlay * @param {Uuid} id - The ID of the {@link Entities.EntityTypes|Web} entity to set keyboard focus to. Use * null or {@link Uuid|Uuid.NULL} to unset keyboard focus from an overlay. */ void setKeyboardFocusOverlay(const QUuid& id) { DependencyManager::get()->setKeyboardFocusEntity(id); } signals: /**jsdoc * Triggered when an overlay is deleted. * @function Overlays.overlayDeleted * @param {Uuid} id - 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(const QUuid& 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} id - 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(const QUuid& id, 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} id - 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(const QUuid& id, 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} id - The ID of the overlay the mouse release event occurred on. * @param {PointerEvent} event - The mouse release event details. * @returns {Signal} */ void mouseReleaseOnOverlay(const QUuid& id, 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} id - The ID of the overlay the mouse moved event occurred on. * @param {PointerEvent} event - The mouse move event details. * @returns {Signal} */ void mouseMoveOnOverlay(const QUuid& id, 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} id - 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(const QUuid& id, 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} id - The ID of the overlay the hover over event occurred on. * @param {PointerEvent} event - The hover over event details. * @returns {Signal} */ void hoverOverOverlay(const QUuid& id, 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} id - The ID of the overlay the hover leave event occurred on. * @param {PointerEvent} event - The hover leave event details. * @returns {Signal} */ void hoverLeaveOverlay(const QUuid& id, const PointerEvent& event); private: void cleanupOverlaysToDelete(); mutable QMutex _mutex { QMutex::Recursive }; QMap _overlays; QList _overlaysToDelete; unsigned int _stackOrder { 1 }; bool _enabled { true }; std::atomic _shuttingDown { false }; PointerEvent calculateOverlayPointerEvent(const QUuid& id, const PickRay& ray, const RayToOverlayIntersectionResult& rayPickResult, QMouseEvent* event, PointerEvent::EventType eventType); QUuid _currentClickingOnOverlayID; QUuid _currentHoverOverOverlayID; static QString entityToOverlayType(const QString& type); static QString overlayToEntityType(const QString& type); static std::unordered_map _entityToOverlayTypes; static std::unordered_map _overlayToEntityTypes; QVariantMap convertEntityToOverlayProperties(const EntityItemProperties& entityProps); EntityItemProperties convertOverlayToEntityProperties(QVariantMap& overlayProps, const QString& type, bool add, const QUuid& id); EntityItemProperties convertOverlayToEntityProperties(QVariantMap& overlayProps, std::pair& rotationToSave, const QString& type, bool add, const QUuid& id = QUuid()); private slots: void mousePressPointerEvent(const QUuid& id, const PointerEvent& event); void mouseMovePointerEvent(const QUuid& id, const PointerEvent& event); void mouseReleasePointerEvent(const QUuid& id, const PointerEvent& event); void hoverEnterPointerEvent(const QUuid& id, const PointerEvent& event); void hoverOverPointerEvent(const QUuid& id, const PointerEvent& event); void hoverLeavePointerEvent(const QUuid& id, const PointerEvent& event); }; #define ADD_TYPE_MAP(entity, overlay) \ _entityToOverlayTypes[#entity] = #overlay; \ _overlayToEntityTypes[#overlay] = #entity; #endif // hifi_Overlays_h