Controller API
Contents
- 1 Table of Contents
- 2 Properties
- 3 Methods
- 4 Events
- 5 Overview
- 6 Hand Controller
- 7 Controller.Standard
- 8 Methods
- 9 disableMapping()
- 10 enableMapping()
- 11 getPoseValue()
- 12 getReticlePosition()
- 13 getValue()
- 14 Haptics
- 15 MappingObject.enable()
- 16 MappingObject.from()
- 17 newMapping()
- 18 parseMapping()
- 19 RouteObject.clamp()
- 20 RouteObject.constrainToInteger()
- 21 RouteObject.constrainToPositiveInteger()
- 22 RouteObject.deadZone()
- 23 RouteObject.debug()
- 24 RouteObject.hysteresis()
- 25 RouteObject.invert()
- 26 RouteObject.peek()
- 27 RouteObject.pulse()
- 28 RouteObject.scale()
- 29 RouteObject.to()
- 30 RouteObject.when()
- 31 setReticlePosition()
- 32 Events
- 33 hardwareChanged()
- 34 keyPressEvent()
- 35 keyReleaseEvent()
- 36 mouseDoublePressEvent()
- 37 mouseMoveEvent()
- 38 mousePressEvent()
- 39 mouseReleaseEvent()
- 40 touchBeginEvent()
- 41 touchEndEvent()
- 42 touchUpdateEvent()
- 43 wheelEvent()
Table of Contents
Properties
Methods
| Methods |
|---|
| Controller.createInputController(QString,QString) |
| Controller.disableMapping(QString) |
| Controller.enableMapping(QString) |
| Controller.enableMapping(QString,bool) |
| Controller.findAction(QString) |
| Controller.findDevice(QString) |
| Controller.getActionNames() |
| Controller.getActionValue(int) |
| Controller.getActions() |
| Controller.getAllActions() |
| Controller.getAvailableInputs(uint) |
| Controller.getAxisValue(StandardAxisChannel) |
| Controller.getAxisValue(StandardAxisChannel,uint16_t) |
| Controller.getAxisValue(int) |
| Controller.getButtonValue(StandardButtonChannel) |
| Controller.getButtonValue(StandardButtonChannel,uint16_t) |
| Controller.getDeviceName(uint) |
| Controller.getDeviceNames() |
| Controller.getHardware() |
| Controller.getPoseValue(StandardPoseChannel) |
| Controller.getPoseValue(StandardPoseChannel,uint16_t) |
| Controller.getPoseValue(int) |
| Controller.getRecommendedOverlayRect() |
| Controller.getReticlePosition() |
| Controller.getStandard() |
| Controller.getValue(int) |
| Controller.getViewportDimensions() |
| Haptics |
| Controller.loadMapping(QString) |
| Controller.newMapping() |
| Controller.newMapping(QString) |
| Controller.parseMapping(QString) |
| MappingObject.enable() |
| MappingObject.from() |
| RouteObject.clamp() |
| RouteObject.constrainToInteger() |
| RouteObject.constrainToPositiveInteger() |
| RouteObject.deadZone() |
| RouteObject.debug() |
| RouteObject.hysteresis() |
| RouteObject.peek() |
| RouteObject.invert() |
| RouteObject.pulse() |
| RouteObject.scale() |
| RouteObject.to() |
| RouteObject.when() |
| SetReticlePosition() |
Events
| Events |
|---|
| Controller.actionEndEvent(HFActionEvent) |
| Controller.actionEvent(int,float) |
| Controller.actionStartEvent(HFActionEvent) |
| Controller.backEndEvent() |
| Controller.backStartEvent() |
| Controller.captureActionEvents() |
| Controller.captureEntityClickEvents() |
| Controller.captureJoystick(int) |
| Controller.captureKeyEvents(KeyEvent) |
| Controller.captureMouseEvents() |
| Controller.captureTouchEvents() |
| Controller.captureWheelEvents() |
| Controller.hardwareChanged() |
| Controller.inputEvent(int,float) |
| Controller.keyPressEvent(KeyEvent) |
| Controller.keyReleaseEvent(KeyEvent) |
| Controller.mouseDoublePressEvent(MouseEvent) |
| Controller.mouseMoveEvent(MouseEvent) |
| Controller.mousePressEvent(MouseEvent) |
| Controller.mouseReleaseEvent(MouseEvent) |
| Controller.objectNameChanged(QString) |
| Controller.releaseActionEvents() |
| Controller.releaseEntityClickEvents() |
| Controller.releaseInputController(controller::InputController*) |
| Controller.releaseJoystick(int) |
| Controller.releaseKeyEvents(KeyEvent) |
| Controller.releaseMouseEvents() |
| Controller.releaseTouchEvents() |
| Controller.releaseWheelEvents() |
| Controller.touchBeginEvent(TouchEvent) |
| Controller.touchEndEvent(TouchEvent) |
| Controller.touchUpdateEvent(TouchEvent) |
| Controller.triggerHapticPulse(float,float) |
| Controller.triggerHapticPulse(float,float,controller::Hand) |
| Controller.triggerHapticPulseOnDevice(uint,float,float) |
| Controller.triggerHapticPulseOnDevice(uint,float,float,controller::Hand) |
| Controller.triggerShortHapticPulse(float) |
| Controller.triggerShortHapticPulse(float,controller::Hand) |
| Controller.triggerShortHapticPulseOnDevice(uint,float) |
| Controller.triggerShortHapticPulseOnDevice(uint,float,controller::Hand) |
| Controller.wheelEvent(WheelEvent) |
Overview
Mapping Input to Output
A mapping is the set of rules for taking changes in inputs from supported controllers and acting on them in some way. A new mapping is created using Controller.newMapping(). This function takes a string which is used as the mapping name, and returns a MappingObject, as seen in the example below.
<code>// The name of the new mapping var MAPPING_NAME = "com.highfidelity.controllers.example.triggerExample"; // Create a new mapping object var mapping = Controller.newMapping(MAPPING_NAME);</code>
The individual rules in a mapping are known as routes and they define which input goes to which output. The controller API has a predefined list of standard controller inputs (things like button A and Right X axis) in Controller.Standard. You can create a route from one of these inputs to a function using the MappingObject's, from method and the resulting RouteObject's to method.
This example, creates a route from the input Controller.Standard.RT to a new function that prints the value of the controller's right trigger to the debug line.
<code>// Add a route to the mapping object
mapping.from(Controller.Standard.RT).to(function (value) {
print("Right trigger is " + value);
});</code>
At this point, the new mapping object and route won't do anything. For the mapping to go into effect, you need to enable the mapping using Controller.enableMapping(). In addition, when the script ends, it is good practice to disable the mapping using Controller.disableMapping(). A good way to do that is to bind the disable to the script ending event. Here you have a minimal, but functional example mapping script.
<code>// The name of the new mapping
var MAPPING_NAME = "com.highfidelity.controllers.example.triggerExample";
// Create a new mapping object
var mapping = Controller.newMapping(MAPPING_NAME);
// Add a route to the mapping object
mapping.from(Controller.Standard.RT).to(function (value) {
print("Right trigger is " + value);
});
//Enable the new mapping
Controller.enableMapping(MAPPING_NAME);
// Disable the new mapping when the script ends
Script.scriptEnding.connect(function () {
Controller.disableMapping(MAPPING_NAME);
});</code>
For more complete examples, see:
For information on available Controller API functions, objects, and events, see the individual function, object, and event pages in the column to the left.
Mapping to Predefined Output Actions
As mentioned above, the controller API has a list of predefined standard controller inputs (things like button A and Right X axis) in Controller.Standard. It also has a list of predefined application Actions (things like yaw, pitch, or left/right hand pose) in Controller.Actions. A default mapping of standard controller inputs to Actions exists, however, this mapping may not suit your needs, and you can create your own routes from standard input to any of the predefined Actions.
This example creates a route from Controller.Standard.RT input to the predefined Action Controller.Actions.StepYaw.
<code>// Add a route to the mapping object mapping.from(Controller.Standard.RT).to(Controller.Actions.StepYaw);</code>
Using Filters to Customize Output Actions
The custom mapping you want to create may not be as simple as input A -> standard input A -> Action A. For this reason, the controller mapping system provides a number of filters allowing you to customize the action. For example, filters can be used to scale an action to be twice as fast as the default or to create a different threshold for when an action occurs. In this example, a new mapping is created that uses the inverse of the standard mapping by using the invert filter.
<code>{
"name": "Test to Standard",
"channels": [
{ "from": "test.LY", "filters": "invert", "to": "Standard.LY" }
]
}</code>
Filters are methods of the RouteObject. For the complete list of filters, see the RouteObject page.
Creating Conditional Mappings
You may want to use different mappings depending on your user's setup. For example, if your user is using an HMD (such as the Oculus Rift) in addition to a hand-held controller (GamePad, Hydra, etc.), to provide greater user comfort, you may want to provide different controls than when using a GamePad alone. To create conditional mappings, use the RouteObject's when method. Here we have an example of route created only when the application is in HMD mode followed by the route to be used if the application is not in HMD mode.
<code>1 mapping.from(Controller.Test.LY).when(Controller.Application.InHMD).to(Controller.Standard.RY); 2 mapping.from(Controller.Test.LY).to(Controller.Standard.LY);</code>
Mapping Order
In the conditional mapping example above, you'll see that the conditional case (line 1) is above the standard case (line 2). This order is important as mappings use a one read/one write rule. After an input has been read, it is marked as read and can’t be read again. If the standard case were first, the input would be marked as read and the conditional case, even if true, would not be used.
Note: Circular loops not permitted.
Using JSON to Create Mappings
While all of the above examples used scripting to create a mapping, it is also possible to create a mapping as a JSON object. For examples of creating new mappings using a JSON mapping object, see:
Creating a JSON mapping is typically used when adding support for new hardware.
Creating Mappings for New Hardware
Attached controllers are exposed as a tree of identifiers under the global variable Controller. That is, there's Controller.Hardware.Foo where Foo is the hardware name of the controller (Hydra, GamePad, Vive, etc.). Inputs for specific controllers are not mapped directly to Controller.Actions. Instead, the controller API has a predefined mapping referred to as the "standard controller" (defined in standard.json) which maps standard inputs to Controller.Standard to Controller.Actions. Each specific controller is mapped to the standard controller.
<img src="controller-system.png" alt="img" />
Specific controllers are mapped to the standard controller which is mapped to application output actions.
So, for example, the Hydra controls are mapped to standard controls (which are mapped to hardware actions) as seen in hydra.json.
The exception to this are keyboard and mouse inputs (Hardware.Keyboard) which are mapped directly to actions (keyboardMouse.json).
Hand Controller
This API reference guide covers the various methods an entity script can implement that are called by the interface script, handControllerGrab.js # Overview High Fidelity currently supports the hydra and vive hand controllers, with continually updated support as more controllers are released to the market. The "trigger" button is located at the lower underside of both the hydra and the vive and looks similar to a pistol trigger. The equip button is the bumper above the primary trigger in the case of the hydra, and the left side button for the vive. The handControllerGrab.js interface script provides a rich interface for using your hands to interact with the world around you, from picking up physical objects, to pressing buttons, puling triggers, shooting a bow and arrow, and anything else you can imagine!
The following table provides a complete reference for all of the actions an entity script can listen for from the handControllerGrab script. NOTE: The handControllerGrab.js script MUST be running for any entity script implementing the following methods to work properly.
| Method | Description | Example Entity |
|---|---|---|
| stopFarTrigger, startFarTrigger, continueFarTrigger | These methods will be called when a user is more than 0.3 meters away from a non-physical entity, and starts, stops, or continues squeezing the trigger. NOTE: This entity must have the following field in the userData for these methods to be triggered:grabbableKey: { wantsTrigger: true } | A light switch that can be toggled on and off from a distance. |
| stopNearTrigger, startNearTrigger, continueNearTrigger | These methods will be called when a user is less than 0.3 meters away from a non-physical entity, and starts, stops, or continues squeezing the trigger. NOTE: This entity must have the following field in the userData for these methods to be triggered:grabbableKey: { wantsTrigger: true } | A doorbell that rings when a user puts her hand close to it and squeezes the trigger |
| startNearGrab, continueNearGrab | These methods will be called when a user is less than 0.3 meters from a physical entity and starts or continues to squeeze the trigger. | A magic ball that glows with healing light when it's being held close. |
| startDistanceGrab, continueDistanceGrab | These methods will be called when a user is more than 0.3 meters from a physical entity and starts or continues to squeeze the trigger. | A comet that emits beautiful icy particle trails when a user is dragging it through the sky. |
| releaseGrab | This method is called when a user releases the trigger when having been either near or distance grabbing a physical entity | Turn off the magical glowing ball when it's released |
| startEquip, continueEquip, releaseEquip | These methods are called when a user starts, continues, or stops equipping a physical entity. | A pistol that stays in the user's hand even when he's not holding the trigger down. |
Controller.Standard
The controller API has a list of predefined standard controller end points as listed below. End point names are based on the Xbox controller input names. For convenience, aliases based on the Playstation controller names are also available. Inputs are listed below with those for buttons, D-Pad, triggers, and sticks in the first chart and those for finger abstractions and poses in the second.
Buttons, D-Pad , Triggers, Sticks
| Input | Aliases | Description |
|---|---|---|
A |
Cross |
Button |
B |
Circle |
Button |
Back |
Select |
Back button |
DD |
Down |
D-Pad |
DL |
Left |
D-Pad |
DR |
Right |
D-Pad |
DU |
Up |
D-Pad |
LB |
L1 |
Left bumper |
LS |
L3 |
Left stick press |
LSTouch |
Left stick touch | |
LT |
L2 |
Left trigger |
LY |
Left analog stick Y axis | |
LX |
Left analog stick x axis | |
RB |
R1 |
Right bumper |
RS |
R3 |
Right stick press |
RSTouch |
Right stick touch | |
RT |
R2 |
Right trigger |
RY |
RY |
Right analog stick Y axis |
RX |
RX |
Right analog stick X axis |
Start |
Start button | |
X |
Square |
Button |
Y |
Triangle |
Button |
Finger abstractions and poses
Rather than buttons, triggers, etc., some controllers are based on the user's hands (for example, the Hydra or Leap Motion). For these types of controllers, the finger abstraction and pose properties are available to make it easy to create a JSON mapping based on hands rather than specific controls. For controls that map directly to a standard Xbox style game pad, the standard.json mapping creates the aliases to the finger and thumb abstractions. For individual controls that don't map directly to a standard Xbox style game pad, the hardware specific JSON mapping creates the aliases (for example, hydra.json).
The "touch" controls are intended to expose when a user has a finger touching, but not pressing a particular control (as will be needed for the Oculus Touch controller).
| Input | Description |
|---|---|
LeftGrip |
Finger abstraction |
LeftHand |
Pose |
LeftIndexPoint |
Finger abstraction |
LeftGripTouch |
Finger abstraction |
LeftPrimaryIndex |
Finger abstraction |
LeftPrimaryIndexTouch |
Finger abstraction |
LeftPrimaryThumb |
Finger abstraction |
LeftPrimaryThumbTouch |
Finger abstraction |
LeftSecondaryIndex |
Finger abstraction |
LeftSecondaryIndexTouch |
Finger abstraction |
LeftSecondaryThumb |
Finger abstraction |
LeftSecondaryThumbTouch |
Finger abstraction |
LeftThumbUp |
Finger abstraction |
RightGrip |
Finger abstraction |
RightHand |
Pose |
RightIndexPoint |
Finger abstraction |
RightGripTouch |
Finger abstraction |
RightPrimaryIndex |
Finger abstraction |
RightPrimaryIndexTouch |
Finger abstraction |
RightPrimaryThumb |
Finger abstraction |
RightPrimaryThumbTouch |
Finger abstraction |
RightSecondaryIndex |
Finger abstraction |
RightSecondaryIndexTouch |
Finger abstraction |
RightSecondaryThumb |
Finger abstraction |
RightSecondaryThumbTouch |
Finger abstraction |
RightThumbUp |
Finger abstraction |
Methods
disableMapping()
A mapping is the set of rules for taking changes in inputs from supported controllers and acting on them in some way. The individual rules in a mapping are known as routes and they define which input goes to which output.
disableMapping() disables the specified mapping so that the routes it contains are no longer used by the application.
Function
disableMapping(mappingName)
Arguments
- mappingName: string: The name of the mapping. It can be any valid string.
Examples
This example creates a new mapping that specifies a route from Controller.Standard.RT input to custom output. It then enables that mapping so that the new route is used by the application. When the script ends, the mapping is disabled and the application will again use the default mapping for Controller.Standard.RT.
<code>// The name of the new mapping
var MAPPING_NAME = "com.highfidelity.controllers.example.triggerExample";
// Create a new mapping object
var mapping = Controller.newMapping(MAPPING_NAME);
// Add a route to the mapping object
mapping.from(Controller.Standard.RT).to(function (value) {
print("Right trigger is " + value);
});
//Enable the new mapping
Controller.enableMapping(MAPPING_NAME);
// Disable the new mapping when the script ends
Script.scriptEnding.connect(function () {
Controller.disableMapping(MAPPING_NAME);
});</code>
enableMapping()
A mapping is the set of rules for taking changes in inputs from supported controllers and acting on them in some way. The individual rules in a mapping are known as routes and they define which input goes to which output.
enableMapping() enables the specified mapping so that the routes it contains are used by the application.
Function
enableMapping(mappingName)
Arguments
- mappingName: string: The name of the mapping
Examples
This example creates a new mapping that specifies a route from Controller.Standard.RT input to custom output. It then enables that mapping so that the new route is used by the application. When the script ends, the mapping is disabled and the application will again use the default mapping for Controller.Standard.RT.
<code>// The name of the new mapping
var MAPPING_NAME = "com.highfidelity.controllers.example.triggerExample";
// Create a new mapping object
var mapping = Controller.newMapping(MAPPING_NAME);
// Add a route to the mapping object
mapping.from(Controller.Standard.RT).to(function (value) {
print("Right trigger is " + value);
});
//Enable the new mapping
Controller.enableMapping(MAPPING_NAME);
// Disable the new mapping when the script ends
Script.scriptEnding.connect(function () {
Controller.disableMapping(MAPPING_NAME);
});</code>
getPoseValue()
getPoseValue() is used to get the value of a specified endpoint pose. This can be a Standard endpoint object or it can be an individual hardware input pose.
Function
getPoseValue(input) // Returns a pose object
Arguments
- input: object: A Standard endpoint pose, for example
LeftHandorRightHandor an individual hardware input pose
Returns
- pose: object: A JSON object consisting of a translation (vec3), rotation (Quat), velocity (vec3), and angular velocity(vec3)
Examples
This example gets the pose value for the right hand (Controller.Standard.RightHand) and then prints the value (converted to a string) to the debug log.
<code>var poseRight = Controller.getPoseValue(Controller.Standard.RightHand); print (JSON.stringify(poseRight));</code>
With this example, you should see output similar to the following:
<code>{"translation":{"x":0,"y":0,"z":0},"rotation":{"x":0,"y":0,"z":0,"w":1},"velocity":{"x":0,"y":0,"z":0},"angularVelocity":{"x":0,"y":0,"z":0},"valid":false</code>
getReticlePosition()
getReticlePosition() is used to get the current position of the cursor on the screen.
Function
getReticlePosition() // Returns a vec2
Arguments
This function has no parameters.
Returns
- position:Vec2: The x and y positions of the cursor on the screen
Examples
This example gets the current position of the cursor and then prints it to the debug log.
<code>var postition = getReticlePosition();
print ("x: " + position.x + " y: " + position.y);</code>
getValue()
getValue() gets the current value of the specified endpoint object. This can be a Standard endpoint object or it can be individual hardware endpoint object.
Function
getValue(object) // Return float
Arguments
- object:object: The Standard endpoint object whose value is to be retrieved
Returns
- value:float: The current value of the specified endpoint object
Examples
This example prints the current value of the left analog stick Y axis (Controller.Standard.LY) to the debug log.
<code> print("LY value: " + Controller.getValue(Controller.Standard.LY));</code>
Haptics
If a controller supports haptic feedback, you can activate it using the following methods.
If you trigger a pulse while another one is already in progress, the strength and duration of the one that would finish last are honored.
Custom Pulse
<code>Controller.triggerHapticPulse(strength, duration, hand)</code>
The three parameters here are: - strength: a float between 0 and 1 - duration: a number of milliseconds - hand: 0 for left, 1 for right, 2 for both
Short Pulse
This method automatically trigger pulses of 250 ms
<code>Controller.triggerShortHapticPulse(strength, hand)</code>
The two parameters here are: - strength: a float between 0 and 1 - hand: 0 for left, 1 for right, 2 for both
Specific Devices
The methods above will trigger pulses on all devices that can make them. If you'd like to specify the precise devices that will receive pulses, use the following methods:
<code>Controller.triggerHapticPulseOnDevice(deviceID,strength, duration, hand ) Controller.triggerShortHapticPulseOnDevice(deviceID, strength, hand )</code>
MappingObject.enable()
A mapping is the set of rules for taking changes in inputs from supported controllers and acting on them in some way. The individual rules in a mapping are known as routes and they define which input goes to which output. The routes in a mapping will not be used by the application until the mapping has been enabled.
The MappingObject's enable() method is used to enable and disable the mapping.
Function
mapping.enable() // enable the mapping mapping.enable(false) // disable the mapping
Arguments
- false: bool:
falseis used to disable the mapping.
Examples
This example creates a simple JSON formatted mapping. A new mapping object is then created by passing the JSON object as a string to parseMapping. The mapping object's enable() method is then be used to enable and disable the mapping.
<code>// Create a JSON mapping object
var mappingJSON = {
"name": "com.highfidelity.testing.simpleJSONMapping",
"channels": [
{ "from": "Standard.RT", "to": "Actions.ReticleClick", "filters": "constrainToInteger" }
]
};
// Use parseMapping to create a new mapping object
mapping = Controller.parseMapping(JSON.stringify(mappingJSON));
//Enable the new mapping
mapping.enable();
//Disable the new mapping
mapping.enable(false);</code>
MappingObject.from()
The individual rules in a mapping are known as routes and they define which input goes to which output.
The MappingObject's from() method is used to specify the starting point of a route. This starting point can be a specific hardware input or it can be a Standard controller endpoint object.
Note: If you create a direct route from a specific hardware input (for example, Hydra.LX), the default mapping (Hydra.LX to Standard.LX) will be suppressed, because the new route takes precedence.
Function
MappingObject.from(input) // Returns a RouteObject
Arguments
- - input: object**: A Standard controller endpoint object or an individual hardware input
Returns
- object:RouteObject: A JSON object that defines the route
Examples
This example creates a route from the standard controller's right trigger (Controller.Standard.RT) to a custom function that prints the input value to the debug log.
<code>// Add a route to the mapping object ("mapping")
mapping.from(Controller.Standard.RT).to(function (value) {
print("Right trigger is " + value);
});</code>
Here is sample output from pressing the right trigger:
<code>Right trigger value: 0.027346327 Right trigger value: 0.184298423 Right trigger value: 0.249583496 Right trigger value: 0.533287539 Right trigger value: 0.649349544 Right trigger value: 0.838428374 Right trigger value: 0.992342344</code>
newMapping()
A mapping is the set of rules for taking changes in inputs from supported controllers and acting on them in some way. A mapping is stored in a MappingObject.
newMapping() creates a new MappingObject.
Function
newMapping(mappingName) // Returns a MappingObject
Arguments
- mappingName:string: The mapping object name. It can be any valid string; however, it should be a unique name as it is used to access the mapping.
Returns
- object: MappingObject: A JavaScript object of the new mapping
Examples
This example creates a new MappingObject with the name "New_Mapping."
<code>var mapping = Controller.newMapping("New_Mapping");</code>
Note: A new mapping will not go into effect until is has been enabled. You can enable a mapping either by name using the Controller.enableMapping() function, or directly from the mapping object by calling MappingObject.enable(). The mapping can be disabled by calling Controller.disableMapping() or by using enable(false).
Note: If the mapping re-maps a Controller.Standard mapping to another, where the button already has a value defined, the mapping will always fall back to the original default mapping. Be sure to not write into a control that already has a value.
parseMapping()
A mapping is the set of rules for taking changes in inputs from supported controllers and acting on them in some way. In addition to scripting, a mapping can be created as a JSON object.
parseMapping() takes a JSON mapping object converted to string format and creates a new MappingObject.
Function
parseMapping(mappingString) // Return a MappingObject
Arguments
- mappingString:string: A JSON mapping in string format
Returns
- object: MappingObject: A new mapping object
Examples
This example creates a simple JSON formatted mapping. A new mapping object is then created by passing the JSON object as a string to parseMapping(). The mapping object'senable() method is then be used to enable and disable the mapping.
<code>// Create a JSON mapping object
var mappingJSON = {
"name": "com.highfidelity.testing.simpleJSONMapping",
"channels": [
{ "from": "Standard.RT", "to": "Actions.ReticleClick", "filters": "constrainToInteger" }
]
};
// Use parseMapping to create a new mapping object
mapping = Controller.parseMapping(JSON.stringify(mappingJSON));
//Enable the new mapping
mapping.enable();
//Disable the new mapping
mapping.enable(false);</code>
Note: You can also enable and disable the mapping by name using Controller.enableMapping() and Controller.disableMapping().
RouteObject.clamp()
The individual rules in a mapping are known as routes and they define which input goes to which output. The mapping you want to create may not be as simple as input A -> Action A. For this reason, the controller mapping API provides a number of filters allowing you to customize the action.
The RouteObject's clamp method is used to specify that the input value must be within a specified range for output to be sent. If the input value falls outside of the specified range, output is not sent.
Function
clamp(min, max) // Returns this.RouteObject
Arguments
min:float: The minimum value for which output will be sent
max:float: The maximum value for which output will be sent
Returns
- object:RouteObject: Returns this.RouteObject
Examples
In this example, two routes are created. The first route uses the clamp() filter and goes from the standard controller's right trigger (Controller.Standard.RT) to a custom function that prints the right trigger value. The second route does not use the clamp()filter and goes from the standard controller's left trigger (Controller.Standard.LT) to a custom function that prints the left trigger value.
<code>// Add a route to the mapping object ("mapping") from
// the right trigger with the clamp filter
mapping.from(Controller.Standard.RT).clamp(0, 0.5).to(function (value) {
print("Right trigger value: " + value);
});
// Add a route to the mapping object ("mapping") from the
// left trigger without the clamp filter
mapping.from(Controller.Standard.LT).to(function (value) {
print("Left trigger value: " + value);
});</code>
Using this example, you can easily compare the output between a route with the clamp() filter and a route without it. First, here is sample output from pressing the right trigger:
<code>Right trigger value: 0.01232234 Right trigger value: 0.25992253 Right trigger value: 0.38326432 Right trigger value: 0.45975495 Right trigger value: 0.5 Right trigger value: 0.18839423 Right trigger value: 0</code>
As you can see, with the clamp() filter, input values range from the specified min value (0) to the specified max (0.5) value. In comparison, here is sample output from pressing the left trigger which does not use the clamp() filter.
<code>Left trigger value: 0.027346327 Left trigger value: 0.184298423 Left trigger value: 0.249583496 Left trigger value: 0.533287539 Left trigger value: 0.649349544 Left trigger value: 0.838428374 Left trigger value: 0.992342344</code>
As you can see, without the clamp() filter, values range from 0 to 1.
RouteObject.constrainToInteger()
The individual rules in a mapping are known as routes and they define which input goes to which output. The mapping you want to create may not be as simple as input A -> Action A. For this reason, the controller mapping API provides a number of filters allowing you to customize the action.
The RouteObject's constrainToInteger() method rounds the input value to an integer away from zero.
Function
constrainToInteger() // Returns this.RouteObject
Arguments
This function has no parameters.
Returns
- object:RouteObject: Returns this.RouteObject
Examples
Constraining a value to an integer allows you to use analog input as if it were a toggle (or in the case of a bidirectional axis, a three-state switch). Here is an example that creates a route using the constrainToInteger() filter. This route goes from the right analog stick x axis (Controller.Standard.RX) to a custom function that prints the value to the debug log.
<code>mapping.from(Controller.Standard.RX).constrainToInteger().to(function(value) {
print("Right analog stick x axis value: " + value);
});</code>
With this route enabled, sample output from pressing the right analog stick x axis looks something like this:
<code>Right analog stick x axis value: 1 Right analog stick x axis value: 0 Right analog stick x axis value: -1</code>
As you can see, with constrainToInteger(), the function is only called once when the analog stick x axis value is first pushed to the right (value goes to 1), once when the analog stick x axis is in a neutral position (value goes to 0), and once when analog stick x axis is first push to left (value goes to -1).
In comparison, here is the same rout without the constrainToInteger() filter.
<code> mapping.from(Controller.Standard.RX).to(function (value) {
print("Right analog stick x axis value: " + value);
});</code>
With this route enabled, sample output from pressing the right analog stick x axis looks something like this:
<code>Right analog stick x axis value: 0.027346327 Right analog stick x axis value: 0.284298423 Right analog stick x axis value: 0.149583496 Right analog stick x axis value: 0 Right analog stick x axis value: -0.249349544 Right analog stick x axis value: -0.338428374 Right analog stick x axis value: -0.692342344</code>
As you can see, when constrainToInteger() is not used, the function gets called with each and every value change of the right analog stick x axis.
RouteObject.constrainToPositiveInteger()
The individual rules in a mapping are known as routes and they define which input goes to which output. The mapping you want to create may not be as simple as input A -> Action A. For this reason, the controller mapping API provides a number of filters allowing you to customize the action.
The RouteObject's constrainToPositiveInteger() method rounds the input value to 0 or 1.
Function
constrainToPositiveInteger() // Returns this.RouteObject
Arguments
This function has no parameters.
Returns
- object:RouteObject: Returns this.RouteObject
Examples
Constraining a value to an integer allows you to use analog input as if it were a toggle. Here is an example that creates a route using the constrainToPositiveInteger() filter. This route goes from the right analog stick x axis (Controller.Standard.RX) to a custom function that prints the value to the debug log.
<code>mapping.from(Controller.Standard.RX).constrainToPositiveInteger().to(function(value) {
print("Right analog stick x axis value: " + value);
});</code>
With this route enabled, sample output from pressing the right analog stick x axis looks something like this:
<code>Right analog stick x axis value: 1 Right analog stick x axis value: 0</code>
As you can see, with constrainToPositiveInteger(), the function is only called once when the analog stick x axis value is first pushed to the right (value goes to 1) and once when the analog stick x axis is in a neutral position (value goes to 0).
In comparison, here is the same rout without the constrainToPositiveInteger() filter.
<code>mapping.from(Controller.Standard.RX).to(function(value) {
print("Right analog stick x axis value: " + value);
});</code>
With this route enabled, sample output from pressing the right analog stick x axis looks something like this:
<code>Right analog stick x axis value: 0.027346327 Right analog stick x axis value: 0.284298423 Right analog stick x axis value: 0.149583496 Right analog stick x axis value: 0 Right analog stick x axis value: -0.249349544 Right analog stick x axis value: -0.338428374 Right analog stick x axis value: -0.692342344</code>
As you can see, when constrainToPositiveInteger() is not used, the function gets called with each and every value change of the right analog stick x axis.
RouteObject.deadZone()
This may not work at this time.
The individual rules in a mapping are known as routes and they define which input goes to which output. The mapping you want to create may not be as simple as input A -> Action A. For this reason, the controller mapping API provides a number of filters allowing you customize the action.
The RouteObject's deadZone method is used to specify a value at which output will begin to be sent.
Function
or Event deadZone(min) // Returns this.RouteObject
Arguments
- min:float: The value output will begin to be sent
Returns
object:RouteObject: Returns this.RouteObject
Examples
In this example, two routes are created. The first route uses the deadZone filter and goes from the standard controller's right trigger (Controller.Standard.RT) to a custom function that prints the right trigger value. The second route does not use the deadZonefilter and goes from the standard controller's left trigger (Controller.Standard.LT) to a custom function that prints the left trigger value.
<code>// Add a route to the mapping object ("mapping")
mapping.from(Controller.Standard.RT).deadZone(0.5).to(function (value) {
print("Right trigger: " + value);
});
// Add a route to the mapping object ("mapping")
mapping.from(Controller.Standard.LT).to(function (value) {
print("Left trigger: " + value);
});</code>
Using this example, you can easily compare the output between a route with the deadZone filter and a route without it. First, here is sample output from pressing the right trigger:
<code>Right trigger value: 0.533287539 Right trigger value: 0.728184939 Right trigger value: 0.892749237 Right trigger value: 0.649328498 Right trigger value: 0.449324343 Right trigger value: 0.234394234 Right trigger value: 0 Right trigger value: 0.534234324 Right trigger value: 0.628184939</code>
As you can see, with the deadZone filter, output is not sent until after the input value has gone above 0.5 and then output continues to be sent as long as the value is above 0. Output stops being sent when the input value has returned to 0 and doesn't start again until the input value again goes above 0.5. In comparison, here is sample output from pressing the left trigger which does not use the deadZone filter.
<code>Left trigger value: 0.027346327 Left trigger value: 0.184298423 Left trigger value: 0.249583496 Left trigger value: 0.533287539 Left trigger value: 0.649349544 Left trigger value: 0.838428374 Left trigger value: 0.992342344</code>
As you can see, without the deadZone filter, values range from 0 to 1.
RouteObject.debug()
The individual rules in a mapping are known as routes and they define which input goes to which output.
The RouteObject's debug() method is used to enable debug messages.
Function
debug() // returns this.RouteObject
Arguments
This function has no parameters.
Returns
object:RouteObject: Returns this.RouteObject
Examples
This example creates a route with debug messages enabled.
<code>// Add a route to the mapping object ("mapping")
mapping.from(Controller.Standard.RT).debug().to(function (value) {
print("Right trigger is " + value);
});</code>
With debug enabled, you should see output similar to the following in Developer > Log:
<code>[DEBUG] Applying route "" [DEBUG] Value was 0 [DEBUG] Done with mapping</code>
RouteObject.hysteresis()
The individual rules in a mapping are known as routes and they define which input goes to which output. The mapping you want to create may not be as simple as input A -> Action A. For this reason, the controller mapping API provides a number of filters allowing you customize the action.
The RouteObject's hysteresis() method is used to specify a value at which to start sending input and a value at which to stop sending input. When hysteresis() is used, input above the start value is rounded to a positive integer, and input below the stop value is rounded to 0. The purpose of this filter is to prevent flickering between options.
Function or Event
hysteresis(min, max) // Return this.RouteObject
Arguments
min:float: The value at which to stop sending output
max:float: The value at which to start sending output
Returns
- object:RouteObject: Returns this.RouteObject
Examples
This example creates two routes from the standard controller's right trigger (Controller.Standard.RT) to custom functions that print the right trigger value to the debug line. The first route uses the peek() filter to look at the value without registering that the value was looked at. The second route uses the hysteresis() filter. This route looks at the input value and prints the rounded input value to the debug log once when the value goes above 0.7 and once again when it falls below 0.5.
<code>// peek at the value
mapping.from(Controller.Standard.RT).peek().to(function(value) {
print ("Peeked at value: " + value);
});
// print the value with the hysteresis filter
mapping.from(Controller.Standard.RT).hysteresis(0.5, 0.7).to(function(value) {
print ("Hysteresis value: " + value);
});</code>
Here is what typical output might look like:
<code>Peeked at value: 0.123123123 Peeked at value: 0.424577127 Peeked at value: 0.523124560 Peeked at value: 0.723156126 Hysteresis value: 1 Peeked at value: 0.894234342 Peeked at value: 0.634234344 Peeked at value: 0.493124560 Hysteresis value: 0</code>
As you can see, the peeked at values range anywhere from 0 to 1 and are printed to the debug log with every change in value. The hysteresis() values are 0 and 1 and are only printed when input goes above 0.7 (rounded to 1) and when it falls below 0.5 (rounded to 0).
RouteObject.invert()
The individual rules in a mapping are known as routes and they define which input goes to which output. The mapping you want to create may not be as simple as input A -> Action A. For this reason, the controller mapping API provides a number of filters allowing you to customize the action.
The RouteObject's invert() method inverts the scale of the input value.
Function
invert() // Return this.RouteObject
Arguments
This function has no parameters.
Returns
- object:RouteObject: Returns this.RouteObject
Examples
This example creates a route from the standard controller's right analog stick y axis (Controller.Standard.RY) to a custom function that prints the input value.
<code>// Add a route to the mapping object ("mapping")
mapping.from(Controller.Standard.RY).invert().to(function (value) {
print("Right analog stick y axis value: " + value);
});</code>
With this route, if you press the right analog stick forward and then back, you will see output similar to the following:
<code>Right analog stick y axis value: 0.027346327 Right analog stick y axis value: 0.284298423 Right analog stick y axis value: 0.149583496 Right analog stick y axis value: 0 Right analog stick y axis value: -0.249349544 Right analog stick y axis value: -0.338428374 Right analog stick y axis value: -0.692342344</code>
As you can see, as you push the right analog stick y axis forward, values range from 0 to 1 and as you push the stick backwards, values range from 0 to -1. For comparison, here is the same route without the invert() filter.
<code>// Add a route to the mapping object ("mapping")
mapping.from(Controller.Standard.RY).to(function (value) {
print("Right analog stick y axis value: " + value);
});</code>
With this route, if you push the right analog stick forward and then backwards, you will see output similar to the following:
<code>Right analog stick y axis value: -0.013394275 Right analog stick y axis value: -0.234238455 Right analog stick y axis value: -0.103842374 Right analog stick y axis value: 0 Right analog stick y axis value: 0.234872235 Right analog stick y axis value: 0.309342302 Right analog stick y axis value: 0.634329837</code>
As you can see, when you push the right analog stick y axis forward without the invert() filter, values range from 0 to -1 and as you push the stick backwards, values range from 0 to 1.
RouteObject.peek()
Mappings use a "one read/one write" rule. After an input has been read, it is marked as read and can’t be read again.
The RouteObject's peek() method is used to look at an input value without registering that you looked at the input value.
Function
peek() // Return this.RouteObject
Arguments
This function has no parameters.
Returns
- - object:RouteObject: Returns this.RouteObject
Examples
This example creates two routes. The first uses peek() and constrainToInteger() to look at the value of the standard controller's left trigger (Controller.Standard.LT) to determine if it is being pressed or not without marking the left trigger as read. The second route reads the value of the left trigger and prints it to the debug line.
<code>//Add new route to the mapping object ("mapping") that peeks at a value
mapping.from(Controller.Standard.LT).peek().constrainToInteger().to(function(value) {
if (value) {
print ("trigger pressed");
} else {
print ("trigger released");
}
});
//Add a new route to the mapping object ("mapping")
mapping.from(Controller.Standard.LT).to(function(value) {
print("Left trigger value:" + value);
});</code>
RouteObject.pulse()
The individual rules in a mapping are known as routes and they define which input goes to which output. The mapping you want to create may not be as simple as input A -> Action A. For this reason, the controller mapping API provides a number of filters allowing you to customize the action.
The RouteObject's pulse() method is used to specify that the value should be sent at a specified interval.
Function or Event
pulse(interval) // Return this.RouteObject
Arguments
- interval: float: The length of the interval in seconds
Returns
- object:RouteObject: Returns this.RouteObject
Examples
This example creates a mapping route where the value of the standard controller's left trigger (Controller.Standard.LT) is printed to the debug line once every second.
<code>//Add new route that looks at the value once per second
mapping.from(Controller.Standard.LT).pulse(1.0).to(function(value){
print("Left trigger value: " + value);
});</code>
RouteObject.scale()
The individual rules in a mapping are known as routes and they define which input goes to which output. The mapping you want to create may not be as simple as input A -> Action A. For this reason, the controller mapping API provides a number of filters allowing you to customize the action.
The RouteObject's scale() method is used to scale the input value.
Function or Event
scale(multiplier) // Returns this.RouteObject
Arguments
- multiplier: float: The amount to multiply the input value by
Returns
- object:RouteObject: Returns this.RouteObject
Examples
This example adds a route from the standard controller's right trigger (Controller.Standard.RT) to a custom function that prints the scaled value of the right trigger.
<code>// Add a route to the mapping object ("mapping")
mapping.from(Controller.Standard.RT).scale(10).to(function(value) {
print ("Right trigger value:" + value);
});</code>
Here is sample output from pressing the right trigger:
<code>Right trigger value: 0.1232234 Right trigger value: 2.5992253 Right trigger value: 3.8326432 Right trigger value: 4.5975495 Right trigger value: 5.3423533 Right trigger value: 7.8839423 Right trigger value: 9.3957293</code>
As you can see, the value has been scaled by 10, and trigger values range from 0 to 10.
RouteObject.to()
The individual rules in a mapping are known as routes and they define which input goes to which output.
The RouteObject's to() method is used to specify the endpoint of a route.
Function
to(object)
Arguments
- object:object: The endpoint of the route. The endpoint can be a standard output Action or a custom function.
Examples
This example uses the MappingObject's from() method and the resulting RouteObject's to() method to specify a route from the standard controller's right trigger (Controller.Standard.RT) to a custom function that prints the input value to the debug log.
<code>// Add a route to the mapping object ("mapping")
mapping.from(Controller.Standard.RT).to(function (value) {
print("Right trigger is " + value);
});</code>
RouteObject.when()
The individual rules in a mapping are known as routes and they define which input goes to which output. When setting up routes, you may want to use different mappings for different conditions.
The RouteObject's when() method is used to create conditional mappings.
The conditional specified by when() is evaluated before the specified input value is read, and the input value is only read if the condition is true. This is important as mappings use a "one read/one write" rule. After an input has been read, it is marked as read and can’t be read again. If the condition is false, the input is not read, and the route won't suppress later routes that use the same input.
Function
when(condition) // Return this.RouteObject
Arguments
- condition:bool: If
truethe source input is read and route is used. Iffalsethe source input is not read and the route is not used.
Returns
- object:RouteObject: Returns this.RouteObject
Examples
If the user is using an HMD (such as the Oculus Rift) in addition to a GamePad, to provide greater user comfort you may want to provide different controls than when using a GamePad alone. This example creates two routes for the standard controller's right trigger (Controller.Standard.RT). Each route goes to a custom function that prints a line to the debug log when the right trigger is pressed. The first route is used when the application is in HMD mode (Controller.Hardware.Application) while the second is used when the application is not in HMD mode.
<code>// Add a route to the mapping object ("mapping") for
// when Interface is in HMD mode
mapping.from(Controller.Standard.RT).when(Controller.Hardware.Application.InHMD).to(function(value) {
print ("Right trigger pressed while in HMD mode.");
});
// Add a route to the mapping object ("mapping") for
// when Interface is not in HMD mode
mapping.from(Controller.Standard.RT).to(function(value) {
print ("Right trigger pressed while not in HMD mode.");
});</code>
Conditional Mapping Order
In the conditional mapping example above, you'll see that the conditional case (line 4) is above the standard case (line 11). This order is important as mappings use a one read/one write rule. After an input has been read, it is marked as read and can’t be read again. If the standard case were first, the input would be marked as read and the conditional case, even if true, would not be used.
setReticlePosition()
Function
setReticlePosition(position)
Arguments
- position:Vec2: The x and y position to move the cursor to
Examples
This example moves the cursor to the upper left-hand corner of the screen.
<code>var newPosition = {x:0 , y:0};
Controller.setReticlePosition(newPosition);</code>
Events
hardwareChanged()
A hardwareChanged() event is sent when a device (Joystick, GamePad) is registered or unregistered by a plugin.
Note: Not all plugins send hardware changed events. So, for example plugging or unplugging a mouse will not generate a hardware changed event while doing so with and Xbox controller will.
Event
hardwareChanged()
Arguments
This function has no parameters.
Examples
This example prints a line to the debug log when a device (Joystick, GamePad) is registered or unregistered by a plugin.
<code>Controller.hardwareChanged.connect(function(){
print("Hardware changed");
});</code>
Note: Be sure to have the device enabled as an input device in Interface (Avatar > Input Devices). If it is not enabled, messages won't be sent.
keyPressEvent()
A keyPressEvent() is sent when a key is pressed.
Event
keyPressEvent(event)
Arguments
- event:KeyEvent: A JavaScript keyboard event
Examples
This example prints the key pressed to the debug log.
<code>Controller.keyPressEvent.connect(function(event){
print ("You pressed: " + event.text);
});</code>
keyReleaseEvent()
A keyReleaseEvent() is sent when a key has been released after it has been pressed.
Event
keyReleaseEvent(event)
Arguments
- event: KeyEvent: A JavaScript keyboard event
Examples
This example prints the key released to the debug log.
<code>Controller.keyPressEvent.connect(function(event){
print ("The " + event.text + " key has been released");
});</code>
mouseDoublePressEvent()
A mouseDoublePressEvent() is sent when the mouse button has been double-clicked.
Event
mouseDoublePressEvent(event)
Arguments
mouseEvent: MouseEvent: A JavaScript mouse event
Examples
This example prints a line to the debug log when the mouse has been double-clicked.
<code>Controller.mouseDoublePressEvent.connect(function(event){
print ("The mouse has been double-clicked.");
});</code>
mouseMoveEvent()
The mouseMoveEvent() is sent when the mouse has been moved.
Event
mouseMoveEvent(event)
Arguments
- mouseEvent: MouseEvent: A JavaScript mouse event
Examples
This example prints a line to the debug log when the mouse has been moved.
<code>Controller.mouseMoveEvent.connect(function(event){
print ("The mouse has been moved.");
});</code>
mousePressEvent()
The mousePressEvent() is sent when the mouse button has been pressed.
Event
mousePressEvent(event)
Arguments
- mouseEvent: MouseEvent: A JavaScript mouse event
Examples
This example prints a line to the debug log when the mouse button has been pressed. To test this script, open the Script Editor and run the following code:
<code>Controller.mousePressEvent.connect(function(event){
print ("The mouse button has been pressed.");
});</code>
To run the sample as an entity script, wrap the content in an anonymous JavaScript function, save the file, and add the URL to the desired entity in the Script URL textbox:
<code>(function(){
Controller.mousePressEvent.connect(function(event){
print ("The mouse button has been pressed.");
});
})</code>
mouseReleaseEvent()
The mouseReleaseEvent() is sent when the mouse button has been released.
Event
mouseReleaseEvent(event)
Arguments
- mouseEvent: MouseEvent: A JavaScript mouse event
Examples
This example prints a line to the debug log when the mouse button has been released.
<code>Controller.mouseReleaseEvent.connect(function(event){
print ("The mouse button has been released.");
});</code>
touchBeginEvent()
The touchBeginEvent() is sent when a touch event begins.
Event
touchBeginEvent(event)
Arguments
event: TouchEvent: A JavaScript touch event
Examples
This example prints a line to the debug log when a touch event begins.
<code>Controller.touchBeginEvent.connect(function (event) {
print ("A touch event began.");
});</code>
touchEndEvent()
The touchEndEvent() is sent when a touch event has ended.
Event
touchEndEvent(event)
Arguments
- event: TouchEvent: A JavaScript touch event
Examples
This example prints a line to the debug log when a touch event has ended.
<code>Controller.touchEndEvent.connect(function(event){
print ("The touch event has ended.");
});</code>
touchUpdateEvent()
The touchUpdateEvent() is sent when a touch event has been updated.
Event
touchUpdateEvent(event)
Arguments
- event: TouchEvent: A JavaScript touch event
Examples
This example prints a line to the debug log when a touch event has been updated.
<code>Controller.touchUpdateEvent.connect(function(event){
print ("The touch even has been updated.");
});</code>
wheelEvent()
The wheelEvent() is sent when a wheel event has occurred.
Event
wheelEvent(event)
Arguments
event: WheelEvent: A JavaScript wheel event
Examples
This example prints a line to the debug log when a wheel event has occurred.
<code>Controller.wheelEvent.connect(function(event){
print ("A wheel event has occurred.");
});</code>