Re: GamepadObserver (ie. MutationObserver + Gamepad)

2012-08-07 Thread Olli Pettay

On 08/07/2012 03:29 AM, Glenn Maynard wrote:

On Sat, Aug 4, 2012 at 4:24 AM, Olli Pettay olli.pet...@helsinki.fi 
mailto:olli.pet...@helsinki.fi wrote:

5ms is quite low when the aim is 60Hz updates... but with 
incremental/generational GCs 5ms sounds very much possible.


5ms is an *eternity* when you're aiming for 60 FPS, where you only have 16.6ms 
per frame to play with.  That's 30% of your CPU budget just for memory
management.  It doesn't matter if it's 5ms every 100 frames, since it's the 
worst case you have to optimize for.  (I've spent a lot of time optimizing
non-web games to stay at 60 FPS, and it's a battle of microseconds, optimizing away .1ms 
here and .2ms there, so calling 5ms quite low is a bit
troubling.)


It is quite different if you need to assume that GC takes 180-250ms or if it 
takes only 5ms.
But sure, getting anything major done in 16.6ms, and even so that things work 
ok on slower machines too can be tricky.






Re: GamepadObserver (ie. MutationObserver + Gamepad)

2012-08-07 Thread Florian Bösch
On Tue, Aug 7, 2012 at 2:29 AM, Glenn Maynard gl...@zewt.org wrote:

 5ms is an *eternity* when you're aiming for 60 FPS, where you only have
 16.6ms per frame to play with.  That's 30% of your CPU budget just for
 memory management.  It doesn't matter if it's 5ms every 100 frames, since
 it's the worst case you have to optimize for.  (I've spent a lot of time
 optimizing non-web games to stay at 60 FPS, and it's a battle of
 microseconds, optimizing away .1ms here and .2ms there, so calling 5ms
 quite low is a bit troubling.)

On a sidenote, the coming Oculus Rift (VR headset with wide FOV) will be
quite sensitive to lag/jitter and the aim to support that is to have a
total RTT from input - display of no more than 20ms per frame, for every
frame at preferably 120hz (the dev kit display ships @60hz)


Re: GamepadObserver (ie. MutationObserver + Gamepad)

2012-08-04 Thread Florian Bösch
On Sat, Aug 4, 2012 at 3:11 AM, Glenn Maynard gl...@zewt.org wrote:

 On a quick test, Firefox is firing mousemove events at 120Hz; this is
 about the same magnitude of data.  We don't currently have any
 infrastructure for using ArrayBuffers for complex data, so it'd either need
 to be something new (some sort of complex view), or an unfriendly API.
 Either would be a major obstacle to getting anything adopted.

The update rate depends on the device. Tablet updates reach way beyond
120HZ and even my 3D mouse clocks in at about 500 events/s. And a major
obstacle for a realtime input device is when the realtime app trying to use
it stutters/jitters every quarter second because of 180-250ms GC-pauses


Re: GamepadObserver (ie. MutationObserver + Gamepad)

2012-08-04 Thread Florian Bösch
On Sat, Aug 4, 2012 at 11:07 AM, b...@pettay.fi b...@pettay.fi wrote:

 The update rate depends on the device. Tablet updates reach way beyond
 120HZ and even my 3D mouse clocks in at about 500 events/s. And a major
 obstacle for a realtime input device is when the realtime app trying to
 use it stutters/jitters every quarter second because of 180-250ms GC-pauses


 That long GC pauses are bugs in the implementations. File some bugs on all
 the browser engines you see it (after testing latest nightly builds).

It doesn't matter if they're bugs (I often see them in conjunction to array
buffer allocation). Even at the best of times the GC-pauses are no less
than 90ms, and even if you got it down to 60ms, that's still more than 5
frames @80hz. Until you get GC-pauses down to ~5ms or so, any GC use will
introduce unpleasant stuttering/jittering. And even then it's a close call
to not miss a frame.


Re: GamepadObserver (ie. MutationObserver + Gamepad)

2012-08-04 Thread Olli Pettay

On 08/04/2012 12:16 PM, Florian Bösch wrote:



On Sat, Aug 4, 2012 at 11:07 AM, b...@pettay.fi mailto:b...@pettay.fi b...@pettay.fi 
mailto:b...@pettay.fi wrote:

The update rate depends on the device. Tablet updates reach way beyond 
120HZ and even my 3D mouse clocks in at about 500 events/s. And a major
obstacle for a realtime input device is when the realtime app trying to 
use it stutters/jitters every quarter second because of 180-250ms
GC-pauses


That long GC pauses are bugs in the implementations. File some bugs on all 
the browser engines you see it (after testing latest nightly builds).

It doesn't matter if they're bugs (I often see them in conjunction to array 
buffer allocation).

Of course it matters. APIs shouldn't be designed based on implementation bugs



Even at the best of times the GC-pauses are no less
than 90ms, and even if you got it down to 60ms, that's still more than 5 frames 
@80hz. Until you get GC-pauses down to ~5ms or so, any GC use will
introduce unpleasant stuttering/jittering. And even then it's a close call to 
not miss a frame.

5ms is quite low when the aim is 60Hz updates... but with 
incremental/generational GCs 5ms sounds very much possible.




Re: GamepadObserver (ie. MutationObserver + Gamepad)

2012-08-04 Thread Florian Bösch
On Sat, Aug 4, 2012 at 11:24 AM, Olli Pettay olli.pet...@helsinki.fiwrote:

 It doesn't matter if they're bugs (I often see them in conjunction to
 array buffer allocation).

 Of course it matters. APIs shouldn't be designed based on implementation
 bugs

It doesn't because those bugs have not been fixed the last odd 15 years
and with every new vendor repeating them enthusiastically, and the entire
WebGL tool ecosystem is growing around those bugs to avoid to allocate,
ever, during a drawing loop. If you intended to limit the damage, it's too
late, done deal. That should've happend 3 years ago. Now it's just dealing
with the facts.


  Even at the best of times the GC-pauses are no less
 than 90ms, and even if you got it down to 60ms, that's still more than 5
 frames @80hz. Until you get GC-pauses down to ~5ms or so, any GC use will
 introduce unpleasant stuttering/jittering. And even then it's a close
 call to not miss a frame.

 5ms is quite low when the aim is 60Hz updates... but with
 incremental/generational GCs 5ms sounds very much possible.

@60hz you're running  16.6ms/frame. 5ms is nearly 1/3 of a frame. If you
take up say 12ms to render a frame, then a 5ms pause *will* make you skip a
frame. @80hz you take 12.5ms/frame, if your frame needs longer than 7.5ms
to produce, again, 5ms *will* skip a frame. 5ms isn't low, it's actually
generously big. It's an upper acceptable delay we can work with. Most
frames don't take longer than 5ms to produce and render, personally I'm
always aiming at keeping the CPU time per frame in the sub millisecond
region and see to it the GPU part does not exceed 5ms.


