Merge pull request #12976 from ctrlaltdavid/21856

Docs to JSDoc
This commit is contained in:
John Conklin II 2018-04-25 11:36:34 -07:00 committed by GitHub
commit f04200a620
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 2773 additions and 335 deletions

View file

@ -22,6 +22,9 @@
#include <DependencyManager.h>
/**jsdoc
* @namespace SpeechRecognizer
*/
class SpeechRecognizer : public QObject, public Dependency {
Q_OBJECT
SINGLETON_DEPENDENCY
@ -31,12 +34,39 @@ public:
bool getEnabled() const { return _enabled; }
public slots:
/**jsdoc
* @function SpeechRecognizer.setEnabled
* @param {boolean} enabled
*/
void setEnabled(bool enabled);
/**jsdoc
* @function SpeechRecognizer.addCommand
* @param {string} command
*/
void addCommand(const QString& command);
/**jsdoc
* @function SpeechRecognizer.removeCommand
* @param {string} command
*/
void removeCommand(const QString& command);
signals:
/**jsdoc
* @function SpeechRecognizer.commandRecognized
* @param {string} command
* @returns {Signal}
*/
void commandRecognized(const QString& command);
/**jsdoc
* @function SpeechRecognizer.enabledUpdated
* @param {boolean} enabled
* @returns {Signal}
*/
void enabledUpdated(bool enabled);
protected:

File diff suppressed because it is too large Load diff

View file

@ -56,6 +56,19 @@ bool GameplayObjects::removeFromGameplayObjects(const OverlayID& overlayID) {
SelectionScriptingInterface::SelectionScriptingInterface() {
}
/**jsdoc
* <table>
* <thead>
* <tr><th>Value</th><th>Description</th></tr>
* </thead>
* <tbody>
* <tr><td><code>"avatar"</code></td><td></td></tr>
* <tr><td><code>"entity"</code></td><td></td></tr>
* <tr><td><code>"overlay"</code></td><td></td></tr>
* </tbody>
* </table>
* @typedef {string} Selection.ItemType
*/
bool SelectionScriptingInterface::addToSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id) {
if (itemType == "avatar") {
return addToGameplayObjects(listName, (QUuid)id);
@ -255,6 +268,12 @@ void SelectionScriptingInterface::printList(const QString& listName) {
}
}
/**jsdoc
* @typedef {object} Selection.SelectedItemsList
* @property {Uuid[]} avatars - The IDs of the avatars in the selection.
* @property {Uuid[]} entities - The IDs of the entities in the selection.
* @property {Uuid[]} overlays - The IDs of the overlays in the selection.
*/
QVariantMap SelectionScriptingInterface::getSelectedItemsList(const QString& listName) const {
QReadLocker lock(&_selectionListsLock);
QVariantMap list;
@ -461,6 +480,20 @@ bool SelectionHighlightStyle::fromVariantMap(const QVariantMap& properties) {
return true;
}
/**jsdoc
* @typedef {object} Selection.HighlightStyle
* @property {Color} outlineUnoccludedColor - Color of the specified highlight region.
* @property {Color} outlineOccludedColor - ""
* @property {Color} fillUnoccludedColor- ""
* @property {Color} fillOccludedColor- ""
* @property {number} outlineUnoccludedAlpha - Alpha value ranging from <code>0.0</code> (not visible) to <code>1.0</code>
* (fully opaque) for the specified highlight region.
* @property {number} outlineOccludedAlpha - ""
* @property {number} fillUnoccludedAlpha - ""
* @property {number} fillOccludedAlpha - ""
* @property {number} outlineWidth - Width of the outline, in pixels.
* @property {boolean} isOutlineSmooth - <code>true</code> to enable outline smooth fall-off.
*/
QVariantMap SelectionHighlightStyle::toVariantMap() const {
QVariantMap properties;

View file

@ -82,6 +82,46 @@ protected:
render::HighlightStyle _style;
};
/**jsdoc
* The <code>Selection</code> API provides a means of grouping together avatars, entities, and overlays in named lists.
* @namespace Selection
*
* @example <caption>Outline an entity when it is grabbed by a controller.</caption>
* // Create a box and copy the following text into the entity's "Script URL" field.
* (function () {
* print("Starting highlight script...............");
* var _this = this;
* var prevID = 0;
* var listName = "contextOverlayHighlightList";
* var listType = "entity";
*
* _this.startNearGrab = function(entityID){
* if (prevID !== entityID) {
* Selection.addToSelectedItemsList(listName, listType, entityID);
* prevID = entityID;
* }
* };
*
* _this.releaseGrab = function(entityID){
* if (prevID !== 0) {
* Selection.removeFromSelectedItemsList("contextOverlayHighlightList", listType, prevID);
* prevID = 0;
* }
* };
*
* var cleanup = function(){
* Entities.findEntities(MyAvatar.position, 1000).forEach(function(entity) {
* try {
* Selection.removeListFromMap(listName);
* } catch (e) {
* print("Error cleaning up.");
* }
* });
* };
*
* Script.scriptEnding.connect(cleanup);
* });
*/
class SelectionScriptingInterface : public QObject, public Dependency {
Q_OBJECT
@ -89,138 +129,120 @@ public:
SelectionScriptingInterface();
/**jsdoc
* Query the names of all the selection lists
* Get the names of all the selection lists.
* @function Selection.getListNames
* @return An array of names of all the selection lists
* @return {list[]} An array of names of all the selection lists.
*/
Q_INVOKABLE QStringList getListNames() const;
/**jsdoc
* Removes a named selection from the list of selections.
* Delete a named selection list.
* @function Selection.removeListFromMap
* @param listName {string} name of the selection
* @returns {bool} true if the selection existed and was successfully removed.
* @param {string} listName - The name of the selection list.
* @returns {boolean} <code>true</code> if the selection existed and was successfully removed, otherwise <code>false</code>.
*/
Q_INVOKABLE bool removeListFromMap(const QString& listName);
/**jsdoc
* Add an item in a selection.
* Add an item to a selection list.
* @function Selection.addToSelectedItemsList
* @param listName {string} name of the selection
* @param itemType {string} the type of the item (one of "avatar", "entity" or "overlay")
* @param id {EntityID} the Id of the item to add to the selection
* @returns {bool} true if the item was successfully added.
* @param {string} listName - The name of the selection list to add the item to.
* @param {Selection.ItemType} itemType - The type of the item being added.
* @param {Uuid} id - The ID of the item to add to the selection.
* @returns {boolean} <code>true</code> if the item was successfully added, otherwise <code>false</code>.
*/
Q_INVOKABLE bool addToSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id);
/**jsdoc
* Remove an item from a selection.
* Remove an item from a selection list.
* @function Selection.removeFromSelectedItemsList
* @param listName {string} name of the selection
* @param itemType {string} the type of the item (one of "avatar", "entity" or "overlay")
* @param id {EntityID} the Id of the item to remove
* @returns {bool} true if the item was successfully removed.
* @param {string} listName - The name of the selection list to remove the item from.
* @param {Selection.ItemType} itemType - The type of the item being removed.
* @param {Uuid} id - The ID of the item to remove.
* @returns {boolean} <code>true</code> if the item was successfully removed, otherwise <code>false</code>.
* <codefalse</code> is returned if the list doesn't contain any data.
*/
Q_INVOKABLE bool removeFromSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id);
/**jsdoc
* Remove all items from a selection.
* @function Selection.clearSelectedItemsList
* @param listName {string} name of the selection
* @returns {bool} true if the item was successfully cleared.
* @param {string} listName - The name of the selection list.
* @returns {boolean} <code>true</code> if the item was successfully cleared, otherwise <code>false</code>.
*/
Q_INVOKABLE bool clearSelectedItemsList(const QString& listName);
/**jsdoc
* Prints out the list of avatars, entities and overlays stored in a particular selection.
* Print out the list of avatars, entities, and overlays in a selection to the <em>debug log</em> (not the script log).
* @function Selection.printList
* @param listName {string} name of the selection
* @param {string} listName - The name of the selection list.
*/
Q_INVOKABLE void printList(const QString& listName);
/**jsdoc
* Query the list of avatars, entities and overlays stored in a particular selection.
* Get the list of avatars, entities, and overlays stored in a selection list.
* @function Selection.getList
* @param listName {string} name of the selection
* @return a js object describing the content of a selection list with the following properties:
* - "entities": [ and array of the entityID of the entities in the selection]
* - "avatars": [ and array of the avatarID of the avatars in the selection]
* - "overlays": [ and array of the overlayID of the overlays in the selection]
* If the list name doesn't exist, the function returns an empty js object with no properties.
* @param {string} listName - The name of the selection list.
* @return {Selection.SelectedItemsList} The content of a selection list. If the list name doesn't exist, the function
* returns an empty object with no properties.
*/
Q_INVOKABLE QVariantMap getSelectedItemsList(const QString& listName) const;
/**jsdoc
* Query the names of the highlighted selection lists
* Get the names of the highlighted selection lists.
* @function Selection.getHighlightedListNames
* @return An array of names of the selection list currently highlight enabled
* @return {string[]} An array of names of the selection list currently highlight enabled.
*/
Q_INVOKABLE QStringList getHighlightedListNames() const;
/**jsdoc
* Enable highlighting for the named selection.
* If the Selection doesn't exist, it will be created.
* All objects in the list will be displayed with the highlight effect as specified from the highlightStyle.
* The function can be called several times with different values in the style to modify it.
*
* Enable highlighting for a selection list.
* If the selection list doesn't exist, it will be created.
* All objects in the list will be displayed with the highlight effect specified.
* The function can be called several times with different values in the style to modify it.<br />
* Note: This function implicitly calls {@link Selection.enableListToScene}.
* @function Selection.enableListHighlight
* @param listName {string} name of the selection
* @param highlightStyle {jsObject} highlight style fields (see Selection.getListHighlightStyle for a detailed description of the highlightStyle).
* @returns {bool} true if the selection was successfully enabled for highlight.
*
* Note: This function will implicitly call Selection.enableListToScene
* @param {string} listName - The name of the selection list.
* @param {Selection.HighlightStyle} highlightStyle - The highlight style.
* @returns {boolean} true if the selection was successfully enabled for highlight.
*/
Q_INVOKABLE bool enableListHighlight(const QString& listName, const QVariantMap& highlightStyle);
/**jsdoc
* Disable highlighting for the named selection.
* If the Selection doesn't exist or wasn't enabled for highliting then nothing happens simply returning false.
*
* Disable highlighting for the selection list.
* If the selection list doesn't exist or wasn't enabled for highlighting then nothing happens and <code>false</code> is
* returned.<br />
* Note: This function implicitly calls {@link Selection.disableListToScene}.
* @function Selection.disableListHighlight
* @param listName {string} name of the selection
* @returns {bool} true if the selection was successfully disabled for highlight, false otherwise.
*
* Note: This function will implicitly call Selection.disableListToScene
* @param {string} listName - The name of the selection list.
* @returns {boolean} <code>true</code> if the selection was successfully disabled for highlight, otherwise
* <code>false</code>.
*/
Q_INVOKABLE bool disableListHighlight(const QString& listName);
/**jsdoc
* Enable scene selection for the named selection.
* Enable scene selection for the selection list.
* If the Selection doesn't exist, it will be created.
* All objects in the list will be sent to a scene selection.
*
* @function Selection.enableListToScene
* @param listName {string} name of the selection
* @returns {bool} true if the selection was successfully enabled on the scene.
* @param {string} listName - The name of the selection list.
* @returns {boolean} <code>true</code> if the selection was successfully enabled on the scene, otherwise <code>false</code>.
*/
Q_INVOKABLE bool enableListToScene(const QString& listName);
/**jsdoc
* Disable scene selection for the named selection.
* If the Selection doesn't exist or wasn't enabled on the scene then nothing happens simply returning false.
*
* If the selection list doesn't exist or wasn't enabled on the scene then nothing happens and <code>false</code> is
* returned.
* @function Selection.disableListToScene
* @param listName {string} name of the selection
* @returns {bool} true if the selection was successfully disabled on the scene, false otherwise.
* @param {string} listName - The name of the selection list.
* @returns {boolean} true if the selection was successfully disabled on the scene, false otherwise.
*/
Q_INVOKABLE bool disableListToScene(const QString& listName);
/**jsdoc
* Query the highlight style values for the named selection.
* If the Selection doesn't exist or hasn't been highlight enabled yet, it will return an empty object.
* Otherwise, the jsObject describes the highlight style properties:
* - outlineUnoccludedColor: {xColor} Color of the specified highlight region
* - outlineOccludedColor: {xColor} "
* - fillUnoccludedColor: {xColor} "
* - fillOccludedColor: {xColor} "
*
* - outlineUnoccludedAlpha: {float} Alpha value ranging from 0.0 (not visible) to 1.0 (fully opaque) for the specified highlight region
* - outlineOccludedAlpha: {float} "
* - fillUnoccludedAlpha: {float} "
* - fillOccludedAlpha: {float} "
*
* - outlineWidth: {float} width of the outline expressed in pixels
* - isOutlineSmooth: {bool} true to enable oultine smooth falloff
*
* Get the highlight style values for the a selection list.
* If the selection doesn't exist or hasn't been highlight enabled yet, an empty object is returned.
* @function Selection.getListHighlightStyle
* @param listName {string} name of the selection
* @returns {jsObject} highlight style as described above
* @param {string} listName - The name of the selection list.
* @returns {Selection.HighlightStyle} highlight style
*/
Q_INVOKABLE QVariantMap getListHighlightStyle(const QString& listName) const;
@ -232,6 +254,12 @@ public:
void onSelectedItemsListChanged(const QString& listName);
signals:
/**jsoc
* Triggered when a list's content changes.
* @function Selection.selectedItemsListChanged
* @param {string} listName - The name of the selection list that changed.
* @returns {Signal}
*/
void selectedItemsListChanged(const QString& listName);
private:

View file

@ -57,15 +57,7 @@ using AvatarPhysicsCallback = std::function<void(uint32_t)>;
class Avatar : public AvatarData, public scriptable::ModelProvider {
Q_OBJECT
/**jsdoc
* An avatar is representation of yourself or another user. The Avatar API can be used to query or manipulate the avatar of a user.
* NOTE: Avatar extends AvatarData, see those namespace for more properties/methods.
*
* @namespace Avatar
* @augments AvatarData
*
* @property skeletonOffset {Vec3} can be used to apply a translation offset between the avatar's position and the registration point of the 3d model.
*/
// This property has JSDoc in MyAvatar.h.
Q_PROPERTY(glm::vec3 skeletonOffset READ getSkeletonOffset WRITE setSkeletonOffset)
public:
@ -128,14 +120,25 @@ public:
virtual int getJointIndex(const QString& name) const override;
virtual QStringList getJointNames() const override;
/**jsdoc
* @function MyAvatar.getDefaultJointRotation
* @param {number} index
* @returns {Quat}
*/
Q_INVOKABLE virtual glm::quat getDefaultJointRotation(int index) const;
/**jsdoc
* @function MyAvatar.getDefaultJointTranslation
* @param {number} index
* @returns {Vec3}
*/
Q_INVOKABLE virtual glm::vec3 getDefaultJointTranslation(int index) const;
/**jsdoc
* Provides read only access to the default joint rotations in avatar coordinates.
* The default pose of the avatar is defined by the position and orientation of all bones
* in the avatar's model file. Typically this is a t-pose.
* @function Avatar.getAbsoluteDefaultJointRotationInObjectFrame
* in the avatar's model file. Typically this is a T-pose.
* @function MyAvatar.getAbsoluteDefaultJointRotationInObjectFrame
* @param index {number} index number
* @returns {Quat} The rotation of this joint in avatar coordinates.
*/
@ -144,8 +147,8 @@ public:
/**jsdoc
* Provides read only access to the default joint translations in avatar coordinates.
* The default pose of the avatar is defined by the position and orientation of all bones
* in the avatar's model file. Typically this is a t-pose.
* @function Avatar.getAbsoluteDefaultJointTranslationInObjectFrame
* in the avatar's model file. Typically this is a T-pose.
* @function MyAvatar.getAbsoluteDefaultJointTranslationInObjectFrame
* @param index {number} index number
* @returns {Vec3} The position of this joint in avatar coordinates.
*/
@ -170,14 +173,65 @@ public:
virtual void applyCollision(const glm::vec3& contactPoint, const glm::vec3& penetration) { }
/**jsdoc
* Set the offset applied to the current avatar. The offset adjusts the position that the avatar is rendered. For example,
* with an offset of <code>{ x: 0, y: 0.1, z: 0 }</code>, your avatar will appear to be raised off the ground slightly.
* @function MyAvatar.setSkeletonOffset
* @param {Vec3} offset - The skeleton offset to set.
* @example <caption>Raise your avatar off the ground a little.</caption>
* // Raise your avatar off the ground a little.
* MyAvatar.setSkeletonOffset({ x: 0, y: 0.1: z: 0 });
*
* // Restore its offset after 5s.
* Script.setTimeout(function () {
* MyAvatar.setSkeletonOffset(Vec3.ZERO);
* }, 5000);
*/
Q_INVOKABLE void setSkeletonOffset(const glm::vec3& offset);
/**jsdoc
* Get the offset applied to the current avatar. The offset adjusts the position that the avatar is rendered. For example,
* with an offset of <code>{ x: 0, y: 0.1, z: 0 }</code>, your avatar will appear to be raised off the ground slightly.
* @function MyAvatar.getSkeletonOffset
* @returns {Vec3} The current skeleton offset.
* @example <caption>Report your avatar's current skeleton offset.</caption>
* print(JSON.stringify(MyAvatar.getSkeletonOffset());
*/
Q_INVOKABLE glm::vec3 getSkeletonOffset() { return _skeletonOffset; }
virtual glm::vec3 getSkeletonPosition() const;
/**jsdoc
* Get the position of a joint in the current avatar.
* @function MyAvatar.getJointPosition
* @param {number} index - The index of the joint.
* @returns {Vec3} The position of the joint in world coordinates.
*/
Q_INVOKABLE glm::vec3 getJointPosition(int index) const;
/**jsdoc
* Get the position of a joint in the current avatar.
* @function MyAvatar.getJointPosition
* @param {string} name - The name of the joint.
* @returns {Vec3} The position of the joint in world coordinates.
* @example <caption>Report the position of your avatar's hips.</caption>
* print(JSON.stringify(MyAvatar.getJointPosition("Hips")));
*/
Q_INVOKABLE glm::vec3 getJointPosition(const QString& name) const;
/**jsdoc
* Get the position of the current avatar's neck in world coordinates.
* @function MyAvatar.getNeckPosition
* @returns {Vec3} The position of the neck in world coordinates.
* @example <caption>Report the position of your avatar's neck.</caption>
* print(JSON.stringify(MyAvatar.getNeckPosition()));
*/
Q_INVOKABLE glm::vec3 getNeckPosition() const;
/**jsdoc
* @function MyAvatar.getAcceleration
* @returns {Vec3}
*/
Q_INVOKABLE glm::vec3 getAcceleration() const { return _acceleration; }
/// Scales a world space position vector relative to the avatar position and scale
@ -201,24 +255,47 @@ public:
void setPositionViaScript(const glm::vec3& position) override;
void setOrientationViaScript(const glm::quat& orientation) override;
// these call through to the SpatiallyNestable versions, but they are here to expose these to javascript.
/**jsdoc
* @function MyAvatar.getParentID
* @returns {Uuid}
*/
// This calls through to the SpatiallyNestable versions, but is here to expose these to JavaScript.
Q_INVOKABLE virtual const QUuid getParentID() const override { return SpatiallyNestable::getParentID(); }
/**jsdoc
* @function MyAvatar.setParentID
* @param {Uuid} parentID
*/
// This calls through to the SpatiallyNestable versions, but is here to expose these to JavaScript.
Q_INVOKABLE virtual void setParentID(const QUuid& parentID) override;
/**jsdoc
* @function MyAvatar.getParentJointIndex
* @returns {number}
*/
// This calls through to the SpatiallyNestable versions, but is here to expose these to JavaScript.
Q_INVOKABLE virtual quint16 getParentJointIndex() const override { return SpatiallyNestable::getParentJointIndex(); }
/**jsdoc
* @function MyAvatar.setParentJointIndex
* @param {number} parentJointIndex
*/
// This calls through to the SpatiallyNestable versions, but is here to expose these to JavaScript.
Q_INVOKABLE virtual void setParentJointIndex(quint16 parentJointIndex) override;
/**jsdoc
* Information about a single joint in an Avatar's skeleton hierarchy.
* @typedef Avatar.SkeletonJoint
* @property {string} name - name of joint
* @property {number} index - joint index
* @property {number} parentIndex - index of this joint's parent (-1 if no parent)
*/
/**jsdoc
* Returns an array of joints, where each joint is an object containing name, index and parentIndex fields.
* @function Avatar.getSkeleton
* @returns {Avatar.SkeletonJoint[]} returns a list of information about each joint in this avatar's skeleton.
* Returns an array of joints, where each joint is an object containing name, index, and parentIndex fields.
* @function MyAvatar.getSkeleton
* @returns {MyAvatar.SkeletonJoint[]} A list of information about each joint in this avatar's skeleton.
*/
/**jsdoc
* Information about a single joint in an Avatar's skeleton hierarchy.
* @typedef MyAvatar.SkeletonJoint
* @property {string} name - Joint name.
* @property {number} index - Joint index.
* @property {number} parentIndex - Index of this joint's parent (-1 if no parent).
*/
Q_INVOKABLE QList<QVariant> getSkeleton();
@ -235,6 +312,11 @@ public:
void setTargetScale(float targetScale) override;
float getTargetScale() const { return _targetScale; }
/**jsdoc
* @function MyAvatar.getSimulationRate
* @param {string} [rateName=""]
* @returns {number}
*/
Q_INVOKABLE float getSimulationRate(const QString& rateName = QString("")) const;
bool hasNewJointData() const { return _hasNewJointData; }
@ -256,6 +338,7 @@ public:
bool isFading() const { return _isFading; }
void updateFadingStatus(render::ScenePointer scene);
// JSDoc is in AvatarData.h.
Q_INVOKABLE virtual float getEyeHeight() const override;
// returns eye height of avatar in meters, ignoring avatar scale.
@ -282,16 +365,57 @@ public slots:
// FIXME - these should be migrated to use Pose data instead
// thread safe, will return last valid palm from cache
/**jsdoc
* Get the position of the left palm in world coordinates.
* @function MyAvatar.getLeftPalmPosition
* @returns {Vec3} The position of the left palm in world coordinates.
* @example <caption>Report the position of your avatar's left palm.</caption>
* print(JSON.stringify(MyAvatar.getLeftPalmPosition()));
*/
glm::vec3 getLeftPalmPosition() const;
/**jsdoc
* Get the rotation of the left palm in world coordinates.
* @function MyAvatar.getLeftPalmRotation
* @returns {Vec3} The rotation of the left palm in world coordinates.
* @example <caption>Report the rotation of your avatar's left palm.</caption>
* print(JSON.stringify(MyAvatar.getLeftPalmRotation()));
*/
glm::quat getLeftPalmRotation() const;
/**jsdoc
* Get the position of the right palm in world coordinates.
* @function MyAvatar.getRightPalmPosition
* @returns {Vec3} The position of the right palm in world coordinates.
* @example <caption>Report the position of your avatar's right palm.</caption>
* print(JSON.stringify(MyAvatar.getRightPalmPosition()));
*/
glm::vec3 getRightPalmPosition() const;
/**jsdoc
* Get the rotation of the right palm in world coordinates.
* @function MyAvatar.getRightPalmRotation
* @returns {Vec3} The rotation of the right palm in world coordinates.
* @example <caption>Report the rotation of your avatar's right palm.</caption>
* print(JSON.stringify(MyAvatar.getRightPalmRotation()));
*/
glm::quat getRightPalmRotation() const;
// hooked up to Model::setURLFinished signal
void setModelURLFinished(bool success);
// hooked up to Model::rigReady & rigReset signals
/**jsdoc
* @function MyAvatar.rigReady
* @returns {Signal}
*/
// Hooked up to Model::rigReady signal
void rigReady();
/**jsdoc
* @function MyAvatar.rigReset
* @returns {Signal}
*/
// Jooked up to Model::rigReset signal
void rigReset();
protected:

View file

@ -2362,6 +2362,15 @@ glm::vec3 AvatarData::getAbsoluteJointTranslationInObjectFrame(int index) const
return glm::vec3();
}
/**jsdoc
* @typedef MyAvatar.AttachmentData
* @property {string} modelUrl
* @property {string} jointName
* @property {Vec3} translation
* @property {Vec3} rotation
* @property {number} scale
* @property {boolean} soft
*/
QVariant AttachmentData::toVariant() const {
QVariantMap result;
result["modelUrl"] = modelURL;

View file

@ -353,6 +353,7 @@ public:
class AvatarData : public QObject, public SpatiallyNestable {
Q_OBJECT
// The following properties have JSDoc in MyAvatar.h.
Q_PROPERTY(glm::vec3 position READ getWorldPosition WRITE setPositionViaScript)
Q_PROPERTY(float scale READ getTargetScale WRITE setTargetScale)
Q_PROPERTY(float density READ getDensity)
@ -505,7 +506,7 @@ public:
/**jsdoc
* returns the minimum scale allowed for this avatar in the current domain.
* This value can change as the user changes avatars or when changing domains.
* @function AvatarData.getDomainMinScale
* @function MyAvatar.getDomainMinScale
* @returns {number} minimum scale allowed for this avatar in the current domain.
*/
Q_INVOKABLE float getDomainMinScale() const;
@ -513,7 +514,7 @@ public:
/**jsdoc
* returns the maximum scale allowed for this avatar in the current domain.
* This value can change as the user changes avatars or when changing domains.
* @function AvatarData.getDomainMaxScale
* @function MyAvatar.getDomainMaxScale
* @returns {number} maximum scale allowed for this avatar in the current domain.
*/
Q_INVOKABLE float getDomainMaxScale() const;
@ -529,16 +530,16 @@ public:
/**jsdoc
* Provides read only access to the current eye height of the avatar.
* This height is only an estimate and might be incorrect for avatars that are missing standard joints.
* @function AvatarData.getEyeHeight
* @returns {number} eye height of avatar in meters
* @function MyAvatar.getEyeHeight
* @returns {number} Eye height of avatar in meters.
*/
Q_INVOKABLE virtual float getEyeHeight() const { return _targetScale * getUnscaledEyeHeight(); }
/**jsdoc
* Provides read only access to the current height of the avatar.
* This height is only an estimate and might be incorrect for avatars that are missing standard joints.
* @function AvatarData.getHeight
* @returns {number} height of avatar in meters
* @function MyAvatar.getHeight
* @returns {number} Height of avatar in meters.
*/
Q_INVOKABLE virtual float getHeight() const;
@ -547,49 +548,372 @@ public:
void setDomainMinimumHeight(float domainMinimumHeight);
void setDomainMaximumHeight(float domainMaximumHeight);
// Hand State
/**jsdoc
* @function MyAvatar.setHandState
* @param {string} state
*/
Q_INVOKABLE void setHandState(char s) { _handState = s; }
/**jsdoc
* @function MyAvatar.getHandState
* @returns {string}
*/
Q_INVOKABLE char getHandState() const { return _handState; }
const QVector<JointData>& getRawJointData() const { return _jointData; }
/**jsdoc
* @function MyAvatar.setRawJointData
* @param {JointData[]} data
*/
Q_INVOKABLE void setRawJointData(QVector<JointData> data);
/**jsdoc
* Set a specific joint's rotation and position relative to its parent.
* <p>Setting joint data completely overrides/replaces all motion from the default animation system including inverse
* kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints,
* the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate
* joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set
* the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.</p>
* @function MyAvatar.setJointData
* @param {number} index - The index of the joint.
* @param {Quat} rotation - The rotation of the joint relative to its parent.
* @param {Vec3} translation - The translation of the joint relative to its parent.
* @example <caption>Set your avatar to it's default T-pose for a while.<br />
* <img alt="Avatar in T-pose" src="https://docs.highfidelity.com/user/pages/06.api-reference/25.myavatar/t-pose.png" />
* </caption>
* // Set all joint translations and rotations to defaults.
* var i, length, rotation, translation;
* for (i = 0, length = MyAvatar.getJointNames().length; i < length; i++) {
* rotation = MyAvatar.getDefaultJointRotation(i);
* translation = MyAvatar.getDefaultJointTranslation(i);
* MyAvatar.setJointData(i, rotation, translation);
* }
*
* // Restore your avatar's motion after 5s.
* Script.setTimeout(function () {
* MyAvatar.clearJointsData();
* }, 5000);
*/
Q_INVOKABLE virtual void setJointData(int index, const glm::quat& rotation, const glm::vec3& translation);
/**jsdoc
* Set a specific joint's rotation relative to its parent.
* <p>Setting joint data completely overrides/replaces all motion from the default animation system including inverse
* kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints,
* the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate
* joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set
* the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.</p>
* @function MyAvatar.setJointRotation
* @param {number} index - The index of the joint.
* @param {Quat} rotation - The rotation of the joint relative to its parent.
*/
Q_INVOKABLE virtual void setJointRotation(int index, const glm::quat& rotation);
/**jsdoc
* Set a specific joint's translation relative to its parent.
* <p>Setting joint data completely overrides/replaces all motion from the default animation system including inverse
* kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints,
* the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate
* joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set
* the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.</p>
* @function MyAvatar.setJointTranslation
* @param {number} index - The index of the joint.
* @param {Vec3} translation - The translation of the joint relative to its parent.
*/
Q_INVOKABLE virtual void setJointTranslation(int index, const glm::vec3& translation);
/**jsdoc
* Clear joint translations and rotations set by script for a specific joint. This restores all motion from the default
* animation system including inverse kinematics for that joint.
* <p>Note: This is slightly faster than the function variation that specifies the joint name.</p>
* @function MyAvatar.clearJointData
* @param {number} index - The index of the joint.
*/
Q_INVOKABLE virtual void clearJointData(int index);
/**jsdoc
* @function MyAvatar.isJointDataValid
* @param {number} index
* @returns {boolean}
*/
Q_INVOKABLE bool isJointDataValid(int index) const;
/**jsdoc
* Get the rotation of a joint relative to its parent. For information on the joint hierarchy used, see
* <a href="https://docs.highfidelity.com/create-and-explore/avatars/avatar-standards">Avatar Standards</a>.
* @function MyAvatar.getJointRotation
* @param {number} index - The index of the joint.
* @returns {Quat} The rotation of the joint relative to its parent.
*/
Q_INVOKABLE virtual glm::quat getJointRotation(int index) const;
/**jsdoc
* Get the translation of a joint relative to its parent. For information on the joint hierarchy used, see
* <a href="https://docs.highfidelity.com/create-and-explore/avatars/avatar-standards">Avatar Standards</a>.
* @function MyAvatar.getJointTranslation
* @param {number} index - The index of the joint.
* @returns {Vec3} The translation of the joint relative to its parent.
*/
Q_INVOKABLE virtual glm::vec3 getJointTranslation(int index) const;
/**jsdoc
* Set a specific joint's rotation and position relative to its parent.
* <p>Setting joint data completely overrides/replaces all motion from the default animation system including inverse
* kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints,
* the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate
* joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set
* the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.</p>
* @function MyAvatar.setJointData
* @param {string} name - The name of the joint.
* @param {Quat} rotation - The rotation of the joint relative to its parent.
* @param {Vec3} translation - The translation of the joint relative to its parent.
*/
Q_INVOKABLE virtual void setJointData(const QString& name, const glm::quat& rotation, const glm::vec3& translation);
/**jsdoc
* Set a specific joint's rotation relative to its parent.
* <p>Setting joint data completely overrides/replaces all motion from the default animation system including inverse
* kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints,
* the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate
* joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set
* the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.</p>
* @function MyAvatar.setJointRotation
* @param {string} name - The name of the joint.
* @param {Quat} rotation - The rotation of the joint relative to its parent.
* @example <caption>Set your avatar to its default T-pose then rotate its right arm.<br />
* <img alt="Avatar in T-pose with arm rotated"
* src="https://docs.highfidelity.com/user/pages/06.api-reference/25.myavatar/armpose.png" /></caption>
* // Set all joint translations and rotations to defaults.
* var i, length, rotation, translation;
* for (i = 0, length = MyAvatar.getJointNames().length; i < length; i++) {
* rotation = MyAvatar.getDefaultJointRotation(i);
* translation = MyAvatar.getDefaultJointTranslation(i);
* MyAvatar.setJointData(i, rotation, translation);
* }
*
* // Rotate the right arm.
* var newArmRotation = { x: 0.47, y: 0.22, z: -0.02, w: 0.87 };
* MyAvatar.setJointRotation("RightArm", newArmRotation);
*
* // Restore your avatar's motion after 5s.
* Script.setTimeout(function () {
* MyAvatar.clearJointsData();
* }, 5000);
*/
Q_INVOKABLE virtual void setJointRotation(const QString& name, const glm::quat& rotation);
/**jsdoc
* Set a specific joint's translation relative to its parent.
* <p>Setting joint data completely overrides/replaces all motion from the default animation system including inverse
* kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints,
* the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate
* joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set
* the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.</p>
* @function MyAvatar.setJointTranslation
* @param {string} name - The name of the joint.
* @param {Vec3} translation - The translation of the joint relative to its parent.
* @example <caption>Stretch your avatar's neck. Depending on the avatar you are using, you will either see a gap between
* the head and body or you will see the neck stretched.<br />
* <img alt="Avatar with neck stretched"
* src="https://docs.highfidelity.com/user/pages/06.api-reference/25.myavatar/stretched-neck.png" /></caption>
* // Stretch your avatar's neck.
* MyAvatar.setJointTranslation("Neck", { x: 0, y: 25, z: 0 });
*
* // Restore your avatar's neck after 5s.
* Script.setTimeout(function () {
* MyAvatar.clearJointData("Neck");
* }, 5000);
*/
Q_INVOKABLE virtual void setJointTranslation(const QString& name, const glm::vec3& translation);
/**jsdoc
* Clear joint translations and rotations set by script for a specific joint. This restores all motion from the default
* animation system including inverse kinematics for that joint.
* <p>Note: This is slightly slower than the function variation that specifies the joint index.</p>
* @function MyAvatar.clearJointData
* @param {string} name - The name of the joint.
* @example <caption>Offset and restore the position of your avatar's head.</caption>
* // Move your avatar's head up by 25cm from where it should be.
* MyAvatar.setJointTranslation("Neck", { x: 0, y: 0.25, z: 0 });
*
* // Restore your avatar's head to its default position after 5s.
* Script.setTimeout(function () {
* MyAvatar.clearJointData("Neck");
* }, 5000);
*/
Q_INVOKABLE virtual void clearJointData(const QString& name);
/**jsdoc
* @function MyAvatar.isJointDataValid
* @param {string} name
* @returns {boolean}
*/
Q_INVOKABLE virtual bool isJointDataValid(const QString& name) const;
/**jsdoc
* Get the rotation of a joint relative to its parent. For information on the joint hierarchy used, see
* <a href="https://docs.highfidelity.com/create-and-explore/avatars/avatar-standards">Avatar Standards</a>.
* @function MyAvatar.getJointRotation
* @param {string} name - The name of the joint.
* @returns {Quat} The rotation of the joint relative to its parent.
* @example <caption>Report the rotation of your avatar's hips joint.</caption>
* print(JSON.stringify(MyAvatar.getJointRotation("Hips")));
*/
Q_INVOKABLE virtual glm::quat getJointRotation(const QString& name) const;
/**jsdoc
* Get the translation of a joint relative to its parent. For information on the joint hierarchy used, see
* <a href="https://docs.highfidelity.com/create-and-explore/avatars/avatar-standards">Avatar Standards</a>.
* @function MyAvatar.getJointTranslation
* @param {number} name - The name of the joint.
* @returns {Vec3} The translation of the joint relative to its parent.
* @example <caption>Report the translation of your avatar's hips joint.</caption>
* print(JSON.stringify(MyAvatar.getJointRotation("Hips")));
*/
Q_INVOKABLE virtual glm::vec3 getJointTranslation(const QString& name) const;
/**jsdoc
* Get the rotations of all joints in the current avatar. Each joint's rotation is relative to its parent joint.
* @function MyAvatar.getJointRotations
* @returns {Quat[]} The rotations of all joints relative to each's parent. The values are in the same order as the array
* returned by {@link MyAvatar.getJointNames}.
* @example <caption>Report the rotations of all your avatar's joints.</caption>
* print(JSON.stringify(MyAvatar.getJointRotations()));
*/
Q_INVOKABLE virtual QVector<glm::quat> getJointRotations() const;
/**jsdoc
* @function MyAvatar.getJointTranslations
* @returns {Vec3[]}
*/
Q_INVOKABLE virtual QVector<glm::vec3> getJointTranslations() const;
/**jsdoc
* Set the rotations of all joints in the current avatar. Each joint's rotation is relative to its parent joint.
* <p>Setting joint data completely overrides/replaces all motion from the default animation system including inverse
* kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints,
* the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate
* joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set
* the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.</p>
* @function MyAvatar.setJointRotations
* @param {Quat[]} jointRotations - The rotations for all joints in the avatar. The values are in the same order as the
* array returned by {@link MyAvatar.getJointNames}.
* @example <caption>Set your avatar to its default T-pose then rotate its right arm.<br />
* <img alt="Avatar in T-pose" src="https://docs.highfidelity.com/user/pages/06.api-reference/25.myavatar/armpose.png" />
* </caption>
* // Set all joint translations and rotations to defaults.
* var i, length, rotation, translation;
* for (i = 0, length = MyAvatar.getJointNames().length; i < length; i++) {
* rotation = MyAvatar.getDefaultJointRotation(i);
* translation = MyAvatar.getDefaultJointTranslation(i);
* MyAvatar.setJointData(i, rotation, translation);
* }
*
* // Get all join rotations.
* var jointRotations = MyAvatar.getJointRotations();
*
* // Update the rotation of the right arm in the array.
* jointRotations[MyAvatar.getJointIndex("RightArm")] = { x: 0.47, y: 0.22, z: -0.02, w: 0.87 };
*
* // Update all joint rotations.
* MyAvatar.setJointRotations(jointRotations);
*
* // Restore your avatar's motion after 5s.
* Script.setTimeout(function () {
* MyAvatar.clearJointsData();
* }, 5000);
*/
Q_INVOKABLE virtual void setJointRotations(const QVector<glm::quat>& jointRotations);
/**jsdoc
* @function MyAvatar.setJointTranslations
* @param {Vec3[]} translations
*/
Q_INVOKABLE virtual void setJointTranslations(const QVector<glm::vec3>& jointTranslations);
/**jsdoc
* Clear all joint translations and rotations that have been set by script. This restores all motion from the default
* animation system including inverse kinematics for all joints.
* @function MyAvatar.clearJointsData
* @example <caption>Set your avatar to it's default T-pose for a while.</caption>
* // Set all joint translations and rotations to defaults.
* var i, length, rotation, translation;
* for (i = 0, length = MyAvatar.getJointNames().length; i < length; i++) {
* rotation = MyAvatar.getDefaultJointRotation(i);
* translation = MyAvatar.getDefaultJointTranslation(i);
* MyAvatar.setJointData(i, rotation, translation);
* }
*
* // Restore your avatar's motion after 5s.
* Script.setTimeout(function () {
* MyAvatar.clearJointsData();
* }, 5000);
*/
Q_INVOKABLE virtual void clearJointsData();
/**jsdoc
* Get the joint index for a named joint. The joint index value is the position of the joint in the array returned by
* {@link MyAvatar.getJointNames}.
* @function MyAvatar.getJointIndex
* @param {string} name - The name of the joint.
* @returns {number} The index of the joint.
* @example <caption>Report the index of your avatar's left arm joint.</caption>
* print(JSON.stringify(MyAvatar.getJointIndex("LeftArm"));
*/
/// Returns the index of the joint with the specified name, or -1 if not found/unknown.
Q_INVOKABLE virtual int getJointIndex(const QString& name) const;
/**jsdoc
* Get the names of all the joints in the current avatar.
* @function MyAvatar.getJointNames
* @returns {string[]} The joint names.
* @example <caption>Report the names of all the joints in your current avatar.</caption>
* print(JSON.stringify(MyAvatar.getJointNames()));
*/
Q_INVOKABLE virtual QStringList getJointNames() const;
/**jsdoc
* @function MyAvatar.setBlendshape
* @param {string} name
* @param {number} value
*/
Q_INVOKABLE void setBlendshape(QString name, float val) { _headData->setBlendshape(name, val); }
/**jsdoc
* @function MyAvatar.getAttachmentsVariant
* @returns {object}
*/
// FIXME: Can this name be improved? Can it be deprecated?
Q_INVOKABLE QVariantList getAttachmentsVariant() const;
/**jsdoc
* @function MyAvatar.setAttachmentsVariant
* @param {object} variant
*/
// FIXME: Can this name be improved? Can it be deprecated?
Q_INVOKABLE void setAttachmentsVariant(const QVariantList& variant);
/**jsdoc
* @function MyAvatar.updateAvatarEntity
* @param {Uuid} entityID
* @param {string} entityData
*/
Q_INVOKABLE void updateAvatarEntity(const QUuid& entityID, const QByteArray& entityData);
/**jsdoc
* @function MyAvatar.clearAvatarEntity
* @param {Uuid} entityID
*/
Q_INVOKABLE void clearAvatarEntity(const QUuid& entityID);
/**jsdoc
* @function MyAvatar.setForceFaceTrackerConnected
* @param {boolean} connected
*/
Q_INVOKABLE void setForceFaceTrackerConnected(bool connected) { _forceFaceTrackerConnected = connected; }
// key state
@ -627,15 +951,96 @@ public:
markIdentityDataChanged();
}
/**jsdoc
* Get information about all models currently attached to your avatar.
* @function MyAvatar.getAttachmentData
* @returns {MyAvatar.AttachmentData[]} Information about all models attached to your avatar.
* @example <caption>Report the URLs of all current attachments.</caption>
* var attachments = MyAvatar.getaAttachmentData();
* for (var i = 0; i < attachments.length; i++) {
* print (attachments[i].modelURL);
* }
*/
Q_INVOKABLE QVector<AttachmentData> getAttachmentData() const;
/**jsdoc
* Set all models currently attached to your avatar. For example, if you retrieve attachment data using
* {@link MyAvatar.getAttachmentData}, make changes to it, and then want to update your avatar's attachments per the
* changed data. You can also remove all attachments by using setting <code>attachmentData</code> to <code>null</code>.
* @function MyAvatar.setAttachmentData
* @param {MyAvatar.AttachmentData[]} attachmentData - The attachment data defining the models to have attached to your avatar. Use
* <code>null</code> to remove all attachments.
* @example <caption>Remove a hat attachment if your avatar is wearing it.</caption>
* var hatURL = "https://s3.amazonaws.com/hifi-public/tony/cowboy-hat.fbx";
* var attachments = MyAvatar.getAttachmentData();
*
* for (var i = 0; i < attachments.length; i++) {
* if (attachments[i].modelURL === hatURL) {
* attachments.splice(i, 1);
* MyAvatar.setAttachmentData(attachments);
* break;
* }
* }
*/
Q_INVOKABLE virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData);
/**jsdoc
* Attach a model to your avatar. For example, you can give your avatar a hat to wear, a guitar to hold, or a surfboard to
* stand on.
* <p>Note: Attached models are models only; they are not entities and can not be manipulated using the {@link Entities} API.
* Nor can you use this function to attach an entity (such as a sphere or a box) to your avatar.</p>
* @function MyAvatar.attach
* @param {string} modelURL - The URL of the model to attach. Models can be .FBX or .OBJ format.
* @param {string} [jointName=""] - The name of the avatar joint (see {@link MyAvatar.getJointNames}) to attach the model
* to.
* @param {Vec3} [translation=Vec3.ZERO] - The offset to apply to the model relative to the joint position.
* @param {Quat} [rotation=Quat.IDENTITY] - The rotation to apply to the model relative to the joint orientation.
* @param {number} [scale=1.0] - The scale to apply to the model.
* @param {boolean} [isSoft=false] - If the model has a skeleton, set this to <code>true</code> so that the bones of the
* attached model's skeleton are be rotated to fit the avatar's current pose. <code>isSoft</code> is used, for example,
* to have clothing that moves with the avatar.<br />
* If <code>true</code>, the <code>translation</code>, <code>rotation</code>, and <code>scale</code> parameters are
* ignored.
* @param {boolean} [allowDuplicates=false]
* @param {boolean} [useSaved=true]
* @example <caption>Attach a cowboy hat to your avatar's head.</caption>
* var attachment = {
* modelURL: "https://s3.amazonaws.com/hifi-public/tony/cowboy-hat.fbx",
* jointName: "Head",
* translation: {"x": 0, "y": 0.25, "z": 0},
* rotation: {"x": 0, "y": 0, "z": 0, "w": 1},
* scale: 1,
* isSoft: false
* };
*
* MyAvatar.attach(attachment.modelURL,
* attachment.jointName,
* attachment.translation,
* attachment.rotation,
* attachment.scale,
* attachment.isSoft);
*/
Q_INVOKABLE virtual void attach(const QString& modelURL, const QString& jointName = QString(),
const glm::vec3& translation = glm::vec3(), const glm::quat& rotation = glm::quat(),
float scale = 1.0f, bool isSoft = false,
bool allowDuplicates = false, bool useSaved = true);
/**jsdoc
* Detach the most recently attached instance of a particular model from either a specific joint or any joint.
* @function MyAvatar.detachOne
* @param {string} modelURL - The URL of the model to detach.
* @param {string} [jointName=""] - The name of the joint to detach the model from. If <code>""</code>, then the most
* recently attached model is removed from which ever joint it was attached to.
*/
Q_INVOKABLE void detachOne(const QString& modelURL, const QString& jointName = QString());
/**jsdoc
* Detach all instances of a particular model from either a specific joint or all joints.
* @function MyAvatar.detachAll
* @param {string} modelURL - The URL of the model to detach.
* @param {string} [jointName=""] - The name of the joint to detach the model from. If <code>""</code>, then the model is
* detached from all joints.
*/
Q_INVOKABLE void detachAll(const QString& modelURL, const QString& jointName = QString());
QString getSkeletonModelURLFromScript() const { return _skeletonModelURL.toString(); }
@ -657,19 +1062,63 @@ public:
glm::vec3 getClientGlobalPosition() const { return _globalPosition; }
glm::vec3 getGlobalBoundingBoxCorner() const { return _globalPosition + _globalBoundingBoxOffset - _globalBoundingBoxDimensions; }
/**jsdoc
* @function MyAvatar.getAvatarEntityData
* @returns {object}
*/
Q_INVOKABLE AvatarEntityMap getAvatarEntityData() const;
/**jsdoc
* @function MyAvatar.setAvatarEntityData
* @param {object} avatarEntityData
*/
Q_INVOKABLE void setAvatarEntityData(const AvatarEntityMap& avatarEntityData);
virtual void setAvatarEntityDataChanged(bool value) { _avatarEntityDataChanged = value; }
void insertDetachedEntityID(const QUuid entityID);
AvatarEntityIDs getAndClearRecentlyDetachedIDs();
/**jsdoc
* @function MyAvatar.getSensorToWorldMatrix
* @returns {Mat4}
*/
// thread safe
Q_INVOKABLE glm::mat4 getSensorToWorldMatrix() const;
/**jsdoc
* @function MyAvatar.getSensorToWorldScale
* @returns {number}
*/
// thread safe
Q_INVOKABLE float getSensorToWorldScale() const;
/**jsdoc
* @function MyAvatar.getControllerLeftHandMatrix
* @returns {Mat4}
*/
// thread safe
Q_INVOKABLE glm::mat4 getControllerLeftHandMatrix() const;
/**jsdoc
* @function MyAvatar.getControllerRightHandMatrix
* @returns {Mat4}
*/
// thread safe
Q_INVOKABLE glm::mat4 getControllerRightHandMatrix() const;
/**jsdoc
* @function MyAvatar.getDataRate
* @param {string} [rateName=""]
* @returns {number}
*/
Q_INVOKABLE float getDataRate(const QString& rateName = QString("")) const;
/**jsdoc
* @function MyAvatar.getUpdateRate
* @param {string} [rateName=""]
* @returns {number}
*/
Q_INVOKABLE float getUpdateRate(const QString& rateName = QString("")) const;
int getJointCount() const { return _jointData.size(); }
@ -705,17 +1154,60 @@ public:
virtual void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) {}
signals:
/**jsdoc
* @function MyAvatar.displayNameChanged
* @returns {Signal}
*/
void displayNameChanged();
/**jsdoc
* @function MyAvatar.sessionDisplayNameChanged
* @returns {Signal}
*/
void sessionDisplayNameChanged();
/**jsdoc
* @function MyAvatar.skeletonModelURLChanged
* @returns {Signal}
*/
void skeletonModelURLChanged();
/**jsdoc
* @function MyAvatar.lookAtSnappingChanged
* @param {boolean} enabled
* @returns {Signal}
*/
void lookAtSnappingChanged(bool enabled);
/**jsdoc
* @function MyAvatar.sessionUUIDChanged
* @returns {Signal}
*/
void sessionUUIDChanged();
public slots:
/**jsdoc
* @function MyAvatar.sendAvatarDataPacket
* @param {boolean} [sendAll=false]
*/
void sendAvatarDataPacket(bool sendAll = false);
/**jsdoc
* @function MyAvatar.sendIdentityPacket
*/
void sendIdentityPacket();
/**jsdoc
* @function MyAvatar.setJointMappingsFromNetworkReply
*/
void setJointMappingsFromNetworkReply();
/**jsdoc
* @function MyAvatar.setSessionUUID
* @param {Uuid} sessionUUID
*/
virtual void setSessionUUID(const QUuid& sessionUUID) {
if (sessionUUID != getID()) {
if (sessionUUID == QUuid()) {
@ -727,13 +1219,45 @@ public slots:
}
}
/**jsdoc
* @function MyAvatar.getAbsoluteJointRotationInObjectFrame
* @param {number} index
* @returns {Quat}
*/
virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override;
/**jsdoc
* @function MyAvatar.getAbsoluteJointTranslationInObjectFrame
* @param {number} index
* @returns {Vec3}
*/
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override;
/**jsdoc
* @function MyAvatar.setAbsoluteJointRotationInObjectFrame
* @param {number} index
* @param {Quat} rotation
* @returns {boolean}
*/
virtual bool setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) override { return false; }
/**jsdoc
* @function MyAvatar.setAbsoluteJointTranslationInObjectFrame
* @param {number} index
* @param {Vec3} translation
* @returns {boolean}
*/
virtual bool setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) override { return false; }
/**jsdoc
* @function MyAvatar.getTargetScale
* @returns {number}
*/
float getTargetScale() const { return _targetScale; } // why is this a slot?
/**jsdoc
* @function MyAvatar.resetLastSent
*/
void resetLastSent() { _lastToByteArray = 0; }
protected:

View file

@ -172,6 +172,17 @@ private:
ReticleInterface* _reticleInterface { nullptr };
};
/**jsdoc
* @namespace Reticle
* @property {boolean} allowMouseCapture
* @property {number} depth
* @property {Vec2} maximumPosition
* @property {boolean} mouseCaptured
* @property {boolean} pointingAtSystemOverlay
* @property {Vec2} position
* @property {number} scale
* @property {boolean} visible
*/
// Scripting interface available to control the Reticle
class ReticleInterface : public QObject {
Q_OBJECT
@ -187,25 +198,82 @@ class ReticleInterface : public QObject {
public:
ReticleInterface(CompositorHelper* outer) : QObject(outer), _compositor(outer) {}
/**jsdoc
* @function Reticle.isMouseCaptured
* @returns {boolean}
*/
Q_INVOKABLE bool isMouseCaptured() { return _compositor->shouldCaptureMouse(); }
/**jsdoc
* @function Reticle.getAllowMouseCapture
* @returns {boolean}
*/
Q_INVOKABLE bool getAllowMouseCapture() { return _compositor->getAllowMouseCapture(); }
/**jsdoc
* @function Reticle.setAllowMouseCapture
* @param {boolean} allowMouseCaptured
*/
Q_INVOKABLE void setAllowMouseCapture(bool value) { return _compositor->setAllowMouseCapture(value); }
/**jsdoc
* @function Reticle.isPointingAtSystemOverlay
* @returns {boolean}
*/
Q_INVOKABLE bool isPointingAtSystemOverlay() { return !_compositor->getReticleOverDesktop(); }
/**jsdoc
* @function Reticle.getVisible
* @returns {boolean}
*/
Q_INVOKABLE bool getVisible() { return _compositor->getReticleVisible(); }
/**jsdoc
* @function Reticle.setVisible
* @param {boolean} visible
*/
Q_INVOKABLE void setVisible(bool visible) { _compositor->setReticleVisible(visible); }
/**jsdoc
* @function Reticle.getDepth
* @returns {number}
*/
Q_INVOKABLE float getDepth() { return _compositor->getReticleDepth(); }
/**jsdoc
* @function Reticle.setDepth
* @param {number} depth
*/
Q_INVOKABLE void setDepth(float depth) { _compositor->setReticleDepth(depth); }
/**jsdoc
* @function Reticle.getScale
* @returns {number}
*/
Q_INVOKABLE float getScale() const;
/**jsdoc
* @function Reticle.setScale
* @param {number} scale
*/
Q_INVOKABLE void setScale(float scale);
/**jsdoc
* @function Reticle.getPosition
* @returns {Vec2}
*/
Q_INVOKABLE QVariant getPosition() const;
/**jsdoc
* @function Reticle.setPosition
* @param {Vec2} position
*/
Q_INVOKABLE void setPosition(QVariant position);
/**jsdoc
* @function Reticle.getMaximumPosition
* @returns {Vec2}
*/
Q_INVOKABLE glm::vec2 getMaximumPosition() { return _compositor->getReticleMaximumPosition(); }
private:

View file

@ -23,6 +23,9 @@
class QScriptEngine;
class QScriptValue;
/**jsdoc
* @namespace Recording
*/
class RecordingScriptingInterface : public QObject, public Dependency {
Q_OBJECT
@ -32,43 +35,196 @@ public:
void setScriptEngine(QSharedPointer<BaseScriptEngine> scriptEngine) { _scriptEngine = scriptEngine; }
public slots:
/**jsdoc
* @function Recording.loadRecording
* @param {string} url
* @param {Recording~loadRecordingCallback} [callback=null]
*/
/**jsdoc
* Called when {@link Recording.loadRecording} is complete.
* @callback Recording~loadRecordingCallback
* @param {boolean} success
* @param {string} url
*/
void loadRecording(const QString& url, QScriptValue callback = QScriptValue());
/**jsdoc
* @function Recording.startPlaying
*/
void startPlaying();
/**jsdoc
* @function Recording.pausePlayer
*/
void pausePlayer();
/**jsdoc
* @function Recording.stopPlaying
*/
void stopPlaying();
/**jsdoc
* @function Recording.isPlaying
* @returns {boolean}
*/
bool isPlaying() const;
/**jsdoc
* @function Recording.isPaused
* @returns {boolean}
*/
bool isPaused() const;
/**jsdoc
* @function Recording.playerElapsed
* @returns {number}
*/
float playerElapsed() const;
/**jsdoc
* @function Recording.playerLength
* @returns {number}
*/
float playerLength() const;
/**jsdoc
* @function Recording.setPlayerVolume
* @param {number} volume
*/
void setPlayerVolume(float volume);
/**jsdoc
* @function Recording.setPlayerAudioOffset
* @param {number} audioOffset
*/
void setPlayerAudioOffset(float audioOffset);
/**jsdoc
* @function Recording.setPlayerTime
* @param {number} time
*/
void setPlayerTime(float time);
/**jsdoc
* @function Recording.setPlayerLoop
* @param {boolean} loop
*/
void setPlayerLoop(bool loop);
/**jsdoc
* @function Recording.setPlayerUseDisplayName
* @param {boolean} useDisplayName
*/
void setPlayerUseDisplayName(bool useDisplayName);
/**jsdoc
* @function Recording.setPlayerUseAttachments
* @param {boolean} useAttachments
*/
void setPlayerUseAttachments(bool useAttachments);
/**jsdoc
* @function Recording.setPlayerUseHeadModel
* @param {boolean} useHeadModel
* @todo <strong>Note:</strong> This function currently has no effect.
*/
void setPlayerUseHeadModel(bool useHeadModel);
/**jsdoc
* @function Recording.setPlayerUseSkeletonModel
* @param {boolean} useSkeletonModel
* @todo <strong>Note:</strong> This function currently doesn't work.
*/
void setPlayerUseSkeletonModel(bool useSkeletonModel);
/**jsdoc
* @function Recording.setPlayFromCurrentLocation
* @param {boolean} playFromCurrentLocation
*/
void setPlayFromCurrentLocation(bool playFromCurrentLocation);
/**jsdoc
* @function Recording.getPlayerUseDisplayName
* @returns {boolean}
*/
bool getPlayerUseDisplayName() { return _useDisplayName; }
/**jsdoc
* @function Recording.getPlayerUseAttachments
* @returns {boolean}
*/
bool getPlayerUseAttachments() { return _useAttachments; }
/**jsdoc
* @function Recording.getPlayerUseHeadModel
* @returns {boolean}
*/
bool getPlayerUseHeadModel() { return _useHeadModel; }
/**jsdoc
* @function Recording.getPlayerUseSkeletonModel
* @returns {boolean}
*/
bool getPlayerUseSkeletonModel() { return _useSkeletonModel; }
/**jsdoc
* @function Recording.getPlayFromCurrentLocation
* @returns {boolean}
*/
bool getPlayFromCurrentLocation() { return _playFromCurrentLocation; }
/**jsdoc
* @function Recording.startRecording
*/
void startRecording();
/**jsdoc
* @function Recording.stopRecording
*/
void stopRecording();
/**jsdoc
* @function Recording.isRecording
* @returns {boolean}
*/
bool isRecording() const;
/**jsdoc
* @function Recording.recorderElapsed
* @returns {number}
*/
float recorderElapsed() const;
/**jsdoc
* @function Recording.getDefaultRecordingSaveDirectory
* @returns {string}
*/
QString getDefaultRecordingSaveDirectory();
/**jsdoc
* @function Recording.saveRecording
* @param {string} filename
*/
void saveRecording(const QString& filename);
/**jsdoc
* @function Recording.saveRecordingToAsset
* @param {function} getClipAtpUrl
*/
bool saveRecordingToAsset(QScriptValue getClipAtpUrl);
/**jsdoc
* @function Recording.loadLastRecording
*/
void loadLastRecording();
protected:

View file

@ -19,6 +19,13 @@
// TODO: if QT moc ever supports nested classes, subclass these to the interface instead of namespacing
namespace SceneScripting {
/**jsdoc
* @typedef Scene.Stage.Location
* @property {number} longitude
* @property {number} latitude
* @property {number} altitude
*/
class Location : public QObject {
Q_OBJECT
@ -41,6 +48,11 @@ namespace SceneScripting {
};
using LocationPointer = std::unique_ptr<Location>;
/**jsdoc
* @typedef Scene.Stage.Time
* @property {number} hour
* @property {number} day
*/
class Time : public QObject {
Q_OBJECT
@ -60,6 +72,13 @@ namespace SceneScripting {
};
using TimePointer = std::unique_ptr<Time>;
/**jsdoc
* @typedef Scene.Stage.KeyLight
* @property {Vec3} color
* @property {number} intensity
* @property {number} ambientIntensity
* @property {Vec3} direction
*/
class KeyLight : public QObject {
Q_OBJECT
@ -91,6 +110,14 @@ namespace SceneScripting {
};
using KeyLightPointer = std::unique_ptr<KeyLight>;
/**jsdoc
* @class Scene.Stage
* @property {string} backgroundMode
* @property {Scene.Stage.KeyLight} keyLight
* @property {Scene.Stage.Location} location
* @property {boolean} sunModel
* @property {Scene.Stage.Time} time
*/
class Stage : public QObject {
Q_OBJECT
@ -99,10 +126,22 @@ namespace SceneScripting {
: _skyStage{ skyStage },
_location{ new Location{ skyStage } }, _time{ new Time{ skyStage } }, _keyLight{ new KeyLight{ skyStage } }{}
/**jsdoc
* @function Scene.Stage.setOrientation
* @param {Quat} orientation
*/
Q_INVOKABLE void setOrientation(const glm::quat& orientation) const;
Q_PROPERTY(Location* location READ getLocation)
Location* getLocation() const { return _location.get(); }
/**jsdoc
* @function Scene.Stage.setLocation
* @param {number} longitude
* @param {number} latitude
* @param {number} altitude
*/
Q_INVOKABLE void setLocation(float longitude, float latitude, float altitude);
Q_PROPERTY(Time* time READ getTime)
@ -130,10 +169,15 @@ namespace SceneScripting {
using StagePointer = std::unique_ptr<Stage>;
};
/**jsdoc
* @namespace Scene
* @property {boolean} shouldRenderAvatars
* @property {boolean} shouldRenderEntities
* @property {Scene.Stage} stage
*/
class SceneScriptingInterface : public QObject, public Dependency {
Q_OBJECT
SINGLETON_DEPENDENCY
public:
Q_PROPERTY(bool shouldRenderAvatars READ shouldRenderAvatars WRITE setShouldRenderAvatars)
@ -149,7 +193,19 @@ public:
graphics::SunSkyStagePointer getSkyStage() const;
signals:
/**jsdoc
* @function Scene.shouldRenderAvatarsChanged
* @param {boolean} shouldRenderAvatars
* @returns {Signal}
*/
void shouldRenderAvatarsChanged(bool shouldRenderAvatars);
/**jsdoc
* @function Scene.shouldRenderEntitiesChanged
* @param {boolean} shouldRenderEntities
* @returns {Signal}
*/
void shouldRenderEntitiesChanged(bool shouldRenderEntities);
protected:

View file

@ -87,6 +87,10 @@ public:
QUrl definingSandboxURL { QUrl("about:EntityScript") };
};
/**jsdoc
* @namespace Script
* @property {string} context
*/
class ScriptEngine : public BaseScriptEngine, public EntitiesScriptEngineProvider {
Q_OBJECT
Q_PROPERTY(QString context READ getContext)
@ -115,6 +119,11 @@ public:
QString getFilename() const;
/**jsdoc
* Stop the current script.
* @function Script.stop
* @param {boolean} [marshal=false]
*/
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// NOTE - this is intended to be a public interface for Agent scripts, and local scripts, but not for EntityScripts
Q_INVOKABLE void stop(bool marshal = false);
@ -126,26 +135,69 @@ public:
// NOTE - these are NOT intended to be public interfaces available to scripts, the are only Q_INVOKABLE so we can
// properly ensure they are only called on the correct thread
/**jsdoc
* @function Script.registerGlobalObject
* @param {string} name
* @param {object} object
*/
/// registers a global object by name
Q_INVOKABLE void registerGlobalObject(const QString& name, QObject* object);
/**jsdoc
* @function Script.registerGetterSetter
* @param {string} name
* @param {object} getter
* @param {object} setter
* @param {string} [parent=""]
*/
/// registers a global getter/setter
Q_INVOKABLE void registerGetterSetter(const QString& name, QScriptEngine::FunctionSignature getter,
QScriptEngine::FunctionSignature setter, const QString& parent = QString(""));
/**jsdoc
* @function Script.registerFunction
* @param {string} name
* @param {object} function
* @param {number} [numArguments=-1]
*/
/// register a global function
Q_INVOKABLE void registerFunction(const QString& name, QScriptEngine::FunctionSignature fun, int numArguments = -1);
/**jsdoc
* @function Script.registerFunction
* @param {string} parent
* @param {string} name
* @param {object} function
* @param {number} [numArguments=-1]
*/
/// register a function as a method on a previously registered global object
Q_INVOKABLE void registerFunction(const QString& parent, const QString& name, QScriptEngine::FunctionSignature fun,
int numArguments = -1);
/**jsdoc
* @function Script.registerValue
* @param {string} name
* @param {object} value
*/
/// registers a global object by name
Q_INVOKABLE void registerValue(const QString& valueName, QScriptValue value);
/**jsdoc
* @function Script.evaluate
* @param {string} program
* @param {string} filename
* @param {number} [lineNumber=-1]
* @returns {object}
*/
/// evaluate some code in the context of the ScriptEngine and return the result
Q_INVOKABLE QScriptValue evaluate(const QString& program, const QString& fileName, int lineNumber = 1); // this is also used by the script tool widget
/**jsdoc
* @function Script.evaluateInClosure
* @param {object} locals
* @param {object} program
* @returns {object}
*/
Q_INVOKABLE QScriptValue evaluateInClosure(const QScriptValue& locals, const QScriptProgram& program);
/// if the script engine is not already running, this will download the URL and start the process of seting it up
@ -154,24 +206,122 @@ public:
void loadURL(const QUrl& scriptURL, bool reload);
bool hasValidScriptSuffix(const QString& scriptFileName);
/**jsdoc
* @function Script.getContext
* @returns {string}
*/
Q_INVOKABLE QString getContext() const;
/**jsdoc
* @function Script.isClientScript
* @returns {boolean}
*/
Q_INVOKABLE bool isClientScript() const { return _context == CLIENT_SCRIPT; }
/**jsdoc
* @function Script.isEntityClientScript
* @returns {boolean}
*/
Q_INVOKABLE bool isEntityClientScript() const { return _context == ENTITY_CLIENT_SCRIPT; }
/**jsdoc
* @function Script.isEntityServerScript
* @returns {boolean}
*/
Q_INVOKABLE bool isEntityServerScript() const { return _context == ENTITY_SERVER_SCRIPT; }
/**jsdoc
* @function Script.isAgentScript
* @returns {boolean}
*/
Q_INVOKABLE bool isAgentScript() const { return _context == AGENT_SCRIPT; }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// NOTE - these are intended to be public interfaces available to scripts
/**jsdoc
* @function Script.addEventHandler
* @param {Uuid} entityID
* @param {string} eventName
* @param {function} handler
*/
Q_INVOKABLE void addEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler);
/**jsdoc
* @function Script.removeEventHandler
* @param {Uuid} entityID
* @param {string} eventName
* @param {function} handler
*/
Q_INVOKABLE void removeEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler);
/**jsdoc
* Start a new Interface or entity script.
* @function Script.load
* @param {string} filename - The URL of the script to load. Can be relative to the current script.
* @example <caption>Load a script from another script.</caption>
* // First file: scriptA.js
* print("This is script A");
*
* // Second file: scriptB.js
* print("This is script B");
* Script.load("scriptA.js");
*
* // If you run scriptB.js you should see both scripts in the running scripts list.
* // And you should see the following output:
* // This is script B
* // This is script A
*/
Q_INVOKABLE void load(const QString& loadfile);
/**jsdoc
* Include JavaScript from other files in the current script. If a callback is specified the files are loaded and included
* asynchronously, otherwise they are included synchronously (i.e., script execution blocks while the files are included).
* @function Script.include
* @param {string[]} filenames - The URLs of the scripts to include. Each can be relative to the current script.
* @param {function} [callback=null] - The function to call back when the scripts have been included. Can be an in-line
* function or the name of a function.
*/
Q_INVOKABLE void include(const QStringList& includeFiles, QScriptValue callback = QScriptValue());
/**jsdoc
* Include JavaScript from another file in the current script. If a callback is specified the file is loaded and included
* asynchronously, otherwise it is included synchronously (i.e., script execution blocks while the file is included).
* @function Script.include
* @param {string} filename - The URL of the script to include. Can be relative to the current script.
* @param {function} [callback=null] - The function to call back when the script has been included. Can be an in-line
* function or the name of a function.
* @example <caption>Include a script file asynchronously.</caption>
* // First file: scriptA.js
* print("This is script A");
*
* // Second file: scriptB.js
* print("This is script B");
* Script.include("scriptA.js", function () {
* print("Script A has been included");
* });
*
* // If you run scriptB.js you should see only scriptB.js in the running scripts list.
* // And you should see the following output:
* // This is script B
* // This is script A
* // Script A has been included
*/
Q_INVOKABLE void include(const QString& includeFile, QScriptValue callback = QScriptValue());
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// MODULE related methods
/**jsdoc
* @function Script.require
* @param {string} module
*/
Q_INVOKABLE QScriptValue require(const QString& moduleId);
/**jsdoc
* @function Script.resetModuleCache
* @param {boolean} [deleteScriptCache=false]
*/
Q_INVOKABLE void resetModuleCache(bool deleteScriptCache = false);
QScriptValue currentModule();
bool registerModuleWithParent(const QScriptValue& module, const QScriptValue& parent);
@ -179,34 +329,168 @@ public:
QVariantMap fetchModuleSource(const QString& modulePath, const bool forceDownload = false);
QScriptValue instantiateModule(const QScriptValue& module, const QString& sourceCode);
/**jsdoc
* Call a function at a set interval.
* @function Script.setInterval
* @param {function} function - The function to call. Can be an in-line function or the name of a function.
* @param {number} interval - The interval at which to call the function, in ms.
* @returns {object} A handle to the interval timer. Can be used by {@link Script.clearInterval}.
* @example <caption>Print a message every second.</caption>
* Script.setInterval(function () {
* print("Timer fired");
* }, 1000);
*/
Q_INVOKABLE QObject* setInterval(const QScriptValue& function, int intervalMS);
/**jsdoc
* Call a function after a delay.
* @function Script.setTimeout
* @param {function} function - The function to call. Can be an in-line function or the name of a function.
* @param {number} timeout - The delay after which to call the function, in ms.
* @returns {object} A handle to the timeout timer. Can be used by {@link Script.clearTimeout}.
* @example <caption>Print a message after a second.</caption>
* Script.setTimeout(function () {
* print("Timer fired");
* }, 1000);
*/
Q_INVOKABLE QObject* setTimeout(const QScriptValue& function, int timeoutMS);
/**jsdoc
* Stop an interval timer set by {@link Script.setInterval|setInterval}.
* @function Script.clearInterval
* @param {object} timer - The interval timer to clear.
* @example <caption>Stop an interval timer.</caption>
* // Print a message every second.
* var timer = Script.setInterval(function () {
* print("Timer fired");
* }, 1000);
*
* // Stop the timer after 10 seconds.
* Script.setTimeout(function () {
* print("Stop timer");
* Script.clearInterval(timer);
* }, 10000);
*/
Q_INVOKABLE void clearInterval(QObject* timer) { stopTimer(reinterpret_cast<QTimer*>(timer)); }
/**jsdoc
* Clear a timeout timer set by {@link Script.setTimeout|setTimeout}.
* @function Script.clearTimeout
* @param {object} timer - The timeout timer to clear.
* @example <caption>Stop a timeout timer.</caption>
* // Print a message after two seconds.
* var timer = Script.setTimeout(function () {
* print("Timer fired");
* }, 2000);
*
* // Uncomment the following line to stop the timer from firing.
* //Script.clearTimeout(timer);
*/
Q_INVOKABLE void clearTimeout(QObject* timer) { stopTimer(reinterpret_cast<QTimer*>(timer)); }
/**jsdoc
* @function Script.print
* @param {string} message
*/
Q_INVOKABLE void print(const QString& message);
/**jsdoc
* Resolve a relative path to an absolute path.
* @function Script.resolvePath
* @param {string} path - The relative path to resolve.
* @returns {string} The absolute path.
*/
Q_INVOKABLE QUrl resolvePath(const QString& path) const;
/**jsdoc
* @function Script.resourcesPath
* @returns {string}
*/
Q_INVOKABLE QUrl resourcesPath() const;
/**jsdoc
* @function Script.beginProfileRange
* @param {string} label
*/
Q_INVOKABLE void beginProfileRange(const QString& label) const;
/**jsdoc
* @function Script.endProfileRange
* @param {string} label
*/
Q_INVOKABLE void endProfileRange(const QString& label) const;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Entity Script Related methods
/**jsdoc
* @function Script.isEntityScriptRunning
* @param {Uuid} entityID
* @returns {boolean}
*/
Q_INVOKABLE bool isEntityScriptRunning(const EntityItemID& entityID) {
return _entityScripts.contains(entityID) && _entityScripts[entityID].status == EntityScriptStatus::RUNNING;
}
QVariant cloneEntityScriptDetails(const EntityItemID& entityID);
QFuture<QVariant> getLocalEntityScriptDetails(const EntityItemID& entityID) override;
/**jsdoc
* @function Script.loadEntityScript
* @param {Uuid} entityID
* @param {string} script
* @param {boolean} forceRedownload
*/
Q_INVOKABLE void loadEntityScript(const EntityItemID& entityID, const QString& entityScript, bool forceRedownload);
/**jsdoc
* @function Script.unloadEntityScript
* @param {Uuid} entityID
* @param {boolean} [shouldRemoveFromMap=false]
*/
Q_INVOKABLE void unloadEntityScript(const EntityItemID& entityID, bool shouldRemoveFromMap = false); // will call unload method
/**jsdoc
* @function Script.unloadAllEntityScripts
*/
Q_INVOKABLE void unloadAllEntityScripts();
/**jsdoc
* @function Script.callEntityScriptMethod
* @param {Uuid} entityID
* @param {string} methodName
* @param {string[]} parameters
* @param {Uuid} [remoteCallerID=Uuid.NULL]
*/
Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName,
const QStringList& params = QStringList(),
const QUuid& remoteCallerID = QUuid()) override;
/**jsdoc
* @function Script.callEntityScriptMethod
* @param {Uuid} entityID
* @param {string} methodName
* @param {PointerEvent} event
*/
Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const PointerEvent& event);
/**jsdoc
* @function Script.callEntityScriptMethod
* @param {Uuid} entityID
* @param {string} methodName
* @param {Uuid} otherID
* @param {Collision} collision
*/
Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const EntityItemID& otherID, const Collision& collision);
/**jsdoc
* @function Script.requestGarbageCollection
*/
Q_INVOKABLE void requestGarbageCollection() { collectGarbage(); }
/**jsdoc
* @function Script.generateUUID
* @returns {Uuid}
*/
Q_INVOKABLE QUuid generateUUID() { return QUuid::createUuid(); }
bool isFinished() const { return _isFinished; } // used by Application and ScriptWidget
@ -239,33 +523,170 @@ public:
bool getEntityScriptDetails(const EntityItemID& entityID, EntityScriptDetails &details) const;
public slots:
/**jsdoc
* @function Script.callAnimationStateHandler
* @param {function} callback
* @param {object} parameters
* @param {string[]} names
* @param {boolean} useNames
* @param {object} resultHandler
*/
void callAnimationStateHandler(QScriptValue callback, AnimVariantMap parameters, QStringList names, bool useNames, AnimVariantResultHandler resultHandler);
/**jsdoc
* @function Script.updateMemoryCost
* @param {number} deltaSize
*/
void updateMemoryCost(const qint64&);
signals:
/**jsdoc
* @function Script.scriptLoaded
* @param {string} filename
* @returns {Signal}
*/
void scriptLoaded(const QString& scriptFilename);
/**jsdoc
* @function Script.errorLoadingScript
* @param {string} filename
* @returns {Signal}
*/
void errorLoadingScript(const QString& scriptFilename);
/**jsdoc
* Triggered regularly at a system-determined frequency.
* @function Script.update
* @param {number} deltaTime - The time since the last update, in s.
* @returns {Signal}
*/
void update(float deltaTime);
/**jsdoc
* Triggered when the script is ending.
* @function Script.scriptEnding
* @returns {Signal}
* @example <caption>Connect to the <code>scriptEnding</code> signal.</caption>
* print("Script started");
*
* Script.scriptEnding.connect(function () {
* print("Script ending");
* });
*
* Script.setTimeout(function () {
* print("Stopping script");
* Script.stop();
* }, 1000);
*/
void scriptEnding();
/**jsdoc
* @function Script.finished
* @param {string} filename
* @param {object} engine
* @returns {Signal}
*/
void finished(const QString& fileNameString, ScriptEnginePointer);
/**jsdoc
* @function Script.cleanupMenuItem
* @param {string} menuItem
* @returns {Signal}
*/
void cleanupMenuItem(const QString& menuItemString);
/**jsdoc
* @function Script.printedMessage
* @param {string} message
* @param {string} scriptName
* @returns {Signal}
*/
void printedMessage(const QString& message, const QString& scriptName);
/**jsdoc
* @function Script.errorMessage
* @param {string} message
* @param {string} scriptName
* @returns {Signal}
*/
void errorMessage(const QString& message, const QString& scriptName);
/**jsdoc
* @function Script.warningMessage
* @param {string} message
* @param {string} scriptName
* @returns {Signal}
*/
void warningMessage(const QString& message, const QString& scriptName);
/**jsdoc
* @function Script.infoMessage
* @param {string} message
* @param {string} scriptName
* @returns {Signal}
*/
void infoMessage(const QString& message, const QString& scriptName);
/**jsdoc
* @function Script.runningStateChanged
* @returns {Signal}
*/
void runningStateChanged();
/**jsdoc
* @function Script.clearDebugWindow
* @returns {Signal}
*/
void clearDebugWindow();
/**jsdoc
* @function Script.loadScript
* @param {string} scriptName
* @param {boolean} isUserLoaded
* @returns {Signal}
*/
void loadScript(const QString& scriptName, bool isUserLoaded);
/**jsdoc
* @function Script.reloadScript
* @param {string} scriptName
* @param {boolean} isUserLoaded
* @returns {Signal}
*/
void reloadScript(const QString& scriptName, bool isUserLoaded);
/**jsdoc
* @function Script.doneRunning
* @returns {Signal}
*/
void doneRunning();
/**jsdoc
* @function Script.entityScriptDetailsUpdated
* @returns {Signal}
*/
// Emitted when an entity script is added or removed, or when the status of an entity
// script is updated (goes from RUNNING to ERROR_RUNNING_SCRIPT, for example)
void entityScriptDetailsUpdated();
protected:
void init();
/**jsdoc
* @function Script.executeOnScriptThread
* @param {object} function
* @param {ConnectionType} [type=2]
*/
Q_INVOKABLE void executeOnScriptThread(std::function<void()> function, const Qt::ConnectionType& type = Qt::QueuedConnection );
/**jsdoc
* @function Script._requireResolve
* @param {string} module
* @param {string} [relativeTo=""]
* @returns {string}
*/
// note: this is not meant to be called directly, but just to have QMetaObject take care of wiring it up in general;
// then inside of init() we just have to do "Script.require.resolve = Script._requireResolve;"
Q_INVOKABLE QString _requireResolve(const QString& moduleId, const QString& relativeTo = QString());
@ -285,6 +706,16 @@ protected:
QHash<EntityItemID, RegisteredEventHandlers> _registeredHandlers;
void forwardHandlerCall(const EntityItemID& entityID, const QString& eventName, QScriptValueList eventHanderArgs);
/**jsdoc
* @function Script.entityScriptContentAvailable
* @param {Uuid} entityID
* @param {string} scriptOrURL
* @param {string} contents
* @param {boolean} isURL
* @param {boolean} success
* @param {string} status
*/
Q_INVOKABLE void entityScriptContentAvailable(const EntityItemID& entityID, const QString& scriptOrURL, const QString& contents, bool isURL, bool success, const QString& status);
EntityItemID currentEntityIdentifier {}; // Contains the defining entity script entity id during execution, if any. Empty for interface script execution.

View file

@ -27,6 +27,14 @@
class ScriptEngine;
/**jsdoc
* @namespace ScriptDiscoveryService
* @property {string} debugScriptUrl
* @property {string} defaultScriptsPath
* @property {ScriptsModel} scriptsModel
* @property {ScriptsModelFilter} scriptsModelFilter
*/
class NativeScriptInitializers : public ScriptInitializerMixin {
public:
bool registerNativeScriptInitializer(NativeScriptInitializer initializer) override;
@ -63,18 +71,64 @@ public:
QString getDefaultScriptsLocation() const;
/**jsdoc
* @function ScriptDiscoveryService.loadOneScript
* @param {string} filename
*/
Q_INVOKABLE void loadOneScript(const QString& scriptFilename);
/**jsdoc
* @function ScriptDiscoveryService.loadScript
* @param {string} [filename=""]
* @param {boolean} [isUserLoaded=true]
* @param {boolean} [loadScriptFromEditor=false]
* @param {boolean} [activateMainWindow=false]
* @param {boolean} [reload=false]
* @returns {boolean}
*/
Q_INVOKABLE ScriptEnginePointer loadScript(const QUrl& scriptFilename = QString(),
bool isUserLoaded = true, bool loadScriptFromEditor = false, bool activateMainWindow = false, bool reload = false);
/**jsdoc
* @function ScriptDiscoveryService.stopScript
* @param {string} scriptHash
* @param {boolean} [restart=false]
* @returns {boolean}
*/
Q_INVOKABLE bool stopScript(const QString& scriptHash, bool restart = false);
/**jsdoc
* @function ScriptDiscoveryService.reloadAllScripts
*/
Q_INVOKABLE void reloadAllScripts();
/**jsdoc
* @function ScriptDiscoveryService.stopAllScripts
* @param {boolean} [restart=false]
*/
Q_INVOKABLE void stopAllScripts(bool restart = false);
/**jsdoc
* @function ScriptDiscoveryService.getRunning
* @returns {object[]}
*/
Q_INVOKABLE QVariantList getRunning();
/**jsdoc
* @function ScriptDiscoveryService.getPublic
* @returns {object[]}
*/
Q_INVOKABLE QVariantList getPublic();
/**jsdoc
* @function ScriptDiscoveryService.getLocal
* @returns {object[]}
*/
Q_INVOKABLE QVariantList getLocal();
// FIXME: Move to other Q_PROPERTY declarations.
Q_PROPERTY(QString defaultScriptsPath READ getDefaultScriptsLocation)
void defaultScriptsLocationOverridden(bool overridden) { _defaultScriptsLocationOverridden = overridden; };
@ -86,25 +140,120 @@ public:
void addScriptEngine(ScriptEnginePointer);
signals:
/**jsdoc
* @function ScriptDiscoveryService.scriptCountChanged
* @returns {Signal}
*/
void scriptCountChanged();
/**jsdoc
* @function ScriptDiscoveryService.scriptsReloading
* @returns {Signal}
*/
void scriptsReloading();
/**jsdoc
* @function ScriptDiscoveryService.scriptLoadError
* @param {string} filename
* @param {string} error
* @returns {Signal}
*/
void scriptLoadError(const QString& filename, const QString& error);
/**jsdoc
* @function ScriptDiscoveryService.printedMessage
* @param {string} message
* @param {string} engineName
* @returns {Signal}
*/
void printedMessage(const QString& message, const QString& engineName);
/**jsdoc
* @function ScriptDiscoveryService.errorMessage
* @param {string} message
* @param {string} engineName
* @returns {Signal}
*/
void errorMessage(const QString& message, const QString& engineName);
/**jsdoc
* @function ScriptDiscoveryService.warningMessage
* @param {string} message
* @param {string} engineName
* @returns {Signal}
*/
void warningMessage(const QString& message, const QString& engineName);
/**jsdoc
* @function ScriptDiscoveryService.infoMessage
* @param {string} message
* @param {string} engineName
* @returns {Signal}
*/
void infoMessage(const QString& message, const QString& engineName);
/**jsdoc
* @function ScriptDiscoveryService.errorLoadingScript
* @param {string} url
* @returns {Signal}
*/
void errorLoadingScript(const QString& url);
/**jsdoc
* @function ScriptDiscoveryService.clearDebugWindow
* @returns {Signal}
*/
void clearDebugWindow();
public slots:
/**jsdoc
* @function ScriptDiscoveryService.onPrintedMessage
* @param {string} message
* @param {string} scriptName
*/
void onPrintedMessage(const QString& message, const QString& scriptName);
/**jsdoc
* @function ScriptDiscoveryService.onErrorMessage
* @param {string} message
* @param {string} scriptName
*/
void onErrorMessage(const QString& message, const QString& scriptName);
/**jsdoc
* @function ScriptDiscoveryService.onWarningMessage
* @param {string} message
* @param {string} scriptName
*/
void onWarningMessage(const QString& message, const QString& scriptName);
/**jsdoc
* @function ScriptDiscoveryService.onInfoMessage
* @param {string} message
* @param {string} scriptName
*/
void onInfoMessage(const QString& message, const QString& scriptName);
/**jsdoc
* @function ScriptDiscoveryService.onErrorLoadingScript
* @param {string} url
*/
void onErrorLoadingScript(const QString& url);
/**jsdoc
* @function ScriptDiscoveryService.onClearDebugWindow
*/
void onClearDebugWindow();
protected slots:
/**jsdoc
* @function ScriptDiscoveryService.onScriptFinished
* @param {string} filename
* @param {object} engine
*/
void onScriptFinished(const QString& fileNameString, ScriptEnginePointer engine);
protected:

View file

@ -63,17 +63,68 @@ public:
TreeNodeFolder(const QString& foldername, TreeNodeFolder* parent);
};
/**jsdoc
* <p>Provided as a property of {@link ScriptDiscoveryService}.</p>
* <p>Has properties and functions below in addition to those of <a href="http://doc.qt.io/qt-5/qabstractitemmodel.html">
* http://doc.qt.io/qt-5/qabstractitemmodel.html</a>.</p>
* @class ScriptsModel
*/
class ScriptsModel : public QAbstractItemModel {
Q_OBJECT
public:
ScriptsModel(QObject* parent = NULL);
~ScriptsModel();
/**jsdoc
* @function ScriptsModel.index
* @param {number} row
* @param {number} column
* @param {QModelIndex} parent
* @returns {QModelIndex}
*/
QModelIndex index(int row, int column, const QModelIndex& parent) const override;
/**jsdoc
* @function ScriptsModel.parent
* @param {QModelIndex} child
* @returns {QModelIndex}
*/
QModelIndex parent(const QModelIndex& child) const override;
/**jsdoc
* @function ScriptsModel.data
* @param {QModelIndex} index
* @param {number} [role=0]
* returns {string}
*/
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
/**jsdoc
* @function ScriptsModel.rowCount
* @param {QmodelIndex} [parent=null]
* @returns {number}
*/
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
/**jsdoc
* @function ScriptsModel.columnCount
* @param {QmodelIndex} [parent=null]
* @returns {number}
*/
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
/**jsdoc
* @function ScriptsModel.getTreeNodeFromIndex
* @param {QmodelIndex} index
* @returns {TreeNodeBase}
*/
TreeNodeBase* getTreeNodeFromIndex(const QModelIndex& index) const;
/**jsdoc
* @function ScriptsModel.getFolderNodes
* @param {TreeNodeFolder} parent
* @returns {TreeNodeBase[]}
*/
QList<TreeNodeBase*> getFolderNodes(TreeNodeFolder* parent) const;
enum Role {

View file

@ -15,6 +15,12 @@
#include "ScriptsModel.h"
#include <QSortFilterProxyModel>
/**jsdoc
* <p>Provided as a property of {@link ScriptDiscoveryService}.</p>
* <p>Has properties and functions per <a href="http://doc.qt.io/qt-5/qsortfilterproxymodel.html">
* http://doc.qt.io/qt-5/qsortfilterproxymodel.html</a>.</p>
* @class ScriptsModelFilter
*/
class ScriptsModelFilter : public QSortFilterProxyModel {
Q_OBJECT
public:

View file

@ -17,8 +17,12 @@
#include <DependencyManager.h>
/**jsdoc
* @namespace Users
*/
* @namespace Users
* @property {boolean} canKick - <code>true</code> if the domain server allows the node or avatar to kick (ban) avatars,
* otherwise <code>false</code>. <em>Read-only.</em>
* @property {boolean} requestsDomainListData - <code>true</code> if the avatar requests extra data from the mixers (such as
* positional data of an avatar you've ignored). <em>Read-only.</em>
*/
class UsersScriptingInterface : public QObject, public Dependency {
Q_OBJECT
SINGLETON_DEPENDENCY
@ -32,126 +36,151 @@ public:
public slots:
/**jsdoc
* Ignore another user.
* @function Users.ignore
* @param {nodeID} nodeID The node or session ID of the user you want to ignore.
* @param {bool} enable True for ignored; false for un-ignored.
*/
* Personally ignore another user, making them disappear for you and you disappear for them.
* @function Users.ignore
* @param {Uuid} nodeID The node or session ID of the user you want to ignore.
* @param {boolean} enable True for ignored; false for un-ignored.
*/
void ignore(const QUuid& nodeID, bool ignoreEnabled = true);
/**jsdoc
* Gets a bool containing whether you have ignored the given Avatar UUID.
* @function Users.getIgnoreStatus
* @param {nodeID} nodeID The node or session ID of the user whose ignore status you want.
*/
* Get whether or not you have ignored the node with the given UUID.
* @function Users.getIgnoreStatus
* @param {Uuid} nodeID The node or session ID of the user whose ignore status you want.
* @returns {boolean}
*/
bool getIgnoreStatus(const QUuid& nodeID);
/**jsdoc
* Mute another user for you and you only.
* @function Users.personalMute
* @param {nodeID} nodeID The node or session ID of the user you want to mute.
* @param {bool} enable True for enabled; false for disabled.
*/
* Mute another user for you and you only. They won't be able to hear you, and you won't be able to hear them.
* @function Users.personalMute
* @param {Uuid} nodeID The node or session ID of the user you want to mute.
* @param {boolean} muteEnabled True for enabled; false for disabled.
*/
void personalMute(const QUuid& nodeID, bool muteEnabled = true);
/**jsdoc
* Requests a bool containing whether you have personally muted the given Avatar UUID.
* @function Users.requestPersonalMuteStatus
* @param {nodeID} nodeID The node or session ID of the user whose personal mute status you want.
*/
* Get whether or not you have personally muted the node with the given UUID.
* @function Users.requestPersonalMuteStatus
* @param {Uuid} nodeID The node or session ID of the user whose personal mute status you want.
* @returns {boolean}
*/
bool getPersonalMuteStatus(const QUuid& nodeID);
/**jsdoc
* Sets an avatar's gain for you and you only.
* Units are Decibels (dB)
* @function Users.setAvatarGain
* @param {nodeID} nodeID The node or session ID of the user whose gain you want to modify, or null to set the master gain.
* @param {float} gain The gain of the avatar you'd like to set. Units are dB.
* Sets an avatar's gain for you and you only.
* Units are Decibels (dB)
* @function Users.setAvatarGain
* @param {Uuid} nodeID The node or session ID of the user whose gain you want to modify, or null to set the master gain.
* @param {number} gain The gain of the avatar you'd like to set. Units are dB.
*/
void setAvatarGain(const QUuid& nodeID, float gain);
/**jsdoc
* Gets an avatar's gain for you and you only.
* @function Users.getAvatarGain
* @param {nodeID} nodeID The node or session ID of the user whose gain you want to get, or null to get the master gain.
* @return {float} gain (in dB)
* Gets an avatar's gain for you and you only.
* @function Users.getAvatarGain
* @param {Uuid} nodeID The node or session ID of the user whose gain you want to get, or null to get the master gain.
* @returns {number} gain (in dB)
*/
float getAvatarGain(const QUuid& nodeID);
/**jsdoc
* Kick another user.
* @function Users.kick
* @param {nodeID} nodeID The node or session ID of the user you want to kick.
*/
* Kick/ban another user. Removes them from the server and prevents them from returning. Bans by either user name (if
* available) or machine fingerprint otherwise. This will only do anything if you're an admin of the domain you're in.
* @function Users.kick
* @param {Uuid} nodeID The node or session ID of the user you want to kick.
*/
void kick(const QUuid& nodeID);
/**jsdoc
* Mute another user for everyone.
* @function Users.mute
* @param {nodeID} nodeID The node or session ID of the user you want to mute.
*/
* Mutes another user's microphone for everyone. Not permanent; the silenced user can unmute themselves with the UNMUTE
* button in their HUD. This will only do anything if you're an admin of the domain you're in.
* @function Users.mute
* @param {Uuid} nodeID The node or session ID of the user you want to mute.
*/
void mute(const QUuid& nodeID);
/**jsdoc
* Returns a string containing the username associated with the given Avatar UUID
* Get the user name and machine fingerprint associated with the given UUID. This will only do anything if you're an admin
* of the domain you're in.
* @function Users.getUsernameFromID
* @param {nodeID} nodeID The node or session ID of the user whose username you want.
* @param {Uuid} nodeID The node or session ID of the user whose username you want.
*/
void requestUsernameFromID(const QUuid& nodeID);
/**jsdoc
* Returns `true` if the DomainServer will allow this Node/Avatar to make kick
* @function Users.getCanKick
* @return {bool} `true` if the client can kick other users, `false` if not.
*/
* Returns `true` if the DomainServer will allow this Node/Avatar to make kick.
* @function Users.getCanKick
* @returns {boolean} <code>true</code> if the domain server allows the client to kick (ban) other users, otherwise
* <code>false</code>.
*/
bool getCanKick();
/**jsdoc
* Toggle the state of the ignore in radius feature
* @function Users.toggleIgnoreRadius
*/
* Toggle the state of the space bubble feature.
* @function Users.toggleIgnoreRadius
*/
void toggleIgnoreRadius();
/**jsdoc
* Enables the ignore radius feature.
* @function Users.enableIgnoreRadius
*/
* Enables the space bubble feature.
* @function Users.enableIgnoreRadius
*/
void enableIgnoreRadius();
/**jsdoc
* Disables the ignore radius feature.
* @function Users.disableIgnoreRadius
*/
* Disables the space bubble feature.
* @function Users.disableIgnoreRadius
*/
void disableIgnoreRadius();
/**jsdoc
* Returns `true` if the ignore in radius feature is enabled
* @function Users.getIgnoreRadiusEnabled
* @return {bool} `true` if the ignore in radius feature is enabled, `false` if not.
*/
* Returns `true` if the space bubble feature is enabled.
* @function Users.getIgnoreRadiusEnabled
* @returns {boolean} <code>true</code> if the space bubble is enabled, otherwise <code>false</code>.
*/
bool getIgnoreRadiusEnabled();
signals:
/**jsdoc
* @function Users.canKickChanged
* @param {boolean} canKick
* @returns {Signal}
*/
void canKickChanged(bool canKick);
/**jsdoc
* @function Users.ignoreRadiusEnabledChanged
* @param {boolean} isEnabled
* @returns {Signal}
*/
void ignoreRadiusEnabledChanged(bool isEnabled);
/**jsdoc
* Notifies scripts that another user has entered the ignore radius
* @function Users.enteredIgnoreRadius
*/
* Notifies scripts that another user has entered the ignore radius.
* @function Users.enteredIgnoreRadius
* @returns {Signal}
*/
void enteredIgnoreRadius();
/**jsdoc
* Notifies scripts of the username and machine fingerprint associated with a UUID.
* Username and machineFingerprint will be their default constructor output if the requesting user isn't an admin.
* @function Users.usernameFromIDReply
* Notifies scripts of the user name and machine fingerprint associated with a UUID.
* Username and machineFingerprint will be their default constructor output if the requesting user isn't an admin.
* @function Users.usernameFromIDReply
* @param {Uuid} nodeID
* @param {string} userName
* @param {string} machineFingerprint
* @param {boolean} isAdmin
* @returns {Signal}
*/
void usernameFromIDReply(const QString& nodeID, const QString& username, const QString& machineFingerprint, bool isAdmin);
/**jsdoc
* Notifies scripts that a user has disconnected from the domain
* Notifies scripts that a user has disconnected from the domain.
* @function Users.avatarDisconnected
* @param {nodeID} NodeID The session ID of the avatar that has disconnected
* @param {Uuid} nodeID The session ID of the avatar that has disconnected.
* @returns {Signal}
*/
void avatarDisconnected(const QUuid& nodeID);

View file

@ -44,6 +44,23 @@ class OffscreenQmlSurface;
class TabletScriptingInterface : public QObject, public Dependency {
Q_OBJECT
public:
/**jsdoc
* <table>
* <thead>
* <tr><th>Value</th><th>Description</th></tr>
* </thead>
* <tbody>
* <tr><td><code>0</code></td><td>Button click.</td></tr>
* <tr><td><code>1</code></td><td>Button hover.</td></tr>
* <tr><td><code>2</code></td><td>Tablet open.</td></tr>
* <tr><td><code>3</code></td><td>Tablet hands in.</td></tr>
* <tr><td><code>4</code></td><td>Tablet hands out.</td></tr>
* <tr><td><code>5</code></td><td>Last.</td></tr>
* </tbody>
* </table>
* @typedef {number} Tablet.AudioEvents
*/
enum TabletAudioEvents { ButtonClick, ButtonHover, TabletOpen, TabletHandsIn, TabletHandsOut, Last};
Q_ENUM(TabletAudioEvents)
@ -58,14 +75,19 @@ public:
void setToolbarScriptingInterface(ToolbarScriptingInterface* toolbarScriptingInterface) { _toolbarScriptingInterface = toolbarScriptingInterface; }
/**jsdoc
* Creates or retruns a new TabletProxy and returns it.
* Creates or returns a new TabletProxy and returns it.
* @function Tablet.getTablet
* @param name {String} tablet name
* @return {TabletProxy} tablet instance
* @param {string} name - Tablet name.
* @returns {TabletProxy} Tablet instance.
*/
Q_INVOKABLE TabletProxy* getTablet(const QString& tabletId);
void preloadSounds();
/**jsdoc
* @function Tablet.playSound
* @param {Tablet.AudioEvents} sound
*/
Q_INVOKABLE void playSound(TabletAudioEvents aEvent);
void setToolbarMode(bool toolbarMode);
@ -79,8 +101,8 @@ public:
QObject* getFlags();
signals:
/**jsdoc
* Signaled when a tablet message or dialog is created
* @function TabletProxy#tabletNotification
* Triggered when a tablet message or dialog is created.
* @function Tablet.tabletNotification
* @returns {Signal}
*/
void tabletNotification();
@ -98,6 +120,9 @@ protected:
bool _toolbarMode { false };
};
/**jsdoc
* @typedef {object} TabletProxy#ButtonList
*/
class TabletButtonListModel : public QAbstractListModel {
Q_OBJECT
@ -151,9 +176,12 @@ Q_DECLARE_METATYPE(TabletButtonsProxyModel*);
/**jsdoc
* @class TabletProxy
* @property name {string} READ_ONLY: name of this tablet
* @property toolbarMode {bool} - used to transition this tablet into and out of toolbar mode.
* @property {string} name - Name of this tablet. <em>Read-only.</em>
* @property {boolean} toolbarMode - Used to transition this tablet into and out of toolbar mode.
* When tablet is in toolbar mode, all its buttons will appear in a floating toolbar.
* @property {boolean} landscape
* @property {boolean} tabletShown <em>Read-only.</em>
* @property {TabletProxy#ButtonList} buttons <em>Read-only.</em>
*/
class TabletProxy : public QObject {
Q_OBJECT
@ -172,88 +200,136 @@ public:
bool getToolbarMode() const { return _toolbarMode; }
void setToolbarMode(bool toolbarMode);
/**jsdoc
* @function TabletProxy#gotoMenuScreen
* @param {string} [submenu=""]
*/
Q_INVOKABLE void gotoMenuScreen(const QString& submenu = "");
Q_INVOKABLE void initialScreen(const QVariant& url);
/**jsdoc
* transition to the home screen
* @function TabletProxy#initialScreen
* @param {string} url
*/
Q_INVOKABLE void initialScreen(const QVariant& url);
/**jsdoc
* Transition to the home screen.
* @function TabletProxy#gotoHomeScreen
*/
Q_INVOKABLE void gotoHomeScreen();
/**jsdoc
* show the specified web url on the tablet.
* Show the specified Web url on the tablet.
* @function TabletProxy#gotoWebScreen
* @param url {string} url of web page.
* @param [injectedJavaScriptUrl] {string} optional url to an additional JS script to inject into the web page.
* @param {string} url - URL of web page.
* @param {string} [injectedJavaScriptUrl=""] - URL to an additional JS script to inject into the web page.
* @param {boolean} [loadOtherBase=false]
*/
Q_INVOKABLE void gotoWebScreen(const QString& url);
Q_INVOKABLE void gotoWebScreen(const QString& url, const QString& injectedJavaScriptUrl, bool loadOtherBase = false);
/**jsdoc
* @function TabletProxy#loadQMLSource
* @param {string} path
* @param {boolean} [resizable=false]
*/
Q_INVOKABLE void loadQMLSource(const QVariant& path, bool resizable = false);
// FIXME: This currently relies on a script initializing the tablet (hence the bool denoting success);
// it should be initialized internally so it cannot fail
Q_INVOKABLE bool pushOntoStack(const QVariant& path);
Q_INVOKABLE void popFromStack();
Q_INVOKABLE void loadQMLOnTop(const QVariant& path);
Q_INVOKABLE void loadWebScreenOnTop(const QVariant& url);
Q_INVOKABLE void loadWebScreenOnTop(const QVariant& url, const QString& injectedJavaScriptUrl);
Q_INVOKABLE void returnToPreviousApp();
/**jsdoc
* Check if the tablet has a message dialog open
* @function TabletProxy#pushOntoStack
* @param {string} path
* @returns {boolean}
*/
Q_INVOKABLE bool pushOntoStack(const QVariant& path);
/**jsdoc
* @function TabletProxy#popFromStack
*/
Q_INVOKABLE void popFromStack();
/**jsdoc
* @function TabletProxy#loadQMLOnTop
* @param {string} path
*/
Q_INVOKABLE void loadQMLOnTop(const QVariant& path);
/**jsdoc
* @function TabletProxy#loadWebScreenOnTop
* @param {string} path
* @param {string} [injectedJavaScriptURL=""]
*/
Q_INVOKABLE void loadWebScreenOnTop(const QVariant& url);
Q_INVOKABLE void loadWebScreenOnTop(const QVariant& url, const QString& injectedJavaScriptUrl);
/**jsdoc
* @function TabletProxy#returnToPreviousApp
*/
Q_INVOKABLE void returnToPreviousApp();
/**jsdoc
* Check if the tablet has a message dialog open.
* @function TabletProxy#isMessageDialogOpen
* @returns {boolean}
*/
Q_INVOKABLE bool isMessageDialogOpen();
/**jsdoc
* Creates a new button, adds it to this and returns it.
* @function TabletProxy#addButton
* @param properties {Object} button properties UI_TABLET_HACK: enumerate these when we figure out what they should be!
* @param {object} properties - Button properties.
* @returns {TabletButtonProxy}
*/
//FIXME: UI_TABLET_HACK: enumerate the button properties when we figure out what they should be!
Q_INVOKABLE TabletButtonProxy* addButton(const QVariant& properties);
/**jsdoc
* removes button from the tablet
* @function TabletProxy.removeButton
* @param tabletButtonProxy {TabletButtonProxy} button to be removed
* Removes a button from the tablet.
* @function TabletProxy#removeButton
* @param {TabletButtonProxy} button - The button to be removed
*/
Q_INVOKABLE void removeButton(TabletButtonProxy* tabletButtonProxy);
/**jsdoc
* Used to send an event to the html/js embedded in the tablet
* Used to send an event to the HTML/JavaScript embedded in the tablet.
* @function TabletProxy#emitScriptEvent
* @param msg {object|string}
* @param {object|string} message
*/
Q_INVOKABLE void emitScriptEvent(const QVariant& msg);
/**jsdoc
* Used to send an event to the qml embedded in the tablet
* Used to send an event to the QML embedded in the tablet.
* @function TabletProxy#sendToQml
* @param msg {object|string}
* @param {object|string} message
*/
Q_INVOKABLE void sendToQml(const QVariant& msg);
/**jsdoc
* Check if the tablet is on the homescreen
* @function TabletProxy#onHomeScreen()
* Check if the tablet is on the home screen.
* @function TabletProxy#onHomeScreen
* @returns {boolean}
*/
Q_INVOKABLE bool onHomeScreen();
/**jsdoc
* set tablet into our out of landscape mode
* Set tablet into or out of landscape mode.
* @function TabletProxy#setLandscape
* @param landscape {bool} true for landscape, false for portrait
* @param {boolean} landscape - <code>true</code> for landscape, <ode>false</code> for portrait.
*/
Q_INVOKABLE void setLandscape(bool landscape) { _landscape = landscape; }
/**jsdoc
* @function TabletProxy#getLandscape
* @returns {boolean}
*/
Q_INVOKABLE bool getLandscape() { return _landscape; }
/**jsdoc
* @function TabletProxy#isPathLoaded
* @param {string} path
* @returns {boolean}
*/
Q_INVOKABLE bool isPathLoaded(const QVariant& path);
QQuickItem* getTabletRoot() const { return _qmlTabletRoot; }
@ -268,17 +344,17 @@ public:
signals:
/**jsdoc
* Signaled when this tablet receives an event from the html/js embedded in the tablet
* Signaled when this tablet receives an event from the html/js embedded in the tablet.
* @function TabletProxy#webEventReceived
* @param msg {object|string}
* @param {object|string} message
* @returns {Signal}
*/
void webEventReceived(QVariant msg);
/**jsdoc
* Signaled when this tablet receives an event from the qml embedded in the tablet
* Signaled when this tablet receives an event from the qml embedded in the tablet.
* @function TabletProxy#fromQml
* @param msg {object|string}
* @param {object|string} message
* @returns {Signal}
*/
void fromQml(QVariant msg);
@ -286,18 +362,21 @@ signals:
/**jsdoc
* Signaled when this tablet screen changes.
* @function TabletProxy#screenChanged
* @param type {string} - "Home", "Web", "Menu", "QML", "Closed"
* @param url {string} - only valid for Web and QML.
* @param type {string} - "Home", "Web", "Menu", "QML", "Closed".
* @param url {string} - Only valid for Web and QML.
*/
void screenChanged(QVariant type, QVariant url);
/**jsdoc
* Signaled when the tablet becomes visible or becomes invisible
* @function TabletProxy#isTabletShownChanged
* @returns {Signal}
*/
* Signaled when the tablet becomes visible or becomes invisible.
* @function TabletProxy#isTabletShownChanged
* @returns {Signal}
*/
void tabletShownChanged();
/**jsdoc
* @function TabletProxy#toolbarModeChanged
*/
void toolbarModeChanged();
protected slots:
@ -331,7 +410,8 @@ Q_DECLARE_METATYPE(TabletProxy*);
/**jsdoc
* @class TabletButtonProxy
* @property uuid {QUuid} READ_ONLY: uniquely identifies this button
* @property {Uuid} uuid - Uniquely identifies this button. <em>Read-only.</em>
* @property {TabletButtonProxy.ButtonProperties} properties
*/
class TabletButtonProxy : public QObject {
Q_OBJECT
@ -344,48 +424,55 @@ public:
QUuid getUuid() const { return _uuid; }
/**jsdoc
* Returns the current value of this button's properties
* Returns the current value of this button's properties.
* @function TabletButtonProxy#getProperties
* @returns {ButtonProperties}
* @returns {TabletButtonProxy.ButtonProperties}
*/
Q_INVOKABLE QVariantMap getProperties();
/**jsdoc
* Replace the values of some of this button's properties
* Replace the values of some of this button's properties.
* @function TabletButtonProxy#editProperties
* @param {ButtonProperties} properties - set of properties to change
* @param {TabletButtonProxy.ButtonProperties} properties - Set of properties to change.
*/
Q_INVOKABLE void editProperties(const QVariantMap& properties);
signals:
/**jsdoc
* Signaled when this button has been clicked on by the user.
* Triggered when this button has been clicked on by the user.
* @function TabletButtonProxy#clicked
* @returns {Signal}
*/
void clicked();
/**jsdoc
* @function TabletButtonProxy#propertiesChanged
* @returns {Signal}
*/
void propertiesChanged();
protected:
QUuid _uuid;
int _stableOrder;
/**jsdoc
* @typedef TabletButtonProxy.ButtonProperties
* @property {string} icon - URL to button icon. (50 x 50)
* @property {string} hoverIcon - URL to button icon, displayed during mouse hover. (50 x 50)
* @property {string} activeHoverIcon - URL to button icon used when button is active, and during mouse hover. (50 x 50)
* @property {string} activeIcon - URL to button icon used when button is active. (50 x 50)
* @property {string} text - Button caption.
* @property {string} hoverText - Button caption when button is not-active but during mouse hover.
* @property {string} activeText - Button caption when button is active.
* @property {string} activeHoverText - Button caption when button is active and during mouse hover.
* @property {boolean} isActive - <code>true</code> when button is active.
* @property {number} sortOrder - Determines sort order on tablet. lower numbers will appear before larger numbers.
* Default is 100.
*/
// FIXME: There are additional properties.
QVariantMap _properties;
};
Q_DECLARE_METATYPE(TabletButtonProxy*);
/**jsdoc
* @typedef TabletButtonProxy.ButtonProperties
* @property {string} icon - url to button icon. (50 x 50)
* @property {string} hoverIcon - url to button icon, displayed during mouse hover. (50 x 50)
* @property {string} activeHoverIcon - url to button icon used when button is active, and during mouse hover. (50 x 50)
* @property {string} activeIcon - url to button icon used when button is active. (50 x 50)
* @property {string} text - button caption
* @property {string} hoverText - button caption when button is not-active but during mouse hover.
* @property {string} activeText - button caption when button is active
* @property {string} activeHoverText - button caption when button is active and during mouse hover.
* @property {string} isActive - true when button is active.
* @property {number} sortOrder - determines sort order on tablet. lower numbers will appear before larger numbers. default is 100
*/
#endif // hifi_TabletScriptingInterface_h

View file

@ -23,6 +23,7 @@ exports.handlers = {
'../../interface/src/raypick',
'../../libraries/animation/src',
'../../libraries/avatars/src',
'../../libraries/avatars-renderer/src/avatars-renderer',
'../../libraries/controllers/src/controllers/',
'../../libraries/controllers/src/controllers/impl/',
'../../libraries/display-plugins/src/display-plugins/',
@ -37,6 +38,7 @@ exports.handlers = {
'../../libraries/script-engine/src',
'../../libraries/shared/src',
'../../libraries/shared/src/shared',
'../../libraries/ui/src/ui',
'../../plugins/oculus/src',
'../../plugins/openvr/src',
];