@mentra/sdk 2.1.2 → 2.1.4

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.
Files changed (60) hide show
  1. package/dist/app/session/events.d.ts +3 -2
  2. package/dist/app/session/events.d.ts.map +1 -1
  3. package/dist/app/session/events.js +3 -0
  4. package/dist/app/session/index.d.ts +8 -1
  5. package/dist/app/session/index.d.ts.map +1 -1
  6. package/dist/app/session/index.js +9 -0
  7. package/dist/app/session/layouts.d.ts +71 -14
  8. package/dist/app/session/layouts.d.ts.map +1 -1
  9. package/dist/app/session/layouts.js +114 -31
  10. package/dist/app/session/modules/audio.d.ts +2 -2
  11. package/dist/app/session/modules/audio.d.ts.map +1 -1
  12. package/dist/app/session/modules/audio.js +21 -17
  13. package/dist/app/session/modules/camera-managed-extension.d.ts +3 -1
  14. package/dist/app/session/modules/camera-managed-extension.d.ts.map +1 -1
  15. package/dist/app/session/modules/camera-managed-extension.js +26 -18
  16. package/dist/app/session/modules/camera.d.ts +4 -4
  17. package/dist/app/session/modules/camera.d.ts.map +1 -1
  18. package/dist/app/session/modules/camera.js +28 -22
  19. package/dist/app/session/modules/location.d.ts +3 -3
  20. package/dist/app/session/modules/location.d.ts.map +1 -1
  21. package/dist/app/session/modules/location.js +8 -5
  22. package/dist/examples/managed-rtmp-streaming-example.js +3 -0
  23. package/dist/examples/managed-rtmp-streaming-with-restream-example.d.ts +11 -0
  24. package/dist/examples/managed-rtmp-streaming-with-restream-example.d.ts.map +1 -0
  25. package/dist/examples/managed-rtmp-streaming-with-restream-example.js +124 -0
  26. package/dist/index.d.ts +6 -4
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +5 -1
  29. package/dist/types/enums.d.ts +3 -1
  30. package/dist/types/enums.d.ts.map +1 -1
  31. package/dist/types/enums.js +2 -0
  32. package/dist/types/index.d.ts +2 -2
  33. package/dist/types/index.d.ts.map +1 -1
  34. package/dist/types/layouts.d.ts +16 -1
  35. package/dist/types/layouts.d.ts.map +1 -1
  36. package/dist/types/message-types.d.ts +2 -2
  37. package/dist/types/message-types.d.ts.map +1 -1
  38. package/dist/types/message-types.js +3 -3
  39. package/dist/types/messages/app-to-cloud.d.ts +11 -0
  40. package/dist/types/messages/app-to-cloud.d.ts.map +1 -1
  41. package/dist/types/messages/cloud-to-app.d.ts +19 -0
  42. package/dist/types/messages/cloud-to-app.d.ts.map +1 -1
  43. package/dist/types/messages/glasses-to-cloud.d.ts +8 -4
  44. package/dist/types/messages/glasses-to-cloud.d.ts.map +1 -1
  45. package/dist/types/messages/glasses-to-cloud.js +3 -3
  46. package/dist/types/models.d.ts +1 -0
  47. package/dist/types/models.d.ts.map +1 -1
  48. package/dist/types/models.js +1 -0
  49. package/dist/types/streams.d.ts +1 -1
  50. package/dist/types/streams.d.ts.map +1 -1
  51. package/dist/types/streams.js +2 -2
  52. package/dist/types/user-session.d.ts +8 -8
  53. package/dist/types/user-session.d.ts.map +1 -1
  54. package/dist/utils/animation-utils.d.ts +206 -0
  55. package/dist/utils/animation-utils.d.ts.map +1 -0
  56. package/dist/utils/animation-utils.js +340 -0
  57. package/dist/utils/bitmap-utils.d.ts +149 -0
  58. package/dist/utils/bitmap-utils.d.ts.map +1 -0
  59. package/dist/utils/bitmap-utils.js +465 -0
  60. package/package.json +2 -1