Re: GamepadObserver (ie. MutationObserver + Gamepad)

2012-08-04 Thread Florian Bösch
On Sat, Aug 4, 2012 at 11:31 AM, Florian Bösch pya...@gmail.com wrote:

 On Sat, Aug 4, 2012 at 11:24 AM, Olli Pettay olli.pet...@helsinki.fiwrote:

 It doesn't matter if they're bugs (I often see them in conjunction to
 array buffer allocation).

 Of course it matters. APIs shouldn't be designed based on implementation
 bugs

 It doesn't because those bugs have not been fixed the last odd 15 years
 and with every new vendor repeating them enthusiastically, and the entire
 WebGL tool ecosystem is growing around those bugs to avoid to allocate,
 ever, during a drawing loop. If you intended to limit the damage, it's too
 late, done deal. That should've happend 3 years ago. Now it's just dealing
 with the facts.

Btw. about half of those projects reason for existence owes to this bug,
Emscripten http://emscripten.org , LLJS http://mbebenita.github.com/LLJS/ ,
Heap.coffee http://syg.github.com/heap.coffee/ , gl-matrix
https://github.com/toji/gl-matrix and that's OK

It's OK because the other half these projects owe it to array buffers to
make things run blazing fast, since the JIT in V8 enthusiastically
optimizes JS, the reduced pointer indirection speeds things up and the
better cache coherence helps a lot.


Re: GamepadObserver (ie. MutationObserver + Gamepad)

2012-08-04 Thread Florian Bösch
On Sat, Aug 4, 2012 at 11:46 AM, Florian Bösch pya...@gmail.com wrote:

 It's OK because the other half these projects owe it to array buffers to
 make things run blazing fast, since the JIT in V8 enthusiastically
 optimizes JS, the reduced pointer indirection speeds things up and the
 better cache coherence helps a lot.

Longwinded way of saying, if you do realtime APIs and you ignore buffers
you're doing it wrong.


Re: GamepadObserver (ie. MutationObserver + Gamepad)

2012-08-04 Thread Glenn Maynard
Here's a rough sketch of an API that provides clean forwards-compatibility
for devices.  I think this also avoids all of the issues I talked about
earlier: it gives a clean, easy to use event-based API that preserves
ordering and timestamps; it can be used in both an event-based and polling
way; it can retrieve both events and the current state; and most
importantly it doesn't push things into a library, with all of the serious
(and hopefully obvious to everyone on this list) problems that would cause.

// Retrieve a representation of the device, with no actual access to inputs:
var gamepad = getSomeInputDevice();

// Get a list of supported layouts:
console.log(gamepad.layouts);
[X360, NES, SNES, raw]

// Get an interface, specifying which layout to use.
var gamepadInput = gamepad.getLayout(X360);

// Read the current state.
var state = gamepadInput.getCurrentState();
/* state == {
// These values are defined by the X360 layout.
leftThumbStickX: 0, leftThumbStickY: 0,
rightThumbStickX: 0.4, rightThumbStickY: 0.5,
up: true, right: false, down: false, left: false,
buttonX: false, buttonY: false, buttonA: false, buttonB: false,

// Inputs which have no representation in this layout are returned in
raw form.
rawCompassAngle: 45,
} */

// Read the buffer of changes:
var stateChanges = gamepadInput.read();
/* stateChanges == [{
input: rightThumbstickX, // These labels are equal to the object keys
in state above.
value: 0.5,
lastValue: 0.4,
 timestamp: 1336102719319,
}, {
input: rawCompassAngle,
 value: 55,
lastValue: 45,
timestamp: 1336102721319,
}] */

function processInput(stateChanges)
{
// Process inputs:
for(var i = 0; i  stateChanges.length; ++i)
{
var change = stateChanges[i];
var delta = change.lastValue - change.value;
switch(change.input)
{
case left: console.log(Left button was  + change.value?
pushed:released); break;
case leftThumbStickX:
console.log(Left stick X axis: + change.value +  with a
relative change of  + delta);
break;
}
}

// Update the game state.  This API allows us to process all inputs
that happen simultaneously together,
// such as axis changes, and then only update the game state once for
the whole batch.
processInputs();
}

// Receiving an event on change:
gamepadInput.onchange = function(e) { processInput(gamepadInput.read()); };

Some points:

- A browser may support many different layouts for the same device.  For
example, an Xbox 360 controller can easily be used as an NES or SNES
controller, so it can expose those profiles.
- Raw inputs for any unmapped inputs are included for all profiles.  This
allows games to make use of additional controls, without being forced to
drop back to raw to access them at all.
- If a profile is exposed at all, the inputs of the profile must be
completely covered.
- Layout may not always map 1:1 to raw inputs.  For example, the
Playstation controller's D-pad is four buttons in a cross; layouts may map
these four buttons down to two axes.
- All data in getCurrentState is absolute, since it doesn't mutate the
object.  Therefore, purely relative inputs, such as trackballs and
(probably) steering wheels, are returned in an absolute, accumulated form.
To get relative motion, subtract the value from the previous value.

By the way, while I only included NES as an example, having a baseline
layout like that (with a more generic name) is useful: tons of simple games
use only a D-pad and a couple buttons.  This would give them get the widest
input device support possible, by not having to request a profile with far
more features than they need.

I haven't tried to incorporate Florian's suggestion of using something like
ArrayBuffer.  That could be supported later, eg. by providing a
readIntoBuffer(buffer) next to read().  That's too complex to try to tackle
all at once.

-- 
Glenn Maynard


Re: GamepadObserver (ie. MutationObserver + Gamepad)

