From 9f83c606e92b353aa240c888117d2adc05e0bc89 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 17 Apr 2018 11:46:40 +1200 Subject: [PATCH] Controller API JSDoc --- interface/src/Application.cpp | 28 + .../scripting/ControllerScriptingInterface.h | 323 +++++++++++- .../controllers/src/controllers/Actions.cpp | 276 ++++++++++ .../controllers/src/controllers/InputDevice.h | 55 ++ .../controllers/src/controllers/Pose.cpp | 10 +- .../src/controllers/ScriptingInterface.h | 486 +++++++++++++++++- .../src/controllers/StandardController.cpp | 206 ++++++++ .../controllers/impl/MappingBuilderProxy.h | 158 ++++++ .../src/controllers/impl/RouteBuilderProxy.h | 389 ++++++++++++++ .../entities/src/EntityScriptingInterface.h | 2 +- .../src/input-plugins/KeyboardMouseDevice.cpp | 66 +++ libraries/script-engine/src/KeyEvent.cpp | 24 +- libraries/script-engine/src/MouseEvent.cpp | 26 + libraries/script-engine/src/TouchEvent.cpp | 39 ++ libraries/script-engine/src/WheelEvent.cpp | 29 +- libraries/shared/src/PointerEvent.cpp | 6 +- .../oculus/src/OculusControllerManager.cpp | 61 +++ plugins/openvr/src/ViveControllerManager.cpp | 60 +++ tools/jsdoc/plugins/hifi.js | 4 + 19 files changed, 2229 insertions(+), 19 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index aec31f2de4..1af79723ea 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -688,6 +688,34 @@ private: } }; +/**jsdoc + *

The Controller.Hardware.Application object has properties representing Interface's state. The property + * values are integer IDs, uniquely identifying each output. Read-only. These can be can be mapped to actions or + * functions or Controller.Standard items in a {@link RouteObject} mapping. Each data value is either + * 1.0 for "true" or 0.0 for "false".

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
PropertyTypeDataDescription
CameraFirstPersonnumbernumberThe camera is in first-person mode. + *
CameraThirdPersonnumbernumberThe camera is in third-person mode. + *
CameraFSMnumbernumberThe camera is in full screen mirror mode.
CameraIndependentnumbernumberThe camera is in independent mode.
CameraEntitynumbernumberThe camera is in entity mode.
NavigationFocusednumbernumberTODO
InHMDnumbernumberThe user is in HMD mode.
AdvancedMovementnumbernumberAdvanced movement controls are enabled. + *
SnapTurnnumbernumberSnap turn is enabled.
GroundednumbernumberThe user's avatar is on the ground.
+ * @typedef Controller.Hardware-Application + */ + static const QString STATE_IN_HMD = "InHMD"; static const QString STATE_CAMERA_FULL_SCREEN_MIRROR = "CameraFSM"; static const QString STATE_CAMERA_FIRST_PERSON = "CameraFirstPerson"; diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h index 9b24e2a06e..4c1378f321 100644 --- a/interface/src/scripting/ControllerScriptingInterface.h +++ b/interface/src/scripting/ControllerScriptingInterface.h @@ -24,11 +24,154 @@ #include class ScriptEngine; + +/**jsdoc + * The Controller API provides facilities to interact with computer and controller hardware. + * + *
Functions:
+ * + *

Properties

+ * + * + *

Mappings

+ * + * + *

Input, Hardware, and Action Reflection

+ * + * + *

Input, Hardware, and Action Events

+ * + * + *

Mouse, Keyboard, and Touch Events

+ * + * + *

Control Capturing

+ * + * + *

Action Capturing

+ * + * + *

Controller and Action Values

+ * + * + *

Haptics

+ * + * + *

Display Information

+ * + * + *

Virtual Game Pad

+ * + * + *

Input Recordings

+ * + * + * @namespace Controller + * + * @property {Controller.Actions} Actions - Predefined actions on Interface and the user's avatar. These can be used as end + * points in a {@link RouteObject} mapping. A synonym for Controller.Hardware.Actions. + * Read-only.
+ * Default mappings are provided from the Controller.Hardware.Keyboard and Controller.Standard to + * actions in + * + * keyboardMouse.json and + * + * standard.json, respectively. + * + * @property {Controller.Hardware} Hardware - Standard and hardware-specific controller and computer outputs, plus predefined + * actions on Interface and the user's avatar. The outputs can be mapped to Actions or functions in a + * {@link RouteObject} mapping. Additionally, hardware-specific controller outputs can be mapped to Standard + * controller outputs. Read-only. + * + * @property {Controller.Standard} Standard - Standard controller outputs that can be mapped to Actions or + * functions in a {@link RouteObject} mapping. Read-only.
+ * Each hardware device has a mapping from its outputs to Controller.Standard items, specified in a JSON file. + * For example, + * leapmotion.json and + * vive.json. + */ + /// handles scripting of input controller commands from JS class ControllerScriptingInterface : public controller::ScriptingInterface { Q_OBJECT - public: virtual ~ControllerScriptingInterface() {} @@ -53,40 +196,214 @@ public: public slots: + /**jsdoc + * Disable default Interface actions for a particular key event. + * @function Controller.captureKeyEvents + * @param {KeyEvent} event - Details of the key event to be captured. The key property must be specified. The + * text property is ignored. The other properties default to false. + * @example Disable left and right strafing. + * var STRAFE_LEFT = { "key": 16777234, isShifted: true }; + * var STRAFE_RIGHT = { "key": 16777236, isShifted: true }; + * + * Controller.captureKeyEvents(STRAFE_LEFT); + * Controller.captureKeyEvents(STRAFE_RIGHT); + * + * Script.scriptEnding.connect(function () { + * Controller.releaseKeyEvents(STRAFE_LEFT); + * Controller.releaseKeyEvents(STRAFE_RIGHT); + * }); + */ virtual void captureKeyEvents(const KeyEvent& event); + + /**jsdoc + * Re-enable default Interface actions for a particular key event that has been disabled using + * {@link Controller.captureKeyEvents|captureKeyEvents}. + * @function Controller.releaseKeyEvents + * @param {KeyEvent} event - Details of the key event to release from capture. The key property must be + * specified. The text property is ignored. The other properties default to false. + */ virtual void releaseKeyEvents(const KeyEvent& event); + /**jsdoc + * Disable default Interface actions for a joystick. + * @function Controller.captureJoystick + * @param {number} joystickID - The integer ID of the joystick. + * @deprecated This function no longer has any effect. + */ virtual void captureJoystick(int joystickIndex); + + /**jsdoc + * Re-enable default Interface actions for a joystick that has been disabled using + * {@link Controller.captureJoystick|captureJoystick}. + * @function Controller.releaseJoystick + * @param {number} joystickID - The integer ID of the joystick. + * @deprecated This function no longer has any effect. + */ virtual void releaseJoystick(int joystickIndex); + /**jsdoc + * Disable {@link Entities.mousePressOnEntity} and {@link Entities.mouseDoublePressOnEntity} events on entities. + * @function Controller.captureEntityClickEvents + * @example Disable entity click events for a short period. + * Entities.mousePressOnEntity.connect(function (entityID, event) { + * print("Clicked on entity: " + entityID); + * }); + * + * Script.setTimeout(function () { + * Controller.captureEntityClickEvents(); + * }, 5000); + * + * Script.setTimeout(function () { + * Controller.releaseEntityClickEvents(); + * }, 10000); + */ virtual void captureEntityClickEvents(); + + /**jsdoc + * Re-enable {@link Entities.mousePressOnEntity} and {@link Entities.mouseDoublePressOnEntity} events on entities that were + * disabled using {@link Controller.captureEntityClickEvents|captureEntityClickEvents}. + * @function Controller.releaseEntityClickEvents + */ virtual void releaseEntityClickEvents(); + + /**jsdoc + * Get the dimensions of the Interface window's interior if in desktop mode or the HUD surface if in HMD mode. + * @function Controller.getViewportDimensions + * @returns {Vec2} The dimensions of the Interface window interior if in desktop mode or HUD surface if in HMD mode. + */ virtual glm::vec2 getViewportDimensions() const; + + /**jsdoc + * Get the recommended area to position UI on the HUD surface if in HMD mode or Interface's window interior if in desktop + * mode. + * @function Controller.getRecommendedHUDRect + * @returns {Rect} The recommended area in which to position UI. + */ virtual QVariant getRecommendedHUDRect() const; + /**jsdoc + * Enables or disables the virtual game pad that is displayed on certain devices (e.g., Android). + * @function Controller.setVPadEnabled + * @param {boolean} enable - If true then the virtual game pad doesn't work, otherwise it does work provided + * that it is not hidden by {@link Controller.setVPadHidden|setVPadHidden}. + * + */ virtual void setVPadEnabled(bool enable); + + /**jsdoc + * Shows or hides the virtual game pad that is displayed on certain devices (e.g., Android). + * @function Controller.setVPadHidden + * @param {boolean} hidden - If true then the virtual game pad is hidden, otherwise it is shown. + */ virtual void setVPadHidden(bool hidden); // Call it when a window should hide it + + /**jsdoc + * Sets the amount of extra margins between the virtual game pad that is displayed on certain devices (e.g., Android) and + * the bottom of the display. + * @function Controller.setVPadExtraBottomMargin + * @param {number} margin - Integer number of pixels of extra margin. + */ virtual void setVPadExtraBottomMargin(int margin); signals: + /**jsdoc + * Triggered when a keyboard key is pressed. + * @function Controller.keyPressEvent + * @param {KeyEvent} event - Details of the key press. + * @returns {Signal} + * @example Report the KeyEvent details for each key press. + * Controller.keyPressEvent.connect(function (event) { + * print(JSON.stringify(event)); + * }); + */ void keyPressEvent(const KeyEvent& event); + + /**jsdoc + * Triggered when a keyboard key is released from being pressed. + * @function Controller.keyReleaseEvent + * @param {KeyEvent} event - Details of the key release. + * @returns {Signal} + */ void keyReleaseEvent(const KeyEvent& event); + /**jsdoc + * Triggered when the mouse moves. + * @function Controller.mouseMoveEvent + * @param {MouseEvent} event - Details of the mouse movement. + * @returns {Signal} + * @example Report the MouseEvent details for each mouse move. + * Controller.mouseMoveEvent.connect(function (event) { + * print(JSON.stringify(event)); + * }); + */ void mouseMoveEvent(const MouseEvent& event); + + /**jsdoc + * Triggered when a mouse button is pressed. + * @function Controller.mousePressEvent + * @param {MouseEvent} event - Details of the button press. + * @returns {Signal} + */ void mousePressEvent(const MouseEvent& event); + + /**jsdoc + * Triggered when a mouse button is double-pressed. + * @function Controller.mouseDoublePressEvent + * @param {MouseEvent} event - Details of the button double-press. + * @returns {Signal} + */ void mouseDoublePressEvent(const MouseEvent& event); + + /**jsdoc + * Triggered when a mouse button is released from being pressed. + * @function Controller.mouseReleaseEvent + * @param {MouseEvent} event - Details of the button release. + * @returns {Signal} + */ void mouseReleaseEvent(const MouseEvent& event); + /**jsdoc + * Triggered when a touch event starts in the Interface window on a touch-enabled display or device. + * @function Controller.touchBeginEvent + * @param {TouchEvent} event - Details of the touch begin. + * @returns {Signal} + * @example Report the TouchEvent details when a touch event starts. + * Controller.touchBeginEvent.connect(function (event) { + * print(JSON.stringify(event)); + * }); + */ void touchBeginEvent(const TouchEvent& event); + + /**jsdoc + * Triggered when a touch event ends in the Interface window on a touch-enabled display or device. + * @function Controller.touchEndEvent + * @param {TouchEvent} event - Details of the touch end. + * @returns {Signal} + */ void touchEndEvent(const TouchEvent& event); + + /**jsdoc + * Triggered when a touch event update occurs in the Interface window on a touch-enabled display or device. + * @function Controller.touchUpdateEvent + * @param {TouchEvent} event - Details of the touch update. + * @returns {Signal} + */ void touchUpdateEvent(const TouchEvent& event); + /**jsdoc + * Triggered when the mouse wheel is rotated. + * @function Controller.wheelEvent + * @param {WheelEvent} event - Details of the wheel movement. + * @returns {Signal} + * @example Report the WheelEvent details for each wheel rotation. + * Controller.wheelEvent.connect(function (event) { + * print(JSON.stringify(event)); + * }); + */ void wheelEvent(const WheelEvent& event); private: - QString sanatizeName(const QString& name); /// makes a name clean for inclusing in JavaScript - QMultiMap _capturedKeys; QSet _capturedJoysticks; bool _captureEntityClicks; diff --git a/libraries/controllers/src/controllers/Actions.cpp b/libraries/controllers/src/controllers/Actions.cpp index 06a487d6ea..f13a906e3f 100644 --- a/libraries/controllers/src/controllers/Actions.cpp +++ b/libraries/controllers/src/controllers/Actions.cpp @@ -33,6 +33,282 @@ namespace controller { return std::make_shared(input); } + /**jsdoc + *