@@ -0,0 +1,206 @@
1
+ /**
2
+ * 🎬 Animation Utilities Module
3
+ *
4
+ * Provides helper functions for creating and managing bitmap animations in MentraOS applications.
5
+ * Includes timing utilities, animation factories, and performance optimization helpers.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { AnimationUtils } from '@mentra/sdk';
10
+ *
11
+ * // Create animation from files
12
+ * const animation = await AnimationUtils.createBitmapAnimation(
13
+ * session, './frames', 10, 1750, true
14
+ * );
15
+ *
16
+ * // Simple delay utility
17
+ * await AnimationUtils.delay(2000);
18
+ *
19
+ * // Stop animation
20
+ * animation.stop();
21
+ * ```
22
+ */
23
+ import { AppSession } from "../app/session";
24
+ import { LoadFramesOptions } from "./bitmap-utils";
25
+ /**
26
+ * Configuration options for bitmap animations
27
+ */
28
+ export interface AnimationConfig {
29
+ /** Time between frames in milliseconds (default: 1750ms - optimized for MentraOS) */
30
+ intervalMs?: number;
31
+ /** Whether to loop the animation continuously (default: false) */
32
+ repeat?: boolean;
33
+ /** Validate frames before starting animation (default: true) */
34
+ validateFrames?: boolean;
35
+ /** Options for loading frames from files */
36
+ loadOptions?: LoadFramesOptions;
37
+ /** Callback fired when animation starts */
38
+ onStart?: () => void;
39
+ /** Callback fired when animation stops/completes */
40
+ onStop?: () => void;
41
+ /** Callback fired on each frame display */
42
+ onFrame?: (frameIndex: number, totalFrames: number) => void;
43
+ /** Callback fired if animation encounters an error */
44
+ onError?: (error: string) => void;
45
+ }
46
+ /**
47
+ * Animation controller interface
48
+ */
49
+ export interface AnimationController {
50
+ /** Stop the animation */
51
+ stop: () => void;
52
+ /** Check if animation is currently running */
53
+ isRunning: () => boolean;
54
+ /** Get current frame index */
55
+ getCurrentFrame: () => number;
56
+ /** Get total frame count */
57
+ getTotalFrames: () => number;
58
+ }
59
+ /**
60
+ * Performance timing information
61
+ */
62
+ export interface TimingInfo {
63
+ /** Target interval between frames */
64
+ targetInterval: number;
65
+ /** Actual measured interval between frames */
66
+ actualInterval: number;
67
+ /** Timing drift (difference between target and actual) */
68
+ drift: number;
69
+ /** Frame rate (frames per second) */
70
+ fps: number;
71
+ }
72
+ /**
73
+ * Utility class for creating and managing animations in MentraOS applications
74
+ */
75
+ export declare class AnimationUtils {
76
+ /**
77
+ * Simple async delay helper
78
+ *
79
+ * @param ms - Milliseconds to delay
80
+ * @returns Promise that resolves after the specified delay
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * console.log('Starting...');
85
+ * await AnimationUtils.delay(2000);
86
+ * console.log('2 seconds later!');
87
+ * ```
88
+ */
89
+ static delay(ms: number): Promise<void>;
90
+ /**
91
+ * Create bitmap animation from files with advanced configuration
92
+ *
93
+ * @param session - MentraOS app session
94
+ * @param basePath - Directory containing animation frames
95
+ * @param frameCount - Number of frames to load
96
+ * @param config - Animation configuration options
97
+ * @returns Promise resolving to animation controller
98
+ *
99
+ * @example
100
+ * ```typescript
101
+ * // Simple animation
102
+ * const animation = await AnimationUtils.createBitmapAnimation(
103
+ * session, './animations', 10
104
+ * );
105
+ *
106
+ * // Advanced configuration
107
+ * const advancedAnimation = await AnimationUtils.createBitmapAnimation(
108
+ * session, './sprites', 8, {
109
+ * intervalMs: 1000,
110
+ * repeat: true,
111
+ * loadOptions: { filePattern: 'sprite_{i}.bmp', startFrame: 0 },
112
+ * onFrame: (frame, total) => console.log(`Frame ${frame}/${total}`),
113
+ * onError: (error) => console.error('Animation error:', error)
114
+ * }
115
+ * );
116
+ * ```
117
+ */
118
+ static createBitmapAnimation(session: AppSession, basePath: string, frameCount: number, config?: AnimationConfig): Promise<AnimationController>;
119
+ /**
120
+ * Create bitmap animation from pre-loaded frame data
121
+ *
122
+ * @param session - MentraOS app session
123
+ * @param frames - Array of hex-encoded bitmap data
124
+ * @param config - Animation configuration options
125
+ * @returns Animation controller
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * const frames = ['424d461a...', '424d461b...', '424d461c...'];
130
+ * const animation = AnimationUtils.createBitmapAnimationFromFrames(
131
+ * session, frames, { intervalMs: 1500, repeat: true }
132
+ * );
133
+ * ```
134
+ */
135
+ static createBitmapAnimationFromFrames(session: AppSession, frames: string[], config?: Omit<AnimationConfig, "loadOptions" | "validateFrames">): AnimationController;
136
+ /**
137
+ * Create a sequence of bitmap displays with custom timing
138
+ *
139
+ * @param session - MentraOS app session
140
+ * @param sequence - Array of frame data with individual timing
141
+ * @returns Promise that resolves when sequence completes
142
+ *
143
+ * @example
144
+ * ```typescript
145
+ * await AnimationUtils.createBitmapSequence(session, [
146
+ * { frame: frame1Hex, duration: 1000 },
147
+ * { frame: frame2Hex, duration: 500 },
148
+ * { frame: frame3Hex, duration: 2000 }
149
+ * ]);
150
+ * ```
151
+ */
152
+ static createBitmapSequence(session: AppSession, sequence: Array<{
153
+ frame: string;
154
+ duration: number;
155
+ }>): Promise<void>;
156
+ /**
157
+ * Measure animation timing performance
158
+ *
159
+ * @param targetInterval - Expected interval between frames in ms
160
+ * @param measureDuration - How long to measure in ms (default: 10 seconds)
161
+ * @returns Promise resolving to timing performance data
162
+ *
163
+ * @example
164
+ * ```typescript
165
+ * const timing = await AnimationUtils.measureTiming(1750, 10000);
166
+ * console.log(`Target: ${timing.targetInterval}ms, Actual: ${timing.actualInterval}ms`);
167
+ * console.log(`Drift: ${timing.drift}ms, FPS: ${timing.fps.toFixed(1)}`);
168
+ * ```
169
+ */
170
+ static measureTiming(targetInterval: number, measureDuration?: number): Promise<TimingInfo>;
171
+ /**
172
+ * Create optimized animation settings for different hardware
173
+ *
174
+ * @param deviceType - Target device type
175
+ * @returns Recommended animation configuration
176
+ *
177
+ * @example
178
+ * ```typescript
179
+ * const config = AnimationUtils.getOptimizedConfig('even-realities-g1');
180
+ * const animation = await AnimationUtils.createBitmapAnimation(
181
+ * session, './frames', 10, config
182
+ * );
183
+ * ```
184
+ */
185
+ static getOptimizedConfig(deviceType: "even-realities-g1" | "generic"): AnimationConfig;
186
+ /**
187
+ * Preload and cache animation frames for better performance
188
+ *
189
+ * @param basePath - Directory containing frames
190
+ * @param frameCount - Number of frames to preload
191
+ * @param options - Loading options
192
+ * @returns Promise resolving to cached frame data
193
+ *
194
+ * @example
195
+ * ```typescript
196
+ * // Preload frames
197
+ * const cachedFrames = await AnimationUtils.preloadFrames('./animations', 10);
198
+ *
199
+ * // Use cached frames multiple times
200
+ * const animation1 = AnimationUtils.createBitmapAnimationFromFrames(session, cachedFrames);
201
+ * const animation2 = AnimationUtils.createBitmapAnimationFromFrames(session, cachedFrames);
202
+ * ```
203
+ */
204
+ static preloadFrames(basePath: string, frameCount: number, options?: LoadFramesOptions): Promise<string[]>;
205
+ }
206
+ //# sourceMappingURL=animation-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"animation-utils.d.ts","sourceRoot":"","sources":["../../src/utils/animation-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAe,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,qFAAqF;IACrF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gEAAgE;IAChE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5D,sDAAsD;IACtD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,yBAAyB;IACzB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,8CAA8C;IAC9C,SAAS,EAAE,MAAM,OAAO,CAAC;IACzB,8BAA8B;IAC9B,eAAe,EAAE,MAAM,MAAM,CAAC;IAC9B,4BAA4B;IAC5B,cAAc,EAAE,MAAM,MAAM,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,qCAAqC;IACrC,cAAc,EAAE,MAAM,CAAC;IACvB,8CAA8C;IAC9C,cAAc,EAAE,MAAM,CAAC;IACvB,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,qBAAa,cAAc;IACzB;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;WACU,qBAAqB,CAChC,OAAO,EAAE,UAAU,EACnB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,MAAM,GAAE,eAAoB,GAC3B,OAAO,CAAC,mBAAmB,CAAC;IAkD/B;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,+BAA+B,CACpC,OAAO,EAAE,UAAU,EACnB,MAAM,EAAE,MAAM,EAAE,EAChB,MAAM,GAAE,IAAI,CAAC,eAAe,EAAE,aAAa,GAAG,gBAAgB,CAAM,GACnE,mBAAmB;IA6FtB;;;;;;;;;;;;;;;OAeG;WACU,oBAAoB,CAC/B,OAAO,EAAE,UAAU,EACnB,QAAQ,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,GACnD,OAAO,CAAC,IAAI,CAAC;IA2BhB;;;;;;;;;;;;;OAaG;WACU,aAAa,CACxB,cAAc,EAAE,MAAM,EACtB,eAAe,GAAE,MAAc,GAC9B,OAAO,CAAC,UAAU,CAAC;IA2CtB;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,kBAAkB,CACvB,UAAU,EAAE,mBAAmB,GAAG,SAAS,GAC1C,eAAe;IA2BlB;;;;;;;;;;;;;;;;;OAiBG;WACU,aAAa,CACxB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,MAAM,EAAE,CAAC;CAcrB"}
@@ -0,0 +1,340 @@
1
+ "use strict";
2
+ /**
3
+ * 🎬 Animation Utilities Module
4
+ *
5
+ * Provides helper functions for creating and managing bitmap animations in MentraOS applications.
6
+ * Includes timing utilities, animation factories, and performance optimization helpers.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { AnimationUtils } from '@mentra/sdk';
11
+ *
12
+ * // Create animation from files
13
+ * const animation = await AnimationUtils.createBitmapAnimation(
14
+ * session, './frames', 10, 1750, true
15
+ * );
16
+ *
17
+ * // Simple delay utility
18
+ * await AnimationUtils.delay(2000);
19
+ *
20
+ * // Stop animation
21
+ * animation.stop();
22
+ * ```
23
+ */
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.AnimationUtils = void 0;
26
+ const bitmap_utils_1 = require("./bitmap-utils");
27
+ /**
28
+ * Utility class for creating and managing animations in MentraOS applications
29
+ */
30
+ class AnimationUtils {
31
+ /**
32
+ * Simple async delay helper
33
+ *
34
+ * @param ms - Milliseconds to delay
35
+ * @returns Promise that resolves after the specified delay
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * console.log('Starting...');
40
+ * await AnimationUtils.delay(2000);
41
+ * console.log('2 seconds later!');
42
+ * ```
43
+ */
44
+ static delay(ms) {
45
+ return new Promise((resolve) => setTimeout(resolve, ms));
46
+ }
47
+ /**
48
+ * Create bitmap animation from files with advanced configuration
49
+ *
50
+ * @param session - MentraOS app session
51
+ * @param basePath - Directory containing animation frames
52
+ * @param frameCount - Number of frames to load
53
+ * @param config - Animation configuration options
54
+ * @returns Promise resolving to animation controller
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * // Simple animation
59
+ * const animation = await AnimationUtils.createBitmapAnimation(
60
+ * session, './animations', 10
61
+ * );
62
+ *
63
+ * // Advanced configuration
64
+ * const advancedAnimation = await AnimationUtils.createBitmapAnimation(
65
+ * session, './sprites', 8, {
66
+ * intervalMs: 1000,
67
+ * repeat: true,
68
+ * loadOptions: { filePattern: 'sprite_{i}.bmp', startFrame: 0 },
69
+ * onFrame: (frame, total) => console.log(`Frame ${frame}/${total}`),
70
+ * onError: (error) => console.error('Animation error:', error)
71
+ * }
72
+ * );
73
+ * ```
74
+ */
75
+ static async createBitmapAnimation(session, basePath, frameCount, config = {}) {
76
+ const { intervalMs = 1750, // Optimized for MentraOS hardware
77
+ repeat = false, validateFrames = true, loadOptions = {}, onStart, onStop, onFrame, onError, } = config;
78
+ try {
79
+ console.log(`🎬 Loading ${frameCount} animation frames from ${basePath}...`);
80
+ // Load frames with validation
81
+ const frames = await bitmap_utils_1.BitmapUtils.loadBmpFrames(basePath, frameCount, {
82
+ validateFrames,
83
+ ...loadOptions,
84
+ });
85
+ if (frames.length === 0) {
86
+ throw new Error("No frames loaded for animation");
87
+ }
88
+ console.log(`📚 Animation ready: ${frames.length} frames at ${intervalMs}ms intervals`);
89
+ // Create enhanced animation with the loaded frames
90
+ return this.createBitmapAnimationFromFrames(session, frames, {
91
+ intervalMs,
92
+ repeat,
93
+ onStart,
94
+ onStop,
95
+ onFrame,
96
+ onError,
97
+ });
98
+ }
99
+ catch (error) {
100
+ const errorMsg = `Failed to create animation: ${error instanceof Error ? error.message : "Unknown error"}`;
101
+ console.error(`❌ ${errorMsg}`);
102
+ if (onError) {
103
+ onError(errorMsg);
104
+ }
105
+ throw new Error(errorMsg);
106
+ }
107
+ }
108
+ /**
109
+ * Create bitmap animation from pre-loaded frame data
110
+ *
111
+ * @param session - MentraOS app session
112
+ * @param frames - Array of hex-encoded bitmap data
113
+ * @param config - Animation configuration options
114
+ * @returns Animation controller
115
+ *
116
+ * @example
117
+ * ```typescript
118
+ * const frames = ['424d461a...', '424d461b...', '424d461c...'];
119
+ * const animation = AnimationUtils.createBitmapAnimationFromFrames(
120
+ * session, frames, { intervalMs: 1500, repeat: true }
121
+ * );
122
+ * ```
123
+ */
124
+ static createBitmapAnimationFromFrames(session, frames, config = {}) {
125
+ const { intervalMs = 1750, repeat = false, onStart, onStop, onFrame, onError, } = config;
126
+ let isRunning = false;
127
+ const currentFrame = 0;
128
+ let animationController = null;
129
+ const controller = {
130
+ stop: () => {
131
+ if (animationController) {
132
+ animationController.stop();
133
+ animationController = null;
134
+ }
135
+ isRunning = false;
136
+ if (onStop) {
137
+ onStop();
138
+ }
139
+ console.log("🛑 Animation stopped");
140
+ },
141
+ isRunning: () => isRunning,
142
+ getCurrentFrame: () => currentFrame,
143
+ getTotalFrames: () => frames.length,
144
+ };
145
+ try {
146
+ // Start the animation using the session's built-in method
147
+ animationController = session.layouts.showBitmapAnimation(frames, intervalMs, repeat);
148
+ isRunning = true;
149
+ if (onStart) {
150
+ onStart();
151
+ }
152
+ console.log(`🎬 Animation started: ${frames.length} frames at ${intervalMs}ms${repeat ? " (repeating)" : ""}`);
153
+ // If we have frame callbacks, we need to track timing manually
154
+ // This is a limitation of the current SDK - we can't hook into individual frame displays
155
+ if (onFrame) {
156
+ let frameTracker = 0;
157
+ // Call onFrame for the first frame immediately
158
+ onFrame(frameTracker, frames.length);
159
+ const frameInterval = setInterval(() => {
160
+ if (!isRunning) {
161
+ clearInterval(frameInterval);
162
+ return;
163
+ }
164
+ frameTracker = (frameTracker + 1) % frames.length;
165
+ onFrame(frameTracker, frames.length);
166
+ // If not repeating and we've shown all frames, stop tracking
167
+ if (!repeat && frameTracker === frames.length - 1) {
168
+ clearInterval(frameInterval);
169
+ }
170
+ }, intervalMs);
171
+ // Override stop to also clear frame tracking
172
+ const originalStop = controller.stop;
173
+ controller.stop = () => {
174
+ clearInterval(frameInterval);
175
+ originalStop();
176
+ };
177
+ }
178
+ }
179
+ catch (error) {
180
+ const errorMsg = `Failed to start animation: ${error instanceof Error ? error.message : "Unknown error"}`;
181
+ console.error(`❌ ${errorMsg}`);
182
+ if (onError) {
183
+ onError(errorMsg);
184
+ }
185
+ throw new Error(errorMsg);
186
+ }
187
+ return controller;
188
+ }
189
+ /**
190
+ * Create a sequence of bitmap displays with custom timing
191
+ *
192
+ * @param session - MentraOS app session
193
+ * @param sequence - Array of frame data with individual timing
194
+ * @returns Promise that resolves when sequence completes
195
+ *
196
+ * @example
197
+ * ```typescript
198
+ * await AnimationUtils.createBitmapSequence(session, [
199
+ * { frame: frame1Hex, duration: 1000 },
200
+ * { frame: frame2Hex, duration: 500 },
201
+ * { frame: frame3Hex, duration: 2000 }
202
+ * ]);
203
+ * ```
204
+ */
205
+ static async createBitmapSequence(session, sequence) {
206
+ console.log(`🎭 Starting bitmap sequence: ${sequence.length} frames with custom timing`);
207
+ for (let i = 0; i < sequence.length; i++) {
208
+ const { frame, duration } = sequence[i];
209
+ try {
210
+ console.log(`📽️ Sequence frame ${i + 1}/${sequence.length} (${duration}ms)`);
211
+ session.layouts.showBitmapView(frame);
212
+ if (i < sequence.length - 1) {
213
+ // Don't delay after the last frame
214
+ await this.delay(duration);
215
+ }
216
+ }
217
+ catch (error) {
218
+ console.error(`❌ Error in sequence frame ${i + 1}:`, error);
219
+ throw error;
220
+ }
221
+ }
222
+ console.log("✅ Bitmap sequence completed");
223
+ }
224
+ /**
225
+ * Measure animation timing performance
226
+ *
227
+ * @param targetInterval - Expected interval between frames in ms
228
+ * @param measureDuration - How long to measure in ms (default: 10 seconds)
229
+ * @returns Promise resolving to timing performance data
230
+ *
231
+ * @example
232
+ * ```typescript
233
+ * const timing = await AnimationUtils.measureTiming(1750, 10000);
234
+ * console.log(`Target: ${timing.targetInterval}ms, Actual: ${timing.actualInterval}ms`);
235
+ * console.log(`Drift: ${timing.drift}ms, FPS: ${timing.fps.toFixed(1)}`);
236
+ * ```
237
+ */
238
+ static async measureTiming(targetInterval, measureDuration = 10000) {
239
+ return new Promise((resolve) => {
240
+ const timestamps = [];
241
+ const startTime = Date.now();
242
+ const measureInterval = setInterval(() => {
243
+ timestamps.push(Date.now());
244
+ }, targetInterval);
245
+ setTimeout(() => {
246
+ clearInterval(measureInterval);
247
+ if (timestamps.length < 2) {
248
+ resolve({
249
+ targetInterval,
250
+ actualInterval: targetInterval,
251
+ drift: 0,
252
+ fps: 1000 / targetInterval,
253
+ });
254
+ return;
255
+ }
256
+ // Calculate actual interval
257
+ const intervals = [];
258
+ for (let i = 1; i < timestamps.length; i++) {
259
+ intervals.push(timestamps[i] - timestamps[i - 1]);
260
+ }
261
+ const actualInterval = intervals.reduce((a, b) => a + b, 0) / intervals.length;
262
+ const drift = actualInterval - targetInterval;
263
+ const fps = 1000 / actualInterval;
264
+ resolve({
265
+ targetInterval,
266
+ actualInterval,
267
+ drift,
268
+ fps,
269
+ });
270
+ }, measureDuration);
271
+ });
272
+ }
273
+ /**
274
+ * Create optimized animation settings for different hardware
275
+ *
276
+ * @param deviceType - Target device type
277
+ * @returns Recommended animation configuration
278
+ *
279
+ * @example
280
+ * ```typescript
281
+ * const config = AnimationUtils.getOptimizedConfig('even-realities-g1');
282
+ * const animation = await AnimationUtils.createBitmapAnimation(
283
+ * session, './frames', 10, config
284
+ * );
285
+ * ```
286
+ */
287
+ static getOptimizedConfig(deviceType) {
288
+ switch (deviceType) {
289
+ case "even-realities-g1":
290
+ return {
291
+ intervalMs: 1650, // Tested optimal timing for Even Realities G1
292
+ repeat: false,
293
+ validateFrames: true,
294
+ loadOptions: {
295
+ validateFrames: true,
296
+ skipMissingFrames: false,
297
+ },
298
+ };
299
+ case "generic":
300
+ default:
301
+ return {
302
+ intervalMs: 1000,
303
+ repeat: false,
304
+ validateFrames: true,
305
+ loadOptions: {
306
+ validateFrames: true,
307
+ skipMissingFrames: false,
308
+ },
309
+ };
310
+ }
311
+ }
312
+ /**
313
+ * Preload and cache animation frames for better performance
314
+ *
315
+ * @param basePath - Directory containing frames
316
+ * @param frameCount - Number of frames to preload
317
+ * @param options - Loading options
318
+ * @returns Promise resolving to cached frame data
319
+ *
320
+ * @example
321
+ * ```typescript
322
+ * // Preload frames
323
+ * const cachedFrames = await AnimationUtils.preloadFrames('./animations', 10);
324
+ *
325
+ * // Use cached frames multiple times
326
+ * const animation1 = AnimationUtils.createBitmapAnimationFromFrames(session, cachedFrames);
327
+ * const animation2 = AnimationUtils.createBitmapAnimationFromFrames(session, cachedFrames);
328
+ * ```
329
+ */
330
+ static async preloadFrames(basePath, frameCount, options = {}) {
331
+ console.log(`📦 Preloading ${frameCount} frames from ${basePath}...`);
332
+ const frames = await bitmap_utils_1.BitmapUtils.loadBmpFrames(basePath, frameCount, {
333
+ validateFrames: true,
334
+ ...options,
335
+ });
336
+ console.log(`✅ Preloaded ${frames.length} frames (${frames.reduce((total, frame) => total + frame.length, 0)} total characters)`);
337
+ return frames;
338
+ }
339
+ }
340
+ exports.AnimationUtils = AnimationUtils;
@@ -0,0 +1,149 @@
1
+ /**
2
+ * 🎨 Bitmap Utilities Module
3
+ *
4
+ * Provides helper functions for working with bitmap images in MentraOS applications.
5
+ * Includes file loading, data validation, and format conversion utilities.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { BitmapUtils } from '@mentra/sdk';
10
+ *
11
+ * // Load a single BMP file
12
+ * const bmpHex = await BitmapUtils.loadBmpAsHex('./my-image.bmp');
13
+ * session.layouts.showBitmapView(bmpHex);
14
+ *
15
+ * // Load multiple animation frames
16
+ * const frames = await BitmapUtils.loadBmpFrames('./animations', 10);
17
+ * session.layouts.showBitmapAnimation(frames, 1500, true);
18
+ * ```
19
+ */
20
+ /**
21
+ * Validation result for bitmap data
22
+ */
23
+ export interface BitmapValidation {
24
+ /** Whether the bitmap data is valid */
25
+ isValid: boolean;
26
+ /** Total byte count of the bitmap */
27
+ byteCount: number;
28
+ /** Number of black (non-FF) pixels found */
29
+ blackPixels: number;
30
+ /** Array of validation error messages */
31
+ errors: string[];
32
+ /** Additional metadata about the bitmap */
33
+ metadata?: {
34
+ /** Expected bitmap dimensions (if detectable) */
35
+ dimensions?: {
36
+ width: number;
37
+ height: number;
38
+ };
39
+ /** Bitmap file format info */
40
+ format?: string;
41
+ };
42
+ }
43
+ /**
44
+ * Options for loading bitmap frames
45
+ */
46
+ export interface LoadFramesOptions {
47
+ /** File name pattern (default: 'animation_10_frame_{i}.bmp') */
48
+ filePattern?: string;
49
+ /** Starting frame number (default: 1) */
50
+ startFrame?: number;
51
+ /** Validate each frame during loading (default: true) */
52
+ validateFrames?: boolean;
53
+ /** Continue loading if a frame is missing (default: false) */
54
+ skipMissingFrames?: boolean;
55
+ }
56
+ /**
57
+ * Utility class for working with bitmap images in MentraOS applications
58
+ */
59
+ export declare class BitmapUtils {
60
+ /**
61
+ * Load a BMP file as hex string from filesystem
62
+ *
63
+ * @param filePath - Path to the BMP file
64
+ * @returns Promise resolving to hex-encoded bitmap data
65
+ * @throws Error if file cannot be read or is not a valid BMP
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * const bmpHex = await BitmapUtils.loadBmpAsHex('./assets/icon.bmp');
70
+ * session.layouts.showBitmapView(bmpHex);
71
+ * ```
72
+ */
73
+ static loadBmpFromFileAsHex(filePath: string): Promise<string>;
74
+ static convert24BitTo1BitBMP(input24BitBmp: Buffer): Promise<Buffer>;
75
+ static loadBmpFromDataAsHex(bmpData: Buffer): Promise<string>;
76
+ /**
77
+ * Load multiple BMP frames as hex array for animations
78
+ *
79
+ * @param basePath - Directory containing the frame files
80
+ * @param frameCount - Number of frames to load
81
+ * @param options - Loading options and configuration
82
+ * @returns Promise resolving to array of hex-encoded bitmap data
83
+ *
84
+ * @example
85
+ * ```typescript
86
+ * // Load 10 frames with default pattern
87
+ * const frames = await BitmapUtils.loadBmpFrames('./animations', 10);
88
+ *
89
+ * // Load with custom pattern
90
+ * const customFrames = await BitmapUtils.loadBmpFrames('./sprites', 8, {
91
+ * filePattern: 'sprite_{i}.bmp',
92
+ * startFrame: 0
93
+ * });
94
+ * ```
95
+ */
96
+ static loadBmpFrames(basePath: string, frameCount: number, options?: LoadFramesOptions): Promise<string[]>;
97
+ /**
98
+ * Validate BMP hex data integrity and extract metadata
99
+ *
100
+ * @param hexString - Hex-encoded bitmap data
101
+ * @returns Validation result with detailed information
102
+ *
103
+ * @example
104
+ * ```typescript
105
+ * const validation = BitmapUtils.validateBmpHex(bmpHex);
106
+ * if (!validation.isValid) {
107
+ * console.error('Invalid bitmap:', validation.errors);
108
+ * } else {
109
+ * console.log(`Valid bitmap: ${validation.blackPixels} black pixels`);
110
+ * }
111
+ * ```
112
+ */
113
+ static validateBmpHex(hexString: string): BitmapValidation;
114
+ /**
115
+ * Convert bitmap data between different formats
116
+ *
117
+ * @param data - Input bitmap data
118
+ * @param fromFormat - Source format ('hex' | 'base64' | 'buffer')
119
+ * @param toFormat - Target format ('hex' | 'base64' | 'buffer')
120
+ * @returns Converted bitmap data
121
+ *
122
+ * @example
123
+ * ```typescript
124
+ * const base64Data = BitmapUtils.convertFormat(hexData, 'hex', 'base64');
125
+ * const bufferData = BitmapUtils.convertFormat(base64Data, 'base64', 'buffer');
126
+ * ```
127
+ */
128
+ static convertFormat(data: string | Buffer, fromFormat: "hex" | "base64" | "buffer", toFormat: "hex" | "base64" | "buffer"): string | Buffer;
129
+ /**
130
+ * Get bitmap information without full validation
131
+ *
132
+ * @param hexString - Hex-encoded bitmap data
133
+ * @returns Basic bitmap information
134
+ *
135
+ * @example
136
+ * ```typescript
137
+ * const info = BitmapUtils.getBitmapInfo(bmpHex);
138
+ * console.log(`Bitmap: ${info.width}x${info.height}, ${info.blackPixels} black pixels`);
139
+ * ```
140
+ */
141
+ static getBitmapInfo(hexString: string): {
142
+ byteCount: number;
143
+ blackPixels: number;
144
+ width?: number;
145
+ height?: number;
146
+ isValidBmp: boolean;
147
+ };
148
+ }
149
+ //# sourceMappingURL=bitmap-utils.d.ts.map