2012-08-04 Thread Florian Bösch
On Sat, Aug 4, 2012 at 7:03 PM, Glenn Maynard gl...@zewt.org wrote:

 Here's a rough sketch of an API that provides clean forwards-compatibility
 for devices.  I think this also avoids all of the issues I talked about
 earlier: it gives a clean, easy to use event-based API that preserves
 ordering and timestamps; it can be used in both an event-based and polling
 way; it can retrieve both events and the current state; and most
 importantly it doesn't push things into a library, with all of the serious
 (and hopefully obvious to everyone on this list) problems that would cause.

 // Retrieve a representation of the device, with no actual access to
 inputs:
 var gamepad = getSomeInputDevice();

 // Get a list of supported layouts:
 console.log(gamepad.layouts);
 [X360, NES, SNES, raw]

 // Get an interface, specifying which layout to use.
 var gamepadInput = gamepad.getLayout(X360);

 // Read the current state.
 var state = gamepadInput.getCurrentState();
 /* state == {
 // These values are defined by the X360 layout.
 leftThumbStickX: 0, leftThumbStickY: 0,
 rightThumbStickX: 0.4, rightThumbStickY: 0.5,
 up: true, right: false, down: false, left: false,
 buttonX: false, buttonY: false, buttonA: false, buttonB: false,

 // Inputs which have no representation in this layout are returned in
 raw form.
 rawCompassAngle: 45,
 } */

 // Read the buffer of changes:
 var stateChanges = gamepadInput.read();
 /* stateChanges == [{
 input: rightThumbstickX, // These labels are equal to the object
 keys in state above.
 value: 0.5,
 lastValue: 0.4,
  timestamp: 1336102719319,
 }, {
 input: rawCompassAngle,
  value: 55,
 lastValue: 45,
 timestamp: 1336102721319,
 }] */

 function processInput(stateChanges)
 {
 // Process inputs:
 for(var i = 0; i  stateChanges.length; ++i)
 {
 var change = stateChanges[i];
 var delta = change.lastValue - change.value;
 switch(change.input)
 {
 case left: console.log(Left button was  + change.value?
 pushed:released); break;
  case leftThumbStickX:
 console.log(Left stick X axis: + change.value +  with a
 relative change of  + delta);
 break;
 }
 }

 // Update the game state.  This API allows us to process all inputs
 that happen simultaneously together,
 // such as axis changes, and then only update the game state once for
 the whole batch.
 processInputs();
 }

 // Receiving an event on change:
 gamepadInput.onchange = function(e) { processInput(gamepadInput.read());
 };

 Some points:

 - A browser may support many different layouts for the same device.  For
 example, an Xbox 360 controller can easily be used as an NES or SNES
 controller, so it can expose those profiles.
 - Raw inputs for any unmapped inputs are included for all profiles.  This
 allows games to make use of additional controls, without being forced to
 drop back to raw to access them at all.
 - If a profile is exposed at all, the inputs of the profile must be
 completely covered.
 - Layout may not always map 1:1 to raw inputs.  For example, the
 Playstation controller's D-pad is four buttons in a cross; layouts may map
 these four buttons down to two axes.
 - All data in getCurrentState is absolute, since it doesn't mutate the
 object.  Therefore, purely relative inputs, such as trackballs and
 (probably) steering wheels, are returned in an absolute, accumulated form.
 To get relative motion, subtract the value from the previous value.

 By the way, while I only included NES as an example, having a baseline
 layout like that (with a more generic name) is useful: tons of simple games
 use only a D-pad and a couple buttons.  This would give them get the widest
 input device support possible, by not having to request a profile with far
 more features than they need.

 I haven't tried to incorporate Florian's suggestion of using something
 like ArrayBuffer.  That could be supported later, eg. by providing a
 readIntoBuffer(buffer) next to read().  That's too complex to try to tackle
 all at once.

What happens if there is no supported profile?


Re: GamepadObserver (ie. MutationObserver + Gamepad)

2012-08-04 Thread Florian Bösch
On Sat, Aug 4, 2012 at 7:10 PM, Florian Bösch pya...@gmail.com wrote:

 What happens if there is no supported profile?

Oh nm, then it's raw, stupid question.


Re: GamepadObserver (ie. MutationObserver + Gamepad)

2012-08-04 Thread Florian Bösch
On Sat, Aug 4, 2012 at 7:03 PM, Glenn Maynard gl...@zewt.org wrote:

 I haven't tried to incorporate Florian's suggestion of using something
 like ArrayBuffer.  That could be supported later, eg. by providing a
 readIntoBuffer(buffer) next to read().  That's too complex to try to tackle
 all at once.

I've had an idea how improve the issues around current state and button
misses.

- Some uses (like look/strafe/move etc.) that are served by an axis always
use current state. There is no benefit to know the event history leading up
to that state. So this would use the current state.
- Button uses always require all events as button press/release misses
would be bad. So this would get all events.
- A mixed model is where an axis is used with tresholds (like say a weapon
trigger with the index finger). A miss is not bad, but response accuracy
will improve from getting the event as close to the threshold as possible.
So this would inform the API of its thresholds for this axis, so events can
be issued when the high frequency polling detects the axis going over the
it.


Re: GamepadObserver (ie. MutationObserver + Gamepad)

2012-08-03 Thread Glenn Maynard
Sorry for the long-delayed reply.  The tablets thread reminded me about
this mail, which got lost in the black hole known as drafts...

On Mon, May 7, 2012 at 2:33 PM, Scott Graham scot...@chromium.org wrote:

 - As you point out, the 360 controller is by far the most common PC
 gamepad, and on its native platforms its standard API XInput is
 exclusively polling based [4]. That doesn't mean we must or even
 should follow that design, but it does mean that even if we design a
 bunch of fancier/cleverer APIs we're still going to be largely
 constrained by that API. That is, there's not going to be any extra
 information in events that are synthesized from polled data. [5]


Not exactly, since you can poll devices natively with these kinds of APIs
much more quickly (without being excessively wasteful) than you can in JS.
 Polling at 120Hz (or even 1000Hz) natively, in a well-tuned thread, is
much more realistic than doing it in JS.  You can also do it in a
high-priority or realtime thread, so timestamps are as accurate as possible.

  - Native deadzone handling (by the OS or internally to the device) is the
  only way to correctly handle deadzones when you don't have intimate
  knowledge of the hardware.  It should be explicitly (if non-normatively)
  noted that native deadzone handling should be used when available.

 This has been discussed before, and it's certainly important. The one
 complexity that needs to be solved is handling 1D vs. 2D dead zones
 for axes. That is, should the X and Y be deadzoned as independent 1D
 axes, or should they be deadzoned as a 2D vector. I guess this could
 either be left to non-normative discussion and hope the
 implementations do something sensible, or additional API surface will
 be needed for a full solution. (I would probably lean towards
 non-normative, and ignore the separate 1D axes problem, myself.)


Some hardware does deadzoning internally.  Also, the type of deadzoning may
depend on the device; the correct answer may be different for gamepad
thumbsticks and joysticks, for example, and devices with different amounts
of slop need dead zones tuned differently.

I think this should be entirely up to the implementation.  However, it may
be worth a note that it *is* intended that deadzoning be handled either by
the browser or somewhere lower down the stack, and not by web developers
(up the stack).

  I'd suggest a halfway point between polling and events: a function to
  retrieve a list of device changes since the last call, and an event
 fired on
  the object the first time a new change is made.  For example,
 
  var gamepad = window.openGamepad(0);
  gamepad.addEventListener(input, function(e) {
  var changes = gamepad.readChanges();
  }, false);
 
  with changes being an array of objects, each object describing a
 timestamped
  change of state, eg:
 
  changes = [
  {
  button: 0,
  state: 1.0,
  lastState: 0.85,
  timestamp: 1336102719319
  }
  ]
 
  This allows using polling if your application is based on
  requestAnimationFrame, or events if you want to be told when there's
  something to read.  There isn't an excess of events dispatched, because
 the
  event is only dispatched once per call to readChanges; if you only read
  changes once in a while you'll only receive the one event.  It also
 solves
  all of the above problems with a most-recent-state-only interface.

 I think it's a loss to not have a full most-recent-state available.


