cool-retro-term-renderer 1.0.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.
@@ -0,0 +1,539 @@
1
+ import { Terminal } from '@xterm/xterm';
2
+ import * as THREE from 'three';
3
+
4
+ /**
5
+ * TerminalText - Renders terminal text to a texture with CRT effects
6
+ *
7
+ * This implements the basic text rendering from cool-retro-term
8
+ * similar to how QMLTermWidget renders text.
9
+ *
10
+ * Two-Pass Rendering Architecture (matching QML):
11
+ * ================================================
12
+ * Pass 1 (Static): Renders to staticRenderTarget (frameBuffer equivalent)
13
+ * - Screen curvature
14
+ * - Terminal text sampling
15
+ * - RGB shift (chromatic aberration)
16
+ * - Chroma color conversion
17
+ * - Bloom
18
+ * - Brightness
19
+ *
20
+ * Pass 2 (Dynamic): Reads from staticRenderTarget, renders to screen
21
+ * - Horizontal sync distortion
22
+ * - Jitter
23
+ * - Burn-in (samples from staticRenderTarget, not flickered output)
24
+ * - Static noise
25
+ * - Glowing line
26
+ * - Rasterization
27
+ * - Flickering (applied ONLY at the end)
28
+ * - Ambient light
29
+ *
30
+ * This separation ensures flickering doesn't affect the burn-in source,
31
+ * preventing ghosting when text is static (matching QML behavior).
32
+ */
33
+
34
+ declare class TerminalText {
35
+ mesh: THREE.Mesh;
36
+ private staticMaterial;
37
+ private dynamicMaterial;
38
+ private texture;
39
+ private noiseTexture;
40
+ private canvas;
41
+ private ctx;
42
+ private staticRenderTarget;
43
+ private staticScene;
44
+ private staticCamera;
45
+ private staticMesh;
46
+ private burnInRenderTargets;
47
+ private burnInCurrentIndex;
48
+ private burnInMaterial;
49
+ private burnInScene;
50
+ private burnInCamera;
51
+ private burnInMesh;
52
+ private burnInAmount;
53
+ private lastFrameTime;
54
+ private readonly minBurnInFadeTime;
55
+ private readonly maxBurnInFadeTime;
56
+ private text;
57
+ private fontColor;
58
+ private backgroundColor;
59
+ private charWidth;
60
+ private charHeight;
61
+ private cols;
62
+ private rows;
63
+ private fontLoaded;
64
+ private cursorCol;
65
+ private cursorRow;
66
+ private cursorVisible;
67
+ private cursorBlinking;
68
+ private cursorBlinkState;
69
+ private cursorBlinkInterval;
70
+ private readonly CURSOR_BLINK_RATE;
71
+ private selectionStart;
72
+ private selectionEnd;
73
+ private selectionViewportY;
74
+ private screenScaling;
75
+ private totalFontScaling;
76
+ private totalMargin;
77
+ private windowScaling;
78
+ private devicePixelRatio;
79
+ private logicalWidth;
80
+ private logicalHeight;
81
+ private onGridSizeChangeCallback;
82
+ private videoElement;
83
+ private videoTexture;
84
+ private isPlayingVideo;
85
+ private originalTexture;
86
+ constructor(width: number, height: number);
87
+ /**
88
+ * Load the Terminus font from embedded base64
89
+ */
90
+ private loadFont;
91
+ /**
92
+ * Calculate font metrics based on configuration
93
+ */
94
+ private calculateFontMetrics;
95
+ /**
96
+ * Set the terminal text content
97
+ */
98
+ setText(text: string): void;
99
+ /**
100
+ * Set the cursor position
101
+ */
102
+ setCursorPosition(col: number, row: number): void;
103
+ /**
104
+ * Set cursor visibility
105
+ */
106
+ setCursorVisible(visible: boolean): void;
107
+ /**
108
+ * Enable or disable cursor blinking
109
+ */
110
+ setCursorBlinking(blinking: boolean): void;
111
+ private startCursorBlink;
112
+ private stopCursorBlink;
113
+ /**
114
+ * Reset cursor blink state
115
+ */
116
+ resetCursorBlink(): void;
117
+ /**
118
+ * Set text selection range (in absolute buffer coordinates)
119
+ */
120
+ setSelection(start: {
121
+ col: number;
122
+ row: number;
123
+ } | null, end: {
124
+ col: number;
125
+ row: number;
126
+ } | null, viewportY?: number): void;
127
+ /**
128
+ * Update the viewport offset for selection rendering
129
+ */
130
+ updateSelectionViewport(viewportY: number): void;
131
+ /**
132
+ * Clear the current selection
133
+ */
134
+ clearSelection(): void;
135
+ /**
136
+ * Get the current selection range
137
+ */
138
+ getSelection(): {
139
+ start: {
140
+ col: number;
141
+ row: number;
142
+ } | null;
143
+ end: {
144
+ col: number;
145
+ row: number;
146
+ } | null;
147
+ };
148
+ /**
149
+ * Convert pixel coordinates to grid position
150
+ */
151
+ pixelToGrid(pixelX: number, pixelY: number): {
152
+ col: number;
153
+ row: number;
154
+ };
155
+ private isCellSelected;
156
+ private render;
157
+ /**
158
+ * Update the terminal size
159
+ */
160
+ updateSize(width: number, height: number): void;
161
+ /**
162
+ * Set the font color
163
+ */
164
+ setFontColor(hex: string): void;
165
+ /**
166
+ * Set the background color
167
+ */
168
+ setBackgroundColor(hex: string): void;
169
+ /**
170
+ * Set the screen curvature amount
171
+ */
172
+ setScreenCurvature(curvature: number): void;
173
+ /**
174
+ * Set the RGB shift amount (chromatic aberration)
175
+ */
176
+ setRgbShift(amount: number): void;
177
+ /**
178
+ * Set the bloom intensity
179
+ */
180
+ setBloom(intensity: number): void;
181
+ /**
182
+ * Set the brightness level
183
+ */
184
+ setBrightness(level: number): void;
185
+ /**
186
+ * Set the ambient light glow
187
+ */
188
+ setAmbientLight(amount: number): void;
189
+ /**
190
+ * Set the chroma color amount
191
+ */
192
+ setChromaColor(amount: number): void;
193
+ /**
194
+ * Set the flickering intensity
195
+ */
196
+ setFlickering(amount: number): void;
197
+ /**
198
+ * Set the horizontal sync distortion amount
199
+ */
200
+ setHorizontalSync(amount: number): void;
201
+ /**
202
+ * Set the jitter amount (random pixel displacement)
203
+ */
204
+ setJitter(amount: number): void;
205
+ /**
206
+ * Set the static noise intensity
207
+ */
208
+ setStaticNoise(amount: number): void;
209
+ /**
210
+ * Set the glowing line (scanning beam) intensity
211
+ */
212
+ setGlowingLine(amount: number): void;
213
+ /**
214
+ * Set the burn-in (phosphor persistence) intensity
215
+ */
216
+ setBurnIn(amount: number): void;
217
+ private calculateBurnInFadeTime;
218
+ /**
219
+ * Set the rasterization mode
220
+ */
221
+ setRasterizationMode(mode: number): void;
222
+ /**
223
+ * Set the rasterization intensity
224
+ */
225
+ setRasterizationIntensity(intensity: number): void;
226
+ /**
227
+ * Set the virtual resolution (for rasterization patterns)
228
+ */
229
+ setVirtualResolution(cols: number, rows: number): void;
230
+ /**
231
+ * Update the time uniform for animated effects
232
+ */
233
+ updateTime(time: number): void;
234
+ /**
235
+ * Render the static pass and burn-in accumulation to render targets
236
+ */
237
+ renderStaticPass(renderer: THREE.WebGLRenderer): void;
238
+ /**
239
+ * Play a video with CRT effects
240
+ */
241
+ playVideo(videoUrl: string): Promise<void>;
242
+ /**
243
+ * Stop video playback and restore terminal display
244
+ */
245
+ stopVideo(): void;
246
+ /**
247
+ * Check if video is currently playing
248
+ */
249
+ isVideoPlaying(): boolean;
250
+ /**
251
+ * Get the video element (for external control)
252
+ */
253
+ getVideoElement(): HTMLVideoElement | null;
254
+ /**
255
+ * Dispose of resources
256
+ */
257
+ dispose(): void;
258
+ /**
259
+ * Get the current cursor position
260
+ */
261
+ getCursorPosition(): {
262
+ col: number;
263
+ row: number;
264
+ };
265
+ /**
266
+ * Get the number of columns in the terminal grid
267
+ */
268
+ getCols(): number;
269
+ /**
270
+ * Get the number of rows in the terminal grid
271
+ */
272
+ getRows(): number;
273
+ /**
274
+ * Get the terminal grid dimensions
275
+ */
276
+ getGridSize(): {
277
+ cols: number;
278
+ rows: number;
279
+ };
280
+ /**
281
+ * Set a callback to be notified when grid size changes
282
+ */
283
+ onGridSizeChange(callback: (cols: number, rows: number) => void): void;
284
+ }
285
+
286
+ /**
287
+ * CRT Terminal Settings
288
+ * Configuration options for the CRT terminal renderer
289
+ */
290
+ interface CRTTerminalSettings {
291
+ /**
292
+ * The container element to render into
293
+ */
294
+ container: HTMLElement;
295
+ /**
296
+ * Font color in hex format (default: "#0ccc68" - green)
297
+ */
298
+ fontColor?: string;
299
+ /**
300
+ * Background color in hex format (default: "#000000" - black)
301
+ */
302
+ backgroundColor?: string;
303
+ /**
304
+ * Screen curvature amount, 0-1 (default: 0.3)
305
+ */
306
+ screenCurvature?: number;
307
+ /**
308
+ * RGB shift/chromatic aberration amount, 0-0.01 (default: 0)
309
+ */
310
+ rgbShift?: number;
311
+ /**
312
+ * Bloom intensity, 0-1 (default: 0.5538)
313
+ */
314
+ bloom?: number;
315
+ /**
316
+ * Brightness level, 0-1 (default: 0.5)
317
+ */
318
+ brightness?: number;
319
+ /**
320
+ * Ambient light glow, 0-1 (default: 0.2)
321
+ */
322
+ ambientLight?: number;
323
+ /**
324
+ * Chroma color amount (0 = monochrome, 1 = full color) (default: 0)
325
+ */
326
+ chromaColor?: number;
327
+ /**
328
+ * Flickering intensity, 0-1 (default: 0.1)
329
+ */
330
+ flickering?: number;
331
+ /**
332
+ * Horizontal sync distortion, 0-1 (default: 0.08)
333
+ */
334
+ horizontalSync?: number;
335
+ /**
336
+ * Jitter amount (random pixel displacement), 0-1 (default: 0.1997)
337
+ */
338
+ jitter?: number;
339
+ /**
340
+ * Static noise intensity, 0-1 (default: 0.1198)
341
+ */
342
+ staticNoise?: number;
343
+ /**
344
+ * Glowing line (scanning beam) intensity, 0-1 (default: 0.2)
345
+ */
346
+ glowingLine?: number;
347
+ /**
348
+ * Burn-in (phosphor persistence) intensity, 0-1 (default: 0.2517)
349
+ */
350
+ burnIn?: number;
351
+ /**
352
+ * Rasterization mode: 0=none, 1=scanline, 2=pixel, 3=subpixel (default: 1)
353
+ */
354
+ rasterizationMode?: number;
355
+ /**
356
+ * Rasterization intensity, 0-1 (default: 0.5)
357
+ */
358
+ rasterizationIntensity?: number;
359
+ }
360
+ /**
361
+ * Default settings for CRT terminal
362
+ */
363
+ declare const DEFAULT_SETTINGS: Required<Omit<CRTTerminalSettings, "container">>;
364
+
365
+ /**
366
+ * CRTTerminal - Main class for cool-retro-term-webgl
367
+ *
368
+ * This class encapsulates the Three.js scene, shaders, and rendering pipeline
369
+ * for creating a CRT terminal effect. It accepts an XTerm.js terminal instance
370
+ * and renders its output with authentic CRT visual effects.
371
+ *
372
+ * @example
373
+ * ```typescript
374
+ * import { CRTTerminal } from 'cool-retro-term-webgl';
375
+ * import { Terminal } from '@xterm/xterm';
376
+ *
377
+ * const container = document.getElementById('terminal');
378
+ * const crt = new CRTTerminal({ container });
379
+ *
380
+ * const xterm = new Terminal();
381
+ * crt.attachXTerm(xterm);
382
+ *
383
+ * xterm.write('Hello, World!');
384
+ * ```
385
+ */
386
+
387
+ declare class CRTTerminal {
388
+ private container;
389
+ private scene;
390
+ private camera;
391
+ private renderer;
392
+ private terminalText;
393
+ private terminalFrame;
394
+ private animationFrameId;
395
+ private connector;
396
+ private settings;
397
+ private disposed;
398
+ constructor(options: CRTTerminalSettings);
399
+ /**
400
+ * Apply the current settings to the terminal renderer
401
+ *
402
+ * Note: fontColor and backgroundColor are only applied when explicitly
403
+ * set by the user (not matching defaults). This preserves TerminalText's
404
+ * internally calculated "mixed" background color based on contrast settings,
405
+ * which creates the authentic CRT look with subtle color tinting.
406
+ */
407
+ private applySettings;
408
+ /**
409
+ * Handle window resize events
410
+ */
411
+ private handleResize;
412
+ /**
413
+ * Animation loop
414
+ */
415
+ private animate;
416
+ /**
417
+ * Attach an XTerm.js terminal instance to this CRT renderer
418
+ *
419
+ * This creates a connector that syncs the XTerm buffer to the CRT display.
420
+ * The XTerm terminal should be fully configured before attaching.
421
+ *
422
+ * @param xterm The XTerm.js Terminal instance to attach
423
+ */
424
+ attachXTerm(xterm: Terminal): void;
425
+ /**
426
+ * Detach the currently attached XTerm instance
427
+ */
428
+ detachXTerm(): void;
429
+ /**
430
+ * Get the current grid size (columns and rows)
431
+ */
432
+ getGridSize(): {
433
+ cols: number;
434
+ rows: number;
435
+ };
436
+ /**
437
+ * Get the TerminalText renderer (for advanced usage)
438
+ */
439
+ getTerminalText(): TerminalText;
440
+ /**
441
+ * Get the Three.js renderer (for advanced usage)
442
+ */
443
+ getRenderer(): THREE.WebGLRenderer;
444
+ /**
445
+ * Get the Three.js scene (for advanced usage)
446
+ */
447
+ getScene(): THREE.Scene;
448
+ /**
449
+ * Get the Three.js camera (for advanced usage)
450
+ */
451
+ getCamera(): THREE.OrthographicCamera;
452
+ /**
453
+ * Focus the attached XTerm terminal for keyboard input
454
+ */
455
+ focus(): void;
456
+ /**
457
+ * Dispose of all resources
458
+ */
459
+ dispose(): void;
460
+ }
461
+
462
+ /**
463
+ * TerminalFrame - Three.js implementation of the CRT frame
464
+ * Renders the CRT bezel/frame overlay with vignette and shadow effects
465
+ */
466
+
467
+ declare class TerminalFrame {
468
+ mesh: THREE.Mesh;
469
+ private material;
470
+ private uniforms;
471
+ constructor(width: number, height: number);
472
+ /**
473
+ * Update the frame size (call on window resize)
474
+ */
475
+ updateSize(width: number, height: number): void;
476
+ /**
477
+ * Set the screen curvature amount
478
+ */
479
+ setScreenCurvature(curvature: number): void;
480
+ /**
481
+ * Dispose of resources
482
+ */
483
+ dispose(): void;
484
+ }
485
+
486
+ /**
487
+ * XTermConnector - Minimal bridge between xterm.js and TerminalText renderer
488
+ *
489
+ * This connector provides a simple interface to sync XTerm.js buffer content,
490
+ * cursor position, and selection to the CRT renderer. It does NOT handle
491
+ * keyboard input, shell emulation, or any application-specific logic.
492
+ *
493
+ * Users are expected to handle their own XTerm input/output logic.
494
+ */
495
+
496
+ declare class XTermConnector {
497
+ private xterm;
498
+ private terminalText;
499
+ private disposed;
500
+ private isSelecting;
501
+ private selectionStart;
502
+ constructor(xterm: Terminal, terminalText: TerminalText);
503
+ /**
504
+ * Sync the XTerm buffer content to the TerminalText renderer
505
+ */
506
+ syncBuffer(): void;
507
+ /**
508
+ * Sync the cursor position to the TerminalText renderer
509
+ */
510
+ syncCursor(): void;
511
+ /**
512
+ * Manually trigger a full sync (buffer + cursor)
513
+ * Call this after writing to XTerm or on resize
514
+ */
515
+ sync(): void;
516
+ /**
517
+ * Setup mouse selection handlers on a container element
518
+ * This enables text selection in the terminal
519
+ */
520
+ setupMouseSelection(container: HTMLElement): void;
521
+ /**
522
+ * Copy current selection to clipboard
523
+ */
524
+ private copySelectionToClipboard;
525
+ /**
526
+ * Get the underlying XTerm instance
527
+ */
528
+ getXTerm(): Terminal;
529
+ /**
530
+ * Get the TerminalText renderer
531
+ */
532
+ getTerminalText(): TerminalText;
533
+ /**
534
+ * Dispose of resources and event listeners
535
+ */
536
+ dispose(): void;
537
+ }
538
+
539
+ export { CRTTerminal, type CRTTerminalSettings, DEFAULT_SETTINGS, TerminalFrame, TerminalText, XTermConnector };