-
Notifications
You must be signed in to change notification settings - Fork 202
InputManager
OSGJS has a custom way to handle the inputs. For an overview of the system please watch this presentation
The Input Manager will listen to native events and will transform them in composite events. They will be placed in prioritised event queues and dispatched to their listeners during each update loop.
Native events are handled by input sources (Mouse, Keyboard, touch screen, etc).
It also provide an input group system that allows to enable or disable a set of inputs in one go.
The Input Manager is instantiated by the viewer. So there is one input manager for each created viewer.
addInputSource(source): registers an InputSource with the input manager
getInputSource(name): returns an InputSource registered with the InputManager with the given name. Note that the name is defined in the input as the geName() returned value. Stock input sources and their names are:
- InputSourceMouse: 'Mouse'
- InputSourceKeyboard: 'Keyboard'
- InputSourceTouchScreen: 'TouchScreen'
- InputSourceDeviceOrientation: 'DeviceOrientation'
- InputSourceWebVR: 'WebVR'
- InputSourceGamePad: 'GamePad'
group(groupName): gets or creates a group It's recommended to maintain a hierarchical name space style of name for groups. See existing group names in InputConstants.js
addMappings(mappings): adds an input mapping to the InputManager See addMappings in the usage section and in the examples section for more information
setEnable(groupName, enable): enables or disables a group of inputs.
setPriority(eventName, priority): sets the priority of an event or the priority of all the events in a group see usage section for more information
getHigherPriority(groupName): return a priority value that is higher than the one of the given group name.
setParam(paramName, value): sets a parameter on the input manager that can be retrieved with getParam()
getParam(paramName): gets a parameter that has previsously been set with setParam()
cleanup(): disable all groups of this input manager and remove all event listener from the input sources targets
dumpGroups(filter, onlyEnabled): display all the registered groups in the console. Also available anytime as window.dumpInputGroups()
dumpEventSequence(filter, onlyEnabled): display all events registered with the input manager sorted by priority.
Also available as window.dumpEventSequence(filter, onlyEnabled)
viewer.getInputManager();
inputManager.group('group name');
Note that existing groups are declare as constants in InputConstants.js
inputManager.group('group name').addMappings(
{
myMethod: 'nativeevent',
myMethod2: ['nativeevent2', 'nativeevent3']
},
listener
);
or
inputManager.addMappings(
{
'group name:myMethod': 'nativeevent',
'group name:myMethod2': ['nativeevent2', 'nativeevent3']
},
listener
)
Note that this notation will result in the creation of a group 'group name' if it doesn't already exist.
In both examples the inputManager will try to find methods myMethod and myMethod2 in the listener instance
You can also directly bind a function callback
var myCallback = function(ev){
console.log(ev);
};
inputmanager.addMappings(
{
'group name:aName': 'nativeevent'
},
myCallback
)
Group names should be namespaces. For example in osgjs, the input groups for the manipulators are under a master group called "scene": For example, let's say we have those 3 groups.
scene.manipulatros.orbit.mousekeyboard
scene.manipulators.fps.mousekeyboard
scene.manipulators.cad.mousekeyboard
This way ou can disable all the manipulators by calling `` Even is scene.manipulators is not a physical group. Note that this will not remove all the listeners from the canvas but, prevent the event for being placed in the event queues. The groups will have a 'scene.manipulatros' mask.
However doing
inputManager.setEnable('scene.manipulators.orbit.mousekeyboard', false);
Will remove all the listeners from the canvas.
This allows to have complex configurations like this:
scene.manipulatros.orbit.mousekeyboard (enabled)
scene.manipulators.fps.mousekeyboard (disabled)
scene.manipulators.cad.mousekeyboard (enabled)
Calling
inputManager.setEnable('scene.manipulators', false);
Will prevent all events from this groups to reach their listeners. and when calling
inputManager.setEnable('scene.manipulators', true);
All the sub groups will be restored in the state they were before:
scene.manipulatros.orbit.mousekeyboard (enabled)
scene.manipulators.fps.mousekeyboard (disabled)
scene.manipulators.cad.mousekeyboard (enabled)
'click',
'contextmenu',
'dblclick',
'mousedown',
'mouseenter',
'mouseleave',
'mousemove',
'mouseover',
'mouseout',
'mouseup',
'wheel'
'keydown',
'keyup',
'keypress'
'touchstart',
'touchend',
'touchcancel',
'touchmove'
Also all events supported by hammer.js and their derivatives
'pan',
'pinch',
'press',
'rotate',
'swipe',
'singletap',
'doubletap'
for more information on hammer.js event see here
'deviceorientation', // device gyroscope change
'orientationchange' // device portrait / landscape change
'buttondown',
'buttonup',
'buttonvalue', // value change for analog buttons
'axis', // axis change
'gamepadconnected',
'gamepaddisconnected'
'vrdisplayposechanged', // Webvr headset moved
'vrdisplayconnected', // a new webvr headset has been found
'vrdisplaydisconnected', // a webvr headset disconnected
'vrdisplaynotfound' // no vr display were found
Composite events resulting from Mouse events and touch events will have the following data:
- canvasX: The x position of the cursor inside the canvas HTML element.
- canvasY: The y position of the cursor inside the canvas HTML element.
- glX: the x position of the cursor in the gl viewport.
- glX: the y position of the cursor in the gl viewport.
Note that the gl coordinates depends on the pixel ratio used by the viewer. The viewer sets this value as an external parameter on the input manager that is used by the input sources to compute the coordinates.
If you are using a different way of computing the pixel ratio, you can set this parameter yourself on the input manager.
inputManager.setParam('pixelRatio', value);
Then original standard data are copied to the composite event. To see the data contained in standard events please refer to MDN
All composite events contains a _nativeEvent array containing all native events that occured and made this composite event be despatched. This is not recommended to use them except for debugging purpose.
With the InputManager, you can map native events to a callback like this (for example a mousedown):
inputManager.group('group').addMapping(
{
start:'mousedown'
},
listener
)
This will call the listener.start() method each time there is a mousedown event But you can map more advanced events like:
inputManager.group('group').addMapping(
{
start:'mousedown ctrl 2'
},
listener
)
This will call the listener.start() method when ever the mousedown event occur on a right click (mouse button 2) and when the ctrl modifier key is pressed.
For mouse events the supported format is:
'eventname <modkey> <button>'
- eventname is a native event name supported by the InputSourceMouse.
- modkey is one of the ctrl, shift, alt, meta keyword. If you want to exclude a modifier you can prefix it with '!'
- button is the button id number and must be a value >=0.
Note that the order of optional params is not important. For the 'wheel' event, the button parameter has no effect.
examples
inputManager.group('group').addMapping(
{
startPan:'mousedown ctrl 2', // right click control
startZoom:'mousedown !ctrl 2', // right click with control specifically not pressed
startRotate: 'mousedown ctrl shift alt 0' // left click with control shift and alt pressed.
},
listener
)
For keyboard events the supported format is:
'eventname <modkey> <key or code>'
- eventname is a native event name supported by the InputSourceKeyboard.
- modkey is one of the ctrl, shift, alt, meta keyword. If you want to exclude a modifier you can prefix it with '!'
- key or code is the key value (like 'a' for letter a, or a code like 'ArrowUp' exception for the space key that is 'space' and not ' ' ).
Note that the order of optional params is not important.
examples
inputManager.group('group').addMapping(
{
selectAll:'keydown ctrl a', // ctrl + a keys
typeSpace:'keyup space', // release space bar
selectLeft: 'keydown ArrowLeft alt' // press left arrow with the alt key down.
},
listener
)
For touch events the supported format is:
'eventname <number of touches>'
- eventname is a native event name supported by the InputSourceTouchScreen.
- number of touches the number of fingers touching the screen.
Note that release events like "touchend 2" will be triggered if there was a touchstart 2 before and that at least one finger has been released.
examples
inputManager.group('group').addMapping(
{
startPan:'touchstart 2', // 2 fingers touch on the screen
rotateEnvironment:'pan 3', // paning with 3 fingers
flash: 'singletap 2' // Tap event with 2 fingers.
},
listener
)
The gamepad Api is not event based. The inputManager will poll the device each frame and generate appropriate events. For now only the standard gamepad layout is supported. For gamepad events the supported format is:
'eventname <button>'
- eventname is a native event name supported by the InputSourceGamePad.
- button the button index
examples
inputManager.group('group').addMapping(
{
startPan:'buttondown 2', // button 2 has been pressed
rotateEnvironment:'buttonvalue 7', // analog button 7 value changed
flash: 'axis 2' // axis 2 value changed
},
listener
)
There is no rich recognition for device orientation events
examples
inputManager.group('group').addMapping(
{
changeOrientation:'deviceorientation', // the device moved.
switchScreenOrientation:'orientationchange' // screen orientation changed
},
listener
)
There is no rich recognition for webvr events
examples
inputManager.group('group').addMapping(
{
changeOrientation:'vrdisplayposechanged', // the device moved.
registerDevice:'vrdisplayconnected', // a headset has been plugged in
fallbackMode: 'vrdisplaynotfound' // no vr display found
},
listener
)
When initalizing the viewer you can pass a pollInterval parameter. This parameter will define the time the input source will wait between 2 device polling.
InputSources: {
WebVR: {
pollInterval: 2000 // will poll for a headset every 2 seconds
}
}
Note that 'vrdisplayconnected' 'vrdisplaydisconnected' events can only be triggered when the input source is in poll mode.
To disable the poll mode you can set a value lower or equal to 0 for the pollInterval parameter. In this mode, the input source won't poll for the device automatically. You can manually poll the device using
inputManager.getInputSource('WebVR').pollHeadset();
This will trigger the 'vrdisplayconnected' if a device is found or else, the 'vrdisplaynotfound'.