This isn't mutually exclusive with a separate getCurrentState() method.

 Many common styles of applications (rAF+games) would have to add a
 bunch of boilerplate that then merges these events to maintain the
 current state (especially awkward on XInput since the browser will be
 splitting them out of most-recent-state!). I don't see a lot of
 benefit to splitting each individual axis/button change out into a
 separate object. Is there a reason you prefer that way?


It seems natural to me.  You can detect the order of events, their relative
timing, and you don't have to analyze a data structure to determine which
piece changed.  If all you care about is the most recent state, then use
something like getCurrentState().

When readChanges() happens, I guess we'd need to consider some sort of
 staleness? What happens if a client only reads once every second? Or
 one every 5 minutes?


Implementations should definitely be able to cap on the amount of stored
data.

For the most part, events can simply be dropped from the beginning of the
queue.  However, button release events should never be dropped unless
there's another button depress event later in the buffer.  Otherwise,
buttons would get stuck to the application's view.


  The timestamp should be as accurate as possible to when the event
 actually
  happened, in the clock used by Date.now(), so you can tell how long ago
 the
  event happened.  Accurate timestamps are important for games that require
  fine-grained timing; 2D 

Re: GamepadObserver (ie. MutationObserver + Gamepad)

2012-08-03 Thread Florian Bösch
On Sat, Aug 4, 2012 at 12:52 AM, Glenn Maynard gl...@zewt.org wrote:

 On Mon, May 7, 2012 at 2:33 PM, Scott Graham scot...@chromium.org wrote:

 - As you point out, the 360 controller is by far the most common PC
 gamepad, and on its native platforms its standard API XInput is
 exclusively polling based [4]. That doesn't mean we must or even
 should follow that design, but it does mean that even if we design a
 bunch of fancier/cleverer APIs we're still going to be largely
 constrained by that API. That is, there's not going to be any extra
 information in events that are synthesized from polled data. [5]


 Not exactly, since you can poll devices natively with these kinds of APIs
 much more quickly (without being excessively wasteful) than you can in JS.
  Polling at 120Hz (or even 1000Hz) natively, in a well-tuned thread, is
 much more realistic than doing it in JS.  You can also do it in a
 high-priority or realtime thread, so timestamps are as accurate as possible.

Also don't forget that the browser only needs to poll once at each poll
iteration and then the event queues can be multiplexed to any page reading
from them, vastly more efficient.


   - Native deadzone handling (by the OS or internally to the device) is
 the
  only way to correctly handle deadzones when you don't have intimate
  knowledge of the hardware.  It should be explicitly (if non-normatively)
  noted that native deadzone handling should be used when available.

 This has been discussed before, and it's certainly important. The one
 complexity that needs to be solved is handling 1D vs. 2D dead zones
 for axes. That is, should the X and Y be deadzoned as independent 1D
 axes, or should they be deadzoned as a 2D vector. I guess this could
 either be left to non-normative discussion and hope the
 implementations do something sensible, or additional API surface will
 be needed for a full solution. (I would probably lean towards
 non-normative, and ignore the separate 1D axes problem, myself.)


 Some hardware does deadzoning internally.  Also, the type of deadzoning
 may depend on the device; the correct answer may be different for gamepad
 thumbsticks and joysticks, for example, and devices with different amounts
 of slop need dead zones tuned differently.

 I think this should be entirely up to the implementation.  However, it may
 be worth a note that it *is* intended that deadzoning be handled either by
 the browser or somewhere lower down the stack, and not by web developers
 (up the stack).

There is a snag with deadzoning and axis ranges. Driver enumeration of axes
of an auto-calibrated device (or any device really) is often not delivering
any usable information on this. There is a zoo of range/calibration
utilities out there alongside some built-in utilities (don't know if
windows still has those) which may or may not work satisfactory. I've
tested a variety of devices for these issues, and after some work I came to
the conclusion that the only way to reliably determine any dead zones and
ranges is to let the user max out the axes and remember that.


   I'd suggest a halfway point between polling and events: a function to
  retrieve a list of device changes since the last call, and an event
 fired on
  the object the first time a new change is made.  For example,
 
  var gamepad = window.openGamepad(0);
  gamepad.addEventListener(input, function(e) {
  var changes = gamepad.readChanges();
  }, false);
 
  with changes being an array of objects, each object describing a
 timestamped
  change of state, eg:
 
  changes = [
  {
  button: 0,
  state: 1.0,
  lastState: 0.85,
  timestamp: 1336102719319
  }
  ]
 
  This allows using polling if your application is based on
  requestAnimationFrame, or events if you want to be told when there's
  something to read.  There isn't an excess of events dispatched, because
 the
  event is only dispatched once per call to readChanges; if you only read
  changes once in a while you'll only receive the one event.  It also
 solves
  all of the above problems with a most-recent-state-only interface.

 I think it's a loss to not have a full most-recent-state available.


 This isn't mutually exclusive with a separate getCurrentState() method.

The most recent state is certainly important. But in some situations you
want access to the entire queue of events since you last asked for it. I
strongly agree that emptying the event queue is the right way to go. I
strongly disagree that this should be objects. Working trough thousands of
objects would be slow and would trigger the GC like mad. The events should
be filled into an array buffer where they can processed at near C speeds
and will not trigger the GC.


 When readChanges() happens, I guess we'd need to consider some sort of
 staleness? What happens if a client only reads once every second? Or
 one every 5 minutes?


 Implementations should definitely be able to cap on the amount of stored
 data.


Re: GamepadObserver (ie. MutationObserver + Gamepad)

2012-08-03 Thread Glenn Maynard
On Fri, Aug 3, 2012 at 6:17 PM, Florian Bösch pya...@gmail.com wrote:

 There is a snag with deadzoning and axis ranges. Driver enumeration of
 axes of an auto-calibrated device (or any device really) is often not
 delivering any usable information on this. There is a zoo of
 range/calibration utilities out there alongside some built-in utilities
 (don't know if windows still has those) which may or may not work
 satisfactory. I've tested a variety of devices for these issues, and after
 some work I came to the conclusion that the only way to reliably determine
 any dead zones and ranges is to let the user max out the axes and remember
 that.


This is still something implementations can deal with better than web
apps.  (Range calibration in Windows is done globally, but configuring dead
zones is very rare.)

Also, I'm guessing this isn't a problem for the Xbox 360 controller.

I strongly disagree that this should be objects. Working trough thousands
 of objects would be slow and would trigger the GC like mad.


On a quick test, Firefox is firing mousemove events at 120Hz; this is about
the same magnitude of data.  We don't currently have any infrastructure for
using ArrayBuffers for complex data, so it'd either need to be something
new (some sort of complex view), or an unfriendly API.  Either would be a
major obstacle to getting anything adopted.

-- 
Glenn Maynard


Re: GamepadObserver (ie. MutationObserver + Gamepad)

2012-05-07 Thread Scott Graham
On Thu, May 3, 2012 at 9:14 PM, Glenn Maynard gl...@zewt.org wrote:
 Here are some piecemeal thoughts on the subject of gamepads and the
 gamepad spec.  I havn't closely followed earlier discussions (and there
 don't seem to have been any in a while), so much of this may have been
 covered before.


Hi Glenn,

Thanks for thinking about gamepads and the current draft, it's much
appreciated. There's a lot of separate points here that it'd be great
to get other people's thoughts on.

A few high-level things to note in addition to my inline comments:

- As you point out, the 360 controller is by far the most common PC
gamepad, and on its native platforms its standard API XInput is
exclusively polling based [4]. That doesn't mean we must or even
should follow that design, but it does mean that even if we design a
bunch of fancier/cleverer APIs we're still going to be largely
constrained by that API. That is, there's not going to be any extra
information in events that are synthesized from polled data. [5]

- Some of the tradeoffs that you mention in terms of making the API
more usable, or adding more functionality have been discussed before.
In general the preference has been to expose data in a more
raw/unprocessed format to allow for more flexibility to the consumer
of the data. I'm not sure that the correct balance has been struck yet
though. There's a tension between trying to make something usable
out-of-the-box and avoiding getting into specifying things in too much
detail in the spec, which will be harder to evolve and update,
especially if we over-specify in a first version.


 - It should be possible to tell what's changed, not just the current state
 of the device.  Needing to compare each piece of input to the previous state
 is cumbersome.

This is the sort of thing that might go in the content helper library.
It seems reasonable in an event-based api to provide previous and
current though.


 - Native deadzone handling (by the OS or internally to the device) is the
 only way to correctly handle deadzones when you don't have intimate
 knowledge of the hardware.  It should be explicitly (if non-normatively)
 noted that native deadzone handling should be used when available.

This has been discussed before, and it's certainly important. The one
complexity that needs to be solved is handling 1D vs. 2D dead zones
for axes. That is, should the X and Y be deadzoned as independent 1D
axes, or should they be deadzoned as a 2D vector. I guess this could
either be left to non-normative discussion and hope the
implementations do something sensible, or additional API surface will
be needed for a full solution. (I would probably lean towards
non-normative, and ignore the separate 1D axes problem, myself.)


 - It's very important that it's possible to receive gamepad data without
 polling.  We don't need more web pages running setTimeout(0) loops as fast
 as browsers will let them, which is what it encourages.  Not all pages are
 based on a requestAnimationFrame loop.

Noted.


 - An API that can only return the current state loses button presses if
 they're released too quickly.  It's common to press a button while the UI
 thread is held up for one reason or another--and you also can't assume that
 users can't press and release a button in under 16ms (they can).

 - APIs like that also lose the *order* of button presses, when they're
 pressed too quickly.  (I've encountered this problem in my own experience;
 it's definitely possible--it's not even particularly hard--for a user to
 press two buttons in a specific order in under 16ms.)

Both noted, balanced against my comment about XInput above.


 I'd suggest a halfway point between polling and events: a function to
 retrieve a list of device changes since the last call, and an event fired on
 the object the first time a new change is made.  For example,

 var gamepad = window.openGamepad(0);
 gamepad.addEventListener(input, function(e) {
     var changes = gamepad.readChanges();
 }, false);

 with changes being an array of objects, each object describing a timestamped
 change of state, eg:

 changes = [
     {
     button: 0,
     state: 1.0,
     lastState: 0.85,
     timestamp: 1336102719319
     }
 ]

 This allows using polling if your application is based on
 requestAnimationFrame, or events if you want to be told when there's
 something to read.  There isn't an excess of events dispatched, because the
 event is only dispatched once per call to readChanges; if you only read
 changes once in a while you'll only receive the one event.  It also solves
 all of the above problems with a most-recent-state-only interface.

I think it's a loss to not have a full most-recent-state available.
Many common styles of applications (rAF+games) would have to add a
bunch of boilerplate that then merges these events to maintain the
current state (especially awkward on XInput since the browser will be
splitting them out of most-recent-state!). I don't see a 

Inking out a PenObserver, was Re: GamepadObserver (ie. MutationObserver + Gamepad)

2012-05-04 Thread Charles Pritchard
Glenn, all of your points apply well to pressure sensitive pen input. 
Pen vendors are not on the list, but their devices are quite similar.
I've changed the subject line and my responses are to your gamepad notes 
in respect to their application to pen input.


Pen input in this case is pressure sensitive input with high sensitivity 
to time, pressure and coordinates, with a sample rate faster than 60hz. 
Pen devices are commonly connected via USB.
The Gamepad API is an experimental API which deals with similar device 
characteristics. Pen vendors are not active with the W3C though the 
InkML specification did make it into recommendation status.


On 5/3/2012 9:14 PM, Glenn Maynard wrote:
Here are some piecemeal thoughts on the subject of gamepads and the 
gamepad spec.  I havn't closely followed earlier discussions (and 
there don't seem to have been any in a while), so much of this may 
have been covered before.


- It should be possible to tell what's changed, not just the current 
state of the device.  Needing to compare each piece of input to the 
previous state is cumbersome.


There's a variety of options that may not ever change. Some devices may 
simply not support the values. With pen, we've got items like azimuth 
and altitude. Few pens support it.
As authors, we just ignore that input or do feature tests (if pressure 
exists, and those metrics are still 0, then they're likely not supported).



- Native deadzone handling (by the OS or internally to the device) is 
the only way to correctly handle deadzones when you don't have 
intimate knowledge of the hardware.  It should be explicitly (if 
non-normatively) noted that native deadzone handling should be used 
when available.


- It's very important that it's possible to receive gamepad data 
without polling.  We don't need more web pages running setTimeout(0) 
loops as fast as browsers will let them, which is what it encourages.  
Not all pages are based on a requestAnimationFrame loop.


Recently, I found a setTimeout(20ms, then rAF) to work reasonably well 
for my little laptop.  Any faster, and I lose more data points, and 
slower and the lag [drawing to the screen] is disorienting.
That's just a subjective observation on a light-duty laptop with one 
vendor, just using a track pad.



- An API that can only return the current state loses button presses 
if they're released too quickly.  It's common to press a button while 
the UI thread is held up for one reason or another--and you also can't 
assume that users can't press and release a button in under 16ms (they 
can).


The rAF loop can in some circumstances slow the polling or otherwise 
result in data loss.
It's a real pain. We get our best fidelity if the screen is empty and 
we're not drawing. Once we start drawing, we're bound to lose some data.




- APIs like that also lose the *order* of button presses, when they're 
pressed too quickly.  (I've encountered this problem in my own 
experience; it's definitely possible--it's not even particularly 
hard--for a user to press two buttons in a specific order in under 16ms.)


My pen has two buttons in addition to two high sensitivity pressure 
inputs. Wacom introduced onpressurechange events in their Flash SDL. 
In some sense, it's an experimental plugin for WebKit as it runs in Air, 
but it's really closer to the Flash side of things.




I'd suggest a halfway point between polling and events: a function to 
retrieve a list of device changes since the last call, and an event 
fired on the object the first time a new change is made.  For example,


var gamepad = window.openGamepad(0);
gamepad.addEventListener(input, function(e) {
var changes = gamepad.readChanges();
}, false);

with changes being an array of objects, each object describing a 
timestamped change of state, eg:


changes = [
{
button: 0,
state: 1.0,
lastState: 0.85,
timestamp: 1336102719319
}
]


At what point would we consider entries to be stale? Is that something 
that should be a concern?

It'd take quite a lot of changes to be a problem.

As a security issue -- do we need to point out that two windows should 
not have concurrent access to the same gamepad (such as applies to 
keyboard and mouse)?

That's another issue I noticed with pen tablet plugins.

-Charles



Re: GamepadObserver (ie. MutationObserver + Gamepad)

2012-05-03 Thread Rick Waldron
 snip


Weird, because you posted
this:
https://docs.google.com/document/d/1atsxnstVybfovkX_f6xf2P25i1NT0ilCihJuPDwYWEU/edit?hl=en_US

here: https://bugzilla.mozilla.org/show_bug.cgi?id=604039#c40


Just to be clear, I'm not trying to be aggressive or confrontational, but I
just reread my message from last night and realized it could easily be read
that way - apologies!  :)


I'm not sure what you mean. It is my opinion is that it would be
inefficient to spam 50+ button and axis events multiplied by (say) 4
devices @ 60Hz, which is why I've been pursuing the design of a
polling API. So, though what you quoted was written a while back, it
seems to still represent my opinion pretty accurately


I'm not sure if everyone agrees with me on that though, which is why I
said I didn't think there was a consensus. I believe Mozilla's
vendor-prefixed implementation includes some of those type of events,
so perhaps we will soon have more empirical data on the subject.


I agree with both arguments, because you're right: it's simply too much
volume. As for existing data or APIs, Microsoft's DirectInput API provides
both polling and event notifications.

Going back to the notes at
http://dvcs.w3.org/hg/gamepad/raw-file/tip/gamepad.html#other-events I'd
say the single event gamepagechanged, where the event object has a
property describing the complete state of the gamepad, is more in line with
the DirectInput event system. Something like this would also make it easier
to detect multiple, sequentially and/or simultaneously changed states...

eg. press and hold B; while holding B, press A
(for the sake of example, the states will be HIGH and LOW, both start LOW)

Dispatch an event for the change of state on B. B set HIGH
Dispatch an event for the change of state on A. A set HIGH, B still HIGH

When the event is dispatched for the changed state of A, the handler
receives an event object that will show no change to the state of B since
it was set to HIGH.


With separate axis and button events, I dont think this could be reasonably
feasible.


Again, apologies for any perceived negative tone from earlier messages :)


Rick




[snip]


Re: GamepadObserver (ie. MutationObserver + Gamepad)

2012-05-03 Thread Scott Graham
 say the single event gamepagechanged, where the event object has a
 property describing the complete state of the gamepad

That seems fine to me. One caveat is that XInput on Windows (for
example) is a polling-only API anyway, so it might not be reasonable
to expect better data in the event, depending on how it's synthesized.

i.e. Depending on UA, platform, etc., content might get better results
from polling than events, or vice versa.

 Again, apologies for any perceived negative tone from earlier messages :)

shrug Email sucks. :-) Hope my response wasn't too brusque either.

scott



Re: GamepadObserver (ie. MutationObserver + Gamepad)

2012-05-03 Thread Glenn Maynard
Here are some piecemeal thoughts on the subject of gamepads and the
gamepad spec.  I havn't closely followed earlier discussions (and there
don't seem to have been any in a while), so much of this may have been
covered before.

- It should be possible to tell what's changed, not just the current state
of the device.  Needing to compare each piece of input to the previous
state is cumbersome.

- Native deadzone handling (by the OS or internally to the device) is the
only way to correctly handle deadzones when you don't have intimate
knowledge of the hardware.  It should be explicitly (if non-normatively)
noted that native deadzone handling should be used when available.

- It's very important that it's possible to receive gamepad data without
polling.  We don't need more web pages running setTimeout(0) loops as fast
as browsers will let them, which is what it encourages.  Not all pages are
based on a requestAnimationFrame loop.

- An API that can only return the current state loses button presses if
they're released too quickly.  It's common to press a button while the UI
thread is held up for one reason or another--and you also can't assume that
users can't press and release a button in under 16ms (they can).

- APIs like that also lose the *order* of button presses, when they're
pressed too quickly.  (I've encountered this problem in my own experience;
it's definitely possible--it's not even particularly hard--for a user to
press two buttons in a specific order in under 16ms.)

I'd suggest a halfway point between polling and events: a function to
retrieve a list of device changes since the last call, and an event fired
on the object the first time a new change is made.  For example,

var gamepad = window.openGamepad(0);
gamepad.addEventListener(input, function(e) {
var changes = gamepad.readChanges();
}, false);

with changes being an array of objects, each object describing a
timestamped change of state, eg:

changes = [
{
button: 0,
state: 1.0,
lastState: 0.85,
timestamp: 1336102719319
}
]

This allows using polling if your application is based on
requestAnimationFrame, or events if you want to be told when there's
something to read.  There isn't an excess of events dispatched, because the
event is only dispatched once per call to readChanges; if you only read
changes once in a while you'll only receive the one event.  It also solves
all of the above problems with a most-recent-state-only interface.

The timestamp should be as accurate as possible to when the event actually
happened, in the clock used by Date.now(), so you can tell how long ago the
event happened.  Accurate timestamps are important for games that require
fine-grained timing; 2D fighters and rhythm games can make use of this, for
example (they may render at 60 FPS but perform game logic at a much higher
rate).

Finally, some considerations other than the basic API:

Any serious gamepad API must not ignore the realities of the most common
joystick layouts, most importantly the 360 controller (far and away the
most common PC gamepad today).  The API needs to give recommended mappings
from buttons and axes to the parts of those real-world controllers, so
users don't have to configure devices manually.  This is absolutely
critical; every native PC game that supports gamepads now just works for
the 360 controller, requiring no configuration.  (For years joystick APIs
on PCs tried to pretend that joysticks could be boiled down to a bunch of
abstract axes and buttons.  The user experience that results in is abysmal.)

If the gamepad model is known, it should also be explicitly exposed, so
applications can show help texts which match the actual buttons on the
gamepad (with a registry somewhere--which could just be a wiki
page--describing the string to product mappings).  Every native PC game
also now does this, finally catching up to what console games have done for
decades.  If a web API for gamepads doesn't do this, it'll be years behind
everything else.

Additionally, a more involved system of input profiles would be needed for
practical forward-compatibility, eg. so applications can say this is a
list of device types I understand and UAs can expose the device as the
nearest match.  This allows old applications to work better with devices
they don't know about, without requiring the user to manually bind buttons
and axes.  I can't stress how important it is to not require the user to
configure every game manually; it's simply no longer acceptable.

-- 
Glenn Maynard


Re: GamepadObserver (ie. MutationObserver + Gamepad)

2012-05-02 Thread Olli Pettay

On 05/03/2012 12:48 AM, Rick Waldron wrote:

Instead of traditional DOM events being used for Other Events[1], and
considering the high frequency of Gamepad state changes, it might make
sense to provide an API similar to MutationObserver, where a
MutationRecord is created that has snapshots of current and previous
states of axes or buttons...


This is entirely hypothetical:

(new GamepadObserver(function(mutations) {

   console.log( mutations );
   /*
   {
 previousState: {
   readonly attribute string   id;
   readonly attribute long index;
   readonly attribute DOMTimeStamp timestamp;

// Either or both of the following, bases on the options list

   readonly attribute float[]  axes;
   readonly attribute float[]  buttons;
 }

 currentState: {
   readonly attribute string   id;
   readonly attribute long index;
   readonly attribute DOMTimeStamp timestamp;

// Either or both of the following, bases on the options list

   readonly attribute float[]  axes;
   readonly attribute float[]  buttons;
 }
   }
   */
})).observe(navigator.gamepads[0], { axesList: true });

//  axesList, buttonsList

[1] http://dvcs.w3.org/hg/gamepad/raw-file/tip/gamepad.html#other-events


Rick



no need for this kind of thing. Gamepad data is external, so dispatching 
events is better. The event can of course keep

a list of changes since the previous event dispatch.


-Olli




Re: GamepadObserver (ie. MutationObserver + Gamepad)

2012-05-02 Thread Rick Waldron
On Wed, May 2, 2012 at 5:54 PM, Olli Pettay olli.pet...@helsinki.fi wrote:

 On 05/03/2012 12:48 AM, Rick Waldron wrote:

 Instead of traditional DOM events being used for Other Events[1], and
 considering the high frequency of Gamepad state changes, it might make
 sense to provide an API similar to MutationObserver, where a
 MutationRecord is created that has snapshots of current and previous
 states of axes or buttons...


 This is entirely hypothetical:

 (new GamepadObserver(function(**mutations) {

   console.log( mutations );
   /*
   {
 previousState: {
   readonly attribute string   id;
   readonly attribute long index;
   readonly attribute DOMTimeStamp timestamp;

 // Either or both of the following, bases on the options list

   readonly attribute float[]  axes;
   readonly attribute float[]  buttons;
 }

 currentState: {
   readonly attribute string   id;
   readonly attribute long index;
   readonly attribute DOMTimeStamp timestamp;

 // Either or both of the following, bases on the options list

   readonly attribute float[]  axes;
   readonly attribute float[]  buttons;
 }
   }
   */
 })).observe(navigator.**gamepads[0], { axesList: true });

 //  axesList, buttonsList

 [1] http://dvcs.w3.org/hg/gamepad/**raw-file/tip/gamepad.html#**
 other-eventshttp://dvcs.w3.org/hg/gamepad/raw-file/tip/gamepad.html#other-events


 Rick



 no need for this kind of thing. Gamepad data is external, so dispatching
 events is better. The event can of course keep
 a list of changes since the previous event dispatch.


I had originally argued for an event, though met with resistance. The
reasoning was that gamepad state changes are far too high resolution which
would result in high event dispatch volume.

Is there documented discussion surrounding the return to an event being
desirable?

Thanks for your time.


Rick






 -Olli




Re: GamepadObserver (ie. MutationObserver + Gamepad)

2012-05-02 Thread Scott Graham
On Wed, May 2, 2012 at 3:12 PM, Rick Waldron waldron.r...@gmail.com wrote:
 On Wed, May 2, 2012 at 5:54 PM, Olli Pettay olli.pet...@helsinki.fi wrote:

 On 05/03/2012 12:48 AM, Rick Waldron wrote:

 Instead of traditional DOM events being used for Other Events[1], and
 considering the high frequency of Gamepad state changes, it might make
 sense to provide an API similar to MutationObserver, where a
 MutationRecord is created that has snapshots of current and previous
 states of axes or buttons...


 This is entirely hypothetical:

 (new GamepadObserver(function(mutations) {

   console.log( mutations );
   /*
   {
     previousState: {
       readonly attribute string       id;
       readonly attribute long         index;
       readonly attribute DOMTimeStamp timestamp;

 // Either or both of the following, bases on the options list

       readonly attribute float[]      axes;
       readonly attribute float[]      buttons;
     }

     currentState: {
       readonly attribute string       id;
       readonly attribute long         index;
       readonly attribute DOMTimeStamp timestamp;

 // Either or both of the following, bases on the options list

       readonly attribute float[]      axes;
       readonly attribute float[]      buttons;
     }
   }
   */
 })).observe(navigator.gamepads[0], { axesList: true });

 //  axesList, buttonsList

 [1] http://dvcs.w3.org/hg/gamepad/raw-file/tip/gamepad.html#other-events


 Rick



 no need for this kind of thing. Gamepad data is external, so dispatching
 events is better. The event can of course keep
 a list of changes since the previous event dispatch.


 I had originally argued for an event, though met with resistance. The
 reasoning was that gamepad state changes are far too high resolution which
 would result in high event dispatch volume.

 Is there documented discussion surrounding the return to an event being
 desirable?

I'm not aware of any pro/against discussion on that other than the
Mozilla bug: https://bugzilla.mozilla.org/show_bug.cgi?id=604039. I
don't think there's consensus on that point yet.

The observer ability of filtering to desired-only seems interesting. I
guess it might get complex if it was to be filtered more finely than
just axesList/buttonsList.




 Thanks for your time.


 Rick






 -Olli





Re: GamepadObserver (ie. MutationObserver + Gamepad)

