- From: Kearwood Gilbert <notifications@github.com>
- Date: Wed, 14 Sep 2016 18:07:02 -0700
- To: w3c/gamepad <gamepad@noreply.github.com>
- Message-ID: <w3c/gamepad/pull/32/c247204121@github.com>
I have given this a bit of thought and iterated on some WebIDL for an interface that makes the easy "pulse" effects simple while enabling high frequency buffered haptic effects. Here is a rough draft of proposed WebIDL: ``` // Each value is normalized to a range between 0.0 and 1.0 // The actuator type determines the force applied for a given // "value" in GamepadHapticActuatorBuffer or GamepadHapticActuator enum GamepadHapticActuatorType { // Vibration is a rumbling effect often implemented as an offset weight // driven on a rotational axis. // The "value" of a vibration force determines the frequency of the rumble // effect and is normalized between 0.0 and 1.0 "vibration", // Linear actuators shift a weight to an absolute position, changing the // center of gravity of the controller and resulting in an opposing force // that can be felt by the holder. // The "value" of a linear force is the absolute position of the actuator // relative to its center position and is normalized between -1.0 and 1.0 "linear", // XXX - Angular force (steering wheels), springs, dampeners, and other // actuators should be defined as separate GamepadHapticActuatorType's // here instead of being mapped to "vibration" or "linear". }; // Each GamepadHapticActuator corresponds to a motor or other actuator that can // apply a force for the purposes of haptic feedback. In some cases, the // physical arrangement of devices may be represented as a simpler model to this // api. For example, a device with multiple degrees of freedom may process // the actuator values passed into the api with inverse kinematics to determine // the position required for the physical actuators. dictionary GamepadHapticActuator { // type determines the range and effect of the "value" // passed to pulse() and within the GamepadHapticActuatorBuffer. readonly attribute GamepadHapticActuatorType type; // Pulse applies a value to the actuator for duration milliseconds. // If any GamepadHapticEffect is playing, the value passed to pulse() // is applied additively, clamped to limits defined by the actuator type. // The returned promise will resolve true once the pulse has completed. Promise<void> pulse(float value, float duration); }; // GamepadHapticBuffer represents a timeline of values to drive a // GamepadActuator. dictionary GamepadHapticBuffer { // actuator identifies the actuator that will be driven by the // effect. If multiple GamepadHapticBuffer are driving the same // actuator, the values are combined additively and clamped within the // range defined by the actuator type. GamepadHapticActuator actuator; // It is recommended to normalize these values, as they can // be attenuated by setting GamepadHapticEffect.gain sequence<float> values = [ ]; // Durations are expressed in milliseconds sequence<float> durations = [ ]; // The number of iterations to repeat the set of values. // If iterations is 0, then repeat infinitely. attribute unsigned long iterations; }; // GamepadHapticEffect describes any haptic effect that is more complex than // a simple pulse. interface GamepadHapticEffect { // buffers defines which actuators are being driven and with which pattern of // values. // A GamepadHapticEffect can affect a single or multiple Gamepads. // GamepadHapticEffect is associated to a Gamepad through // GamepadHapticBuffer.actuator // If multiple effects or pulses are playing simultaneously, the values of each // actuator are combined additively. attribute bool sequence<GamepadHapticBuffer> buffers; // When GamepadHapticEffect is playing, IsPlaying is true. // The GamepadHapticEffect does not begin playing until play() is called. readonly attribute bool IsPlaying; // play() starts playing the GamepadHapticEffect. // The returned promise will resolve true once the effect is completed or // stop() is called. // If any of the buffers have iterations set to 0 (infinite), the promise // will not resolve true until stop() is called. // Changes to the buffers are not reflected in a playing haptic effect and // will only be applied once the effect is played again. // If the haptic effect is already playing, play() will not interrupt // the haptic effect and will resolve fail the returned promise. // If you wish to play multiple of the same effect additively, multiple // GamepadHapticEffect's should be created, but can share GamepadHapticBuffer's. [Throws] Promise<void> play(); // stop() ends playback of the effect and returns the values of the actuators // to the neutral value as defined by the actuator type. // It is not necessary to call stop() if all of the buffers have non-zero // iterations. void stop(); // XXX Do we wish to have a pause() function? // gain is a 0.0 - 1.0 attenuation of HapticBuffer values. // Unlike changes to buffers, changes to gain are effective immediately on // a playing haptic effect. // Simple dynamic collision effects can be modelled with a set of short, // infinitely repeating HapticBuffer's and an ADSR envelope applied with the // gain attribute. attribute float gain; }; partial interface Gamepad { // hapticActuators enumerates haptic feedback actuators such as rumble motors. readonly attribute GamepadHapticActuator[] hapticActuators; // playingHapticEffects includes any GamepadHapticEffect that are playing // and driving any actuator in this Gamepad. readonly attribute GamepadHapticEffect[] playingHapticEffects; }; ``` -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/w3c/gamepad/pull/32#issuecomment-247204121
Received on Thursday, 15 September 2016 01:07:34 UTC