The Controller.Actions object has properties representing predefined actions on the user's avatar and + * Interface. The property values are integer IDs, uniquely identifying each action. Read-only. These can be used + * as end points in the routes of a {@link MappingObject}. The data routed to each action is either a number or a + * {@link Pose}.

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
PropertyTypeDataDescription
Avatar Movement
TranslateXnumbernumberMove the user's avatar in the direction of its + * x-axis, if the camera isn't in independent or mirror modes.
TranslateYnumbernumberMove the user's avatar in the direction of its + * y-axis, if the camera isn't in independent or mirror modes.
TranslateZnumbernumberMove the user's avatar in the direction of its + * z-axis, if the camera isn't in independent or mirror modes.
PitchnumbernumberRotate the user's avatar head and attached camera + * about its negative x-axis (i.e., positive values pitch down), if the camera isn't in HMD, independent, or mirror + * modes.
YawnumbernumberRotate the user's avatar about its y-axis, if the + * camera isn't in independent or mirror modes.
RollnumbernumberNo action.
StepTranslateXnumbernumberNo action.
StepTranslateYnumbernumberNo action.
StepTranslateZnumbernumberNo action.
StepPitchnumbernumberNo action.
StepYawnumbernumberRotate the user's avatar about its y-axis in a + * step increment, if the camera isn't in independent or mirror modes.
StepRollnumbernumberNo action.
Avatar Skeleton
Hipsnumber{@link Pose}Set the hips pose of the user's avatar. + *
Spine2number{@link Pose}Set the spine2 pose of the user's avatar. + *
Headnumber{@link Pose}Set the head pose of the user's avatar. + *
LeftArmnumber{@link Pose}Set the left arm pose of the user's avatar. + *
RightArmnumber{@link Pose}Set the right arm pose of the user's + * avatar.
LeftHandnumber{@link Pose}Set the left hand pose of the user's + * avatar.
LeftHandThumb1number{@link Pose}Set the left thumb 1 finger joint + * pose of the user's avatar.
LeftHandThumb2number{@link Pose}Set the left thumb 2 finger joint + * pose of the user's avatar.
LeftHandThumb3number{@link Pose}Set the left thumb 3 finger joint + * pose of the user's avatar.
LeftHandThumb4number{@link Pose}Set the left thumb 4 finger joint + * pose of the user's avatar.
LeftHandIndex1number{@link Pose}Set the left index 1 finger joint + * pose of the user's avatar.
LeftHandIndex2number{@link Pose}Set the left index 2 finger joint + * pose of the user's avatar.
LeftHandIndex3number{@link Pose}Set the left index 3 finger joint + * pose of the user's avatar.
LeftHandIndex4number{@link Pose}Set the left index 4 finger joint + * pose of the user's avatar.
LeftHandMiddle1number{@link Pose}Set the left middle 1 finger joint + * pose of the user's avatar.
LeftHandMiddle2number{@link Pose}Set the left middle 2 finger joint + * pose of the user's avatar.
LeftHandMiddle3number{@link Pose}Set the left middle 3 finger joint + * pose of the user's avatar.
LeftHandMiddle4number{@link Pose}Set the left middle 4 finger joint + * pose of the user's avatar.
LeftHandRing1number{@link Pose}Set the left ring 1 finger joint pose + * of the user's avatar.
LeftHandRing2number{@link Pose}Set the left ring 2 finger joint pose + * of the user's avatar.
LeftHandRing3number{@link Pose}Set the left ring 3 finger joint pose + * of the user's avatar.
LeftHandRing4number{@link Pose}Set the left ring 4 finger joint pose + * of the user's avatar.
LeftHandPinky1number{@link Pose}Set the left pinky 1 finger joint + * pose of the user's avatar.
LeftHandPinky2number{@link Pose}Set the left pinky 2 finger joint + * pose of the user's avatar.
LeftHandPinky3number{@link Pose}Set the left pinky 3 finger joint + * pose of the user's avatar.
LeftHandPinky4number{@link Pose}Set the left pinky 4 finger joint + * pose of the user's avatar.
RightHandnumber{@link Pose}Set the right hand of the user's avatar. + *
RightHandThumb1number{@link Pose}Set the right thumb 1 finger joint + * pose of the user's avatar.
RightHandThumb2number{@link Pose}Set the right thumb 2 finger joint + * pose of the user's avatar.
RightHandThumb3number{@link Pose}Set the right thumb 3 finger joint + * pose of the user's avatar.
RightHandThumb4number{@link Pose}Set the right thumb 4 finger joint + * pose of the user's avatar.
RightHandIndex1number{@link Pose}Set the right index 1 finger joint + * pose of the user's avatar.
RightHandIndex2number{@link Pose}Set the right index 2 finger joint + * pose of the user's avatar.
RightHandIndex3number{@link Pose}Set the right index 3 finger joint + * pose of the user's avatar.
RightHandIndex4number{@link Pose}Set the right index 4 finger joint + * pose of the user's avatar.
RightHandMiddle1number{@link Pose}Set the right middle 1 finger + * joint pose of the user's avatar.
RightHandMiddle2number{@link Pose}Set the right middle 2 finger + * joint pose of the user's avatar.
RightHandMiddle3number{@link Pose}Set the right middle 3 finger + * joint pose of the user's avatar.
RightHandMiddle4number{@link Pose}Set the right middle 4 finger + * joint pose of the user's avatar.
RightHandRing1number{@link Pose}Set the right ring 1 finger joint + * pose of the user's avatar.
RightHandRing2number{@link Pose}Set the right ring 2 finger joint + * pose of the user's avatar.
RightHandRing3number{@link Pose}Set the right ring 3 finger joint + * pose of the user's avatar.
RightHandRing4number{@link Pose}Set the right ring 4 finger joint + * pose of the user's avatar.
RightHandPinky1number{@link Pose}Set the right pinky 1 finger joint + * pose of the user's avatar.
RightHandPinky2number{@link Pose}Set the right pinky 2 finger joint + * pose of the user's avatar.
RightHandPinky3number{@link Pose}Set the right pinky 3 finger joint + * pose of the user's avatar.
RightHandPinky4number{@link Pose}Set the right pinky 4 finger joint + * pose of the user's avatar.
LeftFootnumber{@link Pose}Set the left foot pose of the user's + * avatar.
RightFootnumber{@link Pose}Set the right foot pose of the user's + * avatar.
Application
BoomInnumbernumberZoom camera in from third person toward first + * person view.
BoomOutnumbernumberZoom camera out from first person to third + * person view.
CycleCameranumbernumberCycle the camera view from first person, to + * third person, to full screen mirror, then back to first person and repeat.
ContextMenunumbernumberShow / hide the tablet.
ToggleMutenumbernumberToggle the microphone mute.
ToggleOverlaynumbernumberToggle the display of overlays.
SprintnumbernumberSet avatar sprint mode.
ReticleClicknumbernumberSet mouse-pressed.
ReticleXnumbernumberMove the cursor left/right in the x direction. + *
ReticleYnumbernumbermove the cursor up/down in the y direction. + *
ReticleLeftnumbernumberMove the cursor left.
ReticleRightnumbernumberMove the cursor right.
ReticleUpnumbernumberMove the cursor up.
ReticleDownnumbernumberMove the cursor down.
UiNavLateralnumbernumberGenerate a keyboard left or right arrow key + * event.
UiNavVerticalnumbernumberGenerate a keyboard up or down arrow key + * event.
UiNavGroupnumbernumberGenerate a keyboard tab or back-tab key event. + *
UiNavSelectnumbernumberGenerate keyboard an Enter key event. + *
UiNavBacknumbernumberGenerate keyboard an Esc key event.
LeftHandClicknumbernumberDeprecated: : No action. + *
RightHandClicknumbernumberDeprecated:: No action. + *
ShiftnumbernumberDeprecated:: No action.
PrimaryActionnumbernumberDeprecated: : No action. + *
SecondaryActionnumbernumberDeprecated:: No action. + *
Aliases
BackwardnumbernumberAlias for TranslateZ in the + * positive direction.
ForwardnumbernumberAlias for TranslateZ in the negative + * direction.
StrafeRightnumbernumberAlias for TranslateX in the + * positive direction.
StrafeLeftnumbernumberAlias for TranslateX in the + * negative direction.
UpnumbernumberAlias for TranslateY in the positive + * direction.
DownnumbernumberAlias for TranslateY in the negative + * direction.
PitchDownnumbernumberAlias for Pitch in the positive + * direction.
PitchUpnumbernumberAlias for Pitch in the negative + * direction.
YawLeftnumbernumberAlias of Yaw in the positive + * direction.
YawRightnumbernumberAlias for Yaw in the negative + * direction.
Deprecated Aliases
LEFT_HANDnumber{@link Pose}Deprecated: Use + * LeftHand instead.
RIGHT_HANDnumber{@link Pose}Deprecated: Use + * RightHand instead.
BOOM_INnumbernumberDeprecated: Use + * BoomIn instead.
BOOM_OUTnumbernumberDeprecated: Use + * BoomOut instead.
CONTEXT_MENUnumbernumberDeprecated: Use + * ContextMenu instead.
TOGGLE_MUTEnumbernumberDeprecated: Use + * ToggleMute instead.
SPRINTnumbernumberDeprecated: Use + * Sprint instead.
LONGITUDINAL_BACKWARDnumbernumberDeprecated: Use + * Backward instead.
LONGITUDINAL_FORWARDnumbernumberDeprecated: Use + * Forward instead.
LATERAL_LEFTnumbernumberDeprecated: Use + * StrafeLeft instead.
LATERAL_RIGHTnumbernumberDeprecated: Use + * StrafeRight instead.
VERTICAL_UPnumbernumberDeprecated: Use + * Up instead.
VERTICAL_DOWNnumbernumberDeprecated: Use + * Down instead.
PITCH_DOWNnumbernumberDeprecated: Use + * PitchDown instead.
PITCH_UPnumbernumberDeprecated: Use + * PitchUp instead.
YAW_LEFTnumbernumberDeprecated: Use + * YawLeft instead.
YAW_RIGHTnumbernumberDeprecated: Use + * YawRight instead.
LEFT_HAND_CLICKnumbernumberDeprecated: Use + * LeftHandClick instead.
RIGHT_HAND_CLICKnumbernumberDeprecated: Use + * RightHandClick instead.
SHIFTnumbernumberDeprecated: Use + * Shift instead.
ACTION1numbernumberDeprecated: Use + * PrimaryAction instead.
ACTION2numbernumberDeprecated: Use + * SecondaryAction instead.
Deprecated Trackers
TrackedObject00number{@link Pose}Deprecated: No + * action.
TrackedObject01number{@link Pose}Deprecated: No + * action.
TrackedObject02number{@link Pose}Deprecated: No + * action.
TrackedObject03number{@link Pose}Deprecated: No + * action.
TrackedObject04number{@link Pose}Deprecated: No + * action.
TrackedObject05number{@link Pose}Deprecated: No + * action.
TrackedObject06number{@link Pose}Deprecated: No + * action.
TrackedObject07number{@link Pose}Deprecated: No + * action.
TrackedObject08number{@link Pose}Deprecated: No + * action.
TrackedObject09number{@link Pose}Deprecated: No + * action.
TrackedObject10number{@link Pose}Deprecated: No + * action.
TrackedObject11number{@link Pose}Deprecated: No + * action.
TrackedObject12number{@link Pose}Deprecated: No + * action.
TrackedObject13number{@link Pose}Deprecated: No + * action.
TrackedObject14number{@link Pose}Deprecated: No + * action.
TrackedObject15number{@link Pose}Deprecated: No + * action.
+ * @typedef Controller.Actions + */ // Device functions Input::NamedVector ActionsDevice::getAvailableInputs() const { static Input::NamedVector availableInputs { diff --git a/libraries/controllers/src/controllers/InputDevice.h b/libraries/controllers/src/controllers/InputDevice.h index ff665d912d..30a58eb2f0 100644 --- a/libraries/controllers/src/controllers/InputDevice.h +++ b/libraries/controllers/src/controllers/InputDevice.h @@ -31,12 +31,67 @@ namespace controller { class Endpoint; using EndpointPointer = std::shared_ptr; +/**jsdoc + *

Some controller actions may be associated with one or both hands:

+ * + * + * + * + * + * + * + * + * + *
ValueDescription
0Left hand.
1Right hand.
2Both hands.
+ * @typedef {number} Controller.Hand + */ enum Hand { LEFT = 0, RIGHT, BOTH }; +/**jsdoc + *

The Controller.Hardware object has properties representing standard and hardware-specific controller and + * computer outputs, plus predefined actions on Interface and the user's avatar. Read-only. The outputs can be mapped + * to actions or functions in a {@link RouteObject} mapping. Additionally, hardware-specific controller outputs can be mapped + * to standard controller outputs. + * + *

Controllers typically implement a subset of the {@link Controller.Standard} controls, plus they may implement some extras. + * Some common controllers are included in the table. You can see the outputs provided by these and others by + * viewing their {@link Controller.MappingJSON|MappingJSON} files at + * + * https://github.com/highfidelity/hifi/tree/master/interface/resources/controllers.

+ * + * + * + * + * + * + * + * + * + * + * + * + *
PropertyTypeDescription
Controller.Hardware.ActionsobjectSynonym for {@link Controller.Actions}.
Controller.Hardware.ApplicationobjectInterface state outputs. See + * {@link Controller.Hardware-Application}.
Controller.Hardware.KeyboardobjectKeyboard, mouse, and touch pad outputs. See + * {@link Controller.Hardware-Keyboard}.
Controller.Hardware.OculusTouchobjectOculus Rift HMD outputs. See + * {@link Controller.Hardware-OculusTouch}.
Controller.Hardware.ViveobjectVive HMD outputs. See + * {@link Controller.Hardware-Vive}.
+ * @typedef Controller.Hardware + * @example List all the currently available Controller.Hardware properties. + * function printProperties(string, item) { + * print(string); + * for (var key in item) { + * if (item.hasOwnProperty(key)) { + * printProperties(string + "." + key, item[key]); + * } + * } + * } + * + * printProperties("Controller.Hardware", Controller.Hardware); + */ // NOTE: If something inherits from both InputDevice and InputPlugin, InputPlugin must go first. // e.g. class Example : public InputPlugin, public InputDevice // instead of class Example : public InputDevice, public InputPlugin diff --git a/libraries/controllers/src/controllers/Pose.cpp b/libraries/controllers/src/controllers/Pose.cpp index fc0891799e..6f0296c09d 100644 --- a/libraries/controllers/src/controllers/Pose.cpp +++ b/libraries/controllers/src/controllers/Pose.cpp @@ -30,6 +30,15 @@ namespace controller { velocity == right.getVelocity() && angularVelocity == right.getAngularVelocity(); } + /**jsdoc + * The pose of a joint or other item relative to the world or a parent. + * @typedef {object} Pose + * @property {Vec3} translation - Translation. + * @property {Quat} rotation - Rotation. + * @property {Vec3} velocity - Velocity in m/s. + * @property {Vec3} angularVelocity - Angular velocity in rad/s. + * @property {boolean} valid - true if the pose is valid, otherwise false. + */ QScriptValue Pose::toScriptValue(QScriptEngine* engine, const Pose& pose) { QScriptValue obj = engine->newObject(); obj.setProperty("translation", vec3toScriptValue(engine, pose.translation)); @@ -37,7 +46,6 @@ namespace controller { obj.setProperty("velocity", vec3toScriptValue(engine, pose.velocity)); obj.setProperty("angularVelocity", vec3toScriptValue(engine, pose.angularVelocity)); obj.setProperty("valid", pose.valid); - return obj; } diff --git a/libraries/controllers/src/controllers/ScriptingInterface.h b/libraries/controllers/src/controllers/ScriptingInterface.h index fbc87898a4..fa5a21a791 100644 --- a/libraries/controllers/src/controllers/ScriptingInterface.h +++ b/libraries/controllers/src/controllers/ScriptingInterface.h @@ -1,6 +1,6 @@ // -// AbstractControllerScriptingInterface.h -// libraries/script-engine/src +// ScriptingInterface.h +// libraries/controllers/src/controllers // // Created by Brad Hefta-Gaub on 12/17/13. // Copyright 2013 High Fidelity, Inc. @@ -61,6 +61,8 @@ namespace controller { /// handles scripting of input controller commands from JS class ScriptingInterface : public QObject, public Dependency { Q_OBJECT + + // These properties have JSDoc in ControllerScriptingInterface.h. Q_PROPERTY(QVariantMap Hardware READ getHardware CONSTANT FINAL) Q_PROPERTY(QVariantMap Actions READ getActions CONSTANT FINAL) Q_PROPERTY(QVariantMap Standard READ getStandard CONSTANT FINAL) @@ -69,42 +71,373 @@ namespace controller { ScriptingInterface(); virtual ~ScriptingInterface() {}; + /**jsdoc + * Get a list of all available actions. + * @function Controller.getAllActions + * @returns {Action[]} All available actions. + * @deprecated This function no longer works. + */ + // FIXME: This function causes a JavaScript crash: https://highfidelity.manuscript.com/f/cases/edit/13921 Q_INVOKABLE QVector getAllActions(); + + /**jsdoc + * Get a list of all available inputs for a hardware device. + * @function Controller.getAvailableInputs + * @param {number} deviceID - Integer ID of the hardware device. + * @returns {NamedPair[]} All available inputs for the device. + * @deprecated This function no longer works. + */ + // FIXME: This function causes a JavaScript crash: https://highfidelity.manuscript.com/f/cases/edit/13922 Q_INVOKABLE QVector getAvailableInputs(unsigned int device); + + /**jsdoc + * Find the name of a particular controller from its device ID. + * @function Controller.getDeviceName + * @param {number} deviceID - The integer ID of the device. + * @returns {string} The name of the device if found, otherwise "unknown". + * @example Get the name of the Oculus Touch controller from its ID. + * var deviceID = Controller.findDevice("OculusTouch"); + * print("Device ID = " + deviceID); + * + * var deviceName = Controller.getDeviceName(deviceID); + * print("Device name = " + deviceName); + */ Q_INVOKABLE QString getDeviceName(unsigned int device); + + /**jsdoc + * Get the current value of an action. + * @function Controller.getActionValue + * @param {number} actionID - The integer ID of the action. + * @returns {number} The current value of the action. + * @example Periodically report the value of the "TranslateX" action. + * var actionID = Controller.findAction("TranslateX"); + * + * function reportValue() { + * print(Controller.getActionValue(actionID)); + * } + * reportTimer = Script.setInterval(reportValue, 1000); + */ Q_INVOKABLE float getActionValue(int action); + + /**jsdoc + * Find the ID of a specific controller from its device name. + * @function Controller.findDevice + * @param {string} deviceName - The name of the device to find. + * @returns {number} The integer ID of the device if available, otherwise 65535. + * @example Get the ID of the Oculus Touch. + * var deviceID = Controller.findDevice("OculusTouch"); + * print("Device ID = " + deviceID); + */ Q_INVOKABLE int findDevice(QString name); + + /**jsdoc + * Get the names of all currently available controller devices plus "Actions", "Application", and "Standard". + * @function Controller.getDeviceNames + * @returns {string[]} An array of device names. + * @example Get the names of all currently available controller devices. + * var deviceNames = Controller.getDeviceNames(); + * print(JSON.stringify(deviceNames)); + * // ["Standard","Keyboard","LeapMotion","OculusTouch","Application","Actions"] or similar. + */ Q_INVOKABLE QVector getDeviceNames(); + + /**jsdoc + * Find the ID of an action from its name. + * @function Controller.findAction + * @param {string} actionName - The name of the action: one of the {@link Controller.Actions} property names. + * @returns {number} The integer ID of the action if found, otherwise 4095. Note that this value is not + * the same as the value of the relevant {@link Controller.Actions} property. + * @example Get the ID of the "TranslateY" action. Compare with the property value. + * var actionID = Controller.findAction("TranslateY"); + * print("Action ID = " + actionID); // 1 + * print("Property value = " + Controller.Actions.TranslateY); // 537001728 or similar value. + */ Q_INVOKABLE int findAction(QString actionName); + + /**jsdoc + * Get the names of all actions available as properties of {@link Controller.Actions}. + * @function Controller.getActionNames + * @returns {string[]} An array of action names. + * @example Get the names of all actions. + * var actionNames = Controller.getActionNames(); + * print("Action names: " + JSON.stringify(actionNames)); + * // ["TranslateX","TranslateY","TranslateZ","Roll", ... + */ Q_INVOKABLE QVector getActionNames() const; + /**jsdoc + * Get the value of a controller button or axis output. Note: Also gets the value of a controller axis output. + * @function Controller.getValue + * @param {number} source - The {@link Controller.Standard} or {@link Controller.Hardware} item. + * @returns {number} The current value of the controller item output if source is valid, otherwise + * 0. + * @example Report the Standard and Vive right trigger values. + * var triggerValue = Controller.getValue(Controller.Standard.RT); + * print("Trigger value: " + triggerValue); + * + * if (Controller.Hardware.Vive) { + * triggerValue = Controller.getValue(Controller.Hardware.Vive.RT); + * print("Vive trigger value: " + triggerValue); + * } else { + * print("No Vive present"); + * } + */ Q_INVOKABLE float getValue(const int& source) const; - Q_INVOKABLE float getButtonValue(StandardButtonChannel source, uint16_t device = 0) const; - Q_INVOKABLE float getAxisValue(StandardAxisChannel source, uint16_t device = 0) const; + + /**jsdoc + * Get the value of a controller axis output. Note: Also gets the value of a controller button output. + * @function Controller.getAxisValue + * @param {number} source - The {@link Controller.Standard} or {@link Controller.Hardware} item. + * @returns {number} The current value of the controller item output if source is valid, otherwise + * 0. + */ + // TODO: getAxisValue() should use const int& parameter? Or others shouldn't? Q_INVOKABLE float getAxisValue(int source) const; + + /**jsdoc + * Get the value of a controller pose output. + * @function Controller.getPoseValue + * @param {number} source - The {@link Controller.Standard} or {@link Controller.Hardware} pose output. + * @returns {Pose} The current value of the controller pose output if source is a pose output, otherwise + * an invalid pose with Pose.valid == false. + * @exammple Report the right hand's pose. + * var pose = Controller.getPoseValue(Controller.Standard.RightHand); + * print("Pose: " + JSON.stringify(pose)); + */ Q_INVOKABLE Pose getPoseValue(const int& source) const; + + /**jsdoc + * Get the value of a button on a particular device. + * @function Controller.getButtonValue + * @param {StandardButtonChannel} source - The button to get the value of. + * @param {number} [device=0] - The ID of the hardware device to get the value from. The default value of + * 0 corresponds to Standard. + * @returns {number} The current value of the button if the parameters are valid, otherwise 0. + * @deprecated This function no longer works. + */ + // FIXME: This function causes a JavaScript crash: https://highfidelity.manuscript.com/f/cases/edit/14139 + Q_INVOKABLE float getButtonValue(StandardButtonChannel source, uint16_t device = 0) const; + + /**jsdoc + * Get the value of an axis control on a particular device. + * @function Controller.getAxisValue + * @variation 0 + * @param {StandardAxisChannel} source - The axis to get the value of. + * @param {number} [device=0] - The ID of the hardware device to get the value from. The default value of + * 0 corresponds to Standard. + * @returns {number} The current value of the axis if the parameters are valid, otherwise 0. + * @deprecated This function no longer works. + */ + Q_INVOKABLE float getAxisValue(StandardAxisChannel source, uint16_t device = 0) const; + + /**jsdoc + * Get the value of an pose control on a particular device. + * @function Controller.getPoseValue + * @variation 0 + * @param {StandardPoseChannel} source - The pose to get the value of. + * @param {number} [device=0] - The ID of the hardware device to get the value from. The default value of + * 0 corresponds to Standard. + * @returns {Pose} The current value of the controller pose output if the parameters are valid, otherwise an invalid + * pose with Pose.valid == false. + * @deprecated This function no longer works. + */ Q_INVOKABLE Pose getPoseValue(StandardPoseChannel source, uint16_t device = 0) const; + /**jsdoc + * Triggers a haptic pulse on connected and enabled devices that have the capability. + * @function Controller.triggerHapticPulse + * @param {number} strength - The strength of the haptic pulse, 0.01.0. + * @param {number} duration - The duration of the haptic pulse, in milliseconds. + * @param {Controller.Hand} hand=2 - The hand or hands to trigger the haptic pulse on. + * @example Trigger a haptic pulse on the right hand. + * var HAPTIC_STRENGTH = 0.5; + * var HAPTIC_DURATION = 10; + * var RIGHT_HAND = 1; + * Controller.triggerHapticPulse(HAPTIC_STRENGTH, HAPTIC_DURATION, RIGHT_HAND); + */ Q_INVOKABLE bool triggerHapticPulse(float strength, float duration, controller::Hand hand = BOTH) const; - Q_INVOKABLE bool triggerShortHapticPulse(float strength, controller::Hand hand = BOTH) const; - Q_INVOKABLE bool triggerHapticPulseOnDevice(unsigned int device, float strength, float duration, controller::Hand hand = BOTH) const; - Q_INVOKABLE bool triggerShortHapticPulseOnDevice(unsigned int device, float strength, controller::Hand hand = BOTH) const; + /**jsdoc + * Triggers a 250ms haptic pulse on connected and enabled devices that have the capability. + * @function Controller.triggerShortHapticPulse + * @param {number} strength - The strength of the haptic pulse, 0.01.0. + * @param {Controller.Hand} hand=2 - The hand or hands to trigger the haptic pulse on. + */ + Q_INVOKABLE bool triggerShortHapticPulse(float strength, controller::Hand hand = BOTH) const; + + /**jsdoc + * Triggers a haptic pulse on a particular device if connected and enabled and it has the capability. + * @function Controller.triggerHapticPulseOnDevice + * @param {number} deviceID - The ID of the device to trigger the haptic pulse on. + * @param {number} strength - The strength of the haptic pulse, 0.01.0. + * @param {number} duration - The duration of the haptic pulse, in milliseconds. + * @param {Controller.Hand} hand=2 - The hand or hands to trigger the haptic pulse on. + * @example Trigger a haptic pulse on an Oculus Touch controller. + * var HAPTIC_STRENGTH = 0.5; + * var deviceID = Controller.findDevice("OculusTouch"); + * var HAPTIC_DURATION = 10; + * var RIGHT_HAND = 1; + * Controller.triggerHapticPulseOnDevice(deviceID, HAPTIC_STRENGTH, HAPTIC_DURATION, RIGHT_HAND); + */ + Q_INVOKABLE bool triggerHapticPulseOnDevice(unsigned int device, float strength, float duration, + controller::Hand hand = BOTH) const; + + /**jsdoc + * Triggers a 250ms haptic pulse on a particular device if connected and enabled and it has the capability. + * @function Controller.triggerShortHapticPulseOnDevice + * @param {number} deviceID - The ID of the device to trigger the haptic pulse on. + * @param {number} strength - The strength of the haptic pulse, 0.01.0. + * @param {Controller.Hand} hand=2 - The hand or hands to trigger the haptic pulse on. + */ + Q_INVOKABLE bool triggerShortHapticPulseOnDevice(unsigned int device, float strength, controller::Hand hand = BOTH) + const; + + + /**jsdoc + * Create a new controller mapping. Routes can then be added to the mapping using {@link MappingObject} methods and + * routed to Standard controls, Actions, or script functions using {@link RouteObject} + * methods. The mapping can then be enabled using {@link Controller.enableMapping|enableMapping} for it to take effect. + * @function Controller.newMapping + * @param {string} mappingName=Uuid.generate() - A unique name for the mapping. If not specified a new UUID generated + * by {@link Uuid.generate} is used. + * @returns {MappingObject} A controller mapping object. + * @example Create a simple mapping that makes the right trigger move your avatar up. + * var MAPPING_NAME = "com.highfidelity.controllers.example.newMapping"; + * var mapping = Controller.newMapping(MAPPING_NAME); + * + * mapping.from(Controller.Standard.RT).to(Controller.Actions.TranslateY); + * Controller.enableMapping(MAPPING_NAME); + * + * Script.scriptEnding.connect(function () { + * Controller.disableMapping(MAPPING_NAME); + * }); + */ Q_INVOKABLE QObject* newMapping(const QString& mappingName = QUuid::createUuid().toString()); + + /**jsdoc + * Enable or disable a controller mapping. When enabled, the routes in the mapping have effect. + * @function Controller.enableMapping + * @param {string} mappingName - The name of the mapping. + * @param {boolean} enable=true - If true then the mapping is enabled, otherwise it is disabled. + */ Q_INVOKABLE void enableMapping(const QString& mappingName, bool enable = true); + + /**jsdoc + * Disable a controller mapping. When disabled, the routes in the mapping have no effect. + * @function Controller.disableMapping + * @param {string} mappingName - The name of the mapping. + */ Q_INVOKABLE void disableMapping(const QString& mappingName) { enableMapping(mappingName, false); } + + /**jsdoc + * Create a new controller mapping from a {@link Controller.MappingJSON|MappingJSON} string. Use + * {@link Controller.enableMapping|enableMapping} to enable the mapping for it to take effect. + * @function Controller.parseMapping + * @param {string} jsonString - A JSON string of the {@link Controller.MappingJSON|MappingJSON}. + * @returns {MappingObject} A controller mapping object. + * @example Create a simple mapping that makes the right trigger move your avatar up. + * var mappingJSON = { + * "name": "com.highfidelity.controllers.example.jsonMapping", + * "channels": [ + * { "from": "Standard.RT", "to": "Actions.TranslateY" } + * ] + * }; + * + * var mapping = Controller.parseMapping(JSON.stringify(mappingJSON)); + * mapping.enable(); + * + * Script.scriptEnding.connect(function () { + * mapping.disable(); + * }); + */ Q_INVOKABLE QObject* parseMapping(const QString& json); + + /**jsdoc + * Create a new controller mapping from a {@link Controller.MappingJSON|MappingJSON} JSON file at a URL. Use + * {@link Controller.enableMapping|enableMapping} to enable the mapping for it to take effect. + * @function Controller.loadMapping + * @param {string} jsonURL - The URL the {@link Controller.MappingJSON|MappingJSON} JSON file. + * @returns {MappingObject} A controller mapping object. + * @todo Implement this function. It currently does not load the mapping from the file; it just returns + * null. + */ Q_INVOKABLE QObject* loadMapping(const QString& jsonUrl); + + /**jsdoc + * Get the {@link Controller.Hardware} property tree. Calling this function is the same as using the {@link Controller} + * property, Controller.Hardware. + * @function Controller.getHardware + * @returns {Controller.Hardware} The {@link Controller.Hardware} property tree. + */ Q_INVOKABLE const QVariantMap getHardware() { return _hardware; } - Q_INVOKABLE const QVariantMap getActions() { return _actions; } + + /**jsdoc + * Get the {@link Controller.Actions} property tree. Calling this function is the same as using the {@link Controller} + * property, Controller.Actions. + * @function Controller.getActions + * @returns {Controller.Actions} The {@link Controller.Actions} property tree. + */ + Q_INVOKABLE const QVariantMap getActions() { return _actions; } //undefined + + /**jsdoc + * Get the {@link Controller.Standard} property tree. Calling this function is the same as using the {@link Controller} + * property, Controller.Standard. + * @function Controller.getStandard + * @returns {Controller.Standard} The {@link Controller.Standard} property tree. + */ Q_INVOKABLE const QVariantMap getStandard() { return _standard; } + + + /**jsdoc + * Start making a recording of currently active controllers. + * @function Controller.startInputRecording + */ Q_INVOKABLE void startInputRecording(); + + /**jsdoc + * Stop making a recording started by {@link Controller.startInputRecording|startInputRecording}. + * @function Controller.stopInputRecording + */ Q_INVOKABLE void stopInputRecording(); + + /**jsdoc + * Play back the current recording from the beginning. The current recording may have been recorded by + * {@link Controller.startInputRecording|startInputRecording} and + * {@link Controller.stopInputRecording|stopInputRecording}, or loaded by + * {@link Controller.loadInputRecording|loadInputRecording}. + * @function Controller.startInputPlayback + */ Q_INVOKABLE void startInputPlayback(); + + /**jsdoc + * Stop play back of a recording started by {@link Controller.startInputPlayback|startInputPlayback}. + * @function Controller.stopInputPlayback + */ Q_INVOKABLE void stopInputPlayback(); + + /**jsdoc + * Save the current recording to a file. The current recording may have been recorded by + * {@link Controller.startInputRecording|startInputRecording} and + * {@link Controller.stopInputRecording|stopInputRecording}, or loaded by + * {@link Controller.loadInputRecording|loadInputRecording}. It is saved in the directory returned by + * {@link Controller.getInputRecorderSaveDirectory|getInputRecorderSaveDirectory}. + * @function Controller.saveInputRecording + */ Q_INVOKABLE void saveInputRecording(); + + /**jsdoc + * Load an input recording, ready for play back. + * @function Controller.loadInputRecording + * @parameter {string} file - The path to the recording file. + */ Q_INVOKABLE void loadInputRecording(const QString& file); + + /**jsdoc + * Get the directory in which input recordings are saved. + * @function Controller.getInputRecorderSaveDirectory + * @returns {string} The directory in which input recordings are saved. + */ Q_INVOKABLE QString getInputRecorderSaveDirectory(); bool isMouseCaptured() const { return _mouseCaptured; } @@ -114,21 +447,156 @@ namespace controller { public slots: + /**jsdoc + * Disable processing of mouse "move", "press", "double-press", and "release" events into + * {@link Controller.Hardware|Controller.Hardware.Keyboard} outputs. + * @function Controller.captureMouseEvents + * @example Disable Controller.Hardware.Keyboard mouse events for a short period. + * var MAPPING_NAME = "com.highfidelity.controllers.example.newMapping"; + * var mapping = Controller.newMapping(MAPPING_NAME); + * mapping.from(Controller.Hardware.Keyboard.MouseX).to(function (x) { + * print("Mouse x = " + x); + * }); + * mapping.from(Controller.Hardware.Keyboard.MouseY).to(function (y) { + * print("Mouse y = " + y); + * }); + * Controller.enableMapping(MAPPING_NAME); + * Script.scriptEnding.connect(function () { + * Controller.disableMapping(MAPPING_NAME); + * }); + * + * Script.setTimeout(function () { + * Controller.captureMouseEvents(); + * }, 5000); + * + * Script.setTimeout(function () { + * Controller.releaseMouseEvents(); + * }, 10000); + */ virtual void captureMouseEvents() { _mouseCaptured = true; } + + /**jsdoc + * Enable processing of mouse "move", "press", "double-press", and "release" events into + * {@link Controller.Hardware-Keyboard|Controller.Hardware.Keyboard} outputs that was disabled using + * {@link Controller.captureMouseEvents|captureMouseEvents}. + * @function Controller.releaseMouseEvents + */ virtual void releaseMouseEvents() { _mouseCaptured = false; } + + /**jsdoc + * Disable processing of touch "begin", "update", and "end" events into + * {@link Controller.Hardware|Controller.Hardware.Keyboard}, + * {@link Controller.Hardware|Controller.Hardware.Touchscreen}, and + * {@link Controller.Hardware|Controller.Hardware.TouchscreenVirtualPad} outputs. + * @function Controller.captureTouchEvents + */ virtual void captureTouchEvents() { _touchCaptured = true; } + + /**jsdoc + * Enable processing of touch "begin", "update", and "end" events into + * {@link Controller.Hardware|Controller.Hardware.Keyboard}, + * {@link Controller.Hardware|Controller.Hardware.Touchscreen}, and + * {@link Controller.Hardware|Controller.Hardware.TouchscreenVirtualPad} outputs that was disabled using + * {@link Controller.captureTouchEvents|captureTouchEvents}. + * @function Controller.releaseTouchEvents + */ virtual void releaseTouchEvents() { _touchCaptured = false; } + + /**jsdoc + * Disable processing of mouse wheel rotation events into {@link Controller.Hardware|Controller.Hardware.Keyboard} + * outputs. + * @function Controller.captureWheelEvents + */ virtual void captureWheelEvents() { _wheelCaptured = true; } + + /**jsdoc + * Enable processing of mouse wheel rotation events into {@link Controller.Hardware|Controller.Hardware.Keyboard} + * outputs that was disabled using {@link Controller.captureWheelEvents|captureWheelEvents}. + * @function Controller.releaseWheelEvents + */ virtual void releaseWheelEvents() { _wheelCaptured = false; } + + /**jsdoc + * Disable translating and rotating the user's avatar in response to keyboard and controller controls. + * @function Controller.captureActionEvents + * @example Disable avatar translation and rotation for a short period. + * Script.setTimeout(function () { + * Controller.captureActionEvents(); + * }, 5000); + * + * Script.setTimeout(function () { + * Controller.releaseActionEvents(); + * }, 10000); + */ virtual void captureActionEvents() { _actionsCaptured = true; } + + /**jsdoc + * Enable translating and rotating the user's avatar in response to keyboard and controller controls that was disabled + * using {@link Controller.captureActionEvents|captureActionEvents}. + * @function Controller.releaseActionEvents + */ virtual void releaseActionEvents() { _actionsCaptured = false; } signals: + /**jsdoc + * Triggered when an action occurs. + * @function Controller.actionEvent + * @param {number} actionID - The ID of the action, per {@link Controller.findAction|findAction}. + * @param {number} value - The value associated with the action. + * @returns {Signal} + * @example Report action events as they occur. + * var actionNamesForID = {}; + * var actionNames = Controller.getActionNames(); + * for (var i = 0, length = actionNames.length; i < length; i++) { + * actionNamesForID[Controller.findAction(actionNames[i])] = actionNames[i]; + * } + * + * function onActionEvent(action, value) { + * print("onActionEvent() : " + action + " ( " + actionNamesForID[action] + " ) ; " + value); + * } + * + * Controller.actionEvent.connect(onActionEvent); + * + * Script.scriptEnding.connect(function () { + * Controller.actionEvent.disconnect(onActionEvent); + * }); + */ void actionEvent(int action, float state); + + /**jsdoc + * Triggered when there is a new controller input event. + * @function Controller.inputEvent + * @param {number} action - The input action, per {@link Controller.Standard}. + * @param {number} value - The value associated with the input action. + * @returns {Signal} + * @example Report input events as they occur. + * var inputNamesForID = {}; + * for (var property in Controller.Standard) { + * inputNamesForID[Controller.Standard[property]] = "Controller.Standard." + property; + * } + * + * function onInputEvent(input, value) { + * print("onInputEvent() : " + input + " ( " + inputNamesForID[input] + " ) ; " + value); + * } + * + * Controller.inputEvent.connect(onInputEvent); + * + * Script.scriptEnding.connect(function () { + * Controller.inputEvent.disconnect(onInputEvent); + * }); + */ void inputEvent(int action, float state); + + /**jsdoc + * Triggered when a device is registered or unregistered by a plugin. Not all plugins generate + * hardwareChanged events: for example connecting or disconnecting a mouse will not generate an event but + * connecting or disconnecting an Xbox controller will. + * @function Controller.hardwareChanged + * @returns {Signal} + */ void hardwareChanged(); private: @@ -145,8 +613,6 @@ namespace controller { std::atomic _actionsCaptured { false }; }; - } - #endif // hifi_AbstractControllerScriptingInterface_h diff --git a/libraries/controllers/src/controllers/StandardController.cpp b/libraries/controllers/src/controllers/StandardController.cpp index ed729867df..a7daeb6836 100644 --- a/libraries/controllers/src/controllers/StandardController.cpp +++ b/libraries/controllers/src/controllers/StandardController.cpp @@ -27,6 +27,212 @@ void StandardController::focusOutEvent() { _buttonPressedMap.clear(); }; +/**jsdoc + *

