Entities actions JSDoc

This commit is contained in:
David Rowe 2018-02-27 14:12:20 +13:00
parent c2d8c96463
commit 1fb02d15d7
15 changed files with 296 additions and 2 deletions

View file

@ -15,6 +15,23 @@
#include <EntityItem.h>
#include <ObjectActionTractor.h>
/**jsdoc
* The <code>"far-grab"</code> {@link Entities.ActionType|ActionType} moves and rotates an entity to a target position and
* orientation, optionally relative to another entity, such that the entity doesn't collide with the user's avatar.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
*
* @typedef {object} Entities.ActionArguments-FarGrab
* @property {Vec3} targetPosition=0,0,0 - The target position.
* @property {Quat} targetRotation=0,0,0,1 - The target rotation.
* @property {Uuid} otherID=null - If an entity ID, the <code>targetPosition</code> and <code>targetRotation</code> are
* relative to this entity's position and rotation.
* @property {number} linearTimeScale=3.4e+38 - Controls how long it takes for the entity's position to catch up with the
* target position. The value is the time for the action to catch up to 1/e = 0.368 of the target value, where the action
* is applied using an exponential decay.
* @property {number} angularTimeScale=3.4e+38 - Controls how long it takes for the entity's orientation to catch up with the
* target orientation. The value is the time for the action to catch up to 1/e = 0.368 of the target value, where the
* action is applied using an exponential decay.
*/
class AvatarActionFarGrab : public ObjectActionTractor {
public:
AvatarActionFarGrab(const QUuid& id, EntityItemPointer ownerEntity);

View file

@ -416,6 +416,26 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) {
return true;
}
/**jsdoc
* The <code>"hold"</code> {@link Entities.ActionType|ActionType} positions and rotates an entity relative to an avatar's hand,
* without collisions between the entity and the holding avatar.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
*
* @typedef {object} Entities.ActionArguments-Hold
* @property {Uuid} holderID=MyAvatar.sessionUUID - The ID of the avatar holding the entity.
* @property {Vec3} relativePosition=0,0,0 - The target position relative to the avatar's hand.
* @property {Vec3} relativeRotation=0,0,0,1 - The target rotation relative to the avatar's hand.
* @property {number} timeScale=3.4e+38 - Controls how long it takes for the entity's position and rotation to catch up with
* the target. The value is the time for the action to catch up to 1/e = 0.368 of the target value, where the action is
* applied using an exponential decay.
* @property {string} hand=right - The hand holding the entity: <code>"left"</code> or <code>"right"</code>.
* @property {boolean} kinematic=false - If <code>true</code>, the entity is made kinematic during the action; the entity won't
* lag behind the hand but constraint actions such as <code>"hinge"</code> won't act properly.
* @property {boolean} kinematicSetVelocity=false - If <code>true</code> and <code>kinematic</code> is <code>true</code>, the
* entity's <code>velocity</code> property will be set during the action, e.g., so that other scripts may use the value.
* @property {boolean} ignoreIK=false - If <code>true</code>, the entity follows the HMD controller rather than the avatar's
* hand.
*/
QVariantMap AvatarActionHold::getArguments() {
QVariantMap arguments = ObjectDynamic::getArguments();
withReadLock([&]{

View file

@ -94,6 +94,49 @@ variables. These argument variables are used by the code which is run when bull
#include "EntityDynamicInterface.h"
/**jsdoc
* <p>An entity action may be one of the following types:</p>
* <table>
* <thead>
* <tr><th>Value</th><th>Type</th><th>Description</th><th>Arguments</th></tr>
* </thead>
* <tbody>
* <tr><td><code>"far-grab"</code></td><td>Avatar action</td>
* <td>Moves and rotates an entity to a target position and orientation, optionally relative to another entity, such that
* the entity doesn't collide with the user's avatar.</td>
* <td>{@link Entities.ActionArguments-FarGrab}</td></tr>
* <tr><td><code>"hold"</code></td><td>Avatar action</td>
* <td>Positions and rotates an entity relative to an avatar's hand, without collisions between the entity and the holding
* avatar.</td>
* <td>{@link Entities.ActionArguments-Hold}</td></tr>
* <tr><td><code>"offset"</code></td><td>Object action</td>
* <td>Moves an entity so that it is a set distance away from a target point.</td>
* <td>{@link Entities.ActionArguments-Offset}</td></tr>
* <tr><td><code>"tractor"</code></td><td>Object action</td>
* <td>Moves and rotates an entity to a target position and orientation, optionally relative to another entity.</td>
* <td>{@link Entities.ActionArguments-Tractor}</td></tr>
* <tr><td><code>"travel-oriented"</code></td><td>Object action</td>
* <td>Orients an entity to align with its direction of travel.</td>
* <td>{@link Entities.ActionArguments-TravelOriented}</td></tr>
* <tr><td><code>"hinge"</code></td><td>Object constraint</td>
* <td>Lets an entity pivot about an axis or connects two entities with a hinge joint.</td>
* <td>{@link Entities.ActionArguments-Hinge}</td></tr>
* <tr><td><code>"slider"</code></td><td>Object constraint</td>
* <td>Lets an entity slide and rotate along an axis, or connects two entities that slide and rotate along a shared
* axis.</td>
* <td>{@link Entities.ActionArguments-Slider|ActionArguments-Slider}</td></tr>
* <tr><td><code>"cone-twist"</code></td><td>Object constraint</td>
* <td>Connects two entities with a joint that can move through a cone and can twist.</td>
* <td>{@link Entities.ActionArguments-ConeTwist}</td></tr>
* <tr><td><code>"ball-socket"</code></td><td>Object constraint</td>
* <td>Connects two entities with a ball and socket joint.</td>
* <td>{@link Entities.ActionArguments-BallSocket}</td></tr>
* <tr><td><code>"spring"</code></td><td colspan="3">Synonym for <code>"tractor"</code>. <em>Legacy value.</em></td></tr>
* </tbody>
* </table>
* @typedef {string} Entities.ActionType
*/
// Note: The "none" action type is not listed because it's an internal "uninitialized" value and not useful for scripts.
EntityDynamicType EntityDynamicInterface::dynamicTypeFromString(QString dynamicTypeString) {
QString normalizedDynamicTypeString = dynamicTypeString.toLower().remove('-').remove('_');
if (normalizedDynamicTypeString == "none") {

View file

@ -804,10 +804,69 @@ public slots:
*/
Q_INVOKABLE void dumpTree() const;
/**jsdoc
* Add an action to an entity. An action is registered with the physics engine and is applied every physics simulation
* step. Any entity may have more than one action associated with it, but only as many as will fit in an entity's
* <code>actionData</code> property.
* @function Entities.addAction
* @param {Entities.ActionType} actionType - The type of action.
* @param {Uuid} entityID - The ID of the entity to add the action to.
* @param {Entities.ActionArguments} arguments - Configure the action.
* @returns {Uuid} The ID of the action added if successful, otherwise <code>null</code>.
* @example <caption>Constrain a cube to move along a vertical line.</caption>
* var entityID = Entities.addEntity({
* type: "Box",
* position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0.75, z: -5 })),
* dimensions: { x: 0.5, y: 0.5, z: 0.5 },
* dynamic: true,
* collisionless: false,
* userData: "{ \"grabbableKey\": { \"grabbable\": true, \"kinematic\": false } }",
* lifetime: 300 // Delete after 5 minutes.
* });
*
* var actionID = Entities.addAction("slider", entityID, {
* axis: { x: 0, y: 1, z: 0 },
* linearLow: 0,
* linearHigh: 0.6
* });
*/
Q_INVOKABLE QUuid addAction(const QString& actionTypeString, const QUuid& entityID, const QVariantMap& arguments);
/**jsdoc
* Update an entity action.
* @function Entities.updateAction
* @param (Uuid} entityID - The ID of the entity with the action to update.
* @param {Uuid} actionID - The ID of the action to update.
* @param {Entities.ActionArguments} arguments - The arguments to update.
* @returns {boolean} <code>true</code> if the update was successful, otherwise <code>false</code>.
*/
Q_INVOKABLE bool updateAction(const QUuid& entityID, const QUuid& actionID, const QVariantMap& arguments);
/**jsdoc
* Delete an action from an entity.
* @function Entities.deleteAction
* @param (Uuid} entityID - The ID of entity to delete the action from.
* @param {Uuid} actionID - The ID of the action to delete.
* @returns {boolean} <code>true</code> if the update was successful, otherwise <code>false</code>.
*/
Q_INVOKABLE bool deleteAction(const QUuid& entityID, const QUuid& actionID);
/**jsdoc
* Get the IDs of the actions that are associated with an entity.
* @function Entities.getActionIDs
* @param {Uuid} entityID - The entity to get the action IDs for.
* @returns {Uuid[]} An array of action IDs if any are found, otherwise an empty array.
*/
Q_INVOKABLE QVector<QUuid> getActionIDs(const QUuid& entityID);
/**jsdoc
* Get the arguments of an action.
* @function Entities.getActionArguments
* @param (Uuid} entityID - The ID of the entity with the action.
* @param {Uuid} actionID - The ID of the action to get the arguments of.
* @returns {Entities.ActionArguments} The arguments of the requested action if found, otherwise an empty object.
*/
Q_INVOKABLE QVariantMap getActionArguments(const QUuid& entityID, const QUuid& actionID);

View file

@ -142,6 +142,18 @@ bool ObjectActionOffset::updateArguments(QVariantMap arguments) {
return true;
}
/**jsdoc
* The <code>"offset"</code> {@link Entities.ActionType|ActionType} moves an entity so that it is a set distance away from a
* target point.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
*
* @typedef {object} Entities.ActionArguments-Offset
* @property {Vec3} pointToOffsetFrom=0,0,0 - The target point to offset the entity from.
* @property {number} linearDistance=0 - The distance away from the target point to position the entity.
* @property {number} linearTimeScale=34e+38 - Controls how long it takes for the entity's position to catch up with the
* target offset. The value is the time for the action to catch up to 1/e = 0.368 of the target value, where the action
* is applied using an exponential decay.
*/
QVariantMap ObjectActionOffset::getArguments() {
QVariantMap arguments = ObjectDynamic::getArguments();
withReadLock([&] {

View file

@ -307,6 +307,23 @@ bool ObjectActionTractor::updateArguments(QVariantMap arguments) {
return true;
}
/**jsdoc
* The <code>"tractor"</code> {@link Entities.ActionType|ActionType} moves and rotates an entity to a target position and
* orientation, optionally relative to another entity.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
*
* @typedef {object} Entities.ActionArguments-Tractor
* @property {Vec3} targetPosition=0,0,0 - The target position.
* @property {Quat} targetRotation=0,0,0,1 - The target rotation.
* @property {Uuid} otherID=null - If an entity ID, the <code>targetPosition</code> and <code>targetRotation</code> are
* relative to this entity's position and rotation.
* @property {number} linearTimeScale=3.4e+38 - Controls how long it takes for the entity's position to catch up with the
* target position. The value is the time for the action to catch up to 1/e = 0.368 of the target value, where the action
* is applied using an exponential decay.
* @property {number} angularTimeScale=3.4e+38 - Controls how long it takes for the entity's orientation to catch up with the
* target orientation. The value is the time for the action to catch up to 1/e = 0.368 of the target value, where the
* action is applied using an exponential decay.
*/
QVariantMap ObjectActionTractor::getArguments() {
QVariantMap arguments = ObjectDynamic::getArguments();
withReadLock([&] {

View file

@ -146,6 +146,17 @@ bool ObjectActionTravelOriented::updateArguments(QVariantMap arguments) {
return true;
}
/**jsdoc
* The <code>"travel-oriented"</code> {@link Entities.ActionType|ActionType} orients an entity to align with its direction of
* travel.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
*
* @typedef {object} Entities.ActionArguments-TravelOriented
* @property {Vec3} forward=0,0,0 - The axis of the entity to align with the entity's direction of travel.
* @property {number} angularTimeScale=0.1 - Controls how long it takes for the entity's orientation to catch up with the
* direction of travel. The value is the time for the action to catch up to 1/e = 0.368 of the target value, where the
* action is applied using an exponential decay.
*/
QVariantMap ObjectActionTravelOriented::getArguments() {
QVariantMap arguments = ObjectDynamic::getArguments();
withReadLock([&] {

View file

@ -181,6 +181,15 @@ bool ObjectConstraintBallSocket::updateArguments(QVariantMap arguments) {
return true;
}
/**jsdoc
* The <code>"ball-socket"</code> {@link Entities.ActionType|ActionType} connects two entities with a ball and socket joint.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
*
* @typedef {object} Entities.ActionArguments-BallSocket
* @property {Vec3} pivot=0,0,0 - The local offset of the joint relative to the entity's position.
* @property {Uuid} otherEntityID=null - The ID of the other entity that is connected to the joint.
* @property {Vec3} otherPivot=0,0,0 - The local offset of the joint relative to the other entity's position.
*/
QVariantMap ObjectConstraintBallSocket::getArguments() {
QVariantMap arguments = ObjectDynamic::getArguments();
withReadLock([&] {

View file

@ -261,6 +261,21 @@ bool ObjectConstraintConeTwist::updateArguments(QVariantMap arguments) {
return true;
}
/**jsdoc
* The <code>"cone-twist"</code> {@link Entities.ActionType|ActionType} connects two entities with a joint that can move
* through a cone and can twist.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
*
* @typedef {object} Entities.ActionArguments-ConeTwist
* @property {Vec3} pivot=0,0,0 - The local offset of the joint relative to the entity's position.
* @property {Vec3} axis=1,0,0 - The axis of the entity that moves through the cone. Must be a non-zero vector.
* @property {Uuid} otherEntityID=null - The ID of the other entity that is connected to the joint.
* @property {Vec3} otherPivot=0,0,0 - The local offset of the joint relative to the other entity's position.
* @property {Vec3} otherAxis=1,0,0 - The axis of the other entity that moves through the cone. Must be a non-zero vector.
* @property {number} swingSpan1=6.238 - The angle through which the joint can move in one axis of the cone, in radians.
* @property {number} swingSpan2=6.238 - The angle through which the joint can move in the other axis of the cone, in radians.
* @property {number} twistSpan=6.238 - The angle through with the joint can twist, in radians.
*/
QVariantMap ObjectConstraintConeTwist::getArguments() {
QVariantMap arguments = ObjectDynamic::getArguments();
withReadLock([&] {

View file

@ -245,6 +245,22 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) {
return true;
}
/**jsdoc
* The <code>"hinge"</code> {@link Entities.ActionType|ActionType} lets an entity pivot about an axis or connects two entities
* with a hinge joint.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
*
* @typedef {object} Entities.ActionArguments-Hinge
* @property {Vec3} pivot=0,0,0 - The local offset of the joint relative to the entity's position.
* @property {Vec3} axis=1,0,0 - The axis of the entity that it pivots about. Must be a non-zero vector.
* @property {Uuid} otherEntityID=null - The ID of the other entity that is connected to the joint, if any. If none is
* specified then the first entity simply pivots about its specified <code>axis</code>.
* @property {Vec3} otherPivot=0,0,0 - The local offset of the joint relative to the other entity's position.
* @property {Vec3} otherAxis=1,0,0 - The axis of the other entity that it pivots about. Must be a non-zero vector.
* @property {number} low=-6.283 - The most negative angle that the hinge can take, in radians.
* @property {number} high=6.283 - The most positive angle that the hinge can take, in radians.
* @property {number} angle=0 - The current angle of the hinge. <em>Read-only.</em>
*/
QVariantMap ObjectConstraintHinge::getArguments() {
QVariantMap arguments = ObjectDynamic::getArguments();
withReadLock([&] {

View file

@ -261,6 +261,31 @@ bool ObjectConstraintSlider::updateArguments(QVariantMap arguments) {
return true;
}
/**jsdoc
* The <code>"slider"</code> {@link Entities.ActionType|ActionType} lets an entity slide and rotate along an axis, or connects
* two entities that slide and rotate along a shared axis.
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
*
* @typedef {object} Entities.ActionArguments-Slider
* @property {Vec3} point=0,0,0 - The local position of a point in the entity that slides along the axis.
* @property {Vec3} axis=1,0,0 - The axis of the entity that slides along the joint. Must be a non-zero vector.
* @property {Uuid} otherEntityID=null - The ID of the other entity that is connected to the joint, if any. If non is
* specified then the first entity simply slides and rotates about its specified <code>axis</code>.
* @property {Vec3} otherPoint=0,0,0 - The local position of a point in the other entity that slides along the axis.
* @property {Vec3} axis=1,0,0 - The axis of the other entity that slides along the joint. Must be a non-zero vector.
* @property {number} linearLow=1.17e-38 - The most negative linear offset from the entity's initial point that the entity can
* have along the slider.
* @property {number} linearHigh=3.40e+38 - The most positive linear offset from the entity's initial point that the entity can
* have along the slider.
* @property {number} angularLow=-6.283 - The most negative angle that the entity can rotate about the axis if the action
* involves only one entity, otherwise the most negative angle the rotation can be between the two entities. In radians.
* @property {number} angularHigh=6.283 - The most positive angle that the entity can rotate about the axis if the action
* involves only one entity, otherwise the most positive angle the rotation can be between the two entities. In radians.
* @property {number} linearPosition=0 - The current linear offset the entity is from its initial point if the action involves
* only one entity, otherwise the linear offset between the two entities' action points. <em>Read-only.</em>
* @property {number} angularPosition=0 - The current angular offset of the entity from its initial rotation if the action
* involves only one entity, otherwise the angular offset between the two entities. <em>Read-only.</em>
*/
QVariantMap ObjectConstraintSlider::getArguments() {
QVariantMap arguments = ObjectDynamic::getArguments();
withReadLock([&] {

View file

@ -93,6 +93,38 @@ bool ObjectDynamic::updateArguments(QVariantMap arguments) {
return somethingChanged;
}
/**jsdoc
* Different entity action types have different arguments: some common to all actions (listed below) and some specific to each
* {@link Entities.ActionType|ActionType} (linked to below). The arguments are accessed as an object of property names and
* values.
*
* @typedef {object} Entities.ActionArguments
* @property {Entities.ActionType} type - The type of action.
* @property {string} tag="" - A string that a script can use for its own purposes.
* @property {number} ttl=0 - How long the action should exist, in seconds, before it is automatically deleted. A value of
* <code>0</code> means that the action should not be deleted.
* @property {boolean} isMine=true - Is <code>true</code> if you created the action during your current Interface session,
* <code>false</code> otherwise. <em>Read-only.</em>
* @property {boolean} ::no-motion-state - Is present when the entity hasn't been registered with the physics engine yet (e.g.,
* if the action hasn't been properly configured), otherwise <code>undefined</code>. <em>Read-only.</em>
* @property {boolean} ::active - Is <code>true</code> when the action is modifying the entity's motion, <code>false</code>
* otherwise. Is present once the entity has been registered with the physics engine, otherwise <code>undefined</code>.
* <em>Read-only.</em>
* @property {Entities.PhysicsMotionType} ::motion-type - How the entity moves with the action. Is present once the entity has
* been registered with the physics engine, otherwise <code>undefined</code>. <em>Read-only.</em>
*
* @see The different action types have additional arguments as follows:
* @see {@link Entities.ActionArguments-FarGrab|ActionArguments-FarGrab}
* @see {@link Entities.ActionArguments-Hold|ActionArguments-Hold}
* @see {@link Entities.ActionArguments-Offset|ActionArguments-Offset}
* @see {@link Entities.ActionArguments-Tractor|ActionArguments-Tractor}
* @see {@link Entities.ActionArguments-TravelOriented|ActionArguments-TravelOriented}
* @see {@link Entities.ActionArguments-Hinge|ActionArguments-Hinge}
* @see {@link Entities.ActionArguments-Slider|ActionArguments-Slider}
* @see {@link Entities.ActionArguments-ConeTwist|ActionArguments-ConeTwist}
* @see {@link Entities.ActionArguments-BallSocket|ActionArguments-BallSocket}
*/
// Note: The "type" property is set in EntityItem::getActionArguments().
QVariantMap ObjectDynamic::getArguments() {
QVariantMap arguments;
withReadLock([&]{

View file

@ -29,6 +29,23 @@ enum PhysicsMotionType {
MOTION_TYPE_KINEMATIC // keyframed motion
};
/**jsdoc
* <p>An entity's physics motion type may be one of the following:</p>
* <table>
* <thead>
* <tr><th>Value</th><th>Description</th></tr>
* </thead>
* <tbody>
* <tr><td><code>"static"</code></td><td>There is no motion because the entity is locked &mdash; its <code>locked</code>
* property is set to <code>true</code>.</td></tr>
* <tr><td><code>"kinematic"</code></td><td>Motion is applied without physical laws (e.g., damping) because the entity is
* not locked and has its <code>dynamic</code> property set to <code>false</code>.</td></tr>
* <tr><td><code>"dynamic"</code></td><td>Motion is applied according to physical laws (e.g., damping) because the entity
* is not locked and has its <code>dynamic</code> property set to <code>true</code>.</td></tr>
* </tbody>
* </table>
* @typedef {string} Entities.PhysicsMotionType
*/
inline QString motionTypeToString(PhysicsMotionType motionType) {
switch(motionType) {
case MOTION_TYPE_STATIC: return QString("static");

View file

@ -186,7 +186,7 @@
var prevEntityID = null;
for (var i = 0; i < 7; i++) {
var newID = Entities.addEntity({
name: "hinge test " + i,
name: "slider test " + i,
type: "Box",
color: { blue: 128, green: 40 * i, red: 20 },
dimensions: { x: 0.2, y: 0.1, z: 0.2 },

View file

@ -27,10 +27,11 @@ exports.handlers = {
'../../libraries/entities/src',
'../../libraries/octree/src',
'../../libraries/networking/src',
'../../libraries/physics/src',
'../../libraries/pointers/src',
'../../libraries/script-engine/src',
'../../libraries/shared/src',
'../../libraries/shared/src/shared',
'../../libraries/script-engine/src',
];
var exts = ['.h', '.cpp'];