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> #include <DependencyManager.h>
/**jsdoc
* @namespace SpeechRecognizer
*/
class SpeechRecognizer : public QObject, public Dependency { class SpeechRecognizer : public QObject, public Dependency {
Q_OBJECT Q_OBJECT
SINGLETON_DEPENDENCY SINGLETON_DEPENDENCY
@ -31,12 +34,39 @@ public:
bool getEnabled() const { return _enabled; } bool getEnabled() const { return _enabled; }
public slots: public slots:
/**jsdoc
* @function SpeechRecognizer.setEnabled
* @param {boolean} enabled
*/
void setEnabled(bool enabled); void setEnabled(bool enabled);
/**jsdoc
* @function SpeechRecognizer.addCommand
* @param {string} command
*/
void addCommand(const QString& command); void addCommand(const QString& command);
/**jsdoc
* @function SpeechRecognizer.removeCommand
* @param {string} command
*/
void removeCommand(const QString& command); void removeCommand(const QString& command);
signals: signals:
/**jsdoc
* @function SpeechRecognizer.commandRecognized
* @param {string} command
* @returns {Signal}
*/
void commandRecognized(const QString& command); void commandRecognized(const QString& command);
/**jsdoc
* @function SpeechRecognizer.enabledUpdated
* @param {boolean} enabled
* @returns {Signal}
*/
void enabledUpdated(bool enabled); void enabledUpdated(bool enabled);
protected: 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() { 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) { bool SelectionScriptingInterface::addToSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id) {
if (itemType == "avatar") { if (itemType == "avatar") {
return addToGameplayObjects(listName, (QUuid)id); 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 { QVariantMap SelectionScriptingInterface::getSelectedItemsList(const QString& listName) const {
QReadLocker lock(&_selectionListsLock); QReadLocker lock(&_selectionListsLock);
QVariantMap list; QVariantMap list;
@ -461,6 +480,20 @@ bool SelectionHighlightStyle::fromVariantMap(const QVariantMap& properties) {
return true; 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 SelectionHighlightStyle::toVariantMap() const {
QVariantMap properties; QVariantMap properties;

View file

@ -82,6 +82,46 @@ protected:
render::HighlightStyle _style; 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 { class SelectionScriptingInterface : public QObject, public Dependency {
Q_OBJECT Q_OBJECT
@ -89,138 +129,120 @@ public:
SelectionScriptingInterface(); SelectionScriptingInterface();
/**jsdoc /**jsdoc
* Query the names of all the selection lists * Get the names of all the selection lists.
* @function Selection.getListNames * @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; Q_INVOKABLE QStringList getListNames() const;
/**jsdoc /**jsdoc
* Removes a named selection from the list of selections. * Delete a named selection list.
* @function Selection.removeListFromMap * @function Selection.removeListFromMap
* @param listName {string} name of the selection * @param {string} listName - The name of the selection list.
* @returns {bool} true if the selection existed and was successfully removed. * @returns {boolean} <code>true</code> if the selection existed and was successfully removed, otherwise <code>false</code>.
*/ */
Q_INVOKABLE bool removeListFromMap(const QString& listName); Q_INVOKABLE bool removeListFromMap(const QString& listName);
/**jsdoc /**jsdoc
* Add an item in a selection. * Add an item to a selection list.
* @function Selection.addToSelectedItemsList * @function Selection.addToSelectedItemsList
* @param listName {string} name of the selection * @param {string} listName - The name of the selection list to add the item to.
* @param itemType {string} the type of the item (one of "avatar", "entity" or "overlay") * @param {Selection.ItemType} itemType - The type of the item being added.
* @param id {EntityID} the Id of the item to add to the selection * @param {Uuid} id - The ID of the item to add to the selection.
* @returns {bool} true if the item was successfully added. * @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); Q_INVOKABLE bool addToSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id);
/**jsdoc /**jsdoc
* Remove an item from a selection. * Remove an item from a selection list.
* @function Selection.removeFromSelectedItemsList * @function Selection.removeFromSelectedItemsList
* @param listName {string} name of the selection * @param {string} listName - The name of the selection list to remove the item from.
* @param itemType {string} the type of the item (one of "avatar", "entity" or "overlay") * @param {Selection.ItemType} itemType - The type of the item being removed.
* @param id {EntityID} the Id of the item to remove * @param {Uuid} id - The ID of the item to remove.
* @returns {bool} true if the item was successfully removed. * @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); Q_INVOKABLE bool removeFromSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id);
/**jsdoc /**jsdoc
* Remove all items from a selection. * Remove all items from a selection.
* @function Selection.clearSelectedItemsList * @function Selection.clearSelectedItemsList
* @param listName {string} name of the selection * @param {string} listName - The name of the selection list.
* @returns {bool} true if the item was successfully cleared. * @returns {boolean} <code>true</code> if the item was successfully cleared, otherwise <code>false</code>.
*/ */
Q_INVOKABLE bool clearSelectedItemsList(const QString& listName); Q_INVOKABLE bool clearSelectedItemsList(const QString& listName);
/**jsdoc /**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 * @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); Q_INVOKABLE void printList(const QString& listName);
/**jsdoc /**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 * @function Selection.getList
* @param listName {string} name of the selection * @param {string} listName - The name of the selection list.
* @return a js object describing the content of a selection list with the following properties: * @return {Selection.SelectedItemsList} The content of a selection list. If the list name doesn't exist, the function
* - "entities": [ and array of the entityID of the entities in the selection] * returns an empty object with no properties.
* - "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.
*/ */
Q_INVOKABLE QVariantMap getSelectedItemsList(const QString& listName) const; Q_INVOKABLE QVariantMap getSelectedItemsList(const QString& listName) const;
/**jsdoc /**jsdoc
* Query the names of the highlighted selection lists * Get the names of the highlighted selection lists.
* @function Selection.getHighlightedListNames * @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; Q_INVOKABLE QStringList getHighlightedListNames() const;
/**jsdoc /**jsdoc
* Enable highlighting for the named selection. * Enable highlighting for a selection list.
* If the Selection doesn't exist, it will be created. * If the selection list doesn't exist, it will be created.
* All objects in the list will be displayed with the highlight effect as specified from the highlightStyle. * 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. * 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 * @function Selection.enableListHighlight
* @param listName {string} name of the selection * @param {string} listName - The name of the selection list.
* @param highlightStyle {jsObject} highlight style fields (see Selection.getListHighlightStyle for a detailed description of the highlightStyle). * @param {Selection.HighlightStyle} highlightStyle - The highlight style.
* @returns {bool} true if the selection was successfully enabled for highlight. * @returns {boolean} true if the selection was successfully enabled for highlight.
*
* Note: This function will implicitly call Selection.enableListToScene
*/ */
Q_INVOKABLE bool enableListHighlight(const QString& listName, const QVariantMap& highlightStyle); Q_INVOKABLE bool enableListHighlight(const QString& listName, const QVariantMap& highlightStyle);
/**jsdoc /**jsdoc
* Disable highlighting for the named selection. * Disable highlighting for the selection list.
* If the Selection doesn't exist or wasn't enabled for highliting then nothing happens simply returning false. * 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 * @function Selection.disableListHighlight
* @param listName {string} name of the selection * @param {string} listName - The name of the selection list.
* @returns {bool} true if the selection was successfully disabled for highlight, false otherwise. * @returns {boolean} <code>true</code> if the selection was successfully disabled for highlight, otherwise
* * <code>false</code>.
* Note: This function will implicitly call Selection.disableListToScene
*/ */
Q_INVOKABLE bool disableListHighlight(const QString& listName); Q_INVOKABLE bool disableListHighlight(const QString& listName);
/**jsdoc /**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. * If the Selection doesn't exist, it will be created.
* All objects in the list will be sent to a scene selection. * All objects in the list will be sent to a scene selection.
*
* @function Selection.enableListToScene * @function Selection.enableListToScene
* @param listName {string} name of the selection * @param {string} listName - The name of the selection list.
* @returns {bool} true if the selection was successfully enabled on the scene. * @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); Q_INVOKABLE bool enableListToScene(const QString& listName);
/**jsdoc /**jsdoc
* Disable scene selection for the named selection. * 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 * @function Selection.disableListToScene
* @param listName {string} name of the selection * @param {string} listName - The name of the selection list.
* @returns {bool} true if the selection was successfully disabled on the scene, false otherwise. * @returns {boolean} true if the selection was successfully disabled on the scene, false otherwise.
*/ */
Q_INVOKABLE bool disableListToScene(const QString& listName); Q_INVOKABLE bool disableListToScene(const QString& listName);
/**jsdoc /**jsdoc
* Query the highlight style values for the named selection. * Get the highlight style values for the a selection list.
* If the Selection doesn't exist or hasn't been highlight enabled yet, it will return an empty object. * If the selection doesn't exist or hasn't been highlight enabled yet, an empty object is returned.
* 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
*
* @function Selection.getListHighlightStyle * @function Selection.getListHighlightStyle
* @param listName {string} name of the selection * @param {string} listName - The name of the selection list.
* @returns {jsObject} highlight style as described above * @returns {Selection.HighlightStyle} highlight style
*/ */
Q_INVOKABLE QVariantMap getListHighlightStyle(const QString& listName) const; Q_INVOKABLE QVariantMap getListHighlightStyle(const QString& listName) const;
@ -232,6 +254,12 @@ public:
void onSelectedItemsListChanged(const QString& listName); void onSelectedItemsListChanged(const QString& listName);
signals: 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); void selectedItemsListChanged(const QString& listName);
private: private:

View file

@ -57,15 +57,7 @@ using AvatarPhysicsCallback = std::function<void(uint32_t)>;
class Avatar : public AvatarData, public scriptable::ModelProvider { class Avatar : public AvatarData, public scriptable::ModelProvider {
Q_OBJECT Q_OBJECT
/**jsdoc // This property has JSDoc in MyAvatar.h.
* 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.
*/
Q_PROPERTY(glm::vec3 skeletonOffset READ getSkeletonOffset WRITE setSkeletonOffset) Q_PROPERTY(glm::vec3 skeletonOffset READ getSkeletonOffset WRITE setSkeletonOffset)
public: public:
@ -128,14 +120,25 @@ public:
virtual int getJointIndex(const QString& name) const override; virtual int getJointIndex(const QString& name) const override;
virtual QStringList getJointNames() 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; 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; Q_INVOKABLE virtual glm::vec3 getDefaultJointTranslation(int index) const;
/**jsdoc /**jsdoc
* Provides read only access to the default joint rotations in avatar coordinates. * 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 * 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. * in the avatar's model file. Typically this is a T-pose.
* @function Avatar.getAbsoluteDefaultJointRotationInObjectFrame * @function MyAvatar.getAbsoluteDefaultJointRotationInObjectFrame
* @param index {number} index number * @param index {number} index number
* @returns {Quat} The rotation of this joint in avatar coordinates. * @returns {Quat} The rotation of this joint in avatar coordinates.
*/ */
@ -144,8 +147,8 @@ public:
/**jsdoc /**jsdoc
* Provides read only access to the default joint translations in avatar coordinates. * 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 * 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. * in the avatar's model file. Typically this is a T-pose.
* @function Avatar.getAbsoluteDefaultJointTranslationInObjectFrame * @function MyAvatar.getAbsoluteDefaultJointTranslationInObjectFrame
* @param index {number} index number * @param index {number} index number
* @returns {Vec3} The position of this joint in avatar coordinates. * @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) { } 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); 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; } Q_INVOKABLE glm::vec3 getSkeletonOffset() { return _skeletonOffset; }
virtual glm::vec3 getSkeletonPosition() const; 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; 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; 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; Q_INVOKABLE glm::vec3 getNeckPosition() const;
/**jsdoc
* @function MyAvatar.getAcceleration
* @returns {Vec3}
*/
Q_INVOKABLE glm::vec3 getAcceleration() const { return _acceleration; } Q_INVOKABLE glm::vec3 getAcceleration() const { return _acceleration; }
/// Scales a world space position vector relative to the avatar position and scale /// 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 setPositionViaScript(const glm::vec3& position) override;
void setOrientationViaScript(const glm::quat& orientation) 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(); } 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; 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(); } 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; 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 /**jsdoc
* Returns an array of joints, where each joint is an object containing name, index and parentIndex fields. * Returns an array of joints, where each joint is an object containing name, index, and parentIndex fields.
* @function Avatar.getSkeleton * @function MyAvatar.getSkeleton
* @returns {Avatar.SkeletonJoint[]} returns a list of information about each joint in this avatar's skeleton. * @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(); Q_INVOKABLE QList<QVariant> getSkeleton();
@ -235,6 +312,11 @@ public:
void setTargetScale(float targetScale) override; void setTargetScale(float targetScale) override;
float getTargetScale() const { return _targetScale; } float getTargetScale() const { return _targetScale; }
/**jsdoc
* @function MyAvatar.getSimulationRate
* @param {string} [rateName=""]
* @returns {number}
*/
Q_INVOKABLE float getSimulationRate(const QString& rateName = QString("")) const; Q_INVOKABLE float getSimulationRate(const QString& rateName = QString("")) const;
bool hasNewJointData() const { return _hasNewJointData; } bool hasNewJointData() const { return _hasNewJointData; }
@ -256,6 +338,7 @@ public:
bool isFading() const { return _isFading; } bool isFading() const { return _isFading; }
void updateFadingStatus(render::ScenePointer scene); void updateFadingStatus(render::ScenePointer scene);
// JSDoc is in AvatarData.h.
Q_INVOKABLE virtual float getEyeHeight() const override; Q_INVOKABLE virtual float getEyeHeight() const override;
// returns eye height of avatar in meters, ignoring avatar scale. // 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 // FIXME - these should be migrated to use Pose data instead
// thread safe, will return last valid palm from cache // 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; 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; 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; 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; glm::quat getRightPalmRotation() const;
// hooked up to Model::setURLFinished signal // hooked up to Model::setURLFinished signal
void setModelURLFinished(bool success); 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(); void rigReady();
/**jsdoc
* @function MyAvatar.rigReset
* @returns {Signal}
*/
// Jooked up to Model::rigReset signal
void rigReset(); void rigReset();
protected: protected:

View file

@ -2362,6 +2362,15 @@ glm::vec3 AvatarData::getAbsoluteJointTranslationInObjectFrame(int index) const
return glm::vec3(); 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 { QVariant AttachmentData::toVariant() const {
QVariantMap result; QVariantMap result;
result["modelUrl"] = modelURL; result["modelUrl"] = modelURL;

View file

@ -353,6 +353,7 @@ public:
class AvatarData : public QObject, public SpatiallyNestable { class AvatarData : public QObject, public SpatiallyNestable {
Q_OBJECT Q_OBJECT
// The following properties have JSDoc in MyAvatar.h.
Q_PROPERTY(glm::vec3 position READ getWorldPosition WRITE setPositionViaScript) Q_PROPERTY(glm::vec3 position READ getWorldPosition WRITE setPositionViaScript)
Q_PROPERTY(float scale READ getTargetScale WRITE setTargetScale) Q_PROPERTY(float scale READ getTargetScale WRITE setTargetScale)
Q_PROPERTY(float density READ getDensity) Q_PROPERTY(float density READ getDensity)
@ -505,7 +506,7 @@ public:
/**jsdoc /**jsdoc
* returns the minimum scale allowed for this avatar in the current domain. * 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. * 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. * @returns {number} minimum scale allowed for this avatar in the current domain.
*/ */
Q_INVOKABLE float getDomainMinScale() const; Q_INVOKABLE float getDomainMinScale() const;
@ -513,7 +514,7 @@ public:
/**jsdoc /**jsdoc
* returns the maximum scale allowed for this avatar in the current domain. * 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. * 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. * @returns {number} maximum scale allowed for this avatar in the current domain.
*/ */
Q_INVOKABLE float getDomainMaxScale() const; Q_INVOKABLE float getDomainMaxScale() const;
@ -529,16 +530,16 @@ public:
/**jsdoc /**jsdoc
* Provides read only access to the current eye height of the avatar. * 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. * This height is only an estimate and might be incorrect for avatars that are missing standard joints.
* @function AvatarData.getEyeHeight * @function MyAvatar.getEyeHeight
* @returns {number} eye height of avatar in meters * @returns {number} Eye height of avatar in meters.
*/ */
Q_INVOKABLE virtual float getEyeHeight() const { return _targetScale * getUnscaledEyeHeight(); } Q_INVOKABLE virtual float getEyeHeight() const { return _targetScale * getUnscaledEyeHeight(); }
/**jsdoc /**jsdoc
* Provides read only access to the current height of the avatar. * 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. * This height is only an estimate and might be incorrect for avatars that are missing standard joints.
* @function AvatarData.getHeight * @function MyAvatar.getHeight
* @returns {number} height of avatar in meters * @returns {number} Height of avatar in meters.
*/ */
Q_INVOKABLE virtual float getHeight() const; Q_INVOKABLE virtual float getHeight() const;
@ -547,49 +548,372 @@ public:
void setDomainMinimumHeight(float domainMinimumHeight); void setDomainMinimumHeight(float domainMinimumHeight);
void setDomainMaximumHeight(float domainMaximumHeight); void setDomainMaximumHeight(float domainMaximumHeight);
// Hand State /**jsdoc
* @function MyAvatar.setHandState
* @param {string} state
*/
Q_INVOKABLE void setHandState(char s) { _handState = s; } Q_INVOKABLE void setHandState(char s) { _handState = s; }
/**jsdoc
* @function MyAvatar.getHandState
* @returns {string}
*/
Q_INVOKABLE char getHandState() const { return _handState; } Q_INVOKABLE char getHandState() const { return _handState; }
const QVector<JointData>& getRawJointData() const { return _jointData; } const QVector<JointData>& getRawJointData() const { return _jointData; }
/**jsdoc
* @function MyAvatar.setRawJointData
* @param {JointData[]} data
*/
Q_INVOKABLE void setRawJointData(QVector<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); 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); 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); 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); Q_INVOKABLE virtual void clearJointData(int index);
/**jsdoc
* @function MyAvatar.isJointDataValid
* @param {number} index
* @returns {boolean}
*/
Q_INVOKABLE bool isJointDataValid(int index) const; 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; 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; 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); 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); 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); 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); 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; 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; 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; 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; Q_INVOKABLE virtual QVector<glm::quat> getJointRotations() const;
/**jsdoc
* @function MyAvatar.getJointTranslations
* @returns {Vec3[]}
*/
Q_INVOKABLE virtual QVector<glm::vec3> getJointTranslations() const; 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); 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); 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(); 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. /// 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; 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; 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); } 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; 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); 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); Q_INVOKABLE void updateAvatarEntity(const QUuid& entityID, const QByteArray& entityData);
/**jsdoc
* @function MyAvatar.clearAvatarEntity
* @param {Uuid} entityID
*/
Q_INVOKABLE void clearAvatarEntity(const QUuid& entityID); Q_INVOKABLE void clearAvatarEntity(const QUuid& entityID);
/**jsdoc
* @function MyAvatar.setForceFaceTrackerConnected
* @param {boolean} connected
*/
Q_INVOKABLE void setForceFaceTrackerConnected(bool connected) { _forceFaceTrackerConnected = connected; } Q_INVOKABLE void setForceFaceTrackerConnected(bool connected) { _forceFaceTrackerConnected = connected; }
// key state // key state
@ -627,15 +951,96 @@ public:
markIdentityDataChanged(); 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; 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); 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(), Q_INVOKABLE virtual void attach(const QString& modelURL, const QString& jointName = QString(),
const glm::vec3& translation = glm::vec3(), const glm::quat& rotation = glm::quat(), const glm::vec3& translation = glm::vec3(), const glm::quat& rotation = glm::quat(),
float scale = 1.0f, bool isSoft = false, float scale = 1.0f, bool isSoft = false,
bool allowDuplicates = false, bool useSaved = true); 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()); 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()); Q_INVOKABLE void detachAll(const QString& modelURL, const QString& jointName = QString());
QString getSkeletonModelURLFromScript() const { return _skeletonModelURL.toString(); } QString getSkeletonModelURLFromScript() const { return _skeletonModelURL.toString(); }
@ -657,19 +1062,63 @@ public:
glm::vec3 getClientGlobalPosition() const { return _globalPosition; } glm::vec3 getClientGlobalPosition() const { return _globalPosition; }
glm::vec3 getGlobalBoundingBoxCorner() const { return _globalPosition + _globalBoundingBoxOffset - _globalBoundingBoxDimensions; } glm::vec3 getGlobalBoundingBoxCorner() const { return _globalPosition + _globalBoundingBoxOffset - _globalBoundingBoxDimensions; }
/**jsdoc
* @function MyAvatar.getAvatarEntityData
* @returns {object}
*/
Q_INVOKABLE AvatarEntityMap getAvatarEntityData() const; Q_INVOKABLE AvatarEntityMap getAvatarEntityData() const;
/**jsdoc
* @function MyAvatar.setAvatarEntityData
* @param {object} avatarEntityData
*/
Q_INVOKABLE void setAvatarEntityData(const AvatarEntityMap& avatarEntityData); Q_INVOKABLE void setAvatarEntityData(const AvatarEntityMap& avatarEntityData);
virtual void setAvatarEntityDataChanged(bool value) { _avatarEntityDataChanged = value; } virtual void setAvatarEntityDataChanged(bool value) { _avatarEntityDataChanged = value; }
void insertDetachedEntityID(const QUuid entityID); void insertDetachedEntityID(const QUuid entityID);
AvatarEntityIDs getAndClearRecentlyDetachedIDs(); AvatarEntityIDs getAndClearRecentlyDetachedIDs();
/**jsdoc
* @function MyAvatar.getSensorToWorldMatrix
* @returns {Mat4}
*/
// thread safe // thread safe
Q_INVOKABLE glm::mat4 getSensorToWorldMatrix() const; Q_INVOKABLE glm::mat4 getSensorToWorldMatrix() const;
/**jsdoc
* @function MyAvatar.getSensorToWorldScale
* @returns {number}
*/
// thread safe
Q_INVOKABLE float getSensorToWorldScale() const; Q_INVOKABLE float getSensorToWorldScale() const;
/**jsdoc
* @function MyAvatar.getControllerLeftHandMatrix
* @returns {Mat4}
*/
// thread safe
Q_INVOKABLE glm::mat4 getControllerLeftHandMatrix() const; Q_INVOKABLE glm::mat4 getControllerLeftHandMatrix() const;
/**jsdoc
* @function MyAvatar.getControllerRightHandMatrix
* @returns {Mat4}
*/
// thread safe
Q_INVOKABLE glm::mat4 getControllerRightHandMatrix() const; Q_INVOKABLE glm::mat4 getControllerRightHandMatrix() const;
/**jsdoc
* @function MyAvatar.getDataRate
* @param {string} [rateName=""]
* @returns {number}
*/
Q_INVOKABLE float getDataRate(const QString& rateName = QString("")) const; 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; Q_INVOKABLE float getUpdateRate(const QString& rateName = QString("")) const;
int getJointCount() const { return _jointData.size(); } int getJointCount() const { return _jointData.size(); }
@ -705,17 +1154,60 @@ public:
virtual void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) {} virtual void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) {}
signals: signals:
/**jsdoc
* @function MyAvatar.displayNameChanged
* @returns {Signal}
*/
void displayNameChanged(); void displayNameChanged();
/**jsdoc
* @function MyAvatar.sessionDisplayNameChanged
* @returns {Signal}
*/
void sessionDisplayNameChanged(); void sessionDisplayNameChanged();
/**jsdoc
* @function MyAvatar.skeletonModelURLChanged
* @returns {Signal}
*/
void skeletonModelURLChanged(); void skeletonModelURLChanged();
/**jsdoc
* @function MyAvatar.lookAtSnappingChanged
* @param {boolean} enabled
* @returns {Signal}
*/
void lookAtSnappingChanged(bool enabled); void lookAtSnappingChanged(bool enabled);
/**jsdoc
* @function MyAvatar.sessionUUIDChanged
* @returns {Signal}
*/
void sessionUUIDChanged(); void sessionUUIDChanged();
public slots: public slots:
/**jsdoc
* @function MyAvatar.sendAvatarDataPacket
* @param {boolean} [sendAll=false]
*/
void sendAvatarDataPacket(bool sendAll = false); void sendAvatarDataPacket(bool sendAll = false);
/**jsdoc
* @function MyAvatar.sendIdentityPacket
*/
void sendIdentityPacket(); void sendIdentityPacket();
/**jsdoc
* @function MyAvatar.setJointMappingsFromNetworkReply
*/
void setJointMappingsFromNetworkReply(); void setJointMappingsFromNetworkReply();
/**jsdoc
* @function MyAvatar.setSessionUUID
* @param {Uuid} sessionUUID
*/
virtual void setSessionUUID(const QUuid& sessionUUID) { virtual void setSessionUUID(const QUuid& sessionUUID) {
if (sessionUUID != getID()) { if (sessionUUID != getID()) {
if (sessionUUID == QUuid()) { 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; 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; 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; } 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; } 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? float getTargetScale() const { return _targetScale; } // why is this a slot?
/**jsdoc
* @function MyAvatar.resetLastSent
*/
void resetLastSent() { _lastToByteArray = 0; } void resetLastSent() { _lastToByteArray = 0; }
protected: protected:

View file

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

View file

@ -23,6 +23,9 @@
class QScriptEngine; class QScriptEngine;
class QScriptValue; class QScriptValue;
/**jsdoc
* @namespace Recording
*/
class RecordingScriptingInterface : public QObject, public Dependency { class RecordingScriptingInterface : public QObject, public Dependency {
Q_OBJECT Q_OBJECT
@ -32,43 +35,196 @@ public:
void setScriptEngine(QSharedPointer<BaseScriptEngine> scriptEngine) { _scriptEngine = scriptEngine; } void setScriptEngine(QSharedPointer<BaseScriptEngine> scriptEngine) { _scriptEngine = scriptEngine; }
public slots: 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()); void loadRecording(const QString& url, QScriptValue callback = QScriptValue());
/**jsdoc
* @function Recording.startPlaying
*/
void startPlaying(); void startPlaying();
/**jsdoc
* @function Recording.pausePlayer
*/
void pausePlayer(); void pausePlayer();
/**jsdoc
* @function Recording.stopPlaying
*/
void stopPlaying(); void stopPlaying();
/**jsdoc
* @function Recording.isPlaying
* @returns {boolean}
*/
bool isPlaying() const; bool isPlaying() const;
/**jsdoc
* @function Recording.isPaused
* @returns {boolean}
*/
bool isPaused() const; bool isPaused() const;
/**jsdoc
* @function Recording.playerElapsed
* @returns {number}
*/
float playerElapsed() const; float playerElapsed() const;
/**jsdoc
* @function Recording.playerLength
* @returns {number}
*/
float playerLength() const; float playerLength() const;
/**jsdoc
* @function Recording.setPlayerVolume
* @param {number} volume
*/
void setPlayerVolume(float volume); void setPlayerVolume(float volume);
/**jsdoc
* @function Recording.setPlayerAudioOffset
* @param {number} audioOffset
*/
void setPlayerAudioOffset(float audioOffset); void setPlayerAudioOffset(float audioOffset);
/**jsdoc
* @function Recording.setPlayerTime
* @param {number} time
*/
void setPlayerTime(float time); void setPlayerTime(float time);
/**jsdoc
* @function Recording.setPlayerLoop
* @param {boolean} loop
*/
void setPlayerLoop(bool loop); void setPlayerLoop(bool loop);
/**jsdoc
* @function Recording.setPlayerUseDisplayName
* @param {boolean} useDisplayName
*/
void setPlayerUseDisplayName(bool useDisplayName); void setPlayerUseDisplayName(bool useDisplayName);
/**jsdoc
* @function Recording.setPlayerUseAttachments
* @param {boolean} useAttachments
*/
void setPlayerUseAttachments(bool 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); 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); void setPlayerUseSkeletonModel(bool useSkeletonModel);
/**jsdoc
* @function Recording.setPlayFromCurrentLocation
* @param {boolean} playFromCurrentLocation
*/
void setPlayFromCurrentLocation(bool playFromCurrentLocation); void setPlayFromCurrentLocation(bool playFromCurrentLocation);
/**jsdoc
* @function Recording.getPlayerUseDisplayName
* @returns {boolean}
*/
bool getPlayerUseDisplayName() { return _useDisplayName; } bool getPlayerUseDisplayName() { return _useDisplayName; }
/**jsdoc
* @function Recording.getPlayerUseAttachments
* @returns {boolean}
*/
bool getPlayerUseAttachments() { return _useAttachments; } bool getPlayerUseAttachments() { return _useAttachments; }
/**jsdoc
* @function Recording.getPlayerUseHeadModel
* @returns {boolean}
*/
bool getPlayerUseHeadModel() { return _useHeadModel; } bool getPlayerUseHeadModel() { return _useHeadModel; }
/**jsdoc
* @function Recording.getPlayerUseSkeletonModel
* @returns {boolean}
*/
bool getPlayerUseSkeletonModel() { return _useSkeletonModel; } bool getPlayerUseSkeletonModel() { return _useSkeletonModel; }
/**jsdoc
* @function Recording.getPlayFromCurrentLocation
* @returns {boolean}
*/
bool getPlayFromCurrentLocation() { return _playFromCurrentLocation; } bool getPlayFromCurrentLocation() { return _playFromCurrentLocation; }
/**jsdoc
* @function Recording.startRecording
*/
void startRecording(); void startRecording();
/**jsdoc
* @function Recording.stopRecording
*/
void stopRecording(); void stopRecording();
/**jsdoc
* @function Recording.isRecording
* @returns {boolean}
*/
bool isRecording() const; bool isRecording() const;
/**jsdoc
* @function Recording.recorderElapsed
* @returns {number}
*/
float recorderElapsed() const; float recorderElapsed() const;
/**jsdoc
* @function Recording.getDefaultRecordingSaveDirectory
* @returns {string}
*/
QString getDefaultRecordingSaveDirectory(); QString getDefaultRecordingSaveDirectory();
/**jsdoc
* @function Recording.saveRecording
* @param {string} filename
*/
void saveRecording(const QString& filename); void saveRecording(const QString& filename);
/**jsdoc
* @function Recording.saveRecordingToAsset
* @param {function} getClipAtpUrl
*/
bool saveRecordingToAsset(QScriptValue getClipAtpUrl); bool saveRecordingToAsset(QScriptValue getClipAtpUrl);
/**jsdoc
* @function Recording.loadLastRecording
*/
void loadLastRecording(); void loadLastRecording();
protected: protected:

View file

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

View file

@ -87,6 +87,10 @@ public:
QUrl definingSandboxURL { QUrl("about:EntityScript") }; QUrl definingSandboxURL { QUrl("about:EntityScript") };
}; };
/**jsdoc
* @namespace Script
* @property {string} context
*/
class ScriptEngine : public BaseScriptEngine, public EntitiesScriptEngineProvider { class ScriptEngine : public BaseScriptEngine, public EntitiesScriptEngineProvider {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QString context READ getContext) Q_PROPERTY(QString context READ getContext)
@ -115,6 +119,11 @@ public:
QString getFilename() const; 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 // 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); 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 // 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 // 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 /// registers a global object by name
Q_INVOKABLE void registerGlobalObject(const QString& name, QObject* object); 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 /// registers a global getter/setter
Q_INVOKABLE void registerGetterSetter(const QString& name, QScriptEngine::FunctionSignature getter, Q_INVOKABLE void registerGetterSetter(const QString& name, QScriptEngine::FunctionSignature getter,
QScriptEngine::FunctionSignature setter, const QString& parent = QString("")); 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 /// register a global function
Q_INVOKABLE void registerFunction(const QString& name, QScriptEngine::FunctionSignature fun, int numArguments = -1); 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 /// 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, Q_INVOKABLE void registerFunction(const QString& parent, const QString& name, QScriptEngine::FunctionSignature fun,
int numArguments = -1); int numArguments = -1);
/**jsdoc
* @function Script.registerValue
* @param {string} name
* @param {object} value
*/
/// registers a global object by name /// registers a global object by name
Q_INVOKABLE void registerValue(const QString& valueName, QScriptValue value); 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 /// 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 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); 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 /// 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); void loadURL(const QUrl& scriptURL, bool reload);
bool hasValidScriptSuffix(const QString& scriptFileName); bool hasValidScriptSuffix(const QString& scriptFileName);
/**jsdoc
* @function Script.getContext
* @returns {string}
*/
Q_INVOKABLE QString getContext() const; Q_INVOKABLE QString getContext() const;
/**jsdoc
* @function Script.isClientScript
* @returns {boolean}
*/
Q_INVOKABLE bool isClientScript() const { return _context == CLIENT_SCRIPT; } 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; } 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; } 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; } Q_INVOKABLE bool isAgentScript() const { return _context == AGENT_SCRIPT; }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// NOTE - these are intended to be public interfaces available to scripts // 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); 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); 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); 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()); 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()); Q_INVOKABLE void include(const QString& includeFile, QScriptValue callback = QScriptValue());
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// MODULE related methods // MODULE related methods
/**jsdoc
* @function Script.require
* @param {string} module
*/
Q_INVOKABLE QScriptValue require(const QString& moduleId); Q_INVOKABLE QScriptValue require(const QString& moduleId);
/**jsdoc
* @function Script.resetModuleCache
* @param {boolean} [deleteScriptCache=false]
*/
Q_INVOKABLE void resetModuleCache(bool deleteScriptCache = false); Q_INVOKABLE void resetModuleCache(bool deleteScriptCache = false);
QScriptValue currentModule(); QScriptValue currentModule();
bool registerModuleWithParent(const QScriptValue& module, const QScriptValue& parent); bool registerModuleWithParent(const QScriptValue& module, const QScriptValue& parent);
@ -179,34 +329,168 @@ public:
QVariantMap fetchModuleSource(const QString& modulePath, const bool forceDownload = false); QVariantMap fetchModuleSource(const QString& modulePath, const bool forceDownload = false);
QScriptValue instantiateModule(const QScriptValue& module, const QString& sourceCode); 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); 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); 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)); } 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)); } 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); 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; Q_INVOKABLE QUrl resolvePath(const QString& path) const;
/**jsdoc
* @function Script.resourcesPath
* @returns {string}
*/
Q_INVOKABLE QUrl resourcesPath() const; Q_INVOKABLE QUrl resourcesPath() const;
/**jsdoc
* @function Script.beginProfileRange
* @param {string} label
*/
Q_INVOKABLE void beginProfileRange(const QString& label) const; Q_INVOKABLE void beginProfileRange(const QString& label) const;
/**jsdoc
* @function Script.endProfileRange
* @param {string} label
*/
Q_INVOKABLE void endProfileRange(const QString& label) const; Q_INVOKABLE void endProfileRange(const QString& label) const;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Entity Script Related methods // Entity Script Related methods
/**jsdoc
* @function Script.isEntityScriptRunning
* @param {Uuid} entityID
* @returns {boolean}
*/
Q_INVOKABLE bool isEntityScriptRunning(const EntityItemID& entityID) { Q_INVOKABLE bool isEntityScriptRunning(const EntityItemID& entityID) {
return _entityScripts.contains(entityID) && _entityScripts[entityID].status == EntityScriptStatus::RUNNING; return _entityScripts.contains(entityID) && _entityScripts[entityID].status == EntityScriptStatus::RUNNING;
} }
QVariant cloneEntityScriptDetails(const EntityItemID& entityID); QVariant cloneEntityScriptDetails(const EntityItemID& entityID);
QFuture<QVariant> getLocalEntityScriptDetails(const EntityItemID& entityID) override; 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); 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 Q_INVOKABLE void unloadEntityScript(const EntityItemID& entityID, bool shouldRemoveFromMap = false); // will call unload method
/**jsdoc
* @function Script.unloadAllEntityScripts
*/
Q_INVOKABLE void 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, Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName,
const QStringList& params = QStringList(), const QStringList& params = QStringList(),
const QUuid& remoteCallerID = QUuid()) override; 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); 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); 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(); } Q_INVOKABLE void requestGarbageCollection() { collectGarbage(); }
/**jsdoc
* @function Script.generateUUID
* @returns {Uuid}
*/
Q_INVOKABLE QUuid generateUUID() { return QUuid::createUuid(); } Q_INVOKABLE QUuid generateUUID() { return QUuid::createUuid(); }
bool isFinished() const { return _isFinished; } // used by Application and ScriptWidget bool isFinished() const { return _isFinished; } // used by Application and ScriptWidget
@ -239,33 +523,170 @@ public:
bool getEntityScriptDetails(const EntityItemID& entityID, EntityScriptDetails &details) const; bool getEntityScriptDetails(const EntityItemID& entityID, EntityScriptDetails &details) const;
public slots: 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); void callAnimationStateHandler(QScriptValue callback, AnimVariantMap parameters, QStringList names, bool useNames, AnimVariantResultHandler resultHandler);
/**jsdoc
* @function Script.updateMemoryCost
* @param {number} deltaSize
*/
void updateMemoryCost(const qint64&); void updateMemoryCost(const qint64&);
signals: signals:
/**jsdoc
* @function Script.scriptLoaded
* @param {string} filename
* @returns {Signal}
*/
void scriptLoaded(const QString& scriptFilename); void scriptLoaded(const QString& scriptFilename);
/**jsdoc
* @function Script.errorLoadingScript
* @param {string} filename
* @returns {Signal}
*/
void errorLoadingScript(const QString& scriptFilename); 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); 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(); void scriptEnding();
/**jsdoc
* @function Script.finished
* @param {string} filename
* @param {object} engine
* @returns {Signal}
*/
void finished(const QString& fileNameString, ScriptEnginePointer); void finished(const QString& fileNameString, ScriptEnginePointer);
/**jsdoc
* @function Script.cleanupMenuItem
* @param {string} menuItem
* @returns {Signal}
*/
void cleanupMenuItem(const QString& menuItemString); 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); 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); 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); 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); void infoMessage(const QString& message, const QString& scriptName);
/**jsdoc
* @function Script.runningStateChanged
* @returns {Signal}
*/
void runningStateChanged(); void runningStateChanged();
/**jsdoc
* @function Script.clearDebugWindow
* @returns {Signal}
*/
void clearDebugWindow(); void clearDebugWindow();
/**jsdoc
* @function Script.loadScript
* @param {string} scriptName
* @param {boolean} isUserLoaded
* @returns {Signal}
*/
void loadScript(const QString& scriptName, bool isUserLoaded); 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); void reloadScript(const QString& scriptName, bool isUserLoaded);
/**jsdoc
* @function Script.doneRunning
* @returns {Signal}
*/
void doneRunning(); void doneRunning();
/**jsdoc
* @function Script.entityScriptDetailsUpdated
* @returns {Signal}
*/
// Emitted when an entity script is added or removed, or when the status of an entity // 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) // script is updated (goes from RUNNING to ERROR_RUNNING_SCRIPT, for example)
void entityScriptDetailsUpdated(); void entityScriptDetailsUpdated();
protected: protected:
void init(); 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 ); 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; // 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;" // 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()); Q_INVOKABLE QString _requireResolve(const QString& moduleId, const QString& relativeTo = QString());
@ -285,6 +706,16 @@ protected:
QHash<EntityItemID, RegisteredEventHandlers> _registeredHandlers; QHash<EntityItemID, RegisteredEventHandlers> _registeredHandlers;
void forwardHandlerCall(const EntityItemID& entityID, const QString& eventName, QScriptValueList eventHanderArgs); 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); 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. 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; class ScriptEngine;
/**jsdoc
* @namespace ScriptDiscoveryService
* @property {string} debugScriptUrl
* @property {string} defaultScriptsPath
* @property {ScriptsModel} scriptsModel
* @property {ScriptsModelFilter} scriptsModelFilter
*/
class NativeScriptInitializers : public ScriptInitializerMixin { class NativeScriptInitializers : public ScriptInitializerMixin {
public: public:
bool registerNativeScriptInitializer(NativeScriptInitializer initializer) override; bool registerNativeScriptInitializer(NativeScriptInitializer initializer) override;
@ -63,18 +71,64 @@ public:
QString getDefaultScriptsLocation() const; QString getDefaultScriptsLocation() const;
/**jsdoc
* @function ScriptDiscoveryService.loadOneScript
* @param {string} filename
*/
Q_INVOKABLE void loadOneScript(const QString& scriptFilename); 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(), Q_INVOKABLE ScriptEnginePointer loadScript(const QUrl& scriptFilename = QString(),
bool isUserLoaded = true, bool loadScriptFromEditor = false, bool activateMainWindow = false, bool reload = false); 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); Q_INVOKABLE bool stopScript(const QString& scriptHash, bool restart = false);
/**jsdoc
* @function ScriptDiscoveryService.reloadAllScripts
*/
Q_INVOKABLE void reloadAllScripts(); Q_INVOKABLE void reloadAllScripts();
/**jsdoc
* @function ScriptDiscoveryService.stopAllScripts
* @param {boolean} [restart=false]
*/
Q_INVOKABLE void stopAllScripts(bool restart = false); Q_INVOKABLE void stopAllScripts(bool restart = false);
/**jsdoc
* @function ScriptDiscoveryService.getRunning
* @returns {object[]}
*/
Q_INVOKABLE QVariantList getRunning(); Q_INVOKABLE QVariantList getRunning();
/**jsdoc
* @function ScriptDiscoveryService.getPublic
* @returns {object[]}
*/
Q_INVOKABLE QVariantList getPublic(); Q_INVOKABLE QVariantList getPublic();
/**jsdoc
* @function ScriptDiscoveryService.getLocal
* @returns {object[]}
*/
Q_INVOKABLE QVariantList getLocal(); Q_INVOKABLE QVariantList getLocal();
// FIXME: Move to other Q_PROPERTY declarations.
Q_PROPERTY(QString defaultScriptsPath READ getDefaultScriptsLocation) Q_PROPERTY(QString defaultScriptsPath READ getDefaultScriptsLocation)
void defaultScriptsLocationOverridden(bool overridden) { _defaultScriptsLocationOverridden = overridden; }; void defaultScriptsLocationOverridden(bool overridden) { _defaultScriptsLocationOverridden = overridden; };
@ -86,25 +140,120 @@ public:
void addScriptEngine(ScriptEnginePointer); void addScriptEngine(ScriptEnginePointer);
signals: signals:
/**jsdoc
* @function ScriptDiscoveryService.scriptCountChanged
* @returns {Signal}
*/
void scriptCountChanged(); void scriptCountChanged();
/**jsdoc
* @function ScriptDiscoveryService.scriptsReloading
* @returns {Signal}
*/
void scriptsReloading(); void scriptsReloading();
/**jsdoc
* @function ScriptDiscoveryService.scriptLoadError
* @param {string} filename
* @param {string} error
* @returns {Signal}
*/
void scriptLoadError(const QString& filename, const QString& error); 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); 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); 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); 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); void infoMessage(const QString& message, const QString& engineName);
/**jsdoc
* @function ScriptDiscoveryService.errorLoadingScript
* @param {string} url
* @returns {Signal}
*/
void errorLoadingScript(const QString& url); void errorLoadingScript(const QString& url);
/**jsdoc
* @function ScriptDiscoveryService.clearDebugWindow
* @returns {Signal}
*/
void clearDebugWindow(); void clearDebugWindow();
public slots: public slots:
/**jsdoc
* @function ScriptDiscoveryService.onPrintedMessage
* @param {string} message
* @param {string} scriptName
*/
void onPrintedMessage(const QString& message, const QString& 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); 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); 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); void onInfoMessage(const QString& message, const QString& scriptName);
/**jsdoc
* @function ScriptDiscoveryService.onErrorLoadingScript
* @param {string} url
*/
void onErrorLoadingScript(const QString& url); void onErrorLoadingScript(const QString& url);
/**jsdoc
* @function ScriptDiscoveryService.onClearDebugWindow
*/
void onClearDebugWindow(); void onClearDebugWindow();
protected slots: protected slots:
/**jsdoc
* @function ScriptDiscoveryService.onScriptFinished
* @param {string} filename
* @param {object} engine
*/
void onScriptFinished(const QString& fileNameString, ScriptEnginePointer engine); void onScriptFinished(const QString& fileNameString, ScriptEnginePointer engine);
protected: protected:

View file

@ -63,17 +63,68 @@ public:
TreeNodeFolder(const QString& foldername, TreeNodeFolder* parent); 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 { class ScriptsModel : public QAbstractItemModel {
Q_OBJECT Q_OBJECT
public: public:
ScriptsModel(QObject* parent = NULL); ScriptsModel(QObject* parent = NULL);
~ScriptsModel(); ~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; 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; 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; 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; 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; int columnCount(const QModelIndex& parent = QModelIndex()) const override;
/**jsdoc
* @function ScriptsModel.getTreeNodeFromIndex
* @param {QmodelIndex} index
* @returns {TreeNodeBase}
*/
TreeNodeBase* getTreeNodeFromIndex(const QModelIndex& index) const; TreeNodeBase* getTreeNodeFromIndex(const QModelIndex& index) const;
/**jsdoc
* @function ScriptsModel.getFolderNodes
* @param {TreeNodeFolder} parent
* @returns {TreeNodeBase[]}
*/
QList<TreeNodeBase*> getFolderNodes(TreeNodeFolder* parent) const; QList<TreeNodeBase*> getFolderNodes(TreeNodeFolder* parent) const;
enum Role { enum Role {

View file

@ -15,6 +15,12 @@
#include "ScriptsModel.h" #include "ScriptsModel.h"
#include <QSortFilterProxyModel> #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 { class ScriptsModelFilter : public QSortFilterProxyModel {
Q_OBJECT Q_OBJECT
public: public:

View file

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

View file

@ -44,6 +44,23 @@ class OffscreenQmlSurface;
class TabletScriptingInterface : public QObject, public Dependency { class TabletScriptingInterface : public QObject, public Dependency {
Q_OBJECT Q_OBJECT
public: 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}; enum TabletAudioEvents { ButtonClick, ButtonHover, TabletOpen, TabletHandsIn, TabletHandsOut, Last};
Q_ENUM(TabletAudioEvents) Q_ENUM(TabletAudioEvents)
@ -58,14 +75,19 @@ public:
void setToolbarScriptingInterface(ToolbarScriptingInterface* toolbarScriptingInterface) { _toolbarScriptingInterface = toolbarScriptingInterface; } void setToolbarScriptingInterface(ToolbarScriptingInterface* toolbarScriptingInterface) { _toolbarScriptingInterface = toolbarScriptingInterface; }
/**jsdoc /**jsdoc
* Creates or retruns a new TabletProxy and returns it. * Creates or returns a new TabletProxy and returns it.
* @function Tablet.getTablet * @function Tablet.getTablet
* @param name {String} tablet name * @param {string} name - Tablet name.
* @return {TabletProxy} tablet instance * @returns {TabletProxy} Tablet instance.
*/ */
Q_INVOKABLE TabletProxy* getTablet(const QString& tabletId); Q_INVOKABLE TabletProxy* getTablet(const QString& tabletId);
void preloadSounds(); void preloadSounds();
/**jsdoc
* @function Tablet.playSound
* @param {Tablet.AudioEvents} sound
*/
Q_INVOKABLE void playSound(TabletAudioEvents aEvent); Q_INVOKABLE void playSound(TabletAudioEvents aEvent);
void setToolbarMode(bool toolbarMode); void setToolbarMode(bool toolbarMode);
@ -79,8 +101,8 @@ public:
QObject* getFlags(); QObject* getFlags();
signals: signals:
/**jsdoc /**jsdoc
* Signaled when a tablet message or dialog is created * Triggered when a tablet message or dialog is created.
* @function TabletProxy#tabletNotification * @function Tablet.tabletNotification
* @returns {Signal} * @returns {Signal}
*/ */
void tabletNotification(); void tabletNotification();
@ -98,6 +120,9 @@ protected:
bool _toolbarMode { false }; bool _toolbarMode { false };
}; };
/**jsdoc
* @typedef {object} TabletProxy#ButtonList
*/
class TabletButtonListModel : public QAbstractListModel { class TabletButtonListModel : public QAbstractListModel {
Q_OBJECT Q_OBJECT
@ -151,9 +176,12 @@ Q_DECLARE_METATYPE(TabletButtonsProxyModel*);
/**jsdoc /**jsdoc
* @class TabletProxy * @class TabletProxy
* @property name {string} READ_ONLY: name of this tablet * @property {string} name - Name of this tablet. <em>Read-only.</em>
* @property toolbarMode {bool} - used to transition this tablet into and out of toolbar mode. * @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. * 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 { class TabletProxy : public QObject {
Q_OBJECT Q_OBJECT
@ -172,88 +200,136 @@ public:
bool getToolbarMode() const { return _toolbarMode; } bool getToolbarMode() const { return _toolbarMode; }
void setToolbarMode(bool toolbarMode); void setToolbarMode(bool toolbarMode);
/**jsdoc
* @function TabletProxy#gotoMenuScreen
* @param {string} [submenu=""]
*/
Q_INVOKABLE void gotoMenuScreen(const QString& submenu = ""); Q_INVOKABLE void gotoMenuScreen(const QString& submenu = "");
Q_INVOKABLE void initialScreen(const QVariant& url);
/**jsdoc /**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 * @function TabletProxy#gotoHomeScreen
*/ */
Q_INVOKABLE void gotoHomeScreen(); Q_INVOKABLE void gotoHomeScreen();
/**jsdoc /**jsdoc
* show the specified web url on the tablet. * Show the specified Web url on the tablet.
* @function TabletProxy#gotoWebScreen * @function TabletProxy#gotoWebScreen
* @param url {string} url of web page. * @param {string} url - URL of web page.
* @param [injectedJavaScriptUrl] {string} optional url to an additional JS script to inject into the 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);
Q_INVOKABLE void gotoWebScreen(const QString& url, const QString& injectedJavaScriptUrl, bool loadOtherBase = false); 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); 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); // FIXME: This currently relies on a script initializing the tablet (hence the bool denoting success);
// it should be initialized internally so it cannot fail // 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 /**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 * @function TabletProxy#isMessageDialogOpen
* @returns {boolean}
*/ */
Q_INVOKABLE bool isMessageDialogOpen(); Q_INVOKABLE bool isMessageDialogOpen();
/**jsdoc /**jsdoc
* Creates a new button, adds it to this and returns it. * Creates a new button, adds it to this and returns it.
* @function TabletProxy#addButton * @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} * @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); Q_INVOKABLE TabletButtonProxy* addButton(const QVariant& properties);
/**jsdoc /**jsdoc
* removes button from the tablet * Removes a button from the tablet.
* @function TabletProxy.removeButton * @function TabletProxy#removeButton
* @param tabletButtonProxy {TabletButtonProxy} button to be removed * @param {TabletButtonProxy} button - The button to be removed
*/ */
Q_INVOKABLE void removeButton(TabletButtonProxy* tabletButtonProxy); Q_INVOKABLE void removeButton(TabletButtonProxy* tabletButtonProxy);
/**jsdoc /**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 * @function TabletProxy#emitScriptEvent
* @param msg {object|string} * @param {object|string} message
*/ */
Q_INVOKABLE void emitScriptEvent(const QVariant& msg); Q_INVOKABLE void emitScriptEvent(const QVariant& msg);
/**jsdoc /**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 * @function TabletProxy#sendToQml
* @param msg {object|string} * @param {object|string} message
*/ */
Q_INVOKABLE void sendToQml(const QVariant& msg); Q_INVOKABLE void sendToQml(const QVariant& msg);
/**jsdoc /**jsdoc
* Check if the tablet is on the homescreen * Check if the tablet is on the home screen.
* @function TabletProxy#onHomeScreen() * @function TabletProxy#onHomeScreen
* @returns {boolean}
*/ */
Q_INVOKABLE bool onHomeScreen(); Q_INVOKABLE bool onHomeScreen();
/**jsdoc /**jsdoc
* set tablet into our out of landscape mode * Set tablet into or out of landscape mode.
* @function TabletProxy#setLandscape * @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; } Q_INVOKABLE void setLandscape(bool landscape) { _landscape = landscape; }
/**jsdoc
* @function TabletProxy#getLandscape
* @returns {boolean}
*/
Q_INVOKABLE bool getLandscape() { return _landscape; } Q_INVOKABLE bool getLandscape() { return _landscape; }
/**jsdoc
* @function TabletProxy#isPathLoaded
* @param {string} path
* @returns {boolean}
*/
Q_INVOKABLE bool isPathLoaded(const QVariant& path); Q_INVOKABLE bool isPathLoaded(const QVariant& path);
QQuickItem* getTabletRoot() const { return _qmlTabletRoot; } QQuickItem* getTabletRoot() const { return _qmlTabletRoot; }
@ -268,17 +344,17 @@ public:
signals: signals:
/**jsdoc /**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 * @function TabletProxy#webEventReceived
* @param msg {object|string} * @param {object|string} message
* @returns {Signal} * @returns {Signal}
*/ */
void webEventReceived(QVariant msg); void webEventReceived(QVariant msg);
/**jsdoc /**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 * @function TabletProxy#fromQml
* @param msg {object|string} * @param {object|string} message
* @returns {Signal} * @returns {Signal}
*/ */
void fromQml(QVariant msg); void fromQml(QVariant msg);
@ -286,18 +362,21 @@ signals:
/**jsdoc /**jsdoc
* Signaled when this tablet screen changes. * Signaled when this tablet screen changes.
* @function TabletProxy#screenChanged * @function TabletProxy#screenChanged
* @param type {string} - "Home", "Web", "Menu", "QML", "Closed" * @param type {string} - "Home", "Web", "Menu", "QML", "Closed".
* @param url {string} - only valid for Web and QML. * @param url {string} - Only valid for Web and QML.
*/ */
void screenChanged(QVariant type, QVariant url); void screenChanged(QVariant type, QVariant url);
/**jsdoc /**jsdoc
* Signaled when the tablet becomes visible or becomes invisible * Signaled when the tablet becomes visible or becomes invisible.
* @function TabletProxy#isTabletShownChanged * @function TabletProxy#isTabletShownChanged
* @returns {Signal} * @returns {Signal}
*/ */
void tabletShownChanged(); void tabletShownChanged();
/**jsdoc
* @function TabletProxy#toolbarModeChanged
*/
void toolbarModeChanged(); void toolbarModeChanged();
protected slots: protected slots:
@ -331,7 +410,8 @@ Q_DECLARE_METATYPE(TabletProxy*);
/**jsdoc /**jsdoc
* @class TabletButtonProxy * @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 { class TabletButtonProxy : public QObject {
Q_OBJECT Q_OBJECT
@ -344,48 +424,55 @@ public:
QUuid getUuid() const { return _uuid; } QUuid getUuid() const { return _uuid; }
/**jsdoc /**jsdoc
* Returns the current value of this button's properties * Returns the current value of this button's properties.
* @function TabletButtonProxy#getProperties * @function TabletButtonProxy#getProperties
* @returns {ButtonProperties} * @returns {TabletButtonProxy.ButtonProperties}
*/ */
Q_INVOKABLE QVariantMap getProperties(); Q_INVOKABLE QVariantMap getProperties();
/**jsdoc /**jsdoc
* Replace the values of some of this button's properties * Replace the values of some of this button's properties.
* @function TabletButtonProxy#editProperties * @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); Q_INVOKABLE void editProperties(const QVariantMap& properties);
signals: signals:
/**jsdoc /**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 * @function TabletButtonProxy#clicked
* @returns {Signal} * @returns {Signal}
*/ */
void clicked(); void clicked();
/**jsdoc
* @function TabletButtonProxy#propertiesChanged
* @returns {Signal}
*/
void propertiesChanged(); void propertiesChanged();
protected: protected:
QUuid _uuid; QUuid _uuid;
int _stableOrder; 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; QVariantMap _properties;
}; };
Q_DECLARE_METATYPE(TabletButtonProxy*); 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 #endif // hifi_TabletScriptingInterface_h

View file

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