ive-connect
Version:
A universal haptic device control library for interactive experiences
94 lines (93 loc) • 4.18 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertScriptPositionToDevicePosition = convertScriptPositionToDevicePosition;
exports.createDeviceCommandExecutor = createDeviceCommandExecutor;
exports.createMultiDeviceCommandExecutor = createMultiDeviceCommandExecutor;
/**
* Convert script position (0-100) to device position (0.0-1.0)
*/
function convertScriptPositionToDevicePosition(scriptPos, strokeMin = 0.0, strokeMax = 1.0, invert = false) {
// Normalize scriptPos to 0.0-1.0 range
let normalized = Math.min(1, Math.max(0, scriptPos / 100));
// Apply script inversion first if enabled
if (invert) {
normalized = 1.0 - normalized;
}
// Scale to stroke range
return strokeMin + normalized * (strokeMax - strokeMin);
}
/**
* Create a command executor for a specific device
*/
function createDeviceCommandExecutor(api, deviceInfo, preferences, invertScript = false) {
// If device is disabled, return a no-op executor
if (!preferences.enabled) {
return {
executeAction: async () => {
/* No-op */
},
};
}
// Track last position to detect unchanged positions
let lastPos = -1;
return {
executeAction: async (pos, prevPos, durationMs, strokeRange = { min: 0, max: 1 }) => {
try {
// Convert position to device range with stroke range applied
const position = convertScriptPositionToDevicePosition(pos, strokeRange.min, strokeRange.max, invertScript);
// Apply device-specific intensity scaling if configured
const intensity = preferences.intensity !== undefined ? preferences.intensity : 1.0;
// For vibration and rotation: based on position directly
// If position hasn't changed from last position, set to 0
let speed = Math.min(1.0, Math.max(0, pos / 100)) * intensity;
// If position hasn't changed, set speed to 0
if (Math.abs(pos - lastPos) < 0.00001 && lastPos >= 0) {
speed = 0;
}
// Save position for next time
lastPos = pos;
console.log(`Device ${deviceInfo.name} command:`, {
speed,
position,
durationMs,
strokeRange,
});
// Send appropriate commands based on device capabilities and preferences
if (deviceInfo.canLinear && preferences.useLinear) {
await api.linearDevice(deviceInfo.index, position, durationMs);
}
if (deviceInfo.canVibrate && preferences.useVibrate) {
await api.vibrateDevice(deviceInfo.index, invertScript ? 1 - speed : speed);
}
if (deviceInfo.canRotate && preferences.useRotate) {
await api.rotateDevice(deviceInfo.index, speed, invertScript ? false : true);
}
}
catch (error) {
console.error(`Error executing command for device ${deviceInfo.name}:`, error);
}
},
};
}
/**
* Create a command executor for multiple devices
*/
function createMultiDeviceCommandExecutor(api, devices, preferences, invertScript = false) {
// Create executors for all enabled devices
const deviceExecutors = devices
.filter((device) => {
const devicePrefs = preferences.get(device.index);
return devicePrefs && devicePrefs.enabled;
})
.map((device) => {
const devicePrefs = preferences.get(device.index);
return createDeviceCommandExecutor(api, device, devicePrefs, invertScript);
});
// Create a combined executor that will send commands to all devices
return {
executeAction: async (pos, prevPos, durationMs, strokeRange = { min: 0, max: 1 }) => {
// Execute on all devices in parallel
await Promise.all(deviceExecutors.map((executor) => executor.executeAction(pos, prevPos, durationMs, strokeRange)));
},
};
}