The Controller.Standard object has properties representing standard controller outputs. Those for physical + * controllers are based on the XBox controller, with aliases for PlayStation. The property values are integer IDs, uniquely + * identifying each output. Read-only. These can be can be mapped to actions or functions in a {@link RouteObject} + * mapping.

+ * + *

The data value provided by each control is either a number or a {@link Pose}. Numbers are typically normalized to + * 0.0 or 1.0 for button states, the range 0.0 – 1.0 for unidirectional scales, + * and the range -1.0 – 1.0 for bidirectional scales.

+ * + *

Each hardware device has a mapping from its outputs to Controller.Standard items, specified in a JSON file. + * For example, + * leapmotion.json and + * vive.json.

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
PropertyTypeDataDescription
Buttons
Anumbernumber"A" button pressed.
Bnumbernumber"B" button pressed.
Xnumbernumber"X" button pressed.
Ynumbernumber"Y" button pressed.
DLnumbernumberD-pad left pressed.
DRnumbernumberD-pad right pressed.
DUnumbernumberD-pad up pressed.
DDnumbernumberD-pad down pressed.
Startnumbernumber"Start" center button pressed.
Backnumbernumber"Back" center button pressed.
LBnumbernumberLeft bumper button pressed.
RBnumbernumberRight bumper button pressed.
Sticks
LXnumbernumberLeft stick x-axis scale.
LYnumbernumberleft stick y-axis scale.
RXnumbernumberRight stick x-axis scale.
RYnumbernumberRight stick y-axis scale.
LSnumbernumberLeft stick button pressed.
RSnumbernumberRight stick button pressed.
LSTouchnumbernumberLeft stick is touched.
RSTouchnumbernumberRight stick is touched.
Triggers
LTnumbernumberLeft trigger scale.
RTnumbernumberRight trigger scale.
LTClicknumbernumberLeft trigger click.
RTClicknumbernumberRight trigger click.
LeftGripnumbernumberLeft grip scale.
RightGripnumbernumberRight grip scale.
LeftGripTouchnumbernumberLeft grip is touched.
RightGripTouchnumbernumberRight grip is touched.
Aliases, PlayStation Style Names
CrossnumbernumberAlias for A.
CirclenumbernumberAlias for B.
SquarenumbernumberAlias for X.
TrianglenumbernumberAlias for Y.
LeftnumbernumberAlias for DL.
RightnumbernumberAlias for DR.
UpnumbernumberAlias for DU.
DownnumbernumberAlias for DD.
SelectnumbernumberAlias for Back.
L1numbernumberAlias for LB.
R1numbernumberAlias for RB.
L3numbernumberAlias for LS.
R3numbernumberAlias for RS.
L2numbernumberAlias for LT.
R2numbernumberAlias for RT.
Finger Abstractions
LeftPrimaryThumbnumbernumberLeft primary thumb button pressed.
LeftSecondaryThumbnumbernumberLeft secondary thumb button pressed. + *
RightPrimaryThumbnumbernumberRight primary thumb button pressed. + *
RightSecondaryThumbnumbernumberRight secondary thumb button pressed. + *
LeftPrimaryThumbTouchnumbernumberLeft thumb touching primary thumb + * button.
LeftSecondaryThumbTouchnumbernumberLeft thumb touching secondary thumb + * button.
LeftThumbUpnumbernumberLeft thumb not touching primary or secondary + * thumb buttons.
RightPrimaryThumbTouchnumbernumberRight thumb touching primary thumb + * button.
RightSecondaryThumbTouchnumbernumberRight thumb touching secondary thumb + * button.
RightThumbUpnumbernumberRight thumb not touching primary or secondary + * thumb buttons.
LeftPrimaryIndexnumbernumberLeft primary index control pressed. + * To Do: Implement this for current controllers.
LeftSecondaryIndexnumbernumberLeft secondary index control pressed. + *
RightPrimaryIndexnumbernumberRight primary index control pressed. + * To Do: Implement this for current controllers.
RightSecondaryIndexnumbernumberRight secondary index control pressed. + *
LeftPrimaryIndexTouchnumbernumberLeft index finger is touching primary + * index finger control.
LeftSecondaryIndexTouchnumbernumberLeft index finger is touching + * secondary index finger control.
LeftIndexPointnumbernumberLeft index finger is pointing, not touching + * primary or secondary index finger controls.
RightPrimaryIndexTouchnumbernumberRight index finger is touching primary + * index finger control.
RightSecondaryIndexTouchnumbernumberRight index finger is touching + * secondary index finger control.
RightIndexPointnumbernumberRight index finger is pointing, not touching + * primary or secondary index finger controls.
Avatar Skeleton
Hipsnumber{@link Pose}Hips pose.
Spine2number{@link Pose}Spine2 pose.
Headnumber{@link Pose}Head pose.
LeftArmnumber{@link Pose}Left arm pose.
RightArmnumber{@link Pose}Right arm pose
LeftHandnumber{@link Pose}Left hand pose.
LeftHandThumb1number{@link Pose}Left thumb 1 finger joint pose.
LeftHandThumb2number{@link Pose}Left thumb 2 finger joint pose.
LeftHandThumb3number{@link Pose}Left thumb 3 finger joint pose.
LeftHandThumb4number{@link Pose}Left thumb 4 finger joint pose.
LeftHandIndex1number{@link Pose}Left index 1 finger joint pose.
LeftHandIndex2number{@link Pose}Left index 2 finger joint pose.
LeftHandIndex3number{@link Pose}Left index 3 finger joint pose.
LeftHandIndex4number{@link Pose}Left index 4 finger joint pose.
LeftHandMiddle1number{@link Pose}Left middle 1 finger joint pose. + *
LeftHandMiddle2number{@link Pose}Left middle 2 finger joint pose. + *
LeftHandMiddle3number{@link Pose}Left middle 3 finger joint pose. + *
LeftHandMiddle4number{@link Pose}Left middle 4 finger joint pose. + *
LeftHandRing1number{@link Pose}Left ring 1 finger joint pose.
LeftHandRing2number{@link Pose}Left ring 2 finger joint pose.
LeftHandRing3number{@link Pose}Left ring 3 finger joint pose.
LeftHandRing4number{@link Pose}Left ring 4 finger joint pose.
LeftHandPinky1number{@link Pose}Left pinky 1 finger joint pose.
LeftHandPinky2number{@link Pose}Left pinky 2 finger joint pose.
LeftHandPinky3number{@link Pose}Left pinky 3 finger joint pose.
LeftHandPinky4number{@link Pose}Left pinky 4 finger joint pose.
RightHandnumber{@link Pose}Right hand pose.
RightHandThumb1number{@link Pose}Right thumb 1 finger joint pose. + *
RightHandThumb2number{@link Pose}Right thumb 2 finger joint pose. + *
RightHandThumb3number{@link Pose}Right thumb 3 finger joint pose. + *
RightHandThumb4number{@link Pose}Right thumb 4 finger joint pose. + *
RightHandIndex1number{@link Pose}Right index 1 finger joint pose. + *
RightHandIndex2number{@link Pose}Right index 2 finger joint pose. + *
RightHandIndex3number{@link Pose}Right index 3 finger joint pose. + *
RightHandIndex4number{@link Pose}Right index 4 finger joint pose. + *
RightHandMiddle1number{@link Pose}Right middle 1 finger joint pose. + *
RightHandMiddle2number{@link Pose}Right middle 2 finger joint pose. + *
RightHandMiddle3number{@link Pose}Right middle 3 finger joint pose. + *
RightHandMiddle4number{@link Pose}Right middle 4 finger joint pose. + *
RightHandRing1number{@link Pose}Right ring 1 finger joint pose.
RightHandRing2number{@link Pose}Right ring 2 finger joint pose.
RightHandRing3number{@link Pose}Right ring 3 finger joint pose.
RightHandRing4number{@link Pose}Right ring 4 finger joint pose.
RightHandPinky1number{@link Pose}Right pinky 1 finger joint pose. + *
RightHandPinky2number{@link Pose}Right pinky 2 finger joint pose. + *
RightHandPinky3number{@link Pose}Right pinky 3 finger joint pose. + *
RightHandPinky4number{@link Pose}Right pinky 4 finger joint pose. + *
LeftFootnumber{@link Pose}Left foot pose.
RightFootnumber{@link Pose}Right foot pose.
Trackers
TrackedObject00number{@link Pose}Tracker 0 pose.
TrackedObject01number{@link Pose}Tracker 1 pose.
TrackedObject02number{@link Pose}Tracker 2 pose.
TrackedObject03number{@link Pose}Tracker 3 pose.
TrackedObject04number{@link Pose}Tracker 4 pose.
TrackedObject05number{@link Pose}Tracker 5 pose.
TrackedObject06number{@link Pose}Tracker 6 pose.
TrackedObject07number{@link Pose}Tracker 7 pose.
TrackedObject08number{@link Pose}Tracker 8 pose.
TrackedObject09number{@link Pose}Tracker 9 pose.
TrackedObject10number{@link Pose}Tracker 10 pose.
TrackedObject11number{@link Pose}Tracker 11 pose.
TrackedObject12number{@link Pose}Tracker 12 pose.
TrackedObject13number{@link Pose}Tracker 13 pose.
TrackedObject14number{@link Pose}Tracker 14 pose.
TrackedObject15number{@link Pose}Tracker 15 pose.
+ * @typedef Controller.Standard + */ Input::NamedVector StandardController::getAvailableInputs() const { static Input::NamedVector availableInputs { // Buttons diff --git a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h index ac9a5a300d..86a43c0c13 100644 --- a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h +++ b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h @@ -24,6 +24,101 @@ namespace controller { class ScriptingInterface; class UserInputMapper; +/**jsdoc + *

A {@link Controller} mapping object that can contain a set of routes that map:

+ *
    + *
  • {@link Controller.Standard} outputs to {@link Controller.Actions} actions or script functions.
  • + *
  • {@link Controller.Hardware} outputs to {@link Controller.Standard} outputs, {@link Controller.Actions} actions, or + * script functions.
  • + *
+ * + *

Create by one of the following methods:

+ *
    + *
  • Use {@link Controller.newMapping} to create the mapping object, add routes using {@link MappingObject#from|from} or + * {@link MappingObject#makeAxis|makeAxis}, and map the routes to actions or functions using {@link RouteObject} + * methods.
  • + *
  • Use {@link Controller.parseMapping} or {@link Controller.loadMapping} to load a {@link Controller.MappingJSON}.
  • + *
+ *

Enable the mapping using {@link MappingObject#enable|enable} or {@link Controller.enableMapping} for it to take effect. + * + *

Mappings and their routes are applied according to the following rules:

+ *
    + *
  • One read per output: after a controller output has been read, it can't be read again. Exception: You can use + * {@link RouteObject#peek} to read a value without marking that output as having been read.
  • + *
  • Existing mapping routes take precedence over new mapping routes: within a mapping, if a route is added for a control + * output that already has a route the new route is ignored.
  • + *
  • New mappings override previous mappings: each output is processed using the route in the most recently enabled + * mapping that contains that output.
  • + *

    + * + * @class MappingObject + */ + +/**jsdoc + * A {@link MappingObject} can be specified in JSON format. A simple example is provided below. Full examples — the + * default mappings provided in Interface — can be found at + * + * https://github.com/highfidelity/hifi/tree/master/interface/resources/controllers. + * @typedef {object} Controller.MappingJSON + * @property {string} name - The name of the mapping. + * @property {Controller.MappingJSONRoute[]} channels - An array of routes. + * @example A simple mapping JSON that makes the right trigger move your avatar up after a dead zone. + * { + * "name": "com.highfidelity.controllers.example.jsonMapping", + * "channels": [ + * { + * "from": "Standard.RT", + * "filters": { "type": "deadZone", "min": 0.05 }, + * "to": "Actions.TranslateY" + * } + * ] + * } + */ + +/**jsdoc + * A route in a {@link Controller.MappingJSON}. + * @typedef {object} Controller.MappingJSONRoute + * @property {string|Controller.MappingJSONAxis} from - The name of a {@link Controller.Hardware} property name or an axis + * made from them. If a property name, the leading "Controller.Hardware." can be omitted. + * @property {boolean} [peek=false] - If true then peeking is enabled per {@link RouteObject#peek}. + * @property {boolean} [debug=false] - If true then debug is enabled per {@link RouteObject#debug}. + * @property {string|string[]} [when=[]] - One or more numeric {@link Controller.Hardware} property names which are evaluated + * as booleans and ANDed together. Prepend with a ! to use the logical NOT of the property value. The leading + * "Controller.Hardware." can be omitted from the property names. + * @property {Controller.MappingJSONFilter|Controller.MappingJSONFilter[]} [filters=[]] - One or more filters in the route. + * @property {string} to - The name of a {@link Controller.Actions} or {@link Controller.Standard} property. The leading + * "Controller." can be omitted. + */ + +/**jsdoc + * An axis pair in a {@link Controller.MappingJSONRoute}. + * @typedef {object} Controller.MappingJSONAxis + * @property {string[][]} makeAxis - A two-member array of single-member arrays of {@link Controller.Hardware} property names. + * The leading "Controller.Hardware." can be omitted from the property names. + * @example An axis using the keyboard's left and right keys. + * { "makeAxis" : [ + * ["Keyboard.Left"], + * ["Keyboard.Right"] + * ] + * } + */ + +/**jsdoc + * A filter in a {@link Controller.MappingJSONRoute}. + * @typedef {object} Controller.MappingJSONFilter + * @property {string} type - The name of the filter, being the name of the one of the {@link RouteObject}'s filter methods. + * @property {string} [?] - If the filter method has a first parameter, the property name is the name of that parameter and the + * property value is the value to use. + * @property {string} [?] - If the filter method has a second parameter, the property name is the name of that parameter and + * the property value is the value to use. + * @example A hysteresis filter. + * { + * "type": "hysteresis", + * "min": 0.85, + * "max": 0.9 + * } + */ + // TODO migrate functionality to a MappingBuilder class and make the proxy defer to that // (for easier use in both C++ and JS) class MappingBuilderProxy : public QObject { @@ -32,13 +127,76 @@ public: MappingBuilderProxy(UserInputMapper& parent, Mapping::Pointer mapping) : _parent(parent), _mapping(mapping) { } + /**jsdoc + * Create a new {@link RouteObject} from a controller output, ready to be mapped to a standard control, action, or + * function.
    + * This is a QML-specific version of {@link MappingObject#from|from}: use this version in QML files. + * @function MappingObject#fromQml + * @param {Controller.Standard|Controller.Hardware|function} source - The controller output or function that is the source + * of the route data. If a function, it must return a number or a {@link Pose} value as the route data. + * @returns {RouteObject} A route ready for mapping to an action or function using {@link RouteObject} methods. + */ Q_INVOKABLE QObject* fromQml(const QJSValue& source); + + /**jsdoc + * Create a new {@link RouteObject} from two numeric {@link Controller.Hardware} outputs, one applied in the negative + * direction and the other in the positive direction, ready to be mapped to a standard control, action, or function.
    + * This is a QML-specific version of {@link MappingObject#makeAxis|makeAxis}: use this version in QML files. + * @function MappingObject#makeAxisQml + * @param {Controller.Hardware} source1 - The first, negative-direction controller output. + * @param {Controller.Hardware} source2 - The second, positive-direction controller output. + * @returns {RouteObject} A route ready for mapping to an action or function using {@link RouteObject} methods. The data + * value passed to the route is the combined value of source2 - source1. + */ Q_INVOKABLE QObject* makeAxisQml(const QJSValue& source1, const QJSValue& source2); + /**jsdoc + * Create a new {@link RouteObject} from a controller output, ready to be mapped to a standard control, action, or + * function. + * @function MappingObject#from + * @param {Controller.Standard|Controller.Hardware|function} source - The controller output or function that is the source + * of the route data. If a function, it must return a number or a {@link Pose} value as the route data. + * @returns {RouteObject} A route ready for mapping to an action or function using {@link RouteObject} methods. + */ Q_INVOKABLE QObject* from(const QScriptValue& source); + + /**jsdoc + * Create a new {@link RouteObject} from two numeric {@link Controller.Hardware} outputs, one applied in the negative + * direction and the other in the positive direction, ready to be mapped to a standard control, action, or function. + * @function MappingObject#makeAxis + * @param {Controller.Hardware} source1 - The first, negative-direction controller output. + * @param {Controller.Hardware} source2 - The second, positive-direction controller output. + * @returns {RouteObject} A route ready for mapping to an action or function using {@link RouteObject} methods. The data + * value passed to the route is the combined value of source2 - source1. + * @example Make the Oculus Touch triggers move your avatar up and down. + * var MAPPING_NAME = "com.highfidelity.controllers.example.newMapping"; + * var mapping = Controller.newMapping(MAPPING_NAME); + * mapping + * .makeAxis(Controller.Hardware.OculusTouch.LT, Controller.Hardware.OculusTouch.RT) + * .to(Controller.Actions.Up); + * Controller.enableMapping(MAPPING_NAME); + * + * Script.scriptEnding.connect(function () { + * Controller.disableMapping(MAPPING_NAME); + * }); + */ Q_INVOKABLE QObject* makeAxis(const QScriptValue& source1, const QScriptValue& source2); + /**jsdoc + * Enable or disable the mapping. When enabled, the routes in the mapping take effect.
    + * Synonymous with {@link Controller.enableMapping}. + * @function MappingObject#enable + * @param {boolean} enable=true - If true then the mapping is enabled, otherwise it is disabled. + * @returns {MappingObject} The mapping object, so that further routes can be added. + */ Q_INVOKABLE QObject* enable(bool enable = true); + + /**jsdoc + * Disable the mapping. When disabled, the routes in the mapping have no effect.
    + * Synonymous with {@link Controller.disableMapping}. + * @function MappingObject#disable + * @returns {MappingObject} The mapping object, so that further routes can be added. + */ Q_INVOKABLE QObject* disable() { return enable(false); } protected: diff --git a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h index 92a87e5e39..0336638068 100644 --- a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h +++ b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h @@ -25,6 +25,18 @@ namespace controller { class ScriptingInterface; +/**jsdoc + *

    A route in a {@link MappingObject} used by the {@link Controller} API.

    + * + *

    Create a route using {@link MappingObject} methods and apply this object's methods to process it, terminating with + * {@link RouteObject#to} to apply it to a Standard control, action, or script function.

    + * + *

    Some methods apply to routes with number data, some apply routes with {@link Pose} data, and some apply to both route + * types.

    + * + * @class RouteObject + */ + // TODO migrate functionality to a RouteBuilder class and make the proxy defer to that // (for easier use in both C++ and JS) class RouteBuilderProxy : public QObject { @@ -33,27 +45,404 @@ class RouteBuilderProxy : public QObject { RouteBuilderProxy(UserInputMapper& parent, Mapping::Pointer mapping, Route::Pointer route) : _parent(parent), _mapping(mapping), _route(route) { } + /**jsdoc + * Terminate the route with a standard control, an action, or a script function. The output value from the route is + * sent to the specified destination.
    + * This is a QML-specific version of {@link MappingObject#to|to}: use this version in QML files. + * @function RouteObject#toQml + * @param {Controller.Standard|Controller.Actions|function} destination - The standard control, action, or JavaScript + * function that the route output is mapped to. For a function, the parameter can be either the name of the function or + * an in-line function definition. + */ Q_INVOKABLE void toQml(const QJSValue& destination); + + /**jsdoc + * Process the route only if a condition is satisfied. The condition is evaluated before the route input is read, and + * the input is read only if the condition is true. Thus, if the condition is not met then subsequent + * routes using the same input are processed.
    + * This is a QML-specific version of {@link MappingObject#to|to}: use this version in QML files. + * @function RouteObject#whenQml + * @param {condition|condition[]} expression -

    A condition may be a:

    + *
      + *
    • A boolean or numeric {@link Controller.Hardware} property, which is evaluated as a boolean.
    • + *
    • ! followed by a {@link Controller.Hardware} property, indicating the logical NOT should be + * used.
    • + *
    • A script function returning a boolean value. This can be either the name of the function or an in-line + * definition.
    • + *
    + *

    If an array of conditions is provided, their values are ANDed together.

    + * @returns {RouteObject} The RouteObject with the condition added. + */ Q_INVOKABLE QObject* whenQml(const QJSValue& expression); + /**jsdoc + * Terminate the route with a standard control, an action, or a script function. The output value from the route is + * sent to the specified destination. + * @function RouteObject#to + * @param {Controller.Standard|Controller.Actions|function} destination - The standard control, action, or JavaScript + * function that the route output is mapped to. For a function, the parameter can be either the name of the function or + * an in-line function definition. + * + * @example Make the right trigger move your avatar up. + * var MAPPING_NAME = "com.highfidelity.controllers.example.newMapping"; + * var mapping = Controller.newMapping(MAPPING_NAME); + * + * mapping.from(Controller.Standard.RT).to(Controller.Actions.TranslateY); + * Controller.enableMapping(MAPPING_NAME); + * + * Script.scriptEnding.connect(function () { + * Controller.disableMapping(MAPPING_NAME); + * }); + * + * @example Make the right trigger call a function. + * function onRightTrigger(value) { + * print("Trigger value: " + value); + * } + * + * var MAPPING_NAME = "com.highfidelity.controllers.example.newMapping"; + * var mapping = Controller.newMapping(MAPPING_NAME); + * + * mapping.from(Controller.Standard.RT).to(onRightTrigger); + * Controller.enableMapping(MAPPING_NAME); + * + * Script.scriptEnding.connect(function () { + * Controller.disableMapping(MAPPING_NAME); + * }); + */ Q_INVOKABLE void to(const QScriptValue& destination); + + /**jsdoc + * Enable and disabling writing debug information for a route to the program log. + * @function RouteObject#debug + * @param {boolean} [enable=true] - If true then writing debug information is enabled for the route, + * otherwise it is disabled. + * @returns {RouteObject} The RouteObject with debug output enabled or disabled. + * @example Write debug information to the program log for a right trigger mapping. + * var MAPPING_NAME = "com.highfidelity.controllers.example.newMapping"; + * var mapping = Controller.newMapping(MAPPING_NAME); + * + * mapping.from(Controller.Standard.RT).debug().to(function (value) { + * print("Value: " + value); + * }); + * + * // Information similar to the following is written each frame: + * [DEBUG] [hifi.controllers] Beginning mapping frame + * [DEBUG] [hifi.controllers] Processing device routes + * [DEBUG] [hifi.controllers] Processing standard routes + * [DEBUG] [hifi.controllers] Applying route "" + * [DEBUG] [hifi.controllers] Value was 5.96046e-07 + * [DEBUG] [hifi.controllers] Filtered value was 5.96046e-07 + * + * Controller.enableMapping(MAPPING_NAME); + * + * Script.scriptEnding.connect(function () { + * Controller.disableMapping(MAPPING_NAME); + * }); + */ Q_INVOKABLE QObject* debug(bool enable = true); + + /**jsdoc + * Process the route without marking the controller output as having been read, so that other routes from the same + * controller output can also process. + * @function RouteObject#peek + * @param {boolean} [enable=true] - If true then the route is processed without marking the route's + * controller source as having been read. + * @returns {RouteObject} The RouteObject with the peek feature enabled. + */ Q_INVOKABLE QObject* peek(bool enable = true); + + /**jsdoc + * Process the route only if a condition is satisfied. The condition is evaluated before the route input is read, and + * the input is read only if the condition is true. Thus, if the condition is not met then subsequent + * routes using the same input are processed. + * @function RouteObject#when + * @param {condition|condition[]} expression -

    A condition may be a:

    + *
      + *
    • A numeric {@link Controller.Hardware} property, which is evaluated as a boolean.
    • + *
    • ! followed by a {@link Controller.Hardware} property to use the logical NOT of the property + * value.
    • + *
    • A script function returning a boolean value. This can be either the name of the function or an in-line + * definition.
    • + *
    + *

    If an array of conditions is provided, their values are ANDed together.

    + * @returns {RouteObject} The RouteObject with the condition added. + * @example Process the right trigger differently in HMD and desktop modes. + * var MAPPING_NAME = "com.highfidelity.controllers.example.newMapping"; + * var mapping = Controller.newMapping(MAPPING_NAME); + * + * // Processed only if in HMD mode. + * mapping.from(Controller.Standard.RT) + * .when(Controller.Hardware.Application.InHMD) + * .to(function () { print("Trigger pressed in HMD mode."); }); + * + * // Processed only if previous route not processed. + * mapping.from(Controller.Standard.RT) + * .to(function () { print("Trigger pressed in desktop mode."); }); + * + * Controller.enableMapping(MAPPING_NAME); + * + * Script.scriptEnding.connect(function () { + * Controller.disableMapping(MAPPING_NAME); + * }); + */ Q_INVOKABLE QObject* when(const QScriptValue& expression); + + /**jsdoc + * Filter numeric route values to lie between two values; values outside this range are not passed on through the + * route. + * @function RouteObject#clamp + * @param {number} min - The minimum value to pass through. + * @param {number} max - The maximum value to pass through. + * @returns {RouteObject} The route object with the clamp filter added. + * @example Clamp right trigger values to between 0.3 and 0.7. + * var MAPPING_NAME = "com.highfidelity.controllers.example.newMapping"; + * var mapping = Controller.newMapping(MAPPING_NAME); + * mapping.from(Controller.Standard.RT).clamp(0.3, 0.7).to(function (value) { + * print("Value: " + value); + * }); + * Controller.enableMapping(MAPPING_NAME); + * + * Script.scriptEnding.connect(function () { + * Controller.disableMapping(MAPPING_NAME); + * }); + */ Q_INVOKABLE QObject* clamp(float min, float max); + + /**jsdoc + * Filter numeric route values such that they are rounded to 0 or 1 without output values + * flickering when the input value hovers around 0.5. For example, this enables you to use an analog input + * as if it were a toggle. + * @function RouteObject#hysteresis + * @param {number} min - When the input value drops below this value the output value changes to 0. + * @param {number} max - When the input value rises above this value the output value changes to 1. + * @returns {RouteObject} The RouteObject with the filter applied. + * @example Round the right joystick forward/back values to 0 or 1 with hysteresis. + * var MAPPING_NAME = "com.highfidelity.controllers.example.newMapping"; + * var mapping = Controller.newMapping(MAPPING_NAME); + * mapping.from(Controller.Standard.RY).peek().to(function (value) { + * print("Raw value: " + value); // 0.0 - 1.0. + * }); + * mapping.from(Controller.Standard.RY).hysteresis(0.3, 0.7).to(function (value) { + * print("Hysteresis value: " + value); // 0 or 1. + * }); + * Controller.enableMapping(MAPPING_NAME); + * + * Script.scriptEnding.connect(function () { + * Controller.disableMapping(MAPPING_NAME); + * }); + */ Q_INVOKABLE QObject* hysteresis(float min, float max); + + /**jsdoc + * Filter numeric route values to send at a specified interval. + * @function RouteObject#pulse + * @param {number} interval - The interval between sending values, in seconds. + * @returns {RouteObject} The RouteObject with the filter applied. + * @example Send right trigger values every half second. + * var MAPPING_NAME = "com.highfidelity.controllers.example.newMapping"; + * var mapping = Controller.newMapping(MAPPING_NAME); + * mapping.from(Controller.Standard.RT).pulse(0.5).to(function (value) { + * print("Value: " + value); + * }); + * Controller.enableMapping(MAPPING_NAME); + * + * Script.scriptEnding.connect(function () { + * Controller.disableMapping(MAPPING_NAME); + * }); + */ Q_INVOKABLE QObject* pulse(float interval); + + /**jsdoc + * Filter numeric and {@link Pose} route values to be scaled by a constant amount. + * @function RouteObject#scale + * @param {number} multiplier - The scale to multiply the value by. + * @returns {RouteObject} The RouteObject with the filter applied. + * @example Scale the value of the right joystick forward/back values by 10. + * var MAPPING_NAME = "com.highfidelity.controllers.example.newMapping"; + * var mapping = Controller.newMapping(MAPPING_NAME); + * mapping.from(Controller.Standard.LY).to(function (value) { + * print("L value: " + value); // -1.0 to 1.0 values. + * }); + * mapping.from(Controller.Standard.RY).scale(10.0).to(function (value) { + * print("R value: " + value); // -10.0 to -10.0 values. + * }); + * Controller.enableMapping(MAPPING_NAME); + * + * Script.scriptEnding.connect(function () { + * Controller.disableMapping(MAPPING_NAME); + * }); + */ Q_INVOKABLE QObject* scale(float multiplier); + + /**jsdoc + * Filter numeric and {@link Pose} route values to have the opposite sign, e.g., 0.5 is changed to + * -0.5. + * @function RouteObject#invert + * @returns {RouteObject} The RouteObject with the filter applied. + * @example Invert the value of the right joystick forward/back values. + * var MAPPING_NAME = "com.highfidelity.controllers.example.newMapping"; + * var mapping = Controller.newMapping(MAPPING_NAME); + * mapping.from(Controller.Standard.LY).to(function (value) { + * print("L value: " + value); // -1.0 to 1.0 values, forward to back. + * }); + * mapping.from(Controller.Standard.RY).invert().to(function (value) { + * print("R value: " + value); // 1.0 to -1.0 values, forward to back. + * }); + * Controller.enableMapping(MAPPING_NAME); + * + * Script.scriptEnding.connect(function () { + * Controller.disableMapping(MAPPING_NAME); + * }); + */ Q_INVOKABLE QObject* invert(); + + /**jsdoc + * Filter numeric route values such that they're sent only when the input value is outside a dead-zone. When the input + * passes the dead-zone value, output is sent starting at 0.0 and catching up with the input value. As the + * input returns toward the dead-zone value, output values reduce to 0.0 at the dead-zone value. + * @function RouteObject#deadZone + * @param {number} min - The minimum input value at which to start sending output. For negative input values, the + * negative of this value is used. + * @returns {RouteObject} The RouteObject with the filter applied. + * @example Apply a dead-zone to the right joystick forward/back values. + * var MAPPING_NAME = "com.highfidelity.controllers.example.newMapping"; + * var mapping = Controller.newMapping(MAPPING_NAME); + * mapping.from(Controller.Standard.RY).deadZone(0.2).to(function (value) { + * print("Value: " + value); // 0.0 - 1.0 values once outside the dead-zone. + * }); + * Controller.enableMapping(MAPPING_NAME); + * + * Script.scriptEnding.connect(function () { + * Controller.disableMapping(MAPPING_NAME); + * }); + */ Q_INVOKABLE QObject* deadZone(float min); + + /**jsdoc + * Filter numeric route values such that they are rounded to -1, 0, or 1. + * For example, this enables you to use an analog input as if it were a toggle or, in the case of a bidirectional axis, + * a tri-state switch. + * @function RouteObject#constrainToInteger + * @returns {RouteObject} The RouteObject with the filter applied. + * @example Round the right joystick forward/back values to -1, 0, or + * 1. + * var MAPPING_NAME = "com.highfidelity.controllers.example.newMapping"; + * var mapping = Controller.newMapping(MAPPING_NAME); + * mapping.from(Controller.Standard.RY).constrainToInteger().to(function (value) { + * print("Value: " + value); // -1, 0, or 1 + * }); + * Controller.enableMapping(MAPPING_NAME); + * + * Script.scriptEnding.connect(function () { + * Controller.disableMapping(MAPPING_NAME); + * }); + */ Q_INVOKABLE QObject* constrainToInteger(); + + /**jsdoc + * Filter numeric route values such that they are rounded to 0 or 1. For example, this + * enables you to use an analog input as if it were a toggle. + * @function RouteObject#constrainToPositiveInteger + * @returns {RouteObject} The RouteObject with the filter applied. + * @example Round the right joystick forward/back values to 0 or 1. + * var MAPPING_NAME = "com.highfidelity.controllers.example.newMapping"; + * var mapping = Controller.newMapping(MAPPING_NAME); + * mapping.from(Controller.Standard.RY).constrainToPositiveInteger().to(function (value) { + * print("Value: " + value); // 0, or 1 + * }); + * Controller.enableMapping(MAPPING_NAME); + * + * Script.scriptEnding.connect(function () { + * Controller.disableMapping(MAPPING_NAME); + * }); + */ Q_INVOKABLE QObject* constrainToPositiveInteger(); + + /**jsdoc + * Filter {@link Pose} route values to have a pre-translation applied. + * @function RouteObject#translate + * @param {Vec3} translate - The pre-translation to add to the pose. + * @returns {RouteObject} The RouteObject with the pre-translation applied. + */ + // No JSDoc example because filter not currently used. Q_INVOKABLE QObject* translate(glm::vec3 translate); + + /**jsdoc + * Filter {@link Pose} route values to have a pre-transform applied. + * @function RouteObject#transform + * @param {Mat4} transform - The pre-transform to apply. + * @returns {RouteObject} The RouteObject with the pre-transform applied. + */ + // No JSDoc example because filter not currently used. Q_INVOKABLE QObject* transform(glm::mat4 transform); + + /**jsdoc + * Filter {@link Pose} route values to have a post-transform applied. + * @function RouteObject#postTransform + * @param {Mat4} transform - The post-transform to apply. + * @returns {RouteObject} The RouteObject with the post-transform applied. + */ + // No JSDoc example because filter not currently used. Q_INVOKABLE QObject* postTransform(glm::mat4 transform); + + /**jsdoc + * Filter {@link Pose} route values to have a pre-rotation applied. + * @function RouteObject#rotate + * @param {Quat} rotation - The pre-rotation to add to the pose. + * @returns {RouteObject} The RouteObject with the pre-rotation applied. + */ + // No JSDoc example because filter not currently used. Q_INVOKABLE QObject* rotate(glm::quat rotation); + + /**jsdoc + * Filter {@link Pose} route values to be smoothed by a low velocity filter. The filter's rotation and translation + * values are calculated as: (1 - f) * currentValue + f * previousValue where + * f = currentVelocity / filterConstant. At low velocities, the filter value is largely the previous + * value; at high velocities the value is wholly the current controller value. + * @function RouteObject#lowVelocity + * @param {number} rotationConstant - The rotational velocity, in rad/s, at which the filter value is wholly the latest + * controller value. + * @param {number} translationConstant - The linear velocity, in m/s, at which the filter value is wholly the latest + * controller value. + * @returns {RouteObject} The RouteObject smoothed by low velocity filtering. + */ + // No JSDoc example because filter not currently used. Q_INVOKABLE QObject* lowVelocity(float rotationConstant, float translationConstant); + + /**jsdoc + * Filter {@link Pose} route values to be smoothed by an exponential decay filter. The filter's rotation and + * translation values are calculated as: filterConstant * currentValue + (1 - filterConstant) * + * previousValue. Values near 1 are less smooth with lower latency; values near 0 are more smooth with higher + * latency. + * @function RouteObject#exponentialSmoothing + * @param {number} rotationConstant - Rotation filter constant, 0.0–1.0. + * @param {number} translationConstant - Translation filter constant, 0.0–1.0. + * @returns {RouteObject} The RouteObject smoothed by an exponential filter. + */ + // No JSDoc example because filter used only in Vive.json. Q_INVOKABLE QObject* exponentialSmoothing(float rotationConstant, float translationConstant); + + /**jsdoc + * Filter numeric route values such that a value of 0.0 is changed to 1.0, and other values + * are changed to 0.0. + * @function RouteObject#logicalNot + * @returns {RouteObject} The RouteObject with the filter applied. + * @example Logical NOT of LSTouch value. + * var MAPPING_NAME = "com.highfidelity.controllers.example.newMapping"; + * var mapping = Controller.newMapping(MAPPING_NAME); + * + * mapping.from(Controller.Standard.RSTouch).peek().to(function (value) { + * print("RSTouch: " + value); + * }); + * mapping.from(Controller.Standard.RSTouch).logicalNot().to(function (value) { + * print("localNot of RSTouch: " + value); + * }); + * Controller.enableMapping(MAPPING_NAME); + * + * Script.scriptEnding.connect(function () { + * Controller.disableMapping(MAPPING_NAME); + * }); + */ Q_INVOKABLE QObject* logicalNot(); private: diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 4c2a2a47b4..b696ade022 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -1649,7 +1649,7 @@ signals: /**jsdoc * Triggered when a mouse button is double-clicked while the mouse cursor is on an entity. - * @function Entities.mousePressOnEntity + * @function Entities.mouseDoublePressOnEntity * @param {Uuid} entityID - The ID of the entity that was double-pressed. * @param {PointerEvent} event - Details of the event. * @returns {Signal} diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index ef7f482e44..74b007353d 100755 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -216,6 +216,72 @@ controller::Input KeyboardMouseDevice::InputDevice::makeInput(KeyboardMouseDevic return controller::Input(_deviceID, button, controller::ChannelType::BUTTON); } +/**jsdoc + *

    The Controller.Hardware.Keyboard object has properties representing keyboard, mouse, and display touch + * events. The property values are integer IDs, uniquely identifying each output. Read-only. These can be can be + * mapped to actions or functions or Controller.Standard items in a {@link RouteObject} mapping. For presses, + * each data value is either 1.0 for "true" or 0.0 for "false".

    + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    PropertyTypeDataDescription
    09numbernumberA "0" – "1" key on the + * keyboard or keypad is pressed.
    AZnumbernumberA "A" – "Z" key on the + * keyboard is pressed.
    SpacenumbernumberThe space bar on the keyboard is pressed.
    TabnumbernumberThe tab key on the keyboard is pressed.
    ShiftnumbernumberThe shift key on the keyboard is pressed.
    ControlnumbernumberThe control key on the keyboard is pressed. (The + * "Command" key on OSX.)
    LeftnumbernumberThe left arrow key on the keyboard or keypad is pressed. + *
    RightnumbernumberThe right arrow key on the keyboard or keypad is + * pressed.
    UpnumbernumberThe up arrow key on the keyboard or keypad is pressed. + *
    DownnumbernumberThe down arrow key on the keyboard or keypad is pressed. + *
    PgUpnumbernumberThe page up key on the keyboard or keypad is pressed. + *
    PgDownnumbernumberThe page down key on the keyboard or keypad is pressed. + *
    LeftMouseButtonnumbernumberThe left mouse button pressed.
    MiddleMouseButtonnumbernumberThe middle mouse button pressed.
    RightMouseButtonnumbernumberThe right mouse button pressed.
    LeftMouseClickednumbernumberThe left mouse button clicked.
    MiddleMouseClickednumbernumberThe middle mouse button clicked.
    RightMouseClickednumbernumberThe right mouse button clicked.
    MouseMoveRightnumbernumberThe mouse moved right.
    MouseMoveLeftnumbernumberThe mouse moved left.
    MouseMoveUpnumbernumberThe mouse moved up.
    MouseMoveDownnumbernumberThe mouse moved down.
    MouseXnumbernumberThe mouse x-coordinate changed. The data value is its + * new x-coordinate value.
    MouseYnumbernumberThe mouse y-coordinate changed. The data value is its + * new y-coordinate value.
    MouseWheelRightnumbernumberThe mouse wheel rotated left. The data value + * is the number of units rotated (typically 1.0).
    MouseWheelLeftnumbernumberThe mouse wheel rotated left. The data value + * is the number of units rotated (typically 1.0).
    MouseWheelUpnumbernumberThe mouse wheel rotated up. The data value + * is the number of units rotated (typically 1.0).
    MouseWheelDownnumbernumberThe mouse wheel rotated down. The data value + * is the number of units rotated (typically 1.0).
    TouchpadRightnumbernumberThe average touch on a touch-enabled device + * moved right. The data value is how far the average position of all touch points moved.
    TouchpadLeftnumbernumberThe average touch on a touch-enabled device + * moved left. The data value is how far the average position of all touch points moved.
    TouchpadUpnumbernumberThe average touch on a touch-enabled device + * moved up. The data value is how far the average position of all touch points moved.
    TouchpadDownnumbernumberThe average touch on a touch-enabled device + * moved down. The data value is how far the average position of all touch points moved.
    + * @typedef Controller.Hardware-Keyboard + * @todo Currently, the mouse wheel in an ordinary mouse generates left/right wheel events instead of up/down. + */ controller::Input::NamedVector KeyboardMouseDevice::InputDevice::getAvailableInputs() const { using namespace controller; static QVector availableInputs; diff --git a/libraries/script-engine/src/KeyEvent.cpp b/libraries/script-engine/src/KeyEvent.cpp index 6d3a8aad44..581f9a816b 100644 --- a/libraries/script-engine/src/KeyEvent.cpp +++ b/libraries/script-engine/src/KeyEvent.cpp @@ -150,6 +150,29 @@ KeyEvent::operator QKeySequence() const { return QKeySequence(resultCode); } +/**jsdoc + * A keyboard key event. + * @typedef {object} KeyEvent + * @property {number} key - The Qt keyboard code of the key pressed. For a list of keyboard codes, see + * http://doc.qt.io/qt-5/qt.html#Key-enum. + * @property {string} text - A string describing the key. For example, "a" for the "A" key if the Shift is not + * pressed, "F1" for the F1 key, "SPACE" for the space bar. + * @property {boolean} isShifted - true if a Shift key was pressed when the event was generated, otherwise + * false. + * @property {boolean} isMeta - true if a meta key was pressed when the event was generated, otherwise + * false. On Windows the "meta" key is the Windows key; on OSX it is the Control (Splat) key. + * @property {boolean} isControl - true if a control key was pressed when the event was generated, otherwise + * false. On Windows the "control" key is the Ctrl key; on OSX it is the Command key. + * @property {boolean} isAlt - true if an Alt key was pressed when the event was generated, otherwise + * false. + * @property {boolean} isKeypad - true if the key is on the numeric keypad, otherwise false. + * @property {boolean} isAutoRepeat - true if the event is a repeat for key that is being held down, otherwise + * false. + * @example Report the KeyEvent details for each key press. + * Controller.keyPressEvent.connect(function (event) { + * print(JSON.stringify(event)); + * }); + */ QScriptValue KeyEvent::toScriptValue(QScriptEngine* engine, const KeyEvent& event) { QScriptValue obj = engine->newObject(); obj.setProperty("key", event.key); @@ -275,7 +298,6 @@ void KeyEvent::fromScriptValue(const QScriptValue& object, KeyEvent& event) { } } - const bool wantDebug = false; if (wantDebug) { qCDebug(scriptengine) << "event.key=" << event.key diff --git a/libraries/script-engine/src/MouseEvent.cpp b/libraries/script-engine/src/MouseEvent.cpp index 31bca8054d..20bac96087 100644 --- a/libraries/script-engine/src/MouseEvent.cpp +++ b/libraries/script-engine/src/MouseEvent.cpp @@ -60,6 +60,32 @@ MouseEvent::MouseEvent(const QMouseEvent& event) : } } +/**jsdoc + * A controller mouse movement or button event. + * @typedef {object} MouseEvent + * @property {number} x - Integer x-coordinate of the event on the Interface window or HMD HUD. + * @property {number} y - Integer y-coordinate of the event on the Interface window or HMD HUD. + * @property {string} button - "LEFT", "MIDDLE", or "RIGHT" if a button press or release + * caused the event, otherwise "NONE". + * @property {boolean} isLeftButton - true if the left button was pressed when the event was generated, otherwise + * false. + * @property {boolean} isMiddleButton - true if the middle button was pressed when the event was generated, + * otherwise false. + * @property {boolean} isRightButton - true if the right button was pressed when the event was generated, + * otherwise false. + * @property {boolean} isShifted - true if the Shift key was pressed when the event was generated, otherwise + * false. + * @property {boolean} isMeta - true if the "meta" key was pressed when the event was generated, otherwise + * false. On Windows the "meta" key is the Windows key; on OSX it is the Control (Splat) key. + * @property {boolean} isControl - true if the "control" key was pressed when the event was generated, otherwise + * false. On Windows the "control" key is the Ctrl key; on OSX it is the Command key. + * @property {boolean} isAlt - true if the Alt key was pressed when the event was generated, otherwise + * false. + * @example Report the MouseEvent details for each mouse move. + * Controller.mouseMoveEvent.connect(function (event) { + * print(JSON.stringify(event)); + * }); + */ QScriptValue MouseEvent::toScriptValue(QScriptEngine* engine, const MouseEvent& event) { QScriptValue obj = engine->newObject(); obj.setProperty("x", event.x); diff --git a/libraries/script-engine/src/TouchEvent.cpp b/libraries/script-engine/src/TouchEvent.cpp index 2afd8f75ec..097639d4e8 100644 --- a/libraries/script-engine/src/TouchEvent.cpp +++ b/libraries/script-engine/src/TouchEvent.cpp @@ -165,6 +165,45 @@ void TouchEvent::calculateMetaAttributes(const TouchEvent& other) { } } +/**jsdoc + * A display or device touch event. + * @typedef {object} TouchEvent + * @property {number} x - Integer x-coordinate of the average position of the touch events. + * @property {number} y - Integer y-coordinate of the average position of the touch events. + * @property {boolean} isPressed - true if the touch point has just been pressed, otherwise false. + * @property {boolean} isMoved - true if the touch point has moved, otherwise false. + * @property {boolean} isStationary - true if the touch point has not moved, otherwise false. + * @property {boolean} isReleased - true if the touch point has just been released, otherwise false. + * @property {boolean} isShifted - true if the Shift key was pressed when the event was generated, otherwise + * false. + * @property {boolean} isMeta - true if the "meta" key was pressed when the event was generated, otherwise + * false. On Windows the "meta" key is the Windows key; on OSX it is the Control (Splat) key. + * @property {boolean} isControl - true if the "control" key was pressed when the event was generated, otherwise + * false. On Windows the "control" key is the Ctrl key; on OSX it is the Command key. + * @property {boolean} isAlt - true if the Alt key was pressed when the event was generated, otherwise + * false. + * @property {number} touchPoints - Integer number of touch points. + * @property {Vec2[]} points - The coordinates of the touch points. + * @property {number} radius - The radius of a circle centered on their average position that encompasses the touch points. + * @property {boolean} isPinching - true if the radius has reduced since the most recent touch event + * with a different radius value, otherwise false. + * @property {boolean} isPinchOpening - true if the radius has increased since the most recent touch + * event with a different radius value, otherwise false. + * @property {number} angle - An angle calculated from the touch points, in degrees. + * @property {number} deltaAngle - The change in the angle value since the previous touch event, in degrees, if + * the number of touch points is the same, otherwise 0.0. + * @property {number[]} angles - The angles of each touch point about the center of all the touch points, in degrees. + * @property {boolean} isRotating - true if the angle of the touch event has changed since the + * previous touch event and the number of touch points is the same, otherwise false. + * @property {string} rotating - "clockwise" or "counterClockwise" if the angle of the + * touch event has changed since the previous touch event and the number of touch points is the same, otherwise + * "none". + * + * @example Report the TouchEvent details when a touch event starts. + * Controller.touchBeginEvent.connect(function (event) { + * print(JSON.stringify(event)); + * }); + */ QScriptValue TouchEvent::toScriptValue(QScriptEngine* engine, const TouchEvent& event) { QScriptValue obj = engine->newObject(); obj.setProperty("x", event.x); diff --git a/libraries/script-engine/src/WheelEvent.cpp b/libraries/script-engine/src/WheelEvent.cpp index b329ef58c8..70004d0d3f 100644 --- a/libraries/script-engine/src/WheelEvent.cpp +++ b/libraries/script-engine/src/WheelEvent.cpp @@ -53,7 +53,34 @@ WheelEvent::WheelEvent(const QWheelEvent& event) { isAlt = event.modifiers().testFlag(Qt::AltModifier); } - +/**jsdoc + * A mouse wheel event. + * @typedef {object} WheelEvent + * @property {number} x - Integer x-coordinate of the event on the Interface window or HMD HUD. + * @property {number} y - Integer y-coordinate of the event on the Interface window or HMD HUD. + * @property {number} delta - Integer number indicating the direction and speed to scroll: positive numbers to scroll up, and + * negative numers to scroll down. + * @property {string} orientation - The orientation of the wheel: "VERTICAL" for a typical mouse; + * "HORIZONTAL" for a "horizontal" wheel. + * @property {boolean} isLeftButton - true if the left button was pressed when the event was generated, otherwise + * false. + * @property {boolean} isMiddleButton - true if the middle button was pressed when the event was generated, + * otherwise false. + * @property {boolean} isRightButton - true if the right button was pressed when the event was generated, + * otherwise false. + * @property {boolean} isShifted - true if the Shift key was pressed when the event was generated, otherwise + * false. + * @property {boolean} isMeta - true if the "meta" key was pressed when the event was generated, otherwise + * false. On Windows the "meta" key is the Windows key; on OSX it is the Control (Splat) key. + * @property {boolean} isControl - true if the "control" key was pressed when the event was generated, otherwise + * false. On Windows the "control" key is the Ctrl key; on OSX it is the Command key. + * @property {boolean} isAlt - true if the Alt key was pressed when the event was generated, otherwise + * false. + * @example Report the WheelEvent details for each wheel rotation. + * Controller.wheelEvent.connect(function (event) { + * print(JSON.stringify(event)); + * }); + */ QScriptValue WheelEvent::toScriptValue(QScriptEngine* engine, const WheelEvent& event) { QScriptValue obj = engine->newObject(); obj.setProperty("x", event.x); diff --git a/libraries/shared/src/PointerEvent.cpp b/libraries/shared/src/PointerEvent.cpp index c07de18032..fb855922c2 100644 --- a/libraries/shared/src/PointerEvent.cpp +++ b/libraries/shared/src/PointerEvent.cpp @@ -110,11 +110,13 @@ void PointerEvent::setButton(Button button) { * Shift0x0200000033554432 * A Shift key on the keyboard is pressed. * Control0x0400000067108864 - * A Control key on the keyboard is pressed. + * A control key on the keyboard is pressed. On Windows the "control" key is the Ctrl key; on OSX it is the Command + * key. * Alt0x08000000134217728 * An Alt key on the keyboard is pressed. * Meta0x10000000268435456 - * A Meta or Windows key on the keyboard is pressed. + * A meta key on the keyboard is pressed. On Windows the "meta" key is the Windows key; on OSX it is the Control + * (Splat) key. * Keypad0x20000000536870912 * A keypad button is pressed. * Group0x400000001073741824 diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index d0c717bd20..29c2f9980e 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -383,6 +383,67 @@ void OculusControllerManager::TouchDevice::stopHapticPulse(bool leftHand) { ovr_SetControllerVibration(_parent._session, handType, 0.0f, 0.0f); } +/**jsdoc + *

    The Controller.Hardware.OculusTouch object has properties representing Oculus Rift. The property values are + * integer IDs, uniquely identifying each output. Read-only. These can be can be mapped to actions or functions or + * Controller.Standard items in a {@link RouteObject} mapping.

    + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    PropertyTypeDataDescription
    Buttons
    Anumbernumber"A" button pressed.
    Bnumbernumber"B" button pressed.
    Xnumbernumber"X" button pressed.
    Ynumbernumber"Y" button pressed.
    LeftApplicationMenunumbernumberLeft application menu button pressed. + *
    RightApplicationMenunumbernumberRight application menu button pressed. + *
    Sticks
    LXnumbernumberLeft stick x-axis scale.
    LYnumbernumberLeft stick y-axis scale.
    RXnumbernumberRight stick x-axis scale.
    RYnumbernumberRight stick y-axis scale.
    LSnumbernumberLeft stick button pressed.
    RSnumbernumberRight stick button pressed.
    LSTouchnumbernumberLeft stick is touched.
    RSTouchnumbernumberRight stick is touched.
    Triggers
    LTnumbernumberLeft trigger scale.
    RTnumbernumberRight trigger scale.
    LeftGripnumbernumberLeft grip scale.
    RightGripnumbernumberRight grip scale.
    Finger Abstractions
    LeftPrimaryThumbTouchnumbernumberLeft thumb touching primary thumb + * button.
    LeftSecondaryThumbTouchnumbernumberLeft thumb touching secondary thumb + * button.
    LeftThumbUpnumbernumberLeft thumb not touching primary or secondary + * thumb buttons.
    RightPrimaryThumbTouchnumbernumberRight thumb touching primary thumb + * button.
    RightSecondaryThumbTouchnumbernumberRight thumb touching secondary thumb + * button.
    RightThumbUpnumbernumberRight thumb not touching primary or secondary + * thumb buttons.
    LeftPrimaryIndexTouchnumbernumberLeft index finger is touching primary + * index finger control.
    LeftIndexPointnumbernumberLeft index finger is pointing, not touching + * primary or secondary index finger controls.
    RightPrimaryIndexTouchnumbernumberRight index finger is touching primary + * index finger control.
    RightIndexPointnumbernumberRight index finger is pointing, not touching + * primary or secondary index finger controls.
    Avatar Skeleton
    Headnumber{@link Pose}Head pose.
    LeftHandnumber{@link Pose}Left hand pose.
    RightHandnumber{@link Pose}right hand pose.
    + * @typedef Controller.Hardware-OculusTouch + */ controller::Input::NamedVector OculusControllerManager::TouchDevice::getAvailableInputs() const { using namespace controller; QVector availableInputs{ diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index c58e97cc06..bb0059eac9 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -1232,6 +1232,66 @@ void ViveControllerManager::InputDevice::setConfigFromString(const QString& valu } } +/**jsdoc + *

    The Controller.Hardware.Vive object has properties representing Vive. The property values are integer IDs, + * uniquely identifying each output. Read-only. These can be can be mapped to actions or functions or + * Controller.Standard items in a {@link RouteObject} mapping.

    + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    PropertyTypeDataDescription
    Touch Pad (Sticks)
    LXnumbernumberLeft touch pad x-axis scale.
    LYnumbernumberleft touch pad y-axis scale.
    RXnumbernumberRight stick x-axis scale.
    RYnumbernumberRight stick y-axis scale.
    LSnumbernumberLeft touch pad pressed.
    LS_CENTERnumbernumberLeft touch pad center pressed.
    LS_XnumbernumberLeft touch pad pressed x-coordinate.
    LS_YnumbernumberLeft touch pad pressed y-coordinate.
    RSnumbernumberRight touch pad pressed.
    RS_CENTERnumbernumberRight touch pad center pressed.
    RS_XnumbernumberRight touch pad pressed x-coordinate.
    RS_YnumbernumberRight touch pad pressed y-coordinate.
    LSTouchnumbernumberLeft touch pad is touched.
    RSTouchnumbernumberRight touch pad is touched.
    Triggers
    LTnumbernumberLeft trigger scale.
    RTnumbernumberRight trigger scale.
    LTClicknumbernumberLeft trigger click.
    RTClicknumbernumberRight trigger click.
    LeftGripnumbernumberLeft grip scale.
    RightGripnumbernumberRight grip scale.
    Avatar Skeleton
    Hipsnumber{@link Pose}Hips pose.
    Spine2number{@link Pose}Spine2 pose.
    Headnumber{@link Pose}Head pose.
    LeftArmnumber{@link Pose}Left arm pose.
    RightArmnumber{@link Pose}Right arm pose
    LeftHandnumber{@link Pose}Left hand pose.
    RightHandnumber{@link Pose}Right hand pose.
    Trackers
    TrackedObject00number{@link Pose}Tracker 0 pose.
    TrackedObject01number{@link Pose}Tracker 1 pose.
    TrackedObject02number{@link Pose}Tracker 2 pose.
    TrackedObject03number{@link Pose}Tracker 3 pose.
    TrackedObject04number{@link Pose}Tracker 4 pose.
    TrackedObject05number{@link Pose}Tracker 5 pose.
    TrackedObject06number{@link Pose}Tracker 6 pose.
    TrackedObject07number{@link Pose}Tracker 7 pose.
    TrackedObject08number{@link Pose}Tracker 8 pose.
    TrackedObject09number{@link Pose}Tracker 9 pose.
    TrackedObject10number{@link Pose}Tracker 10 pose.
    TrackedObject11number{@link Pose}Tracker 11 pose.
    TrackedObject12number{@link Pose}Tracker 12 pose.
    TrackedObject13number{@link Pose}Tracker 13 pose.
    TrackedObject14number{@link Pose}Tracker 14 pose.
    TrackedObject15number{@link Pose}Tracker 15 pose.
    + * @typedef Controller.Hardware-Vive + */ controller::Input::NamedVector ViveControllerManager::InputDevice::getAvailableInputs() const { using namespace controller; QVector availableInputs{ diff --git a/tools/jsdoc/plugins/hifi.js b/tools/jsdoc/plugins/hifi.js index 1f73f14b2b..2e12a2d584 100644 --- a/tools/jsdoc/plugins/hifi.js +++ b/tools/jsdoc/plugins/hifi.js @@ -24,8 +24,10 @@ exports.handlers = { '../../libraries/animation/src', '../../libraries/avatars/src', '../../libraries/controllers/src/controllers/', + '../../libraries/controllers/src/controllers/impl/', '../../libraries/graphics-scripting/src/graphics-scripting/', '../../libraries/entities/src', + '../../libraries/input-plugins/src/input-plugins', '../../libraries/model-networking/src/model-networking/', '../../libraries/octree/src', '../../libraries/networking/src', @@ -34,6 +36,8 @@ exports.handlers = { '../../libraries/script-engine/src', '../../libraries/shared/src', '../../libraries/shared/src/shared', + '../../plugins/oculus/src', + '../../plugins/openvr/src', ]; var exts = ['.h', '.cpp'];