ive-connect 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -22,6 +22,7 @@ const DEFAULT_CONFIG = {
22
22
  enabled: true,
23
23
  connectionType: types_1.ButtplugConnectionType.LOCAL,
24
24
  clientName: (0, buttplug_server_1.generateClientName)(),
25
+ strokeRange: { min: 0, max: 1 },
25
26
  allowedFeatures: {
26
27
  vibrate: true,
27
28
  rotate: true,
@@ -161,6 +162,12 @@ class ButtplugDevice extends events_1.EventEmitter {
161
162
  if (config.clientName !== undefined) {
162
163
  this._config.clientName = config.clientName;
163
164
  }
165
+ if (config.strokeRange !== undefined) {
166
+ this._config.strokeRange = {
167
+ min: config.strokeRange.min,
168
+ max: config.strokeRange.max,
169
+ };
170
+ }
164
171
  if (config.allowedFeatures !== undefined) {
165
172
  this._config.allowedFeatures = {
166
173
  ...this._config.allowedFeatures,
@@ -310,7 +317,7 @@ class ButtplugDevice extends events_1.EventEmitter {
310
317
  this._playbackRate = playbackRate;
311
318
  this._loopPlayback = loop;
312
319
  this._lastActionIndex = -1;
313
- // Create command executor for all devices
320
+ // Create command executor for all devices (no stroke range here)
314
321
  const devices = this._api.getDevices();
315
322
  const preferences = this._api.getDevicePreferences();
316
323
  const executor = (0, command_helpers_1.createMultiDeviceCommandExecutor)(this._api, devices, preferences, false);
@@ -319,7 +326,7 @@ class ButtplugDevice extends events_1.EventEmitter {
319
326
  // Create an interval to check for actions
320
327
  this._playbackInterval = setInterval(() => {
321
328
  this._processActions(executor);
322
- }, 20); // Check every 20ms for smoother playback
329
+ }, 20);
323
330
  this.emit("playbackStateChanged", {
324
331
  isPlaying: this._isPlaying,
325
332
  timeMs,
@@ -456,9 +463,11 @@ class ButtplugDevice extends events_1.EventEmitter {
456
463
  // Enforce a minimum duration to prevent erratic movement
457
464
  durationMs = Math.max(100, durationMs);
458
465
  }
459
- // Execute the action on all devices
466
+ // Get current stroke range from config (live updates)
467
+ const strokeRange = this._config.strokeRange || { min: 0, max: 1 };
468
+ // Execute the action on all devices with current stroke range
460
469
  executor
461
- .executeAction(action.pos, prevAction.pos, durationMs)
470
+ .executeAction(action.pos, prevAction.pos, durationMs, strokeRange)
462
471
  .catch((error) => {
463
472
  console.error("Error executing action:", error);
464
473
  });
@@ -8,16 +8,22 @@ import { ButtplugDeviceInfo, DevicePreference } from "./types";
8
8
  /**
9
9
  * Convert script position (0-100) to device position (0.0-1.0)
10
10
  */
11
- export declare function convertScriptPositionToDevicePosition(scriptPos: number, min?: number, max?: number, invert?: boolean): number;
11
+ export declare function convertScriptPositionToDevicePosition(scriptPos: number, strokeMin?: number, strokeMax?: number, invert?: boolean): number;
12
12
  /**
13
13
  * Create a command executor for a specific device
14
14
  */
15
15
  export declare function createDeviceCommandExecutor(api: ButtplugApi, deviceInfo: ButtplugDeviceInfo, preferences: DevicePreference, invertScript?: boolean): {
16
- executeAction: (pos: number, prevPos: number, durationMs: number) => Promise<void>;
16
+ executeAction: (pos: number, prevPos: number, durationMs: number, strokeRange?: {
17
+ min: number;
18
+ max: number;
19
+ }) => Promise<void>;
17
20
  };
18
21
  /**
19
22
  * Create a command executor for multiple devices
20
23
  */
21
24
  export declare function createMultiDeviceCommandExecutor(api: ButtplugApi, devices: ButtplugDeviceInfo[], preferences: Map<number, DevicePreference>, invertScript?: boolean): {
22
- executeAction: (pos: number, prevPos: number, durationMs: number) => Promise<void>;
25
+ executeAction: (pos: number, prevPos: number, durationMs: number, strokeRange?: {
26
+ min: number;
27
+ max: number;
28
+ }) => Promise<void>;
23
29
  };
@@ -6,15 +6,15 @@ exports.createMultiDeviceCommandExecutor = createMultiDeviceCommandExecutor;
6
6
  /**
7
7
  * Convert script position (0-100) to device position (0.0-1.0)
8
8
  */
9
- function convertScriptPositionToDevicePosition(scriptPos, min = 0.0, max = 1.0, invert = false) {
9
+ function convertScriptPositionToDevicePosition(scriptPos, strokeMin = 0.0, strokeMax = 1.0, invert = false) {
10
10
  // Normalize scriptPos to 0.0-1.0 range
11
11
  let normalized = Math.min(1, Math.max(0, scriptPos / 100));
12
12
  // Apply script inversion first if enabled
13
13
  if (invert) {
14
14
  normalized = 1.0 - normalized;
15
15
  }
16
- // Scale to min-max range
17
- return min + normalized * (max - min);
16
+ // Scale to stroke range
17
+ return strokeMin + normalized * (strokeMax - strokeMin);
18
18
  }
19
19
  /**
20
20
  * Create a command executor for a specific device
@@ -31,15 +31,13 @@ function createDeviceCommandExecutor(api, deviceInfo, preferences, invertScript
31
31
  // Track last position to detect unchanged positions
32
32
  let lastPos = -1;
33
33
  return {
34
- executeAction: async (pos, prevPos, durationMs) => {
34
+ executeAction: async (pos, prevPos, durationMs, strokeRange = { min: 0, max: 1 }) => {
35
35
  try {
36
- // Convert position to device range (0.0-1.0)
37
- const position = convertScriptPositionToDevicePosition(pos, 0, // Min
38
- 1, // Max
39
- invertScript);
36
+ // Convert position to device range with stroke range applied
37
+ const position = convertScriptPositionToDevicePosition(pos, strokeRange.min, strokeRange.max, invertScript);
40
38
  // Apply device-specific intensity scaling if configured
41
39
  const intensity = preferences.intensity !== undefined ? preferences.intensity : 1.0;
42
- // For vibration and rotation: based on position directly (Martin style)
40
+ // For vibration and rotation: based on position directly
43
41
  // If position hasn't changed from last position, set to 0
44
42
  let speed = Math.min(1.0, Math.max(0, pos / 100)) * intensity;
45
43
  // If position hasn't changed, set speed to 0
@@ -52,6 +50,7 @@ function createDeviceCommandExecutor(api, deviceInfo, preferences, invertScript
52
50
  speed,
53
51
  position,
54
52
  durationMs,
53
+ strokeRange,
55
54
  });
56
55
  // Send appropriate commands based on device capabilities and preferences
57
56
  if (deviceInfo.canLinear && preferences.useLinear) {
@@ -86,9 +85,9 @@ function createMultiDeviceCommandExecutor(api, devices, preferences, invertScrip
86
85
  });
87
86
  // Create a combined executor that will send commands to all devices
88
87
  return {
89
- executeAction: async (pos, prevPos, durationMs) => {
88
+ executeAction: async (pos, prevPos, durationMs, strokeRange = { min: 0, max: 1 }) => {
90
89
  // Execute on all devices in parallel
91
- await Promise.all(deviceExecutors.map((executor) => executor.executeAction(pos, prevPos, durationMs)));
90
+ await Promise.all(deviceExecutors.map((executor) => executor.executeAction(pos, prevPos, durationMs, strokeRange)));
92
91
  },
93
92
  };
94
93
  }
@@ -24,6 +24,10 @@ export interface ButtplugSettings extends DeviceSettings {
24
24
  connectionType: ButtplugConnectionType;
25
25
  serverUrl?: string;
26
26
  clientName: string;
27
+ strokeRange?: {
28
+ min: number;
29
+ max: number;
30
+ };
27
31
  allowedFeatures: {
28
32
  vibrate: boolean;
29
33
  rotate: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ive-connect",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "A universal haptic device control library for interactive experiences",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",