// // Created by Sam Gondelman 10/20/2017 // Copyright 2017 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 // #ifndef hifi_PointerScriptingInterface_h #define hifi_PointerScriptingInterface_h #include #include "DependencyManager.h" #include #include /**jsdoc * The Pointers API lets you create and manage objects for repeatedly calculating intersections in different ways, as well as the visual representation of those objects. * Pointers can also be configured to automatically generate {@link PointerEvent}s on {@link Entities}. * * @namespace Pointers * * @hifi-interface * @hifi-client-entity * @hifi-avatar */ class PointerScriptingInterface : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY public: unsigned int createLaserPointer(const QVariant& properties) const; unsigned int createStylus(const QVariant& properties) const; unsigned int createParabolaPointer(const QVariant& properties) const; /**jsdoc * A trigger mechanism for Ray and Parabola Pointers. * * @typedef {object} Pointers.Trigger * @property {Controller.Standard|Controller.Actions|function} action This can be a built-in Controller action, like Controller.Standard.LTClick, or a function that evaluates to >= 1.0 when you want to trigger button. * @property {string} button Which button to trigger. "Primary", "Secondary", "Tertiary", and "Focus" are currently supported. Only "Primary" will trigger clicks on web surfaces. If "Focus" is triggered, * it will try to set the entity focus to the object at which the Pointer is aimed. Buttons besides the first three will still trigger events, but event.button will be "None". */ /**jsdoc * Adds a new Pointer * Different {@link PickType}s use different properties, and within one PickType, the properties you choose can lead to a wide range of behaviors. For example, * with PickType.Ray, depending on which optional parameters you pass, you could create a Static Ray Pointer, a Mouse Ray Pointer, or a Joint Ray Pointer. * Pointers created with this method always intersect at least visible and collidable things * @function Pointers.createPointer * @param {PickType} type A PickType that specifies the method of picking to use. Cannot be {@link PickType|PickType.Collision}. * @param {Pointers.LaserPointerProperties|Pointers.StylusPointerProperties|Pointers.ParabolaPointerProperties} properties A PointerProperties object, containing all the properties for initializing this Pointer and the {@link Picks.PickProperties} for the Pick that * this Pointer will use to do its picking. * @returns {number} The ID of the created Pointer. Used for managing the Pointer. 0 if invalid. * * @example Create a left hand Ray Pointer that triggers events on left controller trigger click and changes color when it's intersecting something. * * var end = { * type: "sphere", * dimensions: {x:0.5, y:0.5, z:0.5}, * solid: true, * color: {red:0, green:255, blue:0}, * ignorePickIntersection: true * }; * var end2 = { * type: "sphere", * dimensions: {x:0.5, y:0.5, z:0.5}, * solid: true, * color: {red:255, green:0, blue:0}, * ignorePickIntersection: true * }; * * var renderStates = [ {name: "test", end: end} ]; * var defaultRenderStates = [ {name: "test", distance: 10.0, end: end2} ]; * var pointer = Pointers.createPointer(PickType.Ray, { * joint: "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", * filter: Picks.PICK_LOCAL_ENTITIES | Picks.PICK_DOMAIN_ENTITIES | Picks.PICK_INCLUDE_NONCOLLIDABLE, * renderStates: renderStates, * defaultRenderStates: defaultRenderStates, * distanceScaleEnd: true, * triggers: [ {action: Controller.Standard.LTClick, button: "Focus"}, {action: Controller.Standard.LTClick, button: "Primary"} ], * hover: true, * enabled: true * }); * Pointers.setRenderState(pointer, "test"); */ // TODO: expand Pointers to be able to be fully configurable with PickFilters Q_INVOKABLE unsigned int createPointer(const PickQuery::PickType& type, const QVariant& properties); /**jsdoc * Enables a Pointer. * @function Pointers.enablePointer * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. */ Q_INVOKABLE void enablePointer(unsigned int uid) const { DependencyManager::get()->enablePointer(uid); } /**jsdoc * Disables a Pointer. * @function Pointers.disablePointer * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. */ Q_INVOKABLE void disablePointer(unsigned int uid) const { DependencyManager::get()->disablePointer(uid); } /**jsdoc * Removes a Pointer. * @function Pointers.removePointer * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. */ Q_INVOKABLE void removePointer(unsigned int uid) const { DependencyManager::get()->removePointer(uid); } /**jsdoc * Edit some visual aspect of a Pointer. Currently only supported for Ray Pointers. * @function Pointers.editRenderState * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. * @param {string} renderState The name of the render state you want to edit. * @param {Pointers.RayPointerRenderState} properties The new properties for renderStates item. */ Q_INVOKABLE void editRenderState(unsigned int uid, const QString& renderState, const QVariant& properties) const; /**jsdoc * Set the render state of a Pointer. For Ray Pointers, this means switching between their {@link Pointers.RayPointerRenderState}s, or "" to turn off rendering and hover/trigger events. * For Stylus Pointers, there are three built-in options: "events on" (render and send events, the default), "events off" (render but don't send events), and "disabled" (don't render, don't send events). * @function Pointers.setRenderState * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. * @param {string} renderState The name of the render state to which you want to switch. */ Q_INVOKABLE void setRenderState(unsigned int uid, const QString& renderState) const { DependencyManager::get()->setRenderState(uid, renderState.toStdString()); } /**jsdoc * Get the most recent pick result from this Pointer. This will be updated as long as the Pointer is enabled, regardless of the render state. * @function Pointers.getPrevPickResult * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. * @returns {RayPickResult|StylusPickResult} The most recent intersection result. This will be slightly different for different PickTypes. */ Q_INVOKABLE QVariantMap getPrevPickResult(unsigned int uid) const; /**jsdoc * Sets whether or not to use precision picking. * @function Pointers.setPrecisionPicking * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. * @param {boolean} precisionPicking Whether or not to use precision picking */ Q_INVOKABLE void setPrecisionPicking(unsigned int uid, bool precisionPicking) const { DependencyManager::get()->setPrecisionPicking(uid, precisionPicking); } /**jsdoc * Sets the length of this Pointer. No effect on Stylus Pointers. * @function Pointers.setLength * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. * @param {number} length The desired length of the Pointer. */ Q_INVOKABLE void setLength(unsigned int uid, float length) const { DependencyManager::get()->setLength(uid, length); } /**jsdoc * Sets a list of Entity IDs and/or Avatar IDs to ignore during intersection. Not used by Stylus Pointers. * @function Pointers.setIgnoreItems * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. * @param {Uuid[]} ignoreItems A list of IDs to ignore. */ Q_INVOKABLE void setIgnoreItems(unsigned int uid, const QScriptValue& ignoreEntities) const; /**jsdoc * Sets a list of Entity IDs and/or Avatar IDs to include during intersection, instead of intersecting with everything. Stylus * Pointers only intersect with objects in their include list. * @function Pointers.setIncludeItems * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. * @param {Uuid[]} includeItems A list of IDs to include. */ Q_INVOKABLE void setIncludeItems(unsigned int uid, const QScriptValue& includeEntities) const; /**jsdoc * Lock a Pointer onto a specific object (entity or avatar). Optionally, provide an offset in object-space, otherwise the Pointer will lock on to the center of the object. * Not used by Stylus Pointers. * @function Pointers.setLockEndUUID * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. * @param {Uuid} objectID The ID of the object to which to lock on. * @param {boolean} isAvatar False for entities, true for avatars * @param {Mat4} [offsetMat] The offset matrix to use if you do not want to lock on to the center of the object. */ Q_INVOKABLE void setLockEndUUID(unsigned int uid, const QUuid& objectID, bool isAvatar, const glm::mat4& offsetMat = glm::mat4()) const { DependencyManager::get()->setLockEndUUID(uid, objectID, isAvatar, offsetMat); } /**jsdoc * Check if a Pointer is associated with the left hand. * @function Pointers.isLeftHand * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. * @returns {boolean} True if the Pointer is a Joint Ray Pointer with joint == "_CONTROLLER_LEFTHAND" or "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", or a Stylus Pointer with hand == 0 */ Q_INVOKABLE bool isLeftHand(unsigned int uid) { return DependencyManager::get()->isLeftHand(uid); } /**jsdoc * Check if a Pointer is associated with the right hand. * @function Pointers.isRightHand * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. * @returns {boolean} True if the Pointer is a Joint Ray Pointer with joint == "_CONTROLLER_RIGHTHAND" or "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND", or a Stylus Pointer with hand == 1 */ Q_INVOKABLE bool isRightHand(unsigned int uid) { return DependencyManager::get()->isRightHand(uid); } /**jsdoc * Check if a Pointer is associated with the system mouse. * @function Pointers.isMouse * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. * @returns {boolean} True if the Pointer is a Mouse Ray Pointer, false otherwise. */ Q_INVOKABLE bool isMouse(unsigned int uid) { return DependencyManager::get()->isMouse(uid); } /**jsdoc * Returns information about an existing Pointer * @function Pointers.getPointerProperties * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. * @returns {Pointers.LaserPointerProperties|Pointers.StylusPointerProperties|Pointers.ParabolaPointerProperties} The information about the Pointer. * Currently only includes renderStates and defaultRenderStates with associated entity IDs. */ Q_INVOKABLE QVariantMap getPointerProperties(unsigned int uid) const; }; #endif // hifi_PointerScriptingInterface_h