2012-05-02 Thread Rick Waldron
On Wed, May 2, 2012 at 7:01 PM, Scott Graham scot...@chromium.org wrote:

 On Wed, May 2, 2012 at 3:12 PM, Rick Waldron waldron.r...@gmail.com
 wrote:
  On Wed, May 2, 2012 at 5:54 PM, Olli Pettay olli.pet...@helsinki.fi
 wrote:
 
  On 05/03/2012 12:48 AM, Rick Waldron wrote:
 
  Instead of traditional DOM events being used for Other Events[1], and
  considering the high frequency of Gamepad state changes, it might make
  sense to provide an API similar to MutationObserver, where a
  MutationRecord is created that has snapshots of current and previous
  states of axes or buttons...
 
 
  This is entirely hypothetical:
 
  (new GamepadObserver(function(mutations) {
 
console.log( mutations );
/*
{
  previousState: {
readonly attribute string   id;
readonly attribute long index;
readonly attribute DOMTimeStamp timestamp;
 
  // Either or both of the following, bases on the options list
 
readonly attribute float[]  axes;
readonly attribute float[]  buttons;
  }
 
  currentState: {
readonly attribute string   id;
readonly attribute long index;
readonly attribute DOMTimeStamp timestamp;
 
  // Either or both of the following, bases on the options list
 
readonly attribute float[]  axes;
readonly attribute float[]  buttons;
  }
}
*/
  })).observe(navigator.gamepads[0], { axesList: true });
 
  //  axesList, buttonsList
 
  [1]
 http://dvcs.w3.org/hg/gamepad/raw-file/tip/gamepad.html#other-events
 
 
  Rick
 
 
 
  no need for this kind of thing. Gamepad data is external, so dispatching
  events is better. The event can of course keep
  a list of changes since the previous event dispatch.
 
 
  I had originally argued for an event, though met with resistance. The
  reasoning was that gamepad state changes are far too high resolution
 which
  would result in high event dispatch volume.
 
  Is there documented discussion surrounding the return to an event being
  desirable?

 I'm not aware of any pro/against discussion on that other than the
 Mozilla bug: https://bugzilla.mozilla.org/show_bug.cgi?id=604039. I
 don't think there's consensus on that point yet.


Weird, because you posted this:
https://docs.google.com/document/d/1atsxnstVybfovkX_f6xf2P25i1NT0ilCihJuPDwYWEU/edit?hl=en_US

here: https://bugzilla.mozilla.org/show_bug.cgi?id=604039#c40

In which you state:

*The current proposal for accessing Joysticks from Mozilla is an
 event-based one, mirroring keyboard and mouse input.
 https://wiki.mozilla.org/JoystickAPI*
 At 60fps, with all the of the analog buttons, triggers, vibration,
 gyroscope on modern game pad (PS3, Xbox 360, and others) there will easily
 be many events within each 16ms frame.
 With so many events, it’s both inefficient, as many events will only be
 handled in order to update the “current state”, and complex to correctly
 maintain and update the state, which will have to be written in every
 application.
 On the positive side, events and polling are not mutually exclusive. While
 it seems like the primary use-case for gamepad input is for games, which
 would prefer polling, there may be some uses where the event-based is
 better, say for using the gamepad as an input device to advance frames in a
 presentation.



Rick



 The observer ability of filtering to desired-only seems interesting. I
 guess it might get complex if it was to be filtered more finely than
 just axesList/buttonsList.



 
  Thanks for your time.
 
 
  Rick
 
 
 
 
 
 
  -Olli
 
 



Re: GamepadObserver (ie. MutationObserver + Gamepad)

2012-05-02 Thread Scott Graham
On Wed, May 2, 2012 at 6:09 PM, Rick Waldron waldron.r...@gmail.com wrote:


 On Wed, May 2, 2012 at 7:01 PM, Scott Graham scot...@chromium.org wrote:

 On Wed, May 2, 2012 at 3:12 PM, Rick Waldron waldron.r...@gmail.com
 wrote:
  On Wed, May 2, 2012 at 5:54 PM, Olli Pettay olli.pet...@helsinki.fi
  wrote:
 
  On 05/03/2012 12:48 AM, Rick Waldron wrote:
 
  Instead of traditional DOM events being used for Other Events[1], and
  considering the high frequency of Gamepad state changes, it might make
  sense to provide an API similar to MutationObserver, where a
  MutationRecord is created that has snapshots of current and previous
  states of axes or buttons...
 
 
  This is entirely hypothetical:
 
  (new GamepadObserver(function(mutations) {
 
    console.log( mutations );
    /*
    {
      previousState: {
        readonly attribute string       id;
        readonly attribute long         index;
        readonly attribute DOMTimeStamp timestamp;
 
  // Either or both of the following, bases on the options list
 
        readonly attribute float[]      axes;
        readonly attribute float[]      buttons;
      }
 
      currentState: {
        readonly attribute string       id;
        readonly attribute long         index;
        readonly attribute DOMTimeStamp timestamp;
 
  // Either or both of the following, bases on the options list
 
        readonly attribute float[]      axes;
        readonly attribute float[]      buttons;
      }
    }
    */
  })).observe(navigator.gamepads[0], { axesList: true });
 
  //  axesList, buttonsList
 
  [1]
  http://dvcs.w3.org/hg/gamepad/raw-file/tip/gamepad.html#other-events
 
 
  Rick
 
 
 
  no need for this kind of thing. Gamepad data is external, so
  dispatching
  events is better. The event can of course keep
  a list of changes since the previous event dispatch.
 
 
  I had originally argued for an event, though met with resistance. The
  reasoning was that gamepad state changes are far too high resolution
  which
  would result in high event dispatch volume.
 
  Is there documented discussion surrounding the return to an event being
  desirable?

 I'm not aware of any pro/against discussion on that other than the
 Mozilla bug: https://bugzilla.mozilla.org/show_bug.cgi?id=604039. I
 don't think there's consensus on that point yet.


 Weird, because you posted
 this: https://docs.google.com/document/d/1atsxnstVybfovkX_f6xf2P25i1NT0ilCihJuPDwYWEU/edit?hl=en_US

 here: https://bugzilla.mozilla.org/show_bug.cgi?id=604039#c40

I'm not sure what you mean. It is my opinion is that it would be
inefficient to spam 50+ button and axis events multiplied by (say) 4
devices @ 60Hz, which is why I've been pursuing the design of a
polling API. So, though what you quoted was written a while back, it
seems to still represent my opinion pretty accurately.

I'm not sure if everyone agrees with me on that though, which is why I
said I didn't think there was a consensus. I believe Mozilla's
vendor-prefixed implementation includes some of those type of events,
so perhaps we will soon have more empirical data on the subject.


 In which you state:

 The current proposal for accessing Joysticks from Mozilla is an
 event-based one, mirroring keyboard and mouse input.
 https://wiki.mozilla.org/JoystickAPI
 At 60fps, with all the of the analog buttons, triggers, vibration,
 gyroscope on modern game pad (PS3, Xbox 360, and others) there will easily
 be many events within each 16ms frame.
 With so many events, it’s both inefficient, as many events will only be
 handled in order to update the “current state”, and complex to correctly
 maintain and update the state, which will have to be written in every
 application.
 On the positive side, events and polling are not mutually exclusive. While
 it seems like the primary use-case for gamepad input is for games, which
 would prefer polling, there may be some uses where the event-based is
 better, say for using the gamepad as an input device to advance frames in a
 presentation.



 Rick



 The observer ability of filtering to desired-only seems interesting. I
 guess it might get complex if it was to be filtered more finely than
 just axesList/buttonsList.



 
  Thanks for your time.
 
 
  Rick
 
 
 
 
 
 
  -Olli