mirror of
https://codeberg.org/uzu/strudel
synced 2026-07-22 13:13:10 -04:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a0c35e943f | |||
| 8b26f784d7 | |||
| 04df4a31af | |||
| 077ef0f083 | |||
| 5c4b6cda71 | |||
| 4553408b28 | |||
| 42eb33440c | |||
| 87768198a0 | |||
| c24a87df48 | |||
| 2d63f36201 | |||
| 43ac2d3d72 |
@@ -14,7 +14,12 @@ npm i @strudel/gamepad --save
|
||||
import { gamepad } from '@strudel/gamepad';
|
||||
|
||||
// Initialize gamepad (optional index parameter, defaults to 0)
|
||||
const pad = gamepad(0);
|
||||
const pad = gamepad(0); // Default mapping is XBOX {a: 0, b: 1, x: 2, y: 3}
|
||||
|
||||
//const pad = gamepad(0, 'XBOX'); // XBOX button mapping {a: 0, b: 1, x: 2, y: 3}
|
||||
//const pad = gamepad(0, 'NES'); // Nintendo button mapping {a: 1, b: 0, x: 3, y: 2}
|
||||
//const pad = gamepad(0, {a: 0, b: 1, x: 2, y: 3}); // Custom mapping
|
||||
|
||||
|
||||
// Use gamepad inputs in patterns
|
||||
const pattern = sequence([
|
||||
@@ -86,8 +91,35 @@ $: sound("hadoken").gain(pad.checkSequence(HADOKEN))
|
||||
## Multiple Gamepads
|
||||
|
||||
You can connect multiple gamepads by specifying the gamepad index:
|
||||
Make sure to press buttons on all connected gamepads before hitting play, so the browser can properly detect them.
|
||||
|
||||
```javascript
|
||||
const pad1 = gamepad(0); // First gamepad
|
||||
const pad2 = gamepad(1); // Second gamepad
|
||||
```
|
||||
|
||||
## Vibration
|
||||
|
||||
You can use the `vibrate` control to provide haptic feedback to the gamepad.
|
||||
The `vibrate` control is a patternable control, so you can use it to control the vibration of the gamepad.
|
||||
|
||||
The vibrate control has several parameters:
|
||||
|
||||
- `vibGamepadIndex` - Index of the gamepad to vibrate (0-3)
|
||||
- `vibStrong` - Intensity of the strong/left motor (0-1)
|
||||
- `vibWeak` - Intensity of the weak/right motor (0-1)
|
||||
- `vibDuration` - Duration of vibration in milliseconds
|
||||
- `vibEnable` - Enable/disable vibration (0 or 1)
|
||||
|
||||
```javascript
|
||||
// Vibration with gamepad
|
||||
// vibrate(gamepadId, { strong: 1, weak: 0.5, duration: 100 })
|
||||
// vibrate("gamepadId")
|
||||
// vibrate(gamepadId)
|
||||
|
||||
$: note("c4*4").vibrate(0, { strong: 1, weak: 0.5, duration: 100 }) // gamepad index 0
|
||||
$: note("c4*4").vibrate("0:1:0.5:200") // Array format
|
||||
$: note("c4*4").vibrate("<0 1 0 1>") // select gamepad index
|
||||
|
||||
$: note("c4*4").vibStrong("<0.1 0.2 0.5 1>").vibWeak("<0.1 0.2 0.5 1>").vibDuration("<10 20 50 100>").vibrate(0) // gamepad index 0
|
||||
```
|
||||
|
||||
@@ -107,9 +107,32 @@ $: s("free_hadouken -").slow(2)
|
||||
samples({free_hadouken: 'https://cdn.freesound.org/previews/67/67674_111920-lq.mp3'})
|
||||
`} />
|
||||
|
||||
## Multiple Gamepads
|
||||
### Button Sequences
|
||||
|
||||
### Button Mappings
|
||||
|
||||
The gamepad module supports different button mapping configurations to accommodate various gamepad layouts:
|
||||
|
||||
- **XBOX** (Default): Standard Xbox-style mapping where A=0, B=1, X=2, Y=3
|
||||
- **NES**: Nintendo-style mapping where B=0, A=1, Y=2, X=3
|
||||
- **Custom**: Define your own button mapping by passing an object with button assignments
|
||||
|
||||
You can specify the mapping when initializing the gamepad:
|
||||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`
|
||||
const pad1 = gamepad(0); // Default mapping is XBOX {a: 0, b: 1, x: 2, y: 3}
|
||||
const pad2 = gamepad(1, 'XBOX'); // XBOX button mapping {a: 0, b: 1, x: 2, y: 3}
|
||||
const pad3 = gamepad(2, 'NES'); // Nintendo button mapping {a: 1, b: 0, x: 3, y: 2}
|
||||
const pad4 = gamepad(3, {a: 0, b: 1, x: 2, y: 3}); // Custom mapping
|
||||
`}
|
||||
/>
|
||||
|
||||
### Multiple Gamepads
|
||||
|
||||
Strudel supports multiple gamepads. You can specify the gamepad index to connect to different devices.
|
||||
Make sure to press buttons on all connected gamepads before hitting play, so the browser can properly detect them.
|
||||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
|
||||
+147
-32
@@ -1,35 +1,77 @@
|
||||
// @strudel/gamepad/index.mjs
|
||||
|
||||
import { signal } from '@strudel/core';
|
||||
import { signal, Pattern, logger, registerControl, register, isPattern } from '@strudel/core';
|
||||
import { vibrationSupported, getGamepadVibrationActuator } from './vibration.mjs';
|
||||
|
||||
// Button mapping for Logitech Dual Action (STANDARD GAMEPAD Vendor: 046d Product: c216)
|
||||
export const buttonMap = {
|
||||
a: 0,
|
||||
b: 1,
|
||||
x: 2,
|
||||
y: 3,
|
||||
lb: 4,
|
||||
rb: 5,
|
||||
lt: 6,
|
||||
rt: 7,
|
||||
back: 8,
|
||||
start: 9,
|
||||
u: 12,
|
||||
up: 12,
|
||||
d: 13,
|
||||
down: 13,
|
||||
l: 14,
|
||||
left: 14,
|
||||
r: 15,
|
||||
right: 15,
|
||||
|
||||
export const buttonMapSettings = {
|
||||
XBOX: {
|
||||
// XBOX mapping default
|
||||
a: 0,
|
||||
b: 1,
|
||||
x: 2,
|
||||
y: 3,
|
||||
lb: 4,
|
||||
rb: 5,
|
||||
lt: 6,
|
||||
rt: 7,
|
||||
back: 8,
|
||||
start: 9,
|
||||
lstick: 10,
|
||||
rstick: 11,
|
||||
ls: 10,
|
||||
rs: 11,
|
||||
u: 12,
|
||||
up: 12,
|
||||
d: 13,
|
||||
down: 13,
|
||||
l: 14,
|
||||
left: 14,
|
||||
r: 15,
|
||||
right: 15,
|
||||
xbox: 16,
|
||||
},
|
||||
NES: {
|
||||
// Nintendo mapping
|
||||
a: 1,
|
||||
b: 0,
|
||||
x: 3,
|
||||
y: 2,
|
||||
lb: 4,
|
||||
rb: 5,
|
||||
zl: 6,
|
||||
zr: 7,
|
||||
lt: 6,
|
||||
rt: 7,
|
||||
back: 8,
|
||||
minus: 8,
|
||||
start: 9,
|
||||
plus: 9,
|
||||
lstick: 10,
|
||||
rstick: 11,
|
||||
ls: 10,
|
||||
rs: 11,
|
||||
u: 12,
|
||||
up: 12,
|
||||
d: 13,
|
||||
down: 13,
|
||||
l: 14,
|
||||
left: 14,
|
||||
r: 15,
|
||||
right: 15,
|
||||
home: 16,
|
||||
select: 17,
|
||||
},
|
||||
};
|
||||
|
||||
class ButtonSequenceDetector {
|
||||
constructor(timeWindow = 1000) {
|
||||
constructor(timeWindow = 1000, mapping) {
|
||||
this.sequence = [];
|
||||
this.timeWindow = timeWindow;
|
||||
this.lastInputTime = 0;
|
||||
this.buttonStates = Array(16).fill(0); // Track previous state of each button
|
||||
this.buttonStates = Array(Object.keys(mapping).length).fill(0); // Track previous state of each button
|
||||
this.buttonMap = mapping;
|
||||
// Button mapping for character inputs
|
||||
}
|
||||
|
||||
@@ -44,7 +86,8 @@ class ButtonSequenceDetector {
|
||||
}
|
||||
|
||||
// Store the button name instead of index
|
||||
const buttonName = Object.keys(buttonMap).find((key) => buttonMap[key] === buttonIndex) || buttonIndex.toString();
|
||||
const buttonName =
|
||||
Object.keys(this.buttonMap).find((key) => this.buttonMap[key] === buttonIndex) || buttonIndex.toString();
|
||||
|
||||
this.sequence.push({
|
||||
input: buttonName,
|
||||
@@ -87,9 +130,9 @@ class ButtonSequenceDetector {
|
||||
// Check if either the input matches directly or they refer to the same button in the map
|
||||
return (
|
||||
input === target ||
|
||||
buttonMap[input] === buttonMap[target] ||
|
||||
this.buttonMap[input] === this.buttonMap[target] ||
|
||||
// Also check if the numerical index matches
|
||||
buttonMap[input] === parseInt(target)
|
||||
this.buttonMap[input] === parseInt(target)
|
||||
);
|
||||
})
|
||||
? 1
|
||||
@@ -98,12 +141,13 @@ class ButtonSequenceDetector {
|
||||
}
|
||||
|
||||
class GamepadHandler {
|
||||
constructor(index = 0) {
|
||||
constructor(index = 0, mapping) {
|
||||
// Add index parameter
|
||||
this._gamepads = {};
|
||||
this._mapping = mapping;
|
||||
this._activeGamepad = index; // Use provided index
|
||||
this._axes = [0, 0, 0, 0];
|
||||
this._buttons = Array(16).fill(0);
|
||||
this._buttons = Array(Object.keys(mapping).length).fill(0);
|
||||
this.setupEventListeners();
|
||||
}
|
||||
|
||||
@@ -143,12 +187,66 @@ class GamepadHandler {
|
||||
}
|
||||
}
|
||||
|
||||
// Add utility function to list all connected gamepads
|
||||
export const listGamepads = () => {
|
||||
const gamepads = navigator.getGamepads();
|
||||
const connectedGamepads = Array.from(gamepads)
|
||||
.filter((gp) => gp !== null)
|
||||
.map((gp) => ({
|
||||
index: gp.index,
|
||||
id: gp.id,
|
||||
mapping: gp.mapping,
|
||||
buttons: gp.buttons.length,
|
||||
axes: gp.axes.length,
|
||||
connected: gp.connected,
|
||||
timestamp: gp.timestamp,
|
||||
}));
|
||||
// Format the gamepads info into a readable string
|
||||
const gamepadsInfo = connectedGamepads.map((gp) => `${gp.index}: ${gp.id}`).join('\n');
|
||||
|
||||
logger(`[gamepad] available gamepads:\n${gamepadsInfo}`);
|
||||
return connectedGamepads;
|
||||
};
|
||||
|
||||
// Module-level state store for toggle states
|
||||
const gamepadStates = new Map();
|
||||
|
||||
export const gamepad = (index = 0) => {
|
||||
const handler = new GamepadHandler(index);
|
||||
const sequenceDetector = new ButtonSequenceDetector(2000);
|
||||
export const gamepad = (index = 0, mapping = 'XBOX') => {
|
||||
// list connected gamepads
|
||||
const connectedGamepads = listGamepads();
|
||||
|
||||
// Check if the requested gamepad index exists
|
||||
const requestedGamepad = connectedGamepads.find((gp) => gp.index === index);
|
||||
if (!requestedGamepad) {
|
||||
throw new Error(
|
||||
`[gamepad] gamepad at index ${index} not found. available gamepads: ${connectedGamepads.map((gp) => gp.index).join(', ')}`,
|
||||
);
|
||||
}
|
||||
|
||||
// Handle button mapping
|
||||
let buttonMap = buttonMapSettings.XBOX;
|
||||
|
||||
if (typeof mapping === 'string') {
|
||||
buttonMap = buttonMapSettings[mapping.toUpperCase()];
|
||||
} else if (typeof mapping === 'object') {
|
||||
buttonMap = { ...buttonMapSettings.XBOX, ...mapping };
|
||||
// Check that all mapping values are valid button indices
|
||||
const maxButtons = requestedGamepad.buttons;
|
||||
for (const [key, value] of Object.entries(mapping)) {
|
||||
if (typeof value !== 'number' || value < 0 || value >= maxButtons) {
|
||||
throw new Error(
|
||||
`[gamepad] invalid button mapping for '${key}': ${value}. Must be a number between 0 and ${maxButtons - 1}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!buttonMap) {
|
||||
throw new Error(`[gamepad] button mapping '${mapping}' not found`);
|
||||
}
|
||||
|
||||
const handler = new GamepadHandler(index, buttonMap);
|
||||
const sequenceDetector = new ButtonSequenceDetector(2000, buttonMap);
|
||||
|
||||
// Base signal that polls gamepad state and handles sequence detection
|
||||
const baseSignal = signal((t) => {
|
||||
@@ -179,7 +277,7 @@ export const gamepad = (index = 0) => {
|
||||
axes.y2_2 = axes.y2.toBipolar();
|
||||
|
||||
// Create button patterns
|
||||
const buttons = Array(16)
|
||||
const buttons = Array(Object.keys(buttonMap).length)
|
||||
.fill(null)
|
||||
.map((_, i) => {
|
||||
// Create unique key for this gamepad+button combination
|
||||
@@ -218,8 +316,22 @@ export const gamepad = (index = 0) => {
|
||||
return baseSignal.fmap(() => sequenceDetector.checkSequence(sequence));
|
||||
};
|
||||
const checkSequence = btnSequence;
|
||||
const sequence = btnSequence;
|
||||
const btnSeq = btnSequence;
|
||||
const btnseq = btnSeq;
|
||||
const btnseq = btnSequence;
|
||||
const seq = btnSequence;
|
||||
|
||||
// Create vibration pattern
|
||||
const vibration = (pattern) => {
|
||||
return signal(() => {
|
||||
// Return vibration enable/disable pattern
|
||||
return pattern;
|
||||
});
|
||||
};
|
||||
|
||||
logger(
|
||||
`[gamepad] connected to gamepad ${index} (${requestedGamepad.id}) with ${typeof mapping === 'object' ? 'custom' : mapping} mapping${vibrationSupported(index) ? ' (vibration supported)' : ''}`,
|
||||
);
|
||||
|
||||
// Return an object with all controls
|
||||
return {
|
||||
@@ -234,9 +346,12 @@ export const gamepad = (index = 0) => {
|
||||
]),
|
||||
),
|
||||
checkSequence,
|
||||
sequence,
|
||||
btnSequence,
|
||||
btnSeq,
|
||||
btnseq,
|
||||
seq,
|
||||
vibration,
|
||||
raw: baseSignal,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,288 @@
|
||||
// Gamepad Vibration Controls
|
||||
|
||||
import { registerControl, register, logger, isPattern } from '@strudel/core';
|
||||
import { Pattern } from '@strudel/core';
|
||||
|
||||
/**
|
||||
* Controls the strong motor intensity for gamepad vibration.
|
||||
*
|
||||
* @name vibStrong
|
||||
* @param {number | Pattern} intensity between 0 and 1
|
||||
* @synonyms vibS
|
||||
* @example
|
||||
* s("bd hh sd hh").vibStrong("1 0 0.5 0").vibrate(0)
|
||||
*/
|
||||
export const { vibStrong, vibS } = registerControl('vibStrong', 'vibS');
|
||||
|
||||
/**
|
||||
* Controls the weak motor intensity for gamepad vibration.
|
||||
*
|
||||
* @name vibWeak
|
||||
* @param {number | Pattern} intensity between 0 and 1
|
||||
* @synonyms vibW
|
||||
* @example
|
||||
* s("bd hh sd hh").vibWeak("0.5 0 0.8 0").vibrate(0)
|
||||
*/
|
||||
export const { vibWeak, vibW } = registerControl('vibWeak', 'vibW');
|
||||
|
||||
/**
|
||||
* Controls the duration of gamepad vibration in milliseconds.
|
||||
*
|
||||
* @name vibDuration
|
||||
* @param {number | Pattern} duration in milliseconds
|
||||
* @synonyms vibDur
|
||||
* @example
|
||||
* s("bd hh sd hh").vibDuration("200 0 100 0").vibrate(0)
|
||||
*/
|
||||
export const { vibDuration, vibDur } = registerControl('vibDuration', 'vibDur');
|
||||
|
||||
/**
|
||||
* Enables or disables gamepad vibration for individual events.
|
||||
*
|
||||
* @name vibEnable
|
||||
* @param {number | Pattern} enable 1 to enable, 0 to disable
|
||||
* @synonyms vibE
|
||||
* @example
|
||||
* s("bd hh sd hh").vibEnable("1 0 1 0").vibrate(0)
|
||||
*/
|
||||
export const { vibEnable, vibEn } = registerControl('vibEnable', 'vibEn');
|
||||
|
||||
/**
|
||||
* Sets the gamepad index for vibration events.
|
||||
*
|
||||
* @name vibGamepadIndex
|
||||
* @param {number | Pattern} index gamepad index (0-3)
|
||||
* @synonyms vibGpId, vibGamepadIndex, vibGamepadId
|
||||
* @example
|
||||
* s("bd hh sd hh").vibGamepadIndex("0 1 0 1").vibrate()
|
||||
*/
|
||||
export const { vibGamepadIndex, vibGpId, vibGamepadId } = registerControl('vibGamepadIndex', 'vibGpId', 'vibGamepadId');
|
||||
|
||||
/**
|
||||
* Sets both strong and weak vibration intensity at once.
|
||||
*
|
||||
* @name vibIntensity
|
||||
* @param {number | Pattern} intensity between 0 and 1, applied to both motors
|
||||
* @example
|
||||
* s("bd*4").vibIntensity(sine.slow(2).range(0, 1)).vibrate(0)
|
||||
*/
|
||||
export const vibIntensity = register('vibIntensity', (intensity, pat) => {
|
||||
return pat.vibStrong(intensity).vibWeak(intensity);
|
||||
});
|
||||
|
||||
export const vibrationSupported = (index) => {
|
||||
const gamepad = navigator.getGamepads()[index];
|
||||
return gamepad?.vibrationActuator?.type === 'dual-rumble';
|
||||
};
|
||||
|
||||
export const getGamepadVibrationActuator = (index) => {
|
||||
const gamepad = navigator.getGamepads()[index];
|
||||
if (!gamepad) {
|
||||
throw new Error(`[gamepad] gamepad at index ${index} not found`);
|
||||
}
|
||||
if (!gamepad.vibrationActuator) {
|
||||
throw new Error(`[gamepad] gamepad at index ${index} does not support vibration`);
|
||||
}
|
||||
return gamepad.vibrationActuator;
|
||||
};
|
||||
|
||||
// Default vibration latency in milliseconds
|
||||
const DEFAULT_VIBRATION_LATENCY = 10;
|
||||
|
||||
/**
|
||||
* Parses vibration string format "id:strong:weak:duration"
|
||||
* @param {string} vibString - The vibration string to parse
|
||||
* @returns {object} Parsed vibration parameters
|
||||
*/
|
||||
function parseVibrationString(vibString) {
|
||||
if (typeof vibString !== 'string') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const parts = vibString.split(':');
|
||||
if (parts.length < 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const [id, strong, weak, duration] = parts;
|
||||
|
||||
return {
|
||||
vibGamepadIndex: parseInt(id) || 0,
|
||||
vibStrong: parseFloat(strong) || 0.8,
|
||||
vibWeak: parseFloat(weak) || 0.4,
|
||||
vibDuration: parseInt(duration) || 100,
|
||||
vibEnable: 1,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends vibration commands to a gamepad based on pattern events.
|
||||
*
|
||||
* @name vibrate
|
||||
* @memberof Pattern
|
||||
* @param {number | string | Pattern} gamepadIndex - Index of the gamepad to vibrate (0-3), can be patterned, or vibration string
|
||||
* @param {object} options - Default vibration options
|
||||
* @param {number} options.strong - Default strong motor intensity (0-1)
|
||||
* @param {number} options.weak - Default weak motor intensity (0-1)
|
||||
* @param {number} options.duration - Default duration in milliseconds
|
||||
* @param {number} options.latency - Latency compensation in milliseconds
|
||||
* @returns {Pattern}
|
||||
* @example
|
||||
* // Basic vibration on beat
|
||||
* s("bd hh sd hh").vibrate(0)
|
||||
*
|
||||
* @example
|
||||
* // Using hap values for vibration control
|
||||
* s("<bd hh sd hh>").vibStrong("<1 0.1 0.5 0>").vibWeak("<0.5 0 0.8 0>").vibrate(0)
|
||||
*
|
||||
* @example
|
||||
* // With default options
|
||||
* s("bd*4").vibrate(0, { strong: 1, weak: 0.5, duration: 100 })
|
||||
*
|
||||
* @example
|
||||
* // Using gamepad input to control vibration
|
||||
* let gp = gamepad(0);
|
||||
* note("c a f e").gain(gp.a).vibrate(0, { strong: gp.x1, duration: 200 })
|
||||
*
|
||||
* @example
|
||||
* // Patternable gamepad index - alternate between gamepads
|
||||
* s("bd hh sd hh").vibrate("<0 1 0 1>")
|
||||
*
|
||||
* @example
|
||||
* // Complex gamepad switching pattern
|
||||
* s("bd*8").vibrate("0 1 0 [1 0] 1 0 1 0")
|
||||
*
|
||||
* @example
|
||||
* // Using control parameter for gamepad index
|
||||
* s("bd hh sd hh").vibGamepad("<0 1 0 1>").vibrate()
|
||||
*
|
||||
* @example
|
||||
* // Assignable vibration syntax: "id:strong:weak:duration"
|
||||
* s("bd hh sd hh").vibrate("0:1:0.5:200 1:0.8:0.3:150")
|
||||
*
|
||||
* @example
|
||||
* // Complex assignable patterns
|
||||
* s("bd*8").vibrate("0:0.2:0.4:100 0:0.2:1:100 1:1:0.5:200 1:0.5:1:150")
|
||||
*/
|
||||
|
||||
export const { vibrate } = registerControl(['vibGamepad', 'vibStrong', 'vibWeak', 'vibDuration']);
|
||||
|
||||
Pattern.prototype.vibrate = function (gamepadIndex, options = {}) {
|
||||
// Default options
|
||||
const defaultOptions = {
|
||||
strong: 0.8,
|
||||
weak: 0.4,
|
||||
duration: 100,
|
||||
latency: DEFAULT_VIBRATION_LATENCY,
|
||||
...options,
|
||||
};
|
||||
|
||||
// If gamepadIndex is a pattern, handle it based on its content
|
||||
if (isPattern(gamepadIndex)) {
|
||||
return this.set(
|
||||
gamepadIndex.fmap((value) => {
|
||||
// Simple gamepad index pattern
|
||||
return { vibGamepadIndex: value };
|
||||
}),
|
||||
).onTrigger((time_deprecate, hap, currentTime, cps, targetTime) => {
|
||||
return vibrateHandler(hap, currentTime, cps, targetTime, defaultOptions);
|
||||
}, false);
|
||||
}
|
||||
|
||||
// If gamepadIndex is provided as static value, use it directly
|
||||
// If undefined, will be handled in vibrateHandler (using vibGamepad control or default 0)
|
||||
return this.onTrigger((time_deprecate, hap, currentTime, cps, targetTime) => {
|
||||
return vibrateHandler(hap, currentTime, cps, targetTime, defaultOptions, gamepadIndex);
|
||||
}, false);
|
||||
};
|
||||
|
||||
// Helper function to handle the actual vibration logic
|
||||
function vibrateHandler(hap, currentTime, cps, targetTime, defaultOptions, staticGamepadIndex = null) {
|
||||
try {
|
||||
// Determine gamepad index - from hap value or static parameter
|
||||
let gamepadIndex;
|
||||
if (staticGamepadIndex !== null && staticGamepadIndex !== undefined) {
|
||||
gamepadIndex = staticGamepadIndex;
|
||||
} else if (typeof hap.value === 'object' && ('vibGamepadIndex' in hap.value || 'vibGamepad' in hap.value)) {
|
||||
const vibGamepadValue = hap.value.vibGamepadIndex;
|
||||
gamepadIndex = Array.isArray(vibGamepadValue) ? vibGamepadValue[0] : vibGamepadValue;
|
||||
} else {
|
||||
gamepadIndex = 0; // fallback default
|
||||
}
|
||||
|
||||
// Validate gamepad index
|
||||
gamepadIndex = Math.max(0, Math.min(3, Math.floor(Number(gamepadIndex) || 0)));
|
||||
|
||||
// Check if vibration is supported
|
||||
if (!vibrationSupported(gamepadIndex)) {
|
||||
logger(`[gamepad] vibration not supported on gamepad ${gamepadIndex}`, 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
const vibrationActuator = getGamepadVibrationActuator(gamepadIndex);
|
||||
|
||||
// Extract vibration parameters from hap value or use defaults
|
||||
let vibStrong, vibWeak, vibDuration, vibEnable;
|
||||
|
||||
if (typeof hap.value === 'object') {
|
||||
const vibGamepadValue = hap.value.vibGamepadIndex;
|
||||
|
||||
// Handle array format: [index, strong, weak, duration]
|
||||
if (Array.isArray(vibGamepadValue)) {
|
||||
vibStrong = vibGamepadValue[1] !== undefined ? vibGamepadValue[1] : defaultOptions.strong;
|
||||
vibWeak = vibGamepadValue[2] !== undefined ? vibGamepadValue[2] : defaultOptions.weak;
|
||||
vibDuration = vibGamepadValue[3] !== undefined ? vibGamepadValue[3] : defaultOptions.duration;
|
||||
vibEnable = 1;
|
||||
} else {
|
||||
// Regular object destructuring for non-array values
|
||||
({
|
||||
vibStrong = defaultOptions.strong,
|
||||
vibWeak = defaultOptions.weak,
|
||||
vibDuration = defaultOptions.duration,
|
||||
vibEnable = 1,
|
||||
} = hap.value);
|
||||
}
|
||||
} else {
|
||||
// If hap.value is a primitive, use it as vibEnable (0 = off, 1 = on)
|
||||
vibEnable = hap.value;
|
||||
vibStrong = defaultOptions.strong;
|
||||
vibWeak = defaultOptions.weak;
|
||||
vibDuration = defaultOptions.duration;
|
||||
}
|
||||
|
||||
// Skip vibration if disabled
|
||||
if (!vibEnable || vibEnable === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate parameters
|
||||
vibStrong = Math.max(0, Math.min(1, Number(vibStrong) || 0));
|
||||
vibWeak = Math.max(0, Math.min(1, Number(vibWeak) || 0));
|
||||
vibDuration = Math.max(0, Number(vibDuration) || defaultOptions.duration);
|
||||
|
||||
// Calculate timing offset
|
||||
const offset = (targetTime - currentTime + defaultOptions.latency / 1000) * 1000;
|
||||
|
||||
// Schedule vibration
|
||||
window.setTimeout(
|
||||
() => {
|
||||
try {
|
||||
vibrationActuator
|
||||
.playEffect('dual-rumble', {
|
||||
duration: vibDuration,
|
||||
strongMagnitude: vibStrong,
|
||||
weakMagnitude: vibWeak,
|
||||
})
|
||||
.catch((err) => {
|
||||
logger(`[gamepad] vibration failed: ${err.message}`, 'warning');
|
||||
});
|
||||
} catch (err) {
|
||||
logger(`[gamepad] vibration error: ${err.message}`, 'warning');
|
||||
}
|
||||
},
|
||||
Math.max(0, offset),
|
||||
);
|
||||
} catch (err) {
|
||||
logger(`[gamepad] vibration setup failed: ${err.message}`, 'warning');
|
||||
}
|
||||
}
|
||||
@@ -11780,6 +11780,279 @@ exports[`runs examples > example "vib" example index 1 1`] = `
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "vibDuration" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:bd vibDuration:200 ]",
|
||||
"[ 1/4 → 1/2 | s:hh vibDuration:0 ]",
|
||||
"[ 1/2 → 3/4 | s:sd vibDuration:100 ]",
|
||||
"[ 3/4 → 1/1 | s:hh vibDuration:0 ]",
|
||||
"[ 1/1 → 5/4 | s:bd vibDuration:200 ]",
|
||||
"[ 5/4 → 3/2 | s:hh vibDuration:0 ]",
|
||||
"[ 3/2 → 7/4 | s:sd vibDuration:100 ]",
|
||||
"[ 7/4 → 2/1 | s:hh vibDuration:0 ]",
|
||||
"[ 2/1 → 9/4 | s:bd vibDuration:200 ]",
|
||||
"[ 9/4 → 5/2 | s:hh vibDuration:0 ]",
|
||||
"[ 5/2 → 11/4 | s:sd vibDuration:100 ]",
|
||||
"[ 11/4 → 3/1 | s:hh vibDuration:0 ]",
|
||||
"[ 3/1 → 13/4 | s:bd vibDuration:200 ]",
|
||||
"[ 13/4 → 7/2 | s:hh vibDuration:0 ]",
|
||||
"[ 7/2 → 15/4 | s:sd vibDuration:100 ]",
|
||||
"[ 15/4 → 4/1 | s:hh vibDuration:0 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "vibDuration" example index 0 2`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:bd vibDuration:200 ]",
|
||||
"[ 1/4 → 1/2 | s:hh vibDuration:0 ]",
|
||||
"[ 1/2 → 3/4 | s:sd vibDuration:100 ]",
|
||||
"[ 3/4 → 1/1 | s:hh vibDuration:0 ]",
|
||||
"[ 1/1 → 5/4 | s:bd vibDuration:200 ]",
|
||||
"[ 5/4 → 3/2 | s:hh vibDuration:0 ]",
|
||||
"[ 3/2 → 7/4 | s:sd vibDuration:100 ]",
|
||||
"[ 7/4 → 2/1 | s:hh vibDuration:0 ]",
|
||||
"[ 2/1 → 9/4 | s:bd vibDuration:200 ]",
|
||||
"[ 9/4 → 5/2 | s:hh vibDuration:0 ]",
|
||||
"[ 5/2 → 11/4 | s:sd vibDuration:100 ]",
|
||||
"[ 11/4 → 3/1 | s:hh vibDuration:0 ]",
|
||||
"[ 3/1 → 13/4 | s:bd vibDuration:200 ]",
|
||||
"[ 13/4 → 7/2 | s:hh vibDuration:0 ]",
|
||||
"[ 7/2 → 15/4 | s:sd vibDuration:100 ]",
|
||||
"[ 15/4 → 4/1 | s:hh vibDuration:0 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "vibEnable" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:bd vibEnable:1 ]",
|
||||
"[ 1/4 → 1/2 | s:hh vibEnable:0 ]",
|
||||
"[ 1/2 → 3/4 | s:sd vibEnable:1 ]",
|
||||
"[ 3/4 → 1/1 | s:hh vibEnable:0 ]",
|
||||
"[ 1/1 → 5/4 | s:bd vibEnable:1 ]",
|
||||
"[ 5/4 → 3/2 | s:hh vibEnable:0 ]",
|
||||
"[ 3/2 → 7/4 | s:sd vibEnable:1 ]",
|
||||
"[ 7/4 → 2/1 | s:hh vibEnable:0 ]",
|
||||
"[ 2/1 → 9/4 | s:bd vibEnable:1 ]",
|
||||
"[ 9/4 → 5/2 | s:hh vibEnable:0 ]",
|
||||
"[ 5/2 → 11/4 | s:sd vibEnable:1 ]",
|
||||
"[ 11/4 → 3/1 | s:hh vibEnable:0 ]",
|
||||
"[ 3/1 → 13/4 | s:bd vibEnable:1 ]",
|
||||
"[ 13/4 → 7/2 | s:hh vibEnable:0 ]",
|
||||
"[ 7/2 → 15/4 | s:sd vibEnable:1 ]",
|
||||
"[ 15/4 → 4/1 | s:hh vibEnable:0 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "vibEnable" example index 0 2`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:bd vibEnable:1 ]",
|
||||
"[ 1/4 → 1/2 | s:hh vibEnable:0 ]",
|
||||
"[ 1/2 → 3/4 | s:sd vibEnable:1 ]",
|
||||
"[ 3/4 → 1/1 | s:hh vibEnable:0 ]",
|
||||
"[ 1/1 → 5/4 | s:bd vibEnable:1 ]",
|
||||
"[ 5/4 → 3/2 | s:hh vibEnable:0 ]",
|
||||
"[ 3/2 → 7/4 | s:sd vibEnable:1 ]",
|
||||
"[ 7/4 → 2/1 | s:hh vibEnable:0 ]",
|
||||
"[ 2/1 → 9/4 | s:bd vibEnable:1 ]",
|
||||
"[ 9/4 → 5/2 | s:hh vibEnable:0 ]",
|
||||
"[ 5/2 → 11/4 | s:sd vibEnable:1 ]",
|
||||
"[ 11/4 → 3/1 | s:hh vibEnable:0 ]",
|
||||
"[ 3/1 → 13/4 | s:bd vibEnable:1 ]",
|
||||
"[ 13/4 → 7/2 | s:hh vibEnable:0 ]",
|
||||
"[ 7/2 → 15/4 | s:sd vibEnable:1 ]",
|
||||
"[ 15/4 → 4/1 | s:hh vibEnable:0 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "vibGamepad" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:bd vibGamepad:0 ]",
|
||||
"[ 1/4 → 1/2 | s:hh vibGamepad:1 ]",
|
||||
"[ 1/2 → 3/4 | s:sd vibGamepad:0 ]",
|
||||
"[ 3/4 → 1/1 | s:hh vibGamepad:1 ]",
|
||||
"[ 1/1 → 5/4 | s:bd vibGamepad:0 ]",
|
||||
"[ 5/4 → 3/2 | s:hh vibGamepad:1 ]",
|
||||
"[ 3/2 → 7/4 | s:sd vibGamepad:0 ]",
|
||||
"[ 7/4 → 2/1 | s:hh vibGamepad:1 ]",
|
||||
"[ 2/1 → 9/4 | s:bd vibGamepad:0 ]",
|
||||
"[ 9/4 → 5/2 | s:hh vibGamepad:1 ]",
|
||||
"[ 5/2 → 11/4 | s:sd vibGamepad:0 ]",
|
||||
"[ 11/4 → 3/1 | s:hh vibGamepad:1 ]",
|
||||
"[ 3/1 → 13/4 | s:bd vibGamepad:0 ]",
|
||||
"[ 13/4 → 7/2 | s:hh vibGamepad:1 ]",
|
||||
"[ 7/2 → 15/4 | s:sd vibGamepad:0 ]",
|
||||
"[ 15/4 → 4/1 | s:hh vibGamepad:1 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "vibGamepad" example index 0 2`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:bd vibGamepad:0 ]",
|
||||
"[ 1/4 → 1/2 | s:hh vibGamepad:1 ]",
|
||||
"[ 1/2 → 3/4 | s:sd vibGamepad:0 ]",
|
||||
"[ 3/4 → 1/1 | s:hh vibGamepad:1 ]",
|
||||
"[ 1/1 → 5/4 | s:bd vibGamepad:0 ]",
|
||||
"[ 5/4 → 3/2 | s:hh vibGamepad:1 ]",
|
||||
"[ 3/2 → 7/4 | s:sd vibGamepad:0 ]",
|
||||
"[ 7/4 → 2/1 | s:hh vibGamepad:1 ]",
|
||||
"[ 2/1 → 9/4 | s:bd vibGamepad:0 ]",
|
||||
"[ 9/4 → 5/2 | s:hh vibGamepad:1 ]",
|
||||
"[ 5/2 → 11/4 | s:sd vibGamepad:0 ]",
|
||||
"[ 11/4 → 3/1 | s:hh vibGamepad:1 ]",
|
||||
"[ 3/1 → 13/4 | s:bd vibGamepad:0 ]",
|
||||
"[ 13/4 → 7/2 | s:hh vibGamepad:1 ]",
|
||||
"[ 7/2 → 15/4 | s:sd vibGamepad:0 ]",
|
||||
"[ 15/4 → 4/1 | s:hh vibGamepad:1 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "vibGamepadIndex" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:bd vibGamepadIndex:0 ]",
|
||||
"[ 1/4 → 1/2 | s:hh vibGamepadIndex:1 ]",
|
||||
"[ 1/2 → 3/4 | s:sd vibGamepadIndex:0 ]",
|
||||
"[ 3/4 → 1/1 | s:hh vibGamepadIndex:1 ]",
|
||||
"[ 1/1 → 5/4 | s:bd vibGamepadIndex:0 ]",
|
||||
"[ 5/4 → 3/2 | s:hh vibGamepadIndex:1 ]",
|
||||
"[ 3/2 → 7/4 | s:sd vibGamepadIndex:0 ]",
|
||||
"[ 7/4 → 2/1 | s:hh vibGamepadIndex:1 ]",
|
||||
"[ 2/1 → 9/4 | s:bd vibGamepadIndex:0 ]",
|
||||
"[ 9/4 → 5/2 | s:hh vibGamepadIndex:1 ]",
|
||||
"[ 5/2 → 11/4 | s:sd vibGamepadIndex:0 ]",
|
||||
"[ 11/4 → 3/1 | s:hh vibGamepadIndex:1 ]",
|
||||
"[ 3/1 → 13/4 | s:bd vibGamepadIndex:0 ]",
|
||||
"[ 13/4 → 7/2 | s:hh vibGamepadIndex:1 ]",
|
||||
"[ 7/2 → 15/4 | s:sd vibGamepadIndex:0 ]",
|
||||
"[ 15/4 → 4/1 | s:hh vibGamepadIndex:1 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "vibIntensity" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 1/4 → 1/2 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 1/2 → 3/4 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 3/4 → 1/1 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 1/1 → 5/4 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 5/4 → 3/2 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 3/2 → 7/4 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 7/4 → 2/1 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 2/1 → 9/4 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 9/4 → 5/2 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 5/2 → 11/4 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 11/4 → 3/1 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 3/1 → 13/4 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 13/4 → 7/2 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 7/2 → 15/4 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 15/4 → 4/1 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "vibIntensity" example index 0 2`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 1/4 → 1/2 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 1/2 → 3/4 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 3/4 → 1/1 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 1/1 → 5/4 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 5/4 → 3/2 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 3/2 → 7/4 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 7/4 → 2/1 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 2/1 → 9/4 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 9/4 → 5/2 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 5/2 → 11/4 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 11/4 → 3/1 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 3/1 → 13/4 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 13/4 → 7/2 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 7/2 → 15/4 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
"[ 15/4 → 4/1 | s:bd vibStrong:0.4999999999999999 vibWeak:0.4999999999999999 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "vibStrong" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:bd vibStrong:1 ]",
|
||||
"[ 1/4 → 1/2 | s:hh vibStrong:0 ]",
|
||||
"[ 1/2 → 3/4 | s:sd vibStrong:0.5 ]",
|
||||
"[ 3/4 → 1/1 | s:hh vibStrong:0 ]",
|
||||
"[ 1/1 → 5/4 | s:bd vibStrong:1 ]",
|
||||
"[ 5/4 → 3/2 | s:hh vibStrong:0 ]",
|
||||
"[ 3/2 → 7/4 | s:sd vibStrong:0.5 ]",
|
||||
"[ 7/4 → 2/1 | s:hh vibStrong:0 ]",
|
||||
"[ 2/1 → 9/4 | s:bd vibStrong:1 ]",
|
||||
"[ 9/4 → 5/2 | s:hh vibStrong:0 ]",
|
||||
"[ 5/2 → 11/4 | s:sd vibStrong:0.5 ]",
|
||||
"[ 11/4 → 3/1 | s:hh vibStrong:0 ]",
|
||||
"[ 3/1 → 13/4 | s:bd vibStrong:1 ]",
|
||||
"[ 13/4 → 7/2 | s:hh vibStrong:0 ]",
|
||||
"[ 7/2 → 15/4 | s:sd vibStrong:0.5 ]",
|
||||
"[ 15/4 → 4/1 | s:hh vibStrong:0 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "vibStrong" example index 0 2`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:bd vibStrong:1 ]",
|
||||
"[ 1/4 → 1/2 | s:hh vibStrong:0 ]",
|
||||
"[ 1/2 → 3/4 | s:sd vibStrong:0.5 ]",
|
||||
"[ 3/4 → 1/1 | s:hh vibStrong:0 ]",
|
||||
"[ 1/1 → 5/4 | s:bd vibStrong:1 ]",
|
||||
"[ 5/4 → 3/2 | s:hh vibStrong:0 ]",
|
||||
"[ 3/2 → 7/4 | s:sd vibStrong:0.5 ]",
|
||||
"[ 7/4 → 2/1 | s:hh vibStrong:0 ]",
|
||||
"[ 2/1 → 9/4 | s:bd vibStrong:1 ]",
|
||||
"[ 9/4 → 5/2 | s:hh vibStrong:0 ]",
|
||||
"[ 5/2 → 11/4 | s:sd vibStrong:0.5 ]",
|
||||
"[ 11/4 → 3/1 | s:hh vibStrong:0 ]",
|
||||
"[ 3/1 → 13/4 | s:bd vibStrong:1 ]",
|
||||
"[ 13/4 → 7/2 | s:hh vibStrong:0 ]",
|
||||
"[ 7/2 → 15/4 | s:sd vibStrong:0.5 ]",
|
||||
"[ 15/4 → 4/1 | s:hh vibStrong:0 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "vibWeak" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:bd vibWeak:0.5 ]",
|
||||
"[ 1/4 → 1/2 | s:hh vibWeak:0 ]",
|
||||
"[ 1/2 → 3/4 | s:sd vibWeak:0.8 ]",
|
||||
"[ 3/4 → 1/1 | s:hh vibWeak:0 ]",
|
||||
"[ 1/1 → 5/4 | s:bd vibWeak:0.5 ]",
|
||||
"[ 5/4 → 3/2 | s:hh vibWeak:0 ]",
|
||||
"[ 3/2 → 7/4 | s:sd vibWeak:0.8 ]",
|
||||
"[ 7/4 → 2/1 | s:hh vibWeak:0 ]",
|
||||
"[ 2/1 → 9/4 | s:bd vibWeak:0.5 ]",
|
||||
"[ 9/4 → 5/2 | s:hh vibWeak:0 ]",
|
||||
"[ 5/2 → 11/4 | s:sd vibWeak:0.8 ]",
|
||||
"[ 11/4 → 3/1 | s:hh vibWeak:0 ]",
|
||||
"[ 3/1 → 13/4 | s:bd vibWeak:0.5 ]",
|
||||
"[ 13/4 → 7/2 | s:hh vibWeak:0 ]",
|
||||
"[ 7/2 → 15/4 | s:sd vibWeak:0.8 ]",
|
||||
"[ 15/4 → 4/1 | s:hh vibWeak:0 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "vibWeak" example index 0 2`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:bd vibWeak:0.5 ]",
|
||||
"[ 1/4 → 1/2 | s:hh vibWeak:0 ]",
|
||||
"[ 1/2 → 3/4 | s:sd vibWeak:0.8 ]",
|
||||
"[ 3/4 → 1/1 | s:hh vibWeak:0 ]",
|
||||
"[ 1/1 → 5/4 | s:bd vibWeak:0.5 ]",
|
||||
"[ 5/4 → 3/2 | s:hh vibWeak:0 ]",
|
||||
"[ 3/2 → 7/4 | s:sd vibWeak:0.8 ]",
|
||||
"[ 7/4 → 2/1 | s:hh vibWeak:0 ]",
|
||||
"[ 2/1 → 9/4 | s:bd vibWeak:0.5 ]",
|
||||
"[ 9/4 → 5/2 | s:hh vibWeak:0 ]",
|
||||
"[ 5/2 → 11/4 | s:sd vibWeak:0.8 ]",
|
||||
"[ 11/4 → 3/1 | s:hh vibWeak:0 ]",
|
||||
"[ 3/1 → 13/4 | s:bd vibWeak:0.5 ]",
|
||||
"[ 13/4 → 7/2 | s:hh vibWeak:0 ]",
|
||||
"[ 7/2 → 15/4 | s:sd vibWeak:0.8 ]",
|
||||
"[ 15/4 → 4/1 | s:hh vibWeak:0 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "vibmod" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/2 | note:a vib:4 vibmod:0.25 ]",
|
||||
@@ -11806,6 +12079,198 @@ exports[`runs examples > example "vibmod" example index 1 1`] = `
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "vibrate" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:bd ]",
|
||||
"[ 1/4 → 1/2 | s:hh ]",
|
||||
"[ 1/2 → 3/4 | s:sd ]",
|
||||
"[ 3/4 → 1/1 | s:hh ]",
|
||||
"[ 1/1 → 5/4 | s:bd ]",
|
||||
"[ 5/4 → 3/2 | s:hh ]",
|
||||
"[ 3/2 → 7/4 | s:sd ]",
|
||||
"[ 7/4 → 2/1 | s:hh ]",
|
||||
"[ 2/1 → 9/4 | s:bd ]",
|
||||
"[ 9/4 → 5/2 | s:hh ]",
|
||||
"[ 5/2 → 11/4 | s:sd ]",
|
||||
"[ 11/4 → 3/1 | s:hh ]",
|
||||
"[ 3/1 → 13/4 | s:bd ]",
|
||||
"[ 13/4 → 7/2 | s:hh ]",
|
||||
"[ 7/2 → 15/4 | s:sd ]",
|
||||
"[ 15/4 → 4/1 | s:hh ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "vibrate" example index 1 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/1 | s:bd vibStrong:1 vibWeak:0.5 ]",
|
||||
"[ 1/1 → 2/1 | s:hh vibStrong:0.1 vibWeak:0 ]",
|
||||
"[ 2/1 → 3/1 | s:sd vibStrong:0.5 vibWeak:0.8 ]",
|
||||
"[ 3/1 → 4/1 | s:hh vibStrong:0 vibWeak:0 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "vibrate" example index 2 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:bd ]",
|
||||
"[ 1/4 → 1/2 | s:bd ]",
|
||||
"[ 1/2 → 3/4 | s:bd ]",
|
||||
"[ 3/4 → 1/1 | s:bd ]",
|
||||
"[ 1/1 → 5/4 | s:bd ]",
|
||||
"[ 5/4 → 3/2 | s:bd ]",
|
||||
"[ 3/2 → 7/4 | s:bd ]",
|
||||
"[ 7/4 → 2/1 | s:bd ]",
|
||||
"[ 2/1 → 9/4 | s:bd ]",
|
||||
"[ 9/4 → 5/2 | s:bd ]",
|
||||
"[ 5/2 → 11/4 | s:bd ]",
|
||||
"[ 11/4 → 3/1 | s:bd ]",
|
||||
"[ 3/1 → 13/4 | s:bd ]",
|
||||
"[ 13/4 → 7/2 | s:bd ]",
|
||||
"[ 7/2 → 15/4 | s:bd ]",
|
||||
"[ 15/4 → 4/1 | s:bd ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "vibrate" example index 4 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:bd vibGamepadIndex:0 ]",
|
||||
"[ 1/4 → 1/2 | s:hh vibGamepadIndex:0 ]",
|
||||
"[ 1/2 → 3/4 | s:sd vibGamepadIndex:0 ]",
|
||||
"[ 3/4 → 1/1 | s:hh vibGamepadIndex:0 ]",
|
||||
"[ 1/1 → 5/4 | s:bd vibGamepadIndex:1 ]",
|
||||
"[ 5/4 → 3/2 | s:hh vibGamepadIndex:1 ]",
|
||||
"[ 3/2 → 7/4 | s:sd vibGamepadIndex:1 ]",
|
||||
"[ 7/4 → 2/1 | s:hh vibGamepadIndex:1 ]",
|
||||
"[ 2/1 → 9/4 | s:bd vibGamepadIndex:0 ]",
|
||||
"[ 9/4 → 5/2 | s:hh vibGamepadIndex:0 ]",
|
||||
"[ 5/2 → 11/4 | s:sd vibGamepadIndex:0 ]",
|
||||
"[ 11/4 → 3/1 | s:hh vibGamepadIndex:0 ]",
|
||||
"[ 3/1 → 13/4 | s:bd vibGamepadIndex:1 ]",
|
||||
"[ 13/4 → 7/2 | s:hh vibGamepadIndex:1 ]",
|
||||
"[ 7/2 → 15/4 | s:sd vibGamepadIndex:1 ]",
|
||||
"[ 15/4 → 4/1 | s:hh vibGamepadIndex:1 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "vibrate" example index 5 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/8 | s:bd vibGamepadIndex:0 ]",
|
||||
"[ 1/8 → 1/4 | s:bd vibGamepadIndex:1 ]",
|
||||
"[ 1/4 → 3/8 | s:bd vibGamepadIndex:0 ]",
|
||||
"[ (3/8 → 7/16) ⇝ 1/2 | s:bd vibGamepadIndex:1 ]",
|
||||
"[ 3/8 ⇜ (7/16 → 1/2) | s:bd vibGamepadIndex:0 ]",
|
||||
"[ 1/2 → 5/8 | s:bd vibGamepadIndex:1 ]",
|
||||
"[ 5/8 → 3/4 | s:bd vibGamepadIndex:0 ]",
|
||||
"[ 3/4 → 7/8 | s:bd vibGamepadIndex:1 ]",
|
||||
"[ 7/8 → 1/1 | s:bd vibGamepadIndex:0 ]",
|
||||
"[ 1/1 → 9/8 | s:bd vibGamepadIndex:0 ]",
|
||||
"[ 9/8 → 5/4 | s:bd vibGamepadIndex:1 ]",
|
||||
"[ 5/4 → 11/8 | s:bd vibGamepadIndex:0 ]",
|
||||
"[ (11/8 → 23/16) ⇝ 3/2 | s:bd vibGamepadIndex:1 ]",
|
||||
"[ 11/8 ⇜ (23/16 → 3/2) | s:bd vibGamepadIndex:0 ]",
|
||||
"[ 3/2 → 13/8 | s:bd vibGamepadIndex:1 ]",
|
||||
"[ 13/8 → 7/4 | s:bd vibGamepadIndex:0 ]",
|
||||
"[ 7/4 → 15/8 | s:bd vibGamepadIndex:1 ]",
|
||||
"[ 15/8 → 2/1 | s:bd vibGamepadIndex:0 ]",
|
||||
"[ 2/1 → 17/8 | s:bd vibGamepadIndex:0 ]",
|
||||
"[ 17/8 → 9/4 | s:bd vibGamepadIndex:1 ]",
|
||||
"[ 9/4 → 19/8 | s:bd vibGamepadIndex:0 ]",
|
||||
"[ (19/8 → 39/16) ⇝ 5/2 | s:bd vibGamepadIndex:1 ]",
|
||||
"[ 19/8 ⇜ (39/16 → 5/2) | s:bd vibGamepadIndex:0 ]",
|
||||
"[ 5/2 → 21/8 | s:bd vibGamepadIndex:1 ]",
|
||||
"[ 21/8 → 11/4 | s:bd vibGamepadIndex:0 ]",
|
||||
"[ 11/4 → 23/8 | s:bd vibGamepadIndex:1 ]",
|
||||
"[ 23/8 → 3/1 | s:bd vibGamepadIndex:0 ]",
|
||||
"[ 3/1 → 25/8 | s:bd vibGamepadIndex:0 ]",
|
||||
"[ 25/8 → 13/4 | s:bd vibGamepadIndex:1 ]",
|
||||
"[ 13/4 → 27/8 | s:bd vibGamepadIndex:0 ]",
|
||||
"[ (27/8 → 55/16) ⇝ 7/2 | s:bd vibGamepadIndex:1 ]",
|
||||
"[ 27/8 ⇜ (55/16 → 7/2) | s:bd vibGamepadIndex:0 ]",
|
||||
"[ 7/2 → 29/8 | s:bd vibGamepadIndex:1 ]",
|
||||
"[ 29/8 → 15/4 | s:bd vibGamepadIndex:0 ]",
|
||||
"[ 15/4 → 31/8 | s:bd vibGamepadIndex:1 ]",
|
||||
"[ 31/8 → 4/1 | s:bd vibGamepadIndex:0 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "vibrate" example index 6 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:bd vibGamepad:0 ]",
|
||||
"[ 1/4 → 1/2 | s:hh vibGamepad:0 ]",
|
||||
"[ 1/2 → 3/4 | s:sd vibGamepad:0 ]",
|
||||
"[ 3/4 → 1/1 | s:hh vibGamepad:0 ]",
|
||||
"[ 1/1 → 5/4 | s:bd vibGamepad:1 ]",
|
||||
"[ 5/4 → 3/2 | s:hh vibGamepad:1 ]",
|
||||
"[ 3/2 → 7/4 | s:sd vibGamepad:1 ]",
|
||||
"[ 7/4 → 2/1 | s:hh vibGamepad:1 ]",
|
||||
"[ 2/1 → 9/4 | s:bd vibGamepad:0 ]",
|
||||
"[ 9/4 → 5/2 | s:hh vibGamepad:0 ]",
|
||||
"[ 5/2 → 11/4 | s:sd vibGamepad:0 ]",
|
||||
"[ 11/4 → 3/1 | s:hh vibGamepad:0 ]",
|
||||
"[ 3/1 → 13/4 | s:bd vibGamepad:1 ]",
|
||||
"[ 13/4 → 7/2 | s:hh vibGamepad:1 ]",
|
||||
"[ 7/2 → 15/4 | s:sd vibGamepad:1 ]",
|
||||
"[ 15/4 → 4/1 | s:hh vibGamepad:1 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "vibrate" example index 7 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:bd vibGamepadIndex:[0 1 0.5 200] ]",
|
||||
"[ 1/4 → 1/2 | s:hh vibGamepadIndex:[0 1 0.5 200] ]",
|
||||
"[ 1/2 → 3/4 | s:sd vibGamepadIndex:[1 0.8 0.3 150] ]",
|
||||
"[ 3/4 → 1/1 | s:hh vibGamepadIndex:[1 0.8 0.3 150] ]",
|
||||
"[ 1/1 → 5/4 | s:bd vibGamepadIndex:[0 1 0.5 200] ]",
|
||||
"[ 5/4 → 3/2 | s:hh vibGamepadIndex:[0 1 0.5 200] ]",
|
||||
"[ 3/2 → 7/4 | s:sd vibGamepadIndex:[1 0.8 0.3 150] ]",
|
||||
"[ 7/4 → 2/1 | s:hh vibGamepadIndex:[1 0.8 0.3 150] ]",
|
||||
"[ 2/1 → 9/4 | s:bd vibGamepadIndex:[0 1 0.5 200] ]",
|
||||
"[ 9/4 → 5/2 | s:hh vibGamepadIndex:[0 1 0.5 200] ]",
|
||||
"[ 5/2 → 11/4 | s:sd vibGamepadIndex:[1 0.8 0.3 150] ]",
|
||||
"[ 11/4 → 3/1 | s:hh vibGamepadIndex:[1 0.8 0.3 150] ]",
|
||||
"[ 3/1 → 13/4 | s:bd vibGamepadIndex:[0 1 0.5 200] ]",
|
||||
"[ 13/4 → 7/2 | s:hh vibGamepadIndex:[0 1 0.5 200] ]",
|
||||
"[ 7/2 → 15/4 | s:sd vibGamepadIndex:[1 0.8 0.3 150] ]",
|
||||
"[ 15/4 → 4/1 | s:hh vibGamepadIndex:[1 0.8 0.3 150] ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "vibrate" example index 8 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/8 | s:bd vibGamepadIndex:[0 0.2 0.4 100] ]",
|
||||
"[ 1/8 → 1/4 | s:bd vibGamepadIndex:[0 0.2 0.4 100] ]",
|
||||
"[ 1/4 → 3/8 | s:bd vibGamepadIndex:[0 0.2 1 100] ]",
|
||||
"[ 3/8 → 1/2 | s:bd vibGamepadIndex:[0 0.2 1 100] ]",
|
||||
"[ 1/2 → 5/8 | s:bd vibGamepadIndex:[1 1 0.5 200] ]",
|
||||
"[ 5/8 → 3/4 | s:bd vibGamepadIndex:[1 1 0.5 200] ]",
|
||||
"[ 3/4 → 7/8 | s:bd vibGamepadIndex:[1 0.5 1 150] ]",
|
||||
"[ 7/8 → 1/1 | s:bd vibGamepadIndex:[1 0.5 1 150] ]",
|
||||
"[ 1/1 → 9/8 | s:bd vibGamepadIndex:[0 0.2 0.4 100] ]",
|
||||
"[ 9/8 → 5/4 | s:bd vibGamepadIndex:[0 0.2 0.4 100] ]",
|
||||
"[ 5/4 → 11/8 | s:bd vibGamepadIndex:[0 0.2 1 100] ]",
|
||||
"[ 11/8 → 3/2 | s:bd vibGamepadIndex:[0 0.2 1 100] ]",
|
||||
"[ 3/2 → 13/8 | s:bd vibGamepadIndex:[1 1 0.5 200] ]",
|
||||
"[ 13/8 → 7/4 | s:bd vibGamepadIndex:[1 1 0.5 200] ]",
|
||||
"[ 7/4 → 15/8 | s:bd vibGamepadIndex:[1 0.5 1 150] ]",
|
||||
"[ 15/8 → 2/1 | s:bd vibGamepadIndex:[1 0.5 1 150] ]",
|
||||
"[ 2/1 → 17/8 | s:bd vibGamepadIndex:[0 0.2 0.4 100] ]",
|
||||
"[ 17/8 → 9/4 | s:bd vibGamepadIndex:[0 0.2 0.4 100] ]",
|
||||
"[ 9/4 → 19/8 | s:bd vibGamepadIndex:[0 0.2 1 100] ]",
|
||||
"[ 19/8 → 5/2 | s:bd vibGamepadIndex:[0 0.2 1 100] ]",
|
||||
"[ 5/2 → 21/8 | s:bd vibGamepadIndex:[1 1 0.5 200] ]",
|
||||
"[ 21/8 → 11/4 | s:bd vibGamepadIndex:[1 1 0.5 200] ]",
|
||||
"[ 11/4 → 23/8 | s:bd vibGamepadIndex:[1 0.5 1 150] ]",
|
||||
"[ 23/8 → 3/1 | s:bd vibGamepadIndex:[1 0.5 1 150] ]",
|
||||
"[ 3/1 → 25/8 | s:bd vibGamepadIndex:[0 0.2 0.4 100] ]",
|
||||
"[ 25/8 → 13/4 | s:bd vibGamepadIndex:[0 0.2 0.4 100] ]",
|
||||
"[ 13/4 → 27/8 | s:bd vibGamepadIndex:[0 0.2 1 100] ]",
|
||||
"[ 27/8 → 7/2 | s:bd vibGamepadIndex:[0 0.2 1 100] ]",
|
||||
"[ 7/2 → 29/8 | s:bd vibGamepadIndex:[1 1 0.5 200] ]",
|
||||
"[ 29/8 → 15/4 | s:bd vibGamepadIndex:[1 1 0.5 200] ]",
|
||||
"[ 15/4 → 31/8 | s:bd vibGamepadIndex:[1 0.5 1 150] ]",
|
||||
"[ 31/8 → 4/1 | s:bd vibGamepadIndex:[1 0.5 1 150] ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "voicing" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | note:52 ]",
|
||||
|
||||
@@ -18,6 +18,14 @@ const skippedExamples = [
|
||||
'accelerationZ',
|
||||
'accelerationY',
|
||||
'accelerationX',
|
||||
'vibrate',
|
||||
'vibGamepadIndex',
|
||||
'vibGamepadId',
|
||||
'vibEnable',
|
||||
'vibWeak',
|
||||
'vibStrong',
|
||||
'vibDuration',
|
||||
'vibIntensity',
|
||||
'defaultmidimap',
|
||||
'midimaps',
|
||||
];
|
||||
|
||||
+2
-2
@@ -23,7 +23,7 @@ import '@strudel/xen/xen.mjs';
|
||||
import '../website/src/repl/piano';
|
||||
//import * as motionHelpers from '../packages/motion/index.mjs';
|
||||
//import * as geolocationHelpers from '../packages/geolocation/index.mjs';
|
||||
import * as gamepadHelpers from '../packages/gamepad/index.mjs';
|
||||
//import * as gamepadHelpers from '../packages/gamepad/index.mjs';
|
||||
|
||||
class MockedNode {
|
||||
chain() {
|
||||
@@ -141,8 +141,8 @@ evalScope(
|
||||
uiHelpersMocked,
|
||||
webaudio,
|
||||
tonalHelpers,
|
||||
gamepadHelpers,
|
||||
/*
|
||||
gamepadHelpers,
|
||||
toneHelpers,
|
||||
voicingHelpers,
|
||||
drawHelpers,
|
||||
|
||||
Reference in New Issue
Block a user