@h-rig/cli 0.0.6-alpha.84 → 0.0.6-alpha.86
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.
- package/dist/bin/rig.js +27 -1063
- package/dist/src/app-opentui/bootstrap.js +27 -1063
- package/dist/src/app-opentui/index.js +7 -1024
- package/dist/src/app-opentui/react/App.js +20 -1032
- package/dist/src/app-opentui/react/Backdrop.js +20 -1032
- package/dist/src/app-opentui/react/ChromeHost.js +0 -1039
- package/dist/src/app-opentui/react/launch.js +20 -1032
- package/dist/src/app-opentui/render/constants.d.ts +0 -1
- package/dist/src/app-opentui/render/constants.js +0 -2
- package/dist/src/app-opentui/render/graphics.js +2 -9
- package/dist/src/app-opentui/runtime.js +8 -1025
- package/package.json +8 -8
- package/dist/src/app-opentui/render/image-visual-layer-worker.d.ts +0 -1
- package/dist/src/app-opentui/render/image-visual-layer-worker.js +0 -1084
- package/dist/src/app-opentui/render/image-visual-layer.d.ts +0 -109
- package/dist/src/app-opentui/render/image-visual-layer.js +0 -1068
- package/dist/src/app-opentui/terminal-capabilities.d.ts +0 -7
- package/dist/src/app-opentui/terminal-capabilities.js +0 -15
package/dist/bin/rig.js
CHANGED
|
@@ -24321,22 +24321,9 @@ function panelContentRect(layout, panel) {
|
|
|
24321
24321
|
const contentWidth = Math.max(1, width - paddingX * 2 - 1);
|
|
24322
24322
|
return { left, top, width, height, paddingX, paddingY, contentWidth };
|
|
24323
24323
|
}
|
|
24324
|
-
function panelPixelPlacement(layout, panel, size, minPixels = 8) {
|
|
24325
|
-
const cellW = size.width / layout.width;
|
|
24326
|
-
const cellH = size.height / layout.height;
|
|
24327
|
-
const leftCells = layout.centerLeft + (panel.left ?? 0);
|
|
24328
|
-
const topCells = layout.centerTop + panel.top;
|
|
24329
|
-
const widthCells = panel.width ?? layout.centerWidth;
|
|
24330
|
-
const heightCells = panel.height;
|
|
24331
|
-
const left = Math.round(leftCells * cellW);
|
|
24332
|
-
const top = Math.round(topCells * cellH);
|
|
24333
|
-
const width = Math.round(widthCells * cellW);
|
|
24334
|
-
const height = Math.round(heightCells * cellH);
|
|
24335
|
-
return width > minPixels && height > minPixels ? { left, top, width, height, leftCells, topCells, widthCells, heightCells } : null;
|
|
24336
|
-
}
|
|
24337
24324
|
|
|
24338
24325
|
// packages/cli/src/app-opentui/render/constants.ts
|
|
24339
|
-
var LCG_MULTIPLIER = 1664525, LCG_INCREMENT = 1013904223, LCG_DIVISOR = 4294967295, PACKET_CYAN_PROBABILITY = 0.22, LANE_INTERP_STEPS = 32, LANE_LEN_BASE = 0.32, LANE_LEN_SPREAD = 0.42, LANE_CURVE_RANGE = 0.7, PACKET_SPEED_BASE = 0.003, PACKET_SPEED_SPREAD = 0.009, DISPATCH_LANES_COMPACT = 7, DISPATCH_LANES_WIDE = 12, DISPATCH_PACKETS_COMPACT = 70, DISPATCH_PACKETS_WIDE = 150, CARRIER_NODES_COMPACT = 5, CARRIER_NODES_WIDE = 7, LOOP_GATES_COMPACT = 4, LOOP_GATES_WIDE = 5, DISPATCH_DRONES_COMPACT = 4, DISPATCH_DRONES_WIDE = 8, CORE_DISPATCH_X = 0.3, CORE_DISPATCH_Y = 0.45, CORE_CARRIER_X = 0.5, CORE_CARRIER_Y = 0.54, CORE_LOOP_X = 0.09, CORE_LOOP_Y = 0.56, RAIL_YS_LOOP, RAIL_YS_CARRIER, RAIL_YS_DISPATCH, GLOW_FALLOFF_EXP_ASCII = 2.2
|
|
24326
|
+
var LCG_MULTIPLIER = 1664525, LCG_INCREMENT = 1013904223, LCG_DIVISOR = 4294967295, PACKET_CYAN_PROBABILITY = 0.22, LANE_INTERP_STEPS = 32, LANE_LEN_BASE = 0.32, LANE_LEN_SPREAD = 0.42, LANE_CURVE_RANGE = 0.7, PACKET_SPEED_BASE = 0.003, PACKET_SPEED_SPREAD = 0.009, DISPATCH_LANES_COMPACT = 7, DISPATCH_LANES_WIDE = 12, DISPATCH_PACKETS_COMPACT = 70, DISPATCH_PACKETS_WIDE = 150, CARRIER_NODES_COMPACT = 5, CARRIER_NODES_WIDE = 7, LOOP_GATES_COMPACT = 4, LOOP_GATES_WIDE = 5, DISPATCH_DRONES_COMPACT = 4, DISPATCH_DRONES_WIDE = 8, CORE_DISPATCH_X = 0.3, CORE_DISPATCH_Y = 0.45, CORE_CARRIER_X = 0.5, CORE_CARRIER_Y = 0.54, CORE_LOOP_X = 0.09, CORE_LOOP_Y = 0.56, RAIL_YS_LOOP, RAIL_YS_CARRIER, RAIL_YS_DISPATCH, GLOW_FALLOFF_EXP_ASCII = 2.2;
|
|
24340
24327
|
var init_constants = __esm(() => {
|
|
24341
24328
|
RAIL_YS_LOOP = [0.18, 0.5, 0.82];
|
|
24342
24329
|
RAIL_YS_CARRIER = [0.24, 0.54, 0.82];
|
|
@@ -24755,27 +24742,20 @@ function writeCell(layer, x, y, char, fg2, bg) {
|
|
|
24755
24742
|
function drawFullCell(layer, x, y, bg) {
|
|
24756
24743
|
writeCell(layer, x, y, " ", TRANSPARENT, bg);
|
|
24757
24744
|
}
|
|
24758
|
-
function
|
|
24759
|
-
writeCell(layer, x, y, char, fg2, BACKDROP);
|
|
24760
|
-
}
|
|
24761
|
-
function drawRoundedFill(layer, left, top, right, bottom, dividerY) {
|
|
24745
|
+
function drawPanelFill(layer, left, top, right, bottom, dividerY) {
|
|
24762
24746
|
const bgForY = (y) => y < dividerY ? PANEL_HEADER_BG : PANEL_BG;
|
|
24763
24747
|
for (let y = top;y <= bottom; y += 1) {
|
|
24764
24748
|
const bg = bgForY(y);
|
|
24765
24749
|
for (let x = left;x <= right; x += 1)
|
|
24766
24750
|
drawFullCell(layer, x, y, bg);
|
|
24767
24751
|
}
|
|
24768
|
-
drawCornerCut(layer, left, top, "\u2597", PANEL_HEADER_BG);
|
|
24769
|
-
drawCornerCut(layer, right, top, "\u2596", PANEL_HEADER_BG);
|
|
24770
|
-
drawCornerCut(layer, left, bottom, "\u259D", PANEL_BG);
|
|
24771
|
-
drawCornerCut(layer, right, bottom, "\u2598", PANEL_BG);
|
|
24772
24752
|
}
|
|
24773
24753
|
function drawAdTerminalPanel(layer, layout, panel) {
|
|
24774
24754
|
const rect = panelCellRect(layout, panel);
|
|
24775
24755
|
if (!rect)
|
|
24776
24756
|
return;
|
|
24777
24757
|
const { left, top, width, right, bottom, headerHeight, dividerY } = rect;
|
|
24778
|
-
|
|
24758
|
+
drawPanelFill(layer, left, top, right, bottom, dividerY);
|
|
24779
24759
|
if (dividerY > top && dividerY < bottom) {
|
|
24780
24760
|
for (let x = left + 2;x < right - 1; x += 1) {
|
|
24781
24761
|
writeCell(layer, x, dividerY, "\u2500", PANEL_LINE_DIM, PANEL_BG);
|
|
@@ -24883,963 +24863,6 @@ var init_graphics = __esm(() => {
|
|
|
24883
24863
|
];
|
|
24884
24864
|
});
|
|
24885
24865
|
|
|
24886
|
-
// packages/cli/src/app-opentui/terminal-capabilities.ts
|
|
24887
|
-
import { getCapabilities } from "@earendil-works/pi-tui";
|
|
24888
|
-
function getRigTerminalCapabilities() {
|
|
24889
|
-
const imageProtocol = getCapabilities().images;
|
|
24890
|
-
const supportsKittyImages = imageProtocol === "kitty";
|
|
24891
|
-
return {
|
|
24892
|
-
imageProtocol,
|
|
24893
|
-
supportsKittyImages,
|
|
24894
|
-
visualMode: supportsKittyImages ? "kitty-images" : "framebuffer-fallback"
|
|
24895
|
-
};
|
|
24896
|
-
}
|
|
24897
|
-
var init_terminal_capabilities = () => {};
|
|
24898
|
-
|
|
24899
|
-
// packages/cli/src/app-opentui/render/image-visual-layer.ts
|
|
24900
|
-
import { Worker } from "worker_threads";
|
|
24901
|
-
import { deflateSync } from "zlib";
|
|
24902
|
-
import { allocateImageId, deleteKittyImage } from "@earendil-works/pi-tui";
|
|
24903
|
-
function loadBucket(load) {
|
|
24904
|
-
if (!Number.isFinite(load ?? NaN))
|
|
24905
|
-
return 0;
|
|
24906
|
-
return Math.max(0, Math.min(LOAD_BUCKETS, Math.round((load ?? 0) * LOAD_BUCKETS)));
|
|
24907
|
-
}
|
|
24908
|
-
function imageTransport() {
|
|
24909
|
-
const forced = process.env.RIG_OPENTUI_IMAGE_TRANSPORT;
|
|
24910
|
-
if (forced === "rgba-zlib")
|
|
24911
|
-
return "rgba-zlib";
|
|
24912
|
-
return "png";
|
|
24913
|
-
}
|
|
24914
|
-
function imageResolutionScale() {
|
|
24915
|
-
const raw = Number.parseFloat(process.env.RIG_OPENTUI_IMAGE_SCALE ?? "");
|
|
24916
|
-
if (Number.isFinite(raw) && raw > 0)
|
|
24917
|
-
return Math.max(0.25, Math.min(1, raw));
|
|
24918
|
-
return DEFAULT_IMAGE_RESOLUTION_SCALE;
|
|
24919
|
-
}
|
|
24920
|
-
function rgbaWord(color) {
|
|
24921
|
-
return (color[3] << 24 | color[2] << 16 | color[1] << 8 | color[0]) >>> 0;
|
|
24922
|
-
}
|
|
24923
|
-
function fillRgba(data, color, word = rgbaWord(color)) {
|
|
24924
|
-
if (data.byteOffset % 4 === 0 && data.byteLength % 4 === 0) {
|
|
24925
|
-
new Uint32Array(data.buffer, data.byteOffset, data.byteLength / 4).fill(word);
|
|
24926
|
-
return;
|
|
24927
|
-
}
|
|
24928
|
-
for (let i = 0;i < data.length; i += 4) {
|
|
24929
|
-
data[i] = color[0];
|
|
24930
|
-
data[i + 1] = color[1];
|
|
24931
|
-
data[i + 2] = color[2];
|
|
24932
|
-
data[i + 3] = color[3];
|
|
24933
|
-
}
|
|
24934
|
-
}
|
|
24935
|
-
function sceneStaticTick(scene) {
|
|
24936
|
-
let hash = 0;
|
|
24937
|
-
for (let index = 0;index < scene.length; index += 1)
|
|
24938
|
-
hash = hash * 33 + scene.charCodeAt(index) >>> 0;
|
|
24939
|
-
return 11 + hash % 97;
|
|
24940
|
-
}
|
|
24941
|
-
function charColor(char, row, totalRows) {
|
|
24942
|
-
if (char === "@" || char === "$" || char === "o")
|
|
24943
|
-
return LIME;
|
|
24944
|
-
if (char === "%" || char === "!" || char === "/" || char === "\\" || char === "|")
|
|
24945
|
-
return CYAN;
|
|
24946
|
-
if (char === "." || char === "'" || char === "_" || row < 3 || row > totalRows - 4)
|
|
24947
|
-
return INK_DIM;
|
|
24948
|
-
if (char === "-" || char === "=" || char === "(" || char === ")")
|
|
24949
|
-
return LIME_DIM;
|
|
24950
|
-
return MAGENTA;
|
|
24951
|
-
}
|
|
24952
|
-
function fillRectAlpha(data, width, height, left, top, rectWidth, rectHeight, color, alpha) {
|
|
24953
|
-
const x0 = Math.max(0, Math.floor(left));
|
|
24954
|
-
const y0 = Math.max(0, Math.floor(top));
|
|
24955
|
-
const x1 = Math.min(width, Math.ceil(left + rectWidth));
|
|
24956
|
-
const y1 = Math.min(height, Math.ceil(top + rectHeight));
|
|
24957
|
-
for (let y = y0;y < y1; y += 1) {
|
|
24958
|
-
for (let x = x0;x < x1; x += 1)
|
|
24959
|
-
blendOver(data, (y * width + x) * 4, color, alpha);
|
|
24960
|
-
}
|
|
24961
|
-
}
|
|
24962
|
-
function drawAsciiGlyph(data, width, height, x, y, cellWidth, cellHeight, char, color, alpha) {
|
|
24963
|
-
const pattern = ASCII_GLYPHS[char] ?? ASCII_GLYPHS["*"];
|
|
24964
|
-
const glyphWidth = Math.max(1, cellWidth * 0.56);
|
|
24965
|
-
const glyphHeight = Math.max(1, cellHeight * 0.7);
|
|
24966
|
-
const originX = x + (cellWidth - glyphWidth) * 0.5;
|
|
24967
|
-
const originY = y + (cellHeight - glyphHeight) * 0.5;
|
|
24968
|
-
const pixelWidth = Math.max(1, glyphWidth / pattern[0].length);
|
|
24969
|
-
const pixelHeight = Math.max(1, glyphHeight / pattern.length);
|
|
24970
|
-
for (let row = 0;row < pattern.length; row += 1) {
|
|
24971
|
-
const bits = pattern[row];
|
|
24972
|
-
for (let col = 0;col < bits.length; col += 1) {
|
|
24973
|
-
if (bits[col] !== "1")
|
|
24974
|
-
continue;
|
|
24975
|
-
fillRectAlpha(data, width, height, originX + col * pixelWidth, originY + row * pixelHeight, pixelWidth * 0.72, pixelHeight * 0.72, color, alpha);
|
|
24976
|
-
}
|
|
24977
|
-
}
|
|
24978
|
-
}
|
|
24979
|
-
function drawStaticAsciiFleetBackground(data, width, height, scene, layout, load, activeRuns) {
|
|
24980
|
-
const rows = fleetRows(sceneStaticTick(scene), { animate: true });
|
|
24981
|
-
const cellWidth = width / Math.max(1, layout.width);
|
|
24982
|
-
const cellHeight = height / Math.max(1, layout.height);
|
|
24983
|
-
const sideBySide = layout.width >= FLEET_GRID_WIDTH * 1.9;
|
|
24984
|
-
const leftCells = sideBySide ? Math.max(1, Math.floor(layout.width * 0.3 - FLEET_GRID_WIDTH / 2)) : Math.floor((layout.width - FLEET_GRID_WIDTH) / 2);
|
|
24985
|
-
const topCells = Math.floor((layout.height - FLEET_GRID_HEIGHT) / 2);
|
|
24986
|
-
const fleetLeft = leftCells * cellWidth;
|
|
24987
|
-
const fleetTop = topCells * cellHeight;
|
|
24988
|
-
drawGlow2(data, width, height, width * 0.5, height * 0.5, Math.min(width, height) * 0.4, LIME, 0.022 + load * 0.03);
|
|
24989
|
-
drawGlow2(data, width, height, width * 0.18, height * 0.22, Math.min(width, height) * 0.28, CYAN, 0.018 + load * 0.012);
|
|
24990
|
-
drawGlow2(data, width, height, width * 0.82, height * 0.78, Math.min(width, height) * 0.22, MAGENTA, 0.012 + load * 0.008);
|
|
24991
|
-
let droneTotal = 0;
|
|
24992
|
-
for (const line2 of rows)
|
|
24993
|
-
for (const char of line2)
|
|
24994
|
-
if (char === "@" || char === "$" || char === "%")
|
|
24995
|
-
droneTotal += 1;
|
|
24996
|
-
const litTarget = Math.max(0, Math.min(droneTotal, activeRuns));
|
|
24997
|
-
let droneIndex = 0;
|
|
24998
|
-
for (let row = 0;row < rows.length; row += 1) {
|
|
24999
|
-
const line2 = rows[row];
|
|
25000
|
-
for (let col = 0;col < line2.length; col += 1) {
|
|
25001
|
-
const char = line2[col];
|
|
25002
|
-
if (char === " ")
|
|
25003
|
-
continue;
|
|
25004
|
-
const x = fleetLeft + col * cellWidth;
|
|
25005
|
-
const y = fleetTop + row * cellHeight;
|
|
25006
|
-
const color = charColor(char, row, rows.length);
|
|
25007
|
-
const isDrone = char === "@" || char === "$" || char === "%";
|
|
25008
|
-
const lit = isDrone && droneIndex < litTarget;
|
|
25009
|
-
drawAsciiGlyph(data, width, height, x + cellWidth * 0.07, y + cellHeight * 0.05, cellWidth, cellHeight, char, color, lit ? 0.72 : 0.46);
|
|
25010
|
-
if (isDrone) {
|
|
25011
|
-
droneIndex += 1;
|
|
25012
|
-
drawGlow2(data, width, height, x + cellWidth * 0.5, y + cellHeight * 0.5, Math.max(cellWidth, cellHeight) * 0.95, color, lit ? 0.044 : 0.014);
|
|
25013
|
-
}
|
|
25014
|
-
}
|
|
25015
|
-
}
|
|
25016
|
-
}
|
|
25017
|
-
function applyStaticAtmosphere(data, width, height, load) {
|
|
25018
|
-
const cx = width * 0.5;
|
|
25019
|
-
const cy = height * 0.42;
|
|
25020
|
-
const radius = Math.max(width, height) * 0.78;
|
|
25021
|
-
const minVignette = 0.1 - load * 0.02;
|
|
25022
|
-
for (let y = 0;y < height; y += 1) {
|
|
25023
|
-
for (let x = 0;x < width; x += 1) {
|
|
25024
|
-
const distance = Math.hypot(x - cx, y - cy) / radius;
|
|
25025
|
-
const alpha = Math.max(minVignette, Math.min(0.82, 0.12 + Math.pow(distance, 1.65) * 0.62));
|
|
25026
|
-
blendOver(data, (y * width + x) * 4, BG, alpha);
|
|
25027
|
-
}
|
|
25028
|
-
}
|
|
25029
|
-
drawGlow2(data, width, height, width * 0.82, height * 0.04, Math.min(width, height) * 0.2, LIME, 0.024 + load * 0.012);
|
|
25030
|
-
drawGlow2(data, width, height, width * 0.12, height * 0.18, Math.min(width, height) * 0.16, CYAN, 0.018 + load * 0.008);
|
|
25031
|
-
}
|
|
25032
|
-
function makeCrcTable() {
|
|
25033
|
-
const table = new Uint32Array(256);
|
|
25034
|
-
for (let n = 0;n < 256; n += 1) {
|
|
25035
|
-
let c = n;
|
|
25036
|
-
for (let k = 0;k < 8; k += 1)
|
|
25037
|
-
c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
25038
|
-
table[n] = c >>> 0;
|
|
25039
|
-
}
|
|
25040
|
-
return table;
|
|
25041
|
-
}
|
|
25042
|
-
function crc32(bytes) {
|
|
25043
|
-
let c = 4294967295;
|
|
25044
|
-
for (let i = 0;i < bytes.length; i += 1)
|
|
25045
|
-
c = CRC_TABLE[(c ^ bytes[i]) & 255] ^ c >>> 8;
|
|
25046
|
-
return (c ^ 4294967295) >>> 0;
|
|
25047
|
-
}
|
|
25048
|
-
function chunk2(type, data) {
|
|
25049
|
-
const out = new Uint8Array(12 + data.length);
|
|
25050
|
-
const view = new DataView(out.buffer);
|
|
25051
|
-
view.setUint32(0, data.length);
|
|
25052
|
-
out[4] = type.charCodeAt(0);
|
|
25053
|
-
out[5] = type.charCodeAt(1);
|
|
25054
|
-
out[6] = type.charCodeAt(2);
|
|
25055
|
-
out[7] = type.charCodeAt(3);
|
|
25056
|
-
out.set(data, 8);
|
|
25057
|
-
view.setUint32(8 + data.length, crc32(out.subarray(4, 8 + data.length)));
|
|
25058
|
-
return out;
|
|
25059
|
-
}
|
|
25060
|
-
function encodePng(width, height, rgba) {
|
|
25061
|
-
const ihdr = new Uint8Array(13);
|
|
25062
|
-
const ihdrView = new DataView(ihdr.buffer);
|
|
25063
|
-
ihdrView.setUint32(0, width);
|
|
25064
|
-
ihdrView.setUint32(4, height);
|
|
25065
|
-
ihdr[8] = 8;
|
|
25066
|
-
ihdr[9] = 6;
|
|
25067
|
-
ihdr[10] = 0;
|
|
25068
|
-
ihdr[11] = 0;
|
|
25069
|
-
ihdr[12] = 0;
|
|
25070
|
-
const stride = width * 4;
|
|
25071
|
-
const raw = new Uint8Array((stride + 1) * height);
|
|
25072
|
-
for (let y = 0;y < height; y += 1) {
|
|
25073
|
-
const rawOffset = y * (stride + 1);
|
|
25074
|
-
raw[rawOffset] = 0;
|
|
25075
|
-
raw.set(rgba.subarray(y * stride, y * stride + stride), rawOffset + 1);
|
|
25076
|
-
}
|
|
25077
|
-
const compressed = deflateSync(raw, { level: ZLIB_LEVEL });
|
|
25078
|
-
return Buffer.concat([
|
|
25079
|
-
Buffer.from(PNG_SIGNATURE),
|
|
25080
|
-
Buffer.from(chunk2("IHDR", ihdr)),
|
|
25081
|
-
Buffer.from(chunk2("IDAT", compressed)),
|
|
25082
|
-
Buffer.from(chunk2("IEND", new Uint8Array(0)))
|
|
25083
|
-
]);
|
|
25084
|
-
}
|
|
25085
|
-
function kittyImageSequence(base64, options) {
|
|
25086
|
-
const params = [`a=T`, `f=${options.format}`, `q=2`, `C=1`, `c=${options.columns}`, `r=${options.rows}`, `i=${options.imageId}`, `z=${options.zIndex}`];
|
|
25087
|
-
if (options.format === 32) {
|
|
25088
|
-
params.push(`s=${options.pixelWidth ?? 1}`, `v=${options.pixelHeight ?? 1}`);
|
|
25089
|
-
if (options.compressed)
|
|
25090
|
-
params.push("o=z");
|
|
25091
|
-
}
|
|
25092
|
-
if (base64.length <= KITTY_CHUNK_SIZE)
|
|
25093
|
-
return `\x1B_G${params.join(",")};${base64}\x1B\\`;
|
|
25094
|
-
const chunks = [];
|
|
25095
|
-
for (let offset = 0;offset < base64.length; offset += KITTY_CHUNK_SIZE) {
|
|
25096
|
-
const part = base64.slice(offset, offset + KITTY_CHUNK_SIZE);
|
|
25097
|
-
const last = offset + KITTY_CHUNK_SIZE >= base64.length;
|
|
25098
|
-
chunks.push(`\x1B_G${offset === 0 ? `${params.join(",")},` : ""}m=${last ? 0 : 1};${part}\x1B\\`);
|
|
25099
|
-
}
|
|
25100
|
-
return chunks.join("");
|
|
25101
|
-
}
|
|
25102
|
-
function clampByte(value) {
|
|
25103
|
-
return Math.max(0, Math.min(255, Math.round(value)));
|
|
25104
|
-
}
|
|
25105
|
-
function blendOver(data, index, color, alphaScale = 1) {
|
|
25106
|
-
const alpha = color[3] / 255 * alphaScale;
|
|
25107
|
-
const inv = 1 - alpha;
|
|
25108
|
-
data[index] = clampByte(color[0] * alpha + data[index] * inv);
|
|
25109
|
-
data[index + 1] = clampByte(color[1] * alpha + data[index + 1] * inv);
|
|
25110
|
-
data[index + 2] = clampByte(color[2] * alpha + data[index + 2] * inv);
|
|
25111
|
-
data[index + 3] = 255;
|
|
25112
|
-
}
|
|
25113
|
-
function drawDisc(data, width, height, cx, cy, radius, color, alpha = 1) {
|
|
25114
|
-
const minX = Math.max(0, Math.floor(cx - radius));
|
|
25115
|
-
const maxX = Math.min(width - 1, Math.ceil(cx + radius));
|
|
25116
|
-
const minY = Math.max(0, Math.floor(cy - radius));
|
|
25117
|
-
const maxY = Math.min(height - 1, Math.ceil(cy + radius));
|
|
25118
|
-
for (let y = minY;y <= maxY; y += 1) {
|
|
25119
|
-
for (let x = minX;x <= maxX; x += 1) {
|
|
25120
|
-
const dx = x + 0.5 - cx;
|
|
25121
|
-
const dy = y + 0.5 - cy;
|
|
25122
|
-
const d = Math.sqrt(dx * dx + dy * dy);
|
|
25123
|
-
if (d > radius)
|
|
25124
|
-
continue;
|
|
25125
|
-
const edge = Math.max(0, Math.min(1, radius - d));
|
|
25126
|
-
blendOver(data, (y * width + x) * 4, color, alpha * Math.min(1, 0.35 + edge));
|
|
25127
|
-
}
|
|
25128
|
-
}
|
|
25129
|
-
}
|
|
25130
|
-
function drawGlow2(data, width, height, cx, cy, radius, color, alpha = 0.18) {
|
|
25131
|
-
const minX = Math.max(0, Math.floor(cx - radius));
|
|
25132
|
-
const maxX = Math.min(width - 1, Math.ceil(cx + radius));
|
|
25133
|
-
const minY = Math.max(0, Math.floor(cy - radius));
|
|
25134
|
-
const maxY = Math.min(height - 1, Math.ceil(cy + radius));
|
|
25135
|
-
for (let y = minY;y <= maxY; y += 1) {
|
|
25136
|
-
for (let x = minX;x <= maxX; x += 1) {
|
|
25137
|
-
const dx = x + 0.5 - cx;
|
|
25138
|
-
const dy = y + 0.5 - cy;
|
|
25139
|
-
const d = Math.sqrt(dx * dx + dy * dy);
|
|
25140
|
-
if (d > radius)
|
|
25141
|
-
continue;
|
|
25142
|
-
const falloff = Math.pow(1 - d / Math.max(1, radius), GLOW_FALLOFF_EXP_IMAGE);
|
|
25143
|
-
blendOver(data, (y * width + x) * 4, color, alpha * falloff);
|
|
25144
|
-
}
|
|
25145
|
-
}
|
|
25146
|
-
}
|
|
25147
|
-
function drawLine2(data, width, height, x0, y0, x1, y1, color, alpha = 0.5, thickness = 1.4) {
|
|
25148
|
-
const dx = x1 - x0;
|
|
25149
|
-
const dy = y1 - y0;
|
|
25150
|
-
const steps = Math.max(1, Math.ceil(Math.hypot(dx, dy) * 1.2));
|
|
25151
|
-
for (let i = 0;i <= steps; i += 1) {
|
|
25152
|
-
const t2 = i / steps;
|
|
25153
|
-
drawDisc(data, width, height, x0 + dx * t2, y0 + dy * t2, thickness, color, alpha);
|
|
25154
|
-
}
|
|
25155
|
-
}
|
|
25156
|
-
function roundRectAlpha(px, py, x, y, w, h, r) {
|
|
25157
|
-
const rx = Math.max(x + r, Math.min(px, x + w - r));
|
|
25158
|
-
const ry = Math.max(y + r, Math.min(py, y + h - r));
|
|
25159
|
-
const dx = px - rx;
|
|
25160
|
-
const dy = py - ry;
|
|
25161
|
-
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
25162
|
-
return Math.max(0, Math.min(1, r + 0.75 - dist));
|
|
25163
|
-
}
|
|
25164
|
-
function panelRect(layout, panel, size) {
|
|
25165
|
-
return panelPixelPlacement(layout, panel, size);
|
|
25166
|
-
}
|
|
25167
|
-
function downsampleRegion(data, canvasW, canvasH, rect, scale) {
|
|
25168
|
-
const w = Math.max(1, Math.ceil(rect.width / scale));
|
|
25169
|
-
const h = Math.max(1, Math.ceil(rect.height / scale));
|
|
25170
|
-
const out = new Uint8ClampedArray(w * h * 3);
|
|
25171
|
-
for (let y = 0;y < h; y += 1) {
|
|
25172
|
-
for (let x = 0;x < w; x += 1) {
|
|
25173
|
-
let r = 0, g = 0, b = 0, count = 0;
|
|
25174
|
-
const sx0 = rect.left + x * scale;
|
|
25175
|
-
const sy0 = rect.top + y * scale;
|
|
25176
|
-
for (let yy = 0;yy < scale; yy += 1) {
|
|
25177
|
-
const sy = sy0 + yy;
|
|
25178
|
-
if (sy < 0 || sy >= canvasH)
|
|
25179
|
-
continue;
|
|
25180
|
-
for (let xx = 0;xx < scale; xx += 1) {
|
|
25181
|
-
const sx = sx0 + xx;
|
|
25182
|
-
if (sx < 0 || sx >= canvasW)
|
|
25183
|
-
continue;
|
|
25184
|
-
const i = (sy * canvasW + sx) * 4;
|
|
25185
|
-
r += data[i];
|
|
25186
|
-
g += data[i + 1];
|
|
25187
|
-
b += data[i + 2];
|
|
25188
|
-
count += 1;
|
|
25189
|
-
}
|
|
25190
|
-
}
|
|
25191
|
-
const oi = (y * w + x) * 3;
|
|
25192
|
-
out[oi] = count ? r / count : BG[0];
|
|
25193
|
-
out[oi + 1] = count ? g / count : BG[1];
|
|
25194
|
-
out[oi + 2] = count ? b / count : BG[2];
|
|
25195
|
-
}
|
|
25196
|
-
}
|
|
25197
|
-
return { pixels: out, width: w, height: h };
|
|
25198
|
-
}
|
|
25199
|
-
function blurRgb(buffer, width, height, radius) {
|
|
25200
|
-
const tmp = new Uint8ClampedArray(buffer.length);
|
|
25201
|
-
const out = new Uint8ClampedArray(buffer.length);
|
|
25202
|
-
const window = radius * 2 + 1;
|
|
25203
|
-
for (let y = 0;y < height; y += 1) {
|
|
25204
|
-
let r = 0, g = 0, b = 0;
|
|
25205
|
-
for (let x = -radius;x <= radius; x += 1) {
|
|
25206
|
-
const sx = Math.max(0, Math.min(width - 1, x));
|
|
25207
|
-
const i = (y * width + sx) * 3;
|
|
25208
|
-
r += buffer[i];
|
|
25209
|
-
g += buffer[i + 1];
|
|
25210
|
-
b += buffer[i + 2];
|
|
25211
|
-
}
|
|
25212
|
-
for (let x = 0;x < width; x += 1) {
|
|
25213
|
-
const oi = (y * width + x) * 3;
|
|
25214
|
-
tmp[oi] = r / window;
|
|
25215
|
-
tmp[oi + 1] = g / window;
|
|
25216
|
-
tmp[oi + 2] = b / window;
|
|
25217
|
-
const removeX = Math.max(0, x - radius);
|
|
25218
|
-
const addX = Math.min(width - 1, x + radius + 1);
|
|
25219
|
-
const ri = (y * width + removeX) * 3;
|
|
25220
|
-
const ai = (y * width + addX) * 3;
|
|
25221
|
-
r += tmp.length ? buffer[ai] - buffer[ri] : 0;
|
|
25222
|
-
g += tmp.length ? buffer[ai + 1] - buffer[ri + 1] : 0;
|
|
25223
|
-
b += tmp.length ? buffer[ai + 2] - buffer[ri + 2] : 0;
|
|
25224
|
-
}
|
|
25225
|
-
}
|
|
25226
|
-
for (let x = 0;x < width; x += 1) {
|
|
25227
|
-
let r = 0, g = 0, b = 0;
|
|
25228
|
-
for (let y = -radius;y <= radius; y += 1) {
|
|
25229
|
-
const sy = Math.max(0, Math.min(height - 1, y));
|
|
25230
|
-
const i = (sy * width + x) * 3;
|
|
25231
|
-
r += tmp[i];
|
|
25232
|
-
g += tmp[i + 1];
|
|
25233
|
-
b += tmp[i + 2];
|
|
25234
|
-
}
|
|
25235
|
-
for (let y = 0;y < height; y += 1) {
|
|
25236
|
-
const oi = (y * width + x) * 3;
|
|
25237
|
-
out[oi] = r / window;
|
|
25238
|
-
out[oi + 1] = g / window;
|
|
25239
|
-
out[oi + 2] = b / window;
|
|
25240
|
-
const removeY = Math.max(0, y - radius);
|
|
25241
|
-
const addY = Math.min(height - 1, y + radius + 1);
|
|
25242
|
-
const ri = (removeY * width + x) * 3;
|
|
25243
|
-
const ai = (addY * width + x) * 3;
|
|
25244
|
-
r += tmp[ai] - tmp[ri];
|
|
25245
|
-
g += tmp[ai + 1] - tmp[ri + 1];
|
|
25246
|
-
b += tmp[ai + 2] - tmp[ri + 2];
|
|
25247
|
-
}
|
|
25248
|
-
}
|
|
25249
|
-
return out;
|
|
25250
|
-
}
|
|
25251
|
-
function panelMaskKey(width, height, rect, headerPx, blurScale) {
|
|
25252
|
-
return `${width}x${height}:${rect.left},${rect.top},${rect.width},${rect.height}:${Math.round(headerPx * 100) / 100}:${blurScale}`;
|
|
25253
|
-
}
|
|
25254
|
-
function getPanelMask(width, height, rect, headerPx, blurScale) {
|
|
25255
|
-
const key = panelMaskKey(width, height, rect, headerPx, blurScale);
|
|
25256
|
-
const cached = panelMaskCache.get(key);
|
|
25257
|
-
if (cached)
|
|
25258
|
-
return cached;
|
|
25259
|
-
const radius = Math.max(PANEL_MASK_RADIUS_MIN, Math.min(PANEL_MASK_RADIUS_MAX, Math.round(Math.min(rect.width, rect.height) * PANEL_MASK_RADIUS_FACTOR)));
|
|
25260
|
-
const sampledWidth = Math.max(1, Math.ceil(rect.width / blurScale));
|
|
25261
|
-
const sampledHeight = Math.max(1, Math.ceil(rect.height / blurScale));
|
|
25262
|
-
const x0 = Math.max(0, rect.left);
|
|
25263
|
-
const y0 = Math.max(0, rect.top);
|
|
25264
|
-
const x1 = Math.min(width - 1, rect.left + rect.width - 1);
|
|
25265
|
-
const y1 = Math.min(height - 1, rect.top + rect.height - 1);
|
|
25266
|
-
const indices = [];
|
|
25267
|
-
const sampleIndices = [];
|
|
25268
|
-
const panelAlpha = [];
|
|
25269
|
-
const edgeAlpha = [];
|
|
25270
|
-
const headerFlags = [];
|
|
25271
|
-
const dividerIndices = [];
|
|
25272
|
-
for (let y = y0;y <= y1; y += 1) {
|
|
25273
|
-
for (let x = x0;x <= x1; x += 1) {
|
|
25274
|
-
const a = roundRectAlpha(x + 0.5, y + 0.5, rect.left, rect.top, rect.width, rect.height, radius);
|
|
25275
|
-
if (a <= 0)
|
|
25276
|
-
continue;
|
|
25277
|
-
const edge = roundRectAlpha(x + 0.5, y + 0.5, rect.left + 1.2, rect.top + 1.2, rect.width - 2.4, rect.height - 2.4, Math.max(1, radius - 1.2));
|
|
25278
|
-
const sx = Math.max(0, Math.min(sampledWidth - 1, Math.floor((x - rect.left) / blurScale)));
|
|
25279
|
-
const sy = Math.max(0, Math.min(sampledHeight - 1, Math.floor((y - rect.top) / blurScale)));
|
|
25280
|
-
indices.push((y * width + x) * 4);
|
|
25281
|
-
sampleIndices.push((sy * sampledWidth + sx) * 3);
|
|
25282
|
-
panelAlpha.push(a);
|
|
25283
|
-
edgeAlpha.push(edge < 0.96 ? Math.min(1, (1 - edge) * 0.7) : 0);
|
|
25284
|
-
headerFlags.push(y < rect.top + headerPx ? 1 : 0);
|
|
25285
|
-
}
|
|
25286
|
-
}
|
|
25287
|
-
const dividerY = Math.round(rect.top + headerPx);
|
|
25288
|
-
if (dividerY > y0 && dividerY < y1) {
|
|
25289
|
-
for (let x = x0 + radius;x <= x1 - radius; x += 1) {
|
|
25290
|
-
dividerIndices.push((dividerY * width + x) * 4);
|
|
25291
|
-
}
|
|
25292
|
-
}
|
|
25293
|
-
const mask = {
|
|
25294
|
-
key,
|
|
25295
|
-
indices: Uint32Array.from(indices),
|
|
25296
|
-
sampleIndices: Uint32Array.from(sampleIndices),
|
|
25297
|
-
panelAlpha: Float32Array.from(panelAlpha),
|
|
25298
|
-
edgeAlpha: Float32Array.from(edgeAlpha),
|
|
25299
|
-
headerFlags: Uint8Array.from(headerFlags),
|
|
25300
|
-
dividerIndices: Uint32Array.from(dividerIndices)
|
|
25301
|
-
};
|
|
25302
|
-
panelMaskCache.set(key, mask);
|
|
25303
|
-
while (panelMaskCache.size > PANEL_MASK_CACHE_LIMIT) {
|
|
25304
|
-
const oldest = panelMaskCache.keys().next().value;
|
|
25305
|
-
if (!oldest)
|
|
25306
|
-
break;
|
|
25307
|
-
panelMaskCache.delete(oldest);
|
|
25308
|
-
}
|
|
25309
|
-
return mask;
|
|
25310
|
-
}
|
|
25311
|
-
function compositePanel(data, width, height, rect, headerPx) {
|
|
25312
|
-
const blurScale = PANEL_BLUR_SCALE;
|
|
25313
|
-
const sampled = downsampleRegion(data, width, height, rect, blurScale);
|
|
25314
|
-
const blurRadius = Math.max(PANEL_BLUR_RADIUS_MIN, Math.min(PANEL_BLUR_RADIUS_MAX, Math.round(Math.min(rect.width, rect.height) * PANEL_BLUR_RADIUS_FACTOR)));
|
|
25315
|
-
const blurred = blurRgb(sampled.pixels, sampled.width, sampled.height, blurRadius);
|
|
25316
|
-
const mask = getPanelMask(width, height, rect, headerPx, blurScale);
|
|
25317
|
-
for (let i = 0;i < mask.indices.length; i += 1) {
|
|
25318
|
-
const idx = mask.indices[i];
|
|
25319
|
-
const sampleIdx = mask.sampleIndices[i];
|
|
25320
|
-
data[idx] = blurred[sampleIdx];
|
|
25321
|
-
data[idx + 1] = blurred[sampleIdx + 1];
|
|
25322
|
-
data[idx + 2] = blurred[sampleIdx + 2];
|
|
25323
|
-
data[idx + 3] = 255;
|
|
25324
|
-
blendOver(data, idx, mask.headerFlags[i] ? PANEL_HEADER : PANEL, mask.panelAlpha[i]);
|
|
25325
|
-
const edge = mask.edgeAlpha[i];
|
|
25326
|
-
if (edge > 0)
|
|
25327
|
-
blendOver(data, idx, PANEL_LINE2, edge);
|
|
25328
|
-
}
|
|
25329
|
-
for (let i = 0;i < mask.dividerIndices.length; i += 1) {
|
|
25330
|
-
blendOver(data, mask.dividerIndices[i], PANEL_LINE2, 0.28);
|
|
25331
|
-
}
|
|
25332
|
-
}
|
|
25333
|
-
function drawBigRigWordmark(data, width, height, layout, load) {
|
|
25334
|
-
const sideBySide = layout.width >= FLEET_GRID_WIDTH * 1.9;
|
|
25335
|
-
if (!sideBySide)
|
|
25336
|
-
return;
|
|
25337
|
-
const letters = "RIG";
|
|
25338
|
-
const min = Math.min(width, height);
|
|
25339
|
-
const glyphH = height * 0.42;
|
|
25340
|
-
const glyphW = width * 0.13;
|
|
25341
|
-
const gap = glyphW * 0.3;
|
|
25342
|
-
const totalW = letters.length * glyphW + (letters.length - 1) * gap;
|
|
25343
|
-
const centerX = width * 0.71;
|
|
25344
|
-
const startX = centerX - totalW / 2;
|
|
25345
|
-
const top = (height - glyphH) / 2;
|
|
25346
|
-
const stroke = Math.max(2, min * 0.013);
|
|
25347
|
-
drawGlow2(data, width, height, centerX, top + glyphH / 2, Math.max(glyphW, glyphH) * 0.9, LIME, 0.022 + load * 0.02);
|
|
25348
|
-
const strokeAlpha = 0.1 + load * 0.06;
|
|
25349
|
-
letters.split("").forEach((letter, index) => {
|
|
25350
|
-
const segments = RIG_GLYPH_STROKES[letter];
|
|
25351
|
-
if (!segments)
|
|
25352
|
-
return;
|
|
25353
|
-
const ox = startX + index * (glyphW + gap);
|
|
25354
|
-
for (const [x0, y0, x1, y1] of segments) {
|
|
25355
|
-
drawLine2(data, width, height, ox + x0 * glyphW, top + y0 * glyphH, ox + x1 * glyphW, top + y1 * glyphH, LIME_DIM, strokeAlpha, stroke);
|
|
25356
|
-
}
|
|
25357
|
-
});
|
|
25358
|
-
}
|
|
25359
|
-
function drawBackground(data, width, height, _tick, scene, layout, load, activeRuns) {
|
|
25360
|
-
fillRgba(data, BG, BG_WORD);
|
|
25361
|
-
drawStaticAsciiFleetBackground(data, width, height, scene, layout, load, activeRuns);
|
|
25362
|
-
drawBigRigWordmark(data, width, height, layout, load);
|
|
25363
|
-
applyStaticAtmosphere(data, width, height, load);
|
|
25364
|
-
}
|
|
25365
|
-
function imageVisualFrameKey(input) {
|
|
25366
|
-
const width = Math.max(1, Math.floor(input.pixelSize.width));
|
|
25367
|
-
const height = Math.max(1, Math.floor(input.pixelSize.height));
|
|
25368
|
-
const layer = "layer" in input ? input.layer ?? "full" : "full";
|
|
25369
|
-
const load = loadBucket(input.load);
|
|
25370
|
-
return `${layer}:${width}x${height}:${input.layout.width}x${input.layout.height}:${input.scene}:${input.tick}:l${load}:${input.panels.map((panel) => `${panel.id}:${panel.top}:${panel.height}:${panel.width ?? ""}:${panel.left ?? ""}:${panel.headerHeight ?? ""}`).join("|")}`;
|
|
25371
|
-
}
|
|
25372
|
-
function encodeKittyFrame(width, height, data, input) {
|
|
25373
|
-
if (input.transport === "png") {
|
|
25374
|
-
const png = encodePng(width, height, data);
|
|
25375
|
-
return kittyImageSequence(png.toString("base64"), { columns: input.layout.width, rows: input.layout.height, imageId: input.imageId, zIndex: input.zIndex, format: 100 });
|
|
25376
|
-
}
|
|
25377
|
-
const compressed = deflateSync(data, { level: ZLIB_LEVEL });
|
|
25378
|
-
return kittyImageSequence(compressed.toString("base64"), {
|
|
25379
|
-
columns: input.layout.width,
|
|
25380
|
-
rows: input.layout.height,
|
|
25381
|
-
imageId: input.imageId,
|
|
25382
|
-
zIndex: input.zIndex,
|
|
25383
|
-
format: 32,
|
|
25384
|
-
pixelWidth: width,
|
|
25385
|
-
pixelHeight: height,
|
|
25386
|
-
compressed: true
|
|
25387
|
-
});
|
|
25388
|
-
}
|
|
25389
|
-
function cropRgba(data, sourceWidth, rect) {
|
|
25390
|
-
const out = new Uint8ClampedArray(rect.width * rect.height * 4);
|
|
25391
|
-
for (let y = 0;y < rect.height; y += 1) {
|
|
25392
|
-
const sourceStart = ((rect.top + y) * sourceWidth + rect.left) * 4;
|
|
25393
|
-
out.set(data.subarray(sourceStart, sourceStart + rect.width * 4), y * rect.width * 4);
|
|
25394
|
-
}
|
|
25395
|
-
return out;
|
|
25396
|
-
}
|
|
25397
|
-
function encodePanelPatch(data, sourceWidth, placement, imageId, zIndex) {
|
|
25398
|
-
const patch = cropRgba(data, sourceWidth, placement);
|
|
25399
|
-
const png = encodePng(placement.width, placement.height, patch);
|
|
25400
|
-
const sequence = kittyImageSequence(png.toString("base64"), {
|
|
25401
|
-
columns: Math.max(1, Math.round(placement.widthCells)),
|
|
25402
|
-
rows: Math.max(1, Math.round(placement.heightCells)),
|
|
25403
|
-
imageId,
|
|
25404
|
-
zIndex,
|
|
25405
|
-
format: 100
|
|
25406
|
-
});
|
|
25407
|
-
return `\x1B[${Math.max(1, Math.round(placement.topCells) + 1)};${Math.max(1, Math.round(placement.leftCells) + 1)}H${sequence}`;
|
|
25408
|
-
}
|
|
25409
|
-
function renderImageVisualFrame(input) {
|
|
25410
|
-
const width = Math.max(1, Math.floor(input.pixelSize.width));
|
|
25411
|
-
const height = Math.max(1, Math.floor(input.pixelSize.height));
|
|
25412
|
-
const byteCount = width * height * 4;
|
|
25413
|
-
if (byteCount > MAX_IMAGE_BYTES)
|
|
25414
|
-
return null;
|
|
25415
|
-
const layer = input.layer ?? "full";
|
|
25416
|
-
const data = new Uint8ClampedArray(byteCount);
|
|
25417
|
-
const load = loadBucket(input.load) / LOAD_BUCKETS;
|
|
25418
|
-
const activeRuns = Math.max(0, Math.floor(input.activeRuns ?? 0));
|
|
25419
|
-
drawBackground(data, width, height, 0, input.scene, input.layout, load, activeRuns);
|
|
25420
|
-
if (layer === "split") {
|
|
25421
|
-
const sequences = [encodeKittyFrame(width, height, data, input)];
|
|
25422
|
-
let panelIndex = 0;
|
|
25423
|
-
for (const panel of input.panels) {
|
|
25424
|
-
if (panel.chrome !== "ad-terminal")
|
|
25425
|
-
continue;
|
|
25426
|
-
const placement = panelPixelPlacement(input.layout, panel, { width, height });
|
|
25427
|
-
if (!placement)
|
|
25428
|
-
continue;
|
|
25429
|
-
const cellH = height / input.layout.height;
|
|
25430
|
-
const headerPx = Math.max(cellH * 3, (panel.headerHeight ?? 3) * cellH);
|
|
25431
|
-
compositePanel(data, width, height, placement, headerPx);
|
|
25432
|
-
const imageId = input.imageIds?.[panelIndex] ?? (input.imageId + 1000 + panelIndex >>> 0 || panelIndex + 1);
|
|
25433
|
-
sequences.push(encodePanelPatch(data, width, placement, imageId, -12));
|
|
25434
|
-
panelIndex += 1;
|
|
25435
|
-
}
|
|
25436
|
-
return { key: imageVisualFrameKey(input), sequence: sequences.join("") };
|
|
25437
|
-
}
|
|
25438
|
-
if (layer === "panel-chrome")
|
|
25439
|
-
return { key: imageVisualFrameKey(input), sequence: "" };
|
|
25440
|
-
if (layer === "background") {
|
|
25441
|
-
return { key: imageVisualFrameKey(input), sequence: encodeKittyFrame(width, height, data, input) };
|
|
25442
|
-
}
|
|
25443
|
-
if (layer === "panel-patches") {
|
|
25444
|
-
const sequences = [];
|
|
25445
|
-
let panelIndex = 0;
|
|
25446
|
-
for (const panel of input.panels) {
|
|
25447
|
-
if (panel.chrome !== "ad-terminal")
|
|
25448
|
-
continue;
|
|
25449
|
-
const placement = panelPixelPlacement(input.layout, panel, { width, height });
|
|
25450
|
-
if (!placement)
|
|
25451
|
-
continue;
|
|
25452
|
-
const cellH = height / input.layout.height;
|
|
25453
|
-
const headerPx = Math.max(cellH * 3, (panel.headerHeight ?? 3) * cellH);
|
|
25454
|
-
compositePanel(data, width, height, placement, headerPx);
|
|
25455
|
-
const imageId = input.imageIds?.[panelIndex] ?? (input.imageId + 1000 + panelIndex >>> 0 || panelIndex + 1);
|
|
25456
|
-
sequences.push(encodePanelPatch(data, width, placement, imageId, input.zIndex));
|
|
25457
|
-
panelIndex += 1;
|
|
25458
|
-
}
|
|
25459
|
-
return { key: imageVisualFrameKey(input), sequence: sequences.join("") };
|
|
25460
|
-
}
|
|
25461
|
-
for (const panel of input.panels) {
|
|
25462
|
-
if (panel.chrome !== "ad-terminal")
|
|
25463
|
-
continue;
|
|
25464
|
-
const rect = panelRect(input.layout, panel, { width, height });
|
|
25465
|
-
if (!rect)
|
|
25466
|
-
continue;
|
|
25467
|
-
const cellH = height / input.layout.height;
|
|
25468
|
-
const headerPx = Math.max(cellH * 3, (panel.headerHeight ?? 3) * cellH);
|
|
25469
|
-
compositePanel(data, width, height, rect, headerPx);
|
|
25470
|
-
}
|
|
25471
|
-
return { key: imageVisualFrameKey(input), sequence: encodeKittyFrame(width, height, data, input) };
|
|
25472
|
-
}
|
|
25473
|
-
function shouldRenderImagesInline() {
|
|
25474
|
-
return process.env.RIG_OPENTUI_IMAGE_WORKER === "0" || import.meta.url.includes("$bunfs");
|
|
25475
|
-
}
|
|
25476
|
-
function createImageWorker() {
|
|
25477
|
-
if (shouldRenderImagesInline())
|
|
25478
|
-
return null;
|
|
25479
|
-
const isTypeScriptRuntime = import.meta.url.endsWith(".ts");
|
|
25480
|
-
const workerUrl = new URL(isTypeScriptRuntime ? "./image-visual-layer-worker.ts" : "./image-visual-layer-worker.js", import.meta.url);
|
|
25481
|
-
try {
|
|
25482
|
-
return new Worker(workerUrl);
|
|
25483
|
-
} catch {
|
|
25484
|
-
if (typeof process.versions.bun === "string") {
|
|
25485
|
-
try {
|
|
25486
|
-
return new Worker("./src/app-opentui/render/image-visual-layer-worker.ts");
|
|
25487
|
-
} catch {}
|
|
25488
|
-
}
|
|
25489
|
-
return null;
|
|
25490
|
-
}
|
|
25491
|
-
}
|
|
25492
|
-
function imageOutputBacklogBytes() {
|
|
25493
|
-
const raw = Number.parseInt(process.env.RIG_OPENTUI_IMAGE_BACKLOG_BYTES ?? "", 10);
|
|
25494
|
-
if (Number.isFinite(raw) && raw > 0)
|
|
25495
|
-
return Math.max(64 * 1024, Math.min(2 * 1024 * 1024, raw));
|
|
25496
|
-
return DEFAULT_IMAGE_OUTPUT_BACKLOG_BYTES;
|
|
25497
|
-
}
|
|
25498
|
-
function imageOutputBytesPerSecond() {
|
|
25499
|
-
const raw = Number.parseInt(process.env.RIG_OPENTUI_IMAGE_BYTES_PER_SECOND ?? "", 10);
|
|
25500
|
-
if (Number.isFinite(raw) && raw > 0)
|
|
25501
|
-
return Math.max(128 * 1024, Math.min(2 * 1024 * 1024, raw));
|
|
25502
|
-
return DEFAULT_IMAGE_OUTPUT_BYTES_PER_SECOND;
|
|
25503
|
-
}
|
|
25504
|
-
function pendingLayerKey(key) {
|
|
25505
|
-
return key.split(":", 1)[0] || "full";
|
|
25506
|
-
}
|
|
25507
|
-
|
|
25508
|
-
class ImageVisualLayer {
|
|
25509
|
-
imageId = allocateImageId();
|
|
25510
|
-
panelImageIds = Array.from({ length: 8 }, () => allocateImageId());
|
|
25511
|
-
panelChromeImageIds = Array.from({ length: 8 }, () => allocateImageId());
|
|
25512
|
-
stdout;
|
|
25513
|
-
onFrameReady;
|
|
25514
|
-
protocol;
|
|
25515
|
-
transport = imageTransport();
|
|
25516
|
-
maxOutputBacklogBytes = imageOutputBacklogBytes();
|
|
25517
|
-
outputBytesPerSecond = imageOutputBytesPerSecond();
|
|
25518
|
-
outputBudgetBytes = imageOutputBytesPerSecond();
|
|
25519
|
-
lastBudgetAtMs = Date.now();
|
|
25520
|
-
motionSlot = this.createSlot();
|
|
25521
|
-
workersStarted = false;
|
|
25522
|
-
pendingFrames = new Map;
|
|
25523
|
-
recentWrittenKeys = [];
|
|
25524
|
-
imagesVisible = false;
|
|
25525
|
-
flushPaused = false;
|
|
25526
|
-
requestId = 0;
|
|
25527
|
-
lastBackgroundKey = "";
|
|
25528
|
-
fatalWorkerError = null;
|
|
25529
|
-
destroyed = false;
|
|
25530
|
-
constructor(stdout = process.stdout, onFrameReady) {
|
|
25531
|
-
this.stdout = stdout;
|
|
25532
|
-
this.onFrameReady = onFrameReady;
|
|
25533
|
-
this.protocol = getRigTerminalCapabilities().imageProtocol;
|
|
25534
|
-
}
|
|
25535
|
-
get enabled() {
|
|
25536
|
-
return this.protocol === "kitty";
|
|
25537
|
-
}
|
|
25538
|
-
clear() {
|
|
25539
|
-
if (this.enabled) {
|
|
25540
|
-
if (this.imagesVisible)
|
|
25541
|
-
this.stdout.write([this.imageId, ...this.panelImageIds, ...this.panelChromeImageIds].map((id) => deleteKittyImage(id)).join("") + "\x1B[?25h");
|
|
25542
|
-
this.imagesVisible = false;
|
|
25543
|
-
this.pendingFrames.clear();
|
|
25544
|
-
this.recentWrittenKeys.length = 0;
|
|
25545
|
-
this.resetSlot(this.motionSlot);
|
|
25546
|
-
this.lastBackgroundKey = "";
|
|
25547
|
-
this.outputBudgetBytes = this.outputBytesPerSecond;
|
|
25548
|
-
this.lastBudgetAtMs = Date.now();
|
|
25549
|
-
this.motionSlot.clearedThroughRequestId = this.requestId;
|
|
25550
|
-
}
|
|
25551
|
-
}
|
|
25552
|
-
destroy() {
|
|
25553
|
-
if (this.destroyed)
|
|
25554
|
-
return;
|
|
25555
|
-
this.clear();
|
|
25556
|
-
this.destroyed = true;
|
|
25557
|
-
const workers = [this.motionSlot.worker];
|
|
25558
|
-
this.motionSlot.worker = null;
|
|
25559
|
-
for (const worker of workers)
|
|
25560
|
-
if (worker)
|
|
25561
|
-
worker.terminate().catch(() => {
|
|
25562
|
-
return;
|
|
25563
|
-
});
|
|
25564
|
-
}
|
|
25565
|
-
setFlushPaused(paused) {
|
|
25566
|
-
this.flushPaused = paused;
|
|
25567
|
-
}
|
|
25568
|
-
isReady(input) {
|
|
25569
|
-
if (!this.enabled || this.destroyed)
|
|
25570
|
-
return true;
|
|
25571
|
-
this.throwIfFatal();
|
|
25572
|
-
const splitKey = imageVisualFrameKey({ ...input, tick: 0, layer: "split" });
|
|
25573
|
-
return this.recentWrittenKeys.includes(splitKey) || Array.from(this.pendingFrames.values()).some((frame) => frame.key === splitKey);
|
|
25574
|
-
}
|
|
25575
|
-
render(input) {
|
|
25576
|
-
if (!this.enabled || this.destroyed)
|
|
25577
|
-
return;
|
|
25578
|
-
this.throwIfFatal();
|
|
25579
|
-
if (this.transport !== "png")
|
|
25580
|
-
this.failWorker("renderer", new Error("OpenTUI image visuals require PNG transport for static-background rendering."));
|
|
25581
|
-
this.ensureWorkersStarted();
|
|
25582
|
-
const width = Math.max(1, Math.floor(input.pixelSize.width));
|
|
25583
|
-
const height = Math.max(1, Math.floor(input.pixelSize.height));
|
|
25584
|
-
if (width * height * 4 > MAX_IMAGE_BYTES)
|
|
25585
|
-
return;
|
|
25586
|
-
if (this.isOutputBackedUp())
|
|
25587
|
-
return;
|
|
25588
|
-
this.refillOutputBudget();
|
|
25589
|
-
const splitInput = { ...input, tick: 0, layer: "split" };
|
|
25590
|
-
const splitKey = imageVisualFrameKey(splitInput);
|
|
25591
|
-
if (input.force || splitKey !== this.lastBackgroundKey) {
|
|
25592
|
-
this.scheduleRender(this.motionSlot, splitInput, this.imageId, -30, input.force, this.panelImageIds);
|
|
25593
|
-
this.lastBackgroundKey = splitKey;
|
|
25594
|
-
}
|
|
25595
|
-
}
|
|
25596
|
-
flush() {
|
|
25597
|
-
this.throwIfFatal();
|
|
25598
|
-
if (this.flushPaused)
|
|
25599
|
-
return false;
|
|
25600
|
-
if (this.pendingFrames.size === 0)
|
|
25601
|
-
return false;
|
|
25602
|
-
this.refillOutputBudget();
|
|
25603
|
-
if (this.isOutputBackedUp()) {
|
|
25604
|
-
const retainedSplit = this.pendingFrames.get("split");
|
|
25605
|
-
this.pendingFrames.clear();
|
|
25606
|
-
if (retainedSplit)
|
|
25607
|
-
this.pendingFrames.set("split", retainedSplit);
|
|
25608
|
-
return false;
|
|
25609
|
-
}
|
|
25610
|
-
const framePriority = (frame) => {
|
|
25611
|
-
const layer = pendingLayerKey(frame.key);
|
|
25612
|
-
if (layer === "split")
|
|
25613
|
-
return 1;
|
|
25614
|
-
return 4;
|
|
25615
|
-
};
|
|
25616
|
-
const frames = Array.from(this.pendingFrames.values()).sort((a, b) => framePriority(a) - framePriority(b));
|
|
25617
|
-
const prefix = "\x1B[?25l\x1B7\x1B[s\x1B[H";
|
|
25618
|
-
const suffix = "\x1B[u\x1B8";
|
|
25619
|
-
const selected = [];
|
|
25620
|
-
const retained = new Map;
|
|
25621
|
-
let sequence = "";
|
|
25622
|
-
let byteLength = Buffer.byteLength(prefix + suffix);
|
|
25623
|
-
for (const frame of frames) {
|
|
25624
|
-
const candidate = sequence + frame.sequence;
|
|
25625
|
-
const candidateBytes = Buffer.byteLength(prefix + candidate + suffix);
|
|
25626
|
-
const layer = pendingLayerKey(frame.key);
|
|
25627
|
-
const allowOneStaticFrame = selected.length === 0 && layer === "split";
|
|
25628
|
-
if (candidateBytes <= this.outputBudgetBytes || allowOneStaticFrame) {
|
|
25629
|
-
selected.push(frame);
|
|
25630
|
-
sequence = candidate;
|
|
25631
|
-
byteLength = candidateBytes;
|
|
25632
|
-
} else if (layer === "split") {
|
|
25633
|
-
retained.set(layer, frame);
|
|
25634
|
-
}
|
|
25635
|
-
}
|
|
25636
|
-
this.pendingFrames.clear();
|
|
25637
|
-
for (const [layer, frame] of retained)
|
|
25638
|
-
this.pendingFrames.set(layer, frame);
|
|
25639
|
-
if (!sequence || selected.length === 0)
|
|
25640
|
-
return false;
|
|
25641
|
-
const payload = `${prefix}${sequence}${suffix}`;
|
|
25642
|
-
for (const frame of selected)
|
|
25643
|
-
this.markWritten(frame.key);
|
|
25644
|
-
this.outputBudgetBytes -= byteLength;
|
|
25645
|
-
this.stdout.cork?.();
|
|
25646
|
-
const accepted = this.stdout.write(payload);
|
|
25647
|
-
this.stdout.uncork?.();
|
|
25648
|
-
this.imagesVisible = true;
|
|
25649
|
-
return accepted;
|
|
25650
|
-
}
|
|
25651
|
-
createSlot() {
|
|
25652
|
-
return { worker: null, busy: false, queuedRequest: null, inFlightKey: "", queuedKey: "", clearedThroughRequestId: 0, latestRequestId: 0 };
|
|
25653
|
-
}
|
|
25654
|
-
resetSlot(slot) {
|
|
25655
|
-
slot.busy = false;
|
|
25656
|
-
slot.queuedRequest = null;
|
|
25657
|
-
slot.inFlightKey = "";
|
|
25658
|
-
slot.queuedKey = "";
|
|
25659
|
-
}
|
|
25660
|
-
markWritten(key) {
|
|
25661
|
-
this.recentWrittenKeys.push(key);
|
|
25662
|
-
while (this.recentWrittenKeys.length > RECENT_WRITTEN_LIMIT)
|
|
25663
|
-
this.recentWrittenKeys.shift();
|
|
25664
|
-
}
|
|
25665
|
-
refillOutputBudget() {
|
|
25666
|
-
const now = Date.now();
|
|
25667
|
-
const elapsedMs = Math.max(0, now - this.lastBudgetAtMs);
|
|
25668
|
-
this.lastBudgetAtMs = now;
|
|
25669
|
-
this.outputBudgetBytes = Math.min(this.outputBytesPerSecond, this.outputBudgetBytes + elapsedMs / 1000 * this.outputBytesPerSecond);
|
|
25670
|
-
}
|
|
25671
|
-
isOutputBackedUp() {
|
|
25672
|
-
return Boolean(this.stdout.writableNeedDrain) || this.stdout.writableLength > this.maxOutputBacklogBytes;
|
|
25673
|
-
}
|
|
25674
|
-
stageFrame(frame) {
|
|
25675
|
-
this.pendingFrames.set(pendingLayerKey(frame.key), frame);
|
|
25676
|
-
}
|
|
25677
|
-
isKnownKey(slot, key) {
|
|
25678
|
-
return this.recentWrittenKeys.includes(key) || Array.from(this.pendingFrames.values()).some((frame) => frame.key === key) || key === slot.inFlightKey || key === slot.queuedKey;
|
|
25679
|
-
}
|
|
25680
|
-
ensureWorkersStarted() {
|
|
25681
|
-
if (this.workersStarted)
|
|
25682
|
-
return;
|
|
25683
|
-
this.workersStarted = true;
|
|
25684
|
-
this.startWorker(this.motionSlot, "static-visuals");
|
|
25685
|
-
}
|
|
25686
|
-
failWorker(name, error) {
|
|
25687
|
-
const detail = error instanceof Error ? error.message : String(error);
|
|
25688
|
-
this.fatalWorkerError ??= new Error(`OpenTUI image worker ${name} failed: ${detail}`);
|
|
25689
|
-
throw this.fatalWorkerError;
|
|
25690
|
-
}
|
|
25691
|
-
throwIfFatal() {
|
|
25692
|
-
if (this.fatalWorkerError)
|
|
25693
|
-
throw this.fatalWorkerError;
|
|
25694
|
-
}
|
|
25695
|
-
scheduleRender(slot, input, imageId, zIndex, force, imageIds) {
|
|
25696
|
-
this.throwIfFatal();
|
|
25697
|
-
const key = imageVisualFrameKey(input);
|
|
25698
|
-
if (!force && this.isKnownKey(slot, key))
|
|
25699
|
-
return;
|
|
25700
|
-
const request = {
|
|
25701
|
-
...input,
|
|
25702
|
-
imageId,
|
|
25703
|
-
...imageIds ? { imageIds } : {},
|
|
25704
|
-
zIndex,
|
|
25705
|
-
transport: this.transport,
|
|
25706
|
-
requestId: ++this.requestId,
|
|
25707
|
-
key
|
|
25708
|
-
};
|
|
25709
|
-
slot.latestRequestId = request.requestId;
|
|
25710
|
-
if (!slot.worker) {
|
|
25711
|
-
this.renderInline(slot, request);
|
|
25712
|
-
return;
|
|
25713
|
-
}
|
|
25714
|
-
this.enqueueWorkerRender(slot, request);
|
|
25715
|
-
}
|
|
25716
|
-
startWorker(slot, name) {
|
|
25717
|
-
const worker = createImageWorker();
|
|
25718
|
-
if (!worker)
|
|
25719
|
-
return;
|
|
25720
|
-
slot.worker = worker;
|
|
25721
|
-
worker.on("message", (message2) => this.handleWorkerMessage(slot, message2));
|
|
25722
|
-
worker.once("error", (error) => {
|
|
25723
|
-
if (!this.destroyed)
|
|
25724
|
-
this.fatalWorkerError ??= new Error(`OpenTUI image worker ${name} failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
25725
|
-
});
|
|
25726
|
-
worker.once("exit", (code) => {
|
|
25727
|
-
if (!this.destroyed)
|
|
25728
|
-
this.fatalWorkerError ??= new Error(`OpenTUI image worker ${name} exited unexpectedly with code ${code}.`);
|
|
25729
|
-
});
|
|
25730
|
-
}
|
|
25731
|
-
renderInline(slot, request) {
|
|
25732
|
-
try {
|
|
25733
|
-
const result = renderImageVisualFrame(request);
|
|
25734
|
-
if (result?.sequence && !this.isKnownKey(slot, result.key) && (!this.isOutputBackedUp() || pendingLayerKey(result.key) === "split")) {
|
|
25735
|
-
this.stageFrame({ key: result.key, sequence: result.sequence });
|
|
25736
|
-
this.onFrameReady?.();
|
|
25737
|
-
}
|
|
25738
|
-
} catch (error) {
|
|
25739
|
-
this.failWorker(String(request.layer ?? "visual"), error);
|
|
25740
|
-
}
|
|
25741
|
-
}
|
|
25742
|
-
enqueueWorkerRender(slot, request) {
|
|
25743
|
-
this.throwIfFatal();
|
|
25744
|
-
if (slot.busy) {
|
|
25745
|
-
slot.queuedRequest = request;
|
|
25746
|
-
slot.queuedKey = request.key;
|
|
25747
|
-
return;
|
|
25748
|
-
}
|
|
25749
|
-
this.dispatchWorkerRender(slot, request);
|
|
25750
|
-
}
|
|
25751
|
-
dispatchWorkerRender(slot, request) {
|
|
25752
|
-
this.throwIfFatal();
|
|
25753
|
-
if (!slot.worker)
|
|
25754
|
-
this.failWorker(String(request.layer ?? "visual"), new Error("worker is unavailable"));
|
|
25755
|
-
slot.busy = true;
|
|
25756
|
-
slot.inFlightKey = request.key;
|
|
25757
|
-
try {
|
|
25758
|
-
slot.worker.postMessage(request);
|
|
25759
|
-
} catch (error) {
|
|
25760
|
-
this.failWorker(String(request.layer ?? "visual"), error);
|
|
25761
|
-
}
|
|
25762
|
-
}
|
|
25763
|
-
handleWorkerMessage(slot, message2) {
|
|
25764
|
-
if (this.destroyed || !message2 || typeof message2 !== "object")
|
|
25765
|
-
return;
|
|
25766
|
-
const response = message2;
|
|
25767
|
-
slot.busy = false;
|
|
25768
|
-
slot.inFlightKey = "";
|
|
25769
|
-
const isStale = response.requestId <= slot.clearedThroughRequestId || response.requestId < slot.latestRequestId;
|
|
25770
|
-
if (!isStale) {
|
|
25771
|
-
if (response.error)
|
|
25772
|
-
this.failWorker(pendingLayerKey(response.key), new Error(response.error));
|
|
25773
|
-
if (response.sequence && !this.isKnownKey(slot, response.key) && (!this.isOutputBackedUp() || pendingLayerKey(response.key) === "split")) {
|
|
25774
|
-
this.stageFrame({ key: response.key, sequence: response.sequence });
|
|
25775
|
-
this.onFrameReady?.();
|
|
25776
|
-
}
|
|
25777
|
-
}
|
|
25778
|
-
const next = slot.queuedRequest;
|
|
25779
|
-
slot.queuedRequest = null;
|
|
25780
|
-
slot.queuedKey = "";
|
|
25781
|
-
if (next && !this.isKnownKey(slot, next.key))
|
|
25782
|
-
this.dispatchWorkerRender(slot, next);
|
|
25783
|
-
}
|
|
25784
|
-
}
|
|
25785
|
-
function pixelSizeForRenderer(renderer) {
|
|
25786
|
-
const resolution = renderer.resolution;
|
|
25787
|
-
const base = resolution?.width && resolution?.height ? resolution : { width: renderer.width * 12, height: renderer.height * 24 };
|
|
25788
|
-
const scale = imageResolutionScale();
|
|
25789
|
-
return {
|
|
25790
|
-
width: Math.max(renderer.width, Math.floor(base.width * scale)),
|
|
25791
|
-
height: Math.max(renderer.height, Math.floor(base.height * scale))
|
|
25792
|
-
};
|
|
25793
|
-
}
|
|
25794
|
-
function forceModernImageVisuals() {
|
|
25795
|
-
return getRigTerminalCapabilities().supportsKittyImages;
|
|
25796
|
-
}
|
|
25797
|
-
var PANEL_MASK_RADIUS_MIN = 14, PANEL_MASK_RADIUS_MAX = 34, PANEL_MASK_RADIUS_FACTOR = 0.035, PANEL_BLUR_RADIUS_MIN = 8, PANEL_BLUR_RADIUS_MAX = 28, PANEL_BLUR_RADIUS_FACTOR = 0.018, BG, PANEL, PANEL_HEADER, PANEL_LINE2, LIME, LIME_DIM, CYAN, MAGENTA, INK_DIM, PNG_SIGNATURE, CRC_TABLE, MAX_IMAGE_BYTES, KITTY_CHUNK_SIZE = 4096, PANEL_BLUR_SCALE = 1, PANEL_MASK_CACHE_LIMIT = 16, ZLIB_LEVEL = 1, DEFAULT_IMAGE_RESOLUTION_SCALE = 1, LOAD_BUCKETS = 5, panelMaskCache, BG_WORD, ASCII_GLYPHS, RIG_GLYPH_STROKES, RECENT_WRITTEN_LIMIT = 24, DEFAULT_IMAGE_OUTPUT_BACKLOG_BYTES, DEFAULT_IMAGE_OUTPUT_BYTES_PER_SECOND;
|
|
25798
|
-
var init_image_visual_layer = __esm(() => {
|
|
25799
|
-
init_terminal_capabilities();
|
|
25800
|
-
init_ascii_fleet();
|
|
25801
|
-
init_constants();
|
|
25802
|
-
BG = [7, 8, 9, 255];
|
|
25803
|
-
PANEL = [16, 17, 21, 184];
|
|
25804
|
-
PANEL_HEADER = [16, 17, 21, 190];
|
|
25805
|
-
PANEL_LINE2 = [255, 255, 255, 24];
|
|
25806
|
-
LIME = [204, 255, 77, 255];
|
|
25807
|
-
LIME_DIM = [169, 214, 63, 255];
|
|
25808
|
-
CYAN = [86, 216, 255, 255];
|
|
25809
|
-
MAGENTA = [255, 121, 176, 255];
|
|
25810
|
-
INK_DIM = [108, 110, 121, 255];
|
|
25811
|
-
PNG_SIGNATURE = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]);
|
|
25812
|
-
CRC_TABLE = makeCrcTable();
|
|
25813
|
-
MAX_IMAGE_BYTES = 48 * 1024 * 1024;
|
|
25814
|
-
panelMaskCache = new Map;
|
|
25815
|
-
BG_WORD = rgbaWord(BG);
|
|
25816
|
-
ASCII_GLYPHS = {
|
|
25817
|
-
".": ["00000", "00000", "00000", "00000", "00000", "00100", "00100"],
|
|
25818
|
-
"'": ["00100", "00100", "00000", "00000", "00000", "00000", "00000"],
|
|
25819
|
-
"-": ["00000", "00000", "00000", "11111", "00000", "00000", "00000"],
|
|
25820
|
-
_: ["00000", "00000", "00000", "00000", "00000", "00000", "11111"],
|
|
25821
|
-
"=": ["00000", "11111", "00000", "00000", "11111", "00000", "00000"],
|
|
25822
|
-
"|": ["00100", "00100", "00100", "00100", "00100", "00100", "00100"],
|
|
25823
|
-
"/": ["00001", "00010", "00010", "00100", "01000", "01000", "10000"],
|
|
25824
|
-
"\\": ["10000", "01000", "01000", "00100", "00010", "00010", "00001"],
|
|
25825
|
-
"(": ["00010", "00100", "01000", "01000", "01000", "00100", "00010"],
|
|
25826
|
-
")": ["01000", "00100", "00010", "00010", "00010", "00100", "01000"],
|
|
25827
|
-
"!": ["00100", "00100", "00100", "00100", "00100", "00000", "00100"],
|
|
25828
|
-
"%": ["11001", "11010", "00100", "01000", "10110", "00110", "00000"],
|
|
25829
|
-
$: ["00100", "11110", "10100", "11110", "00101", "11110", "00100"],
|
|
25830
|
-
"@": ["01110", "10001", "10111", "10101", "10111", "10000", "01111"],
|
|
25831
|
-
o: ["00000", "01110", "10001", "10001", "10001", "01110", "00000"],
|
|
25832
|
-
"*": ["00100", "10101", "01110", "11111", "01110", "10101", "00100"]
|
|
25833
|
-
};
|
|
25834
|
-
RIG_GLYPH_STROKES = {
|
|
25835
|
-
R: [[0, 0, 0, 1], [0, 0, 0.82, 0], [0.82, 0, 0.82, 0.5], [0, 0.5, 0.82, 0.5], [0.36, 0.5, 0.92, 1]],
|
|
25836
|
-
I: [[0.5, 0, 0.5, 1], [0.18, 0, 0.82, 0], [0.18, 1, 0.82, 1]],
|
|
25837
|
-
G: [[0.92, 0.08, 0.12, 0], [0.12, 0, 0.12, 1], [0.12, 1, 0.92, 1], [0.92, 0.5, 0.92, 1], [0.5, 0.5, 0.92, 0.5]]
|
|
25838
|
-
};
|
|
25839
|
-
DEFAULT_IMAGE_OUTPUT_BACKLOG_BYTES = 256 * 1024;
|
|
25840
|
-
DEFAULT_IMAGE_OUTPUT_BYTES_PER_SECOND = 850 * 1024;
|
|
25841
|
-
});
|
|
25842
|
-
|
|
25843
24866
|
// packages/cli/src/app-opentui/render/text.ts
|
|
25844
24867
|
import { RGBA as RGBA4, TextAttributes as TextAttributes4, TextRenderable } from "@opentui/core";
|
|
25845
24868
|
function selectableMouseHandler(currentLineRef, onLineMouseDown) {
|
|
@@ -27044,7 +26067,7 @@ function __renderSceneForTest(renderer, state, sceneRenderers) {
|
|
|
27044
26067
|
renderer.root.add(navText);
|
|
27045
26068
|
const registry = buildSceneRendererRegistry(sceneRenderers);
|
|
27046
26069
|
const transition = { scene: state.scene, startedAtMs: 0, minUntilMs: 0 };
|
|
27047
|
-
const selectables = renderNow(renderer, null, null,
|
|
26070
|
+
const selectables = renderNow(renderer, null, null, scrollPanels, null, null, navText, textLines, nativeHost, state, registry, transition);
|
|
27048
26071
|
return { selectables, nativeHost };
|
|
27049
26072
|
}
|
|
27050
26073
|
async function launchRigOpenTuiApp(options) {
|
|
@@ -27056,7 +26079,6 @@ async function launchRigOpenTuiApp(options) {
|
|
|
27056
26079
|
const events = createAppEventBus();
|
|
27057
26080
|
let renderer = null;
|
|
27058
26081
|
let graphics = null;
|
|
27059
|
-
let imageVisuals = null;
|
|
27060
26082
|
let preloaderBackdrop = null;
|
|
27061
26083
|
const scrollPanels = [];
|
|
27062
26084
|
let typeBar = null;
|
|
@@ -27084,7 +26106,7 @@ async function launchRigOpenTuiApp(options) {
|
|
|
27084
26106
|
if (!renderer || destroyed)
|
|
27085
26107
|
return;
|
|
27086
26108
|
const currentState = store.getState();
|
|
27087
|
-
renderedSelectableItems = renderNow(renderer, graphics,
|
|
26109
|
+
renderedSelectableItems = renderNow(renderer, graphics, preloaderBackdrop, scrollPanels, typeBar, brandText, navText, textLines, nativeHost, currentState, sceneRendererRegistry, preloaderTransition, scheduleAppRender);
|
|
27088
26110
|
focusManager.restoreTypeBarFocus(typeBar, { hidden: currentState.scene === "handoff" });
|
|
27089
26111
|
maybeRedirectFromUnresolvedScene(currentState);
|
|
27090
26112
|
};
|
|
@@ -27244,18 +26266,8 @@ async function launchRigOpenTuiApp(options) {
|
|
|
27244
26266
|
});
|
|
27245
26267
|
renderer.setTerminalTitle?.("Operator cockpit");
|
|
27246
26268
|
const layout = computeStageLayout(renderer.width, renderer.height);
|
|
27247
|
-
|
|
27248
|
-
|
|
27249
|
-
const flushImageVisuals = async () => {
|
|
27250
|
-
imageVisuals?.flush();
|
|
27251
|
-
};
|
|
27252
|
-
renderer.setFrameCallback(flushImageVisuals);
|
|
27253
|
-
resources.add(() => renderer?.removeFrameCallback(flushImageVisuals));
|
|
27254
|
-
}
|
|
27255
|
-
if (!imageVisuals?.enabled) {
|
|
27256
|
-
graphics = createGraphicsLayer(renderer, layout);
|
|
27257
|
-
renderer.root.add(graphics);
|
|
27258
|
-
}
|
|
26269
|
+
graphics = createGraphicsLayer(renderer, layout);
|
|
26270
|
+
renderer.root.add(graphics);
|
|
27259
26271
|
preloaderBackdrop = new BoxRenderable3(renderer, {
|
|
27260
26272
|
id: "rig-preloader-backdrop",
|
|
27261
26273
|
position: "absolute",
|
|
@@ -27381,7 +26393,6 @@ async function launchRigOpenTuiApp(options) {
|
|
|
27381
26393
|
stopActivePiHost("renderer destroyed");
|
|
27382
26394
|
stopActiveCommandHost("renderer destroyed");
|
|
27383
26395
|
destroyNativeHost(nativeHost);
|
|
27384
|
-
imageVisuals?.destroy();
|
|
27385
26396
|
if (renderTimer)
|
|
27386
26397
|
clearTimeout(renderTimer);
|
|
27387
26398
|
renderTimer = null;
|
|
@@ -27430,14 +26441,13 @@ async function launchRigOpenTuiApp(options) {
|
|
|
27430
26441
|
clearTimeout(renderTimer);
|
|
27431
26442
|
renderTimer = null;
|
|
27432
26443
|
resources.disposeAll();
|
|
27433
|
-
imageVisuals?.destroy();
|
|
27434
26444
|
stopActivePiHost("app shutdown");
|
|
27435
26445
|
stopActiveCommandHost("app shutdown");
|
|
27436
26446
|
if (renderer && !renderer.isDestroyed)
|
|
27437
26447
|
renderer.destroy();
|
|
27438
26448
|
}
|
|
27439
26449
|
}
|
|
27440
|
-
function renderNow(renderer, graphics,
|
|
26450
|
+
function renderNow(renderer, graphics, preloaderBackdrop, scrollPanels, typeBar, brandText, navText, textLines, nativeHost, state, sceneRendererRegistry, preloaderTransition, scheduleRenderAfter) {
|
|
27441
26451
|
const layout = computeStageLayout(renderer.width, renderer.height);
|
|
27442
26452
|
const hideNav = () => {
|
|
27443
26453
|
if (navText)
|
|
@@ -27446,7 +26456,6 @@ function renderNow(renderer, graphics, imageVisuals, preloaderBackdrop, scrollPa
|
|
|
27446
26456
|
if (layout.tooSmall) {
|
|
27447
26457
|
if (graphics)
|
|
27448
26458
|
clearGraphicsLayer(graphics);
|
|
27449
|
-
imageVisuals?.clear();
|
|
27450
26459
|
if (preloaderBackdrop)
|
|
27451
26460
|
preloaderBackdrop.visible = false;
|
|
27452
26461
|
if (brandText)
|
|
@@ -27480,8 +26489,7 @@ function renderNow(renderer, graphics, imageVisuals, preloaderBackdrop, scrollPa
|
|
|
27480
26489
|
preloaderTransition.minUntilMs = now;
|
|
27481
26490
|
const targetFrame = renderState.typeBar.mode === "command" ? commandPaletteFrame(renderState, layout) : rendererForScene(renderState.scene, sceneRendererRegistry)(renderState, layout);
|
|
27482
26491
|
const targetContentLayout = targetFrame.fullScreen ? { ...layout, centerWidth: layout.width, centerLeft: 0, centerTop: 0, centerHeight: Math.min(layout.height, MAX_SCENE_LINES) } : layout;
|
|
27483
|
-
const
|
|
27484
|
-
let targetVisualReady = true;
|
|
26492
|
+
const targetVisualReady = true;
|
|
27485
26493
|
const fleetStats = fleetStatsFromState(state);
|
|
27486
26494
|
const fleetLoad = fleetStats.load;
|
|
27487
26495
|
const fleetActive = fleetStats.active;
|
|
@@ -27491,23 +26499,7 @@ function renderNow(renderer, graphics, imageVisuals, preloaderBackdrop, scrollPa
|
|
|
27491
26499
|
if (renderState.scene === "command") {
|
|
27492
26500
|
getActiveCommandHost()?.resize(Math.max(40, targetContentLayout.centerWidth - 12), Math.max(10, targetContentLayout.centerHeight - 6));
|
|
27493
26501
|
}
|
|
27494
|
-
if (imageVisuals && targetFrame.terminalActive) {
|
|
27495
|
-
imageVisuals.clear();
|
|
27496
|
-
} else if (imageVisuals && !targetFrame.fullScreen && !sceneJustChanged) {
|
|
27497
|
-
const visualInput = {
|
|
27498
|
-
layout: targetContentLayout,
|
|
27499
|
-
pixelSize: pixelSizeForRenderer(renderer),
|
|
27500
|
-
panels: targetPanelsForImages,
|
|
27501
|
-
scene: state.scene,
|
|
27502
|
-
tick: state.tick,
|
|
27503
|
-
load: fleetLoad,
|
|
27504
|
-
activeRuns: fleetActive
|
|
27505
|
-
};
|
|
27506
|
-
imageVisuals.render(visualInput);
|
|
27507
|
-
targetVisualReady = imageVisuals.isReady(visualInput);
|
|
27508
|
-
}
|
|
27509
26502
|
const preloaderActive = sceneJustChanged && !cachedFastPath || isPreloaderActive(preloaderTransition, targetVisualReady, now);
|
|
27510
|
-
imageVisuals?.setFlushPaused(preloaderActive);
|
|
27511
26503
|
const frame = preloaderActive ? renderAsciiPreloaderFrame(renderState.scene, layout, state.tick) : targetFrame;
|
|
27512
26504
|
if (graphics) {
|
|
27513
26505
|
resizeGraphicsLayer(graphics, layout);
|
|
@@ -27606,7 +26598,6 @@ var init_runtime = __esm(() => {
|
|
|
27606
26598
|
init_theme2();
|
|
27607
26599
|
init_graphics();
|
|
27608
26600
|
init_fleet_stats();
|
|
27609
|
-
init_image_visual_layer();
|
|
27610
26601
|
init_text();
|
|
27611
26602
|
init_panels();
|
|
27612
26603
|
init_type_bar();
|
|
@@ -27666,68 +26657,42 @@ function isTerminalScene(scene) {
|
|
|
27666
26657
|
}
|
|
27667
26658
|
function Backdrop(props) {
|
|
27668
26659
|
const renderer = useRenderer();
|
|
27669
|
-
const imageRef = useRef(null);
|
|
27670
26660
|
const graphicsRef = useRef(null);
|
|
27671
26661
|
useEffect(() => {
|
|
27672
|
-
const
|
|
27673
|
-
|
|
27674
|
-
|
|
27675
|
-
|
|
27676
|
-
const layout = computeStageLayout(renderer.width, renderer.height);
|
|
27677
|
-
const graphics = createGraphicsLayer(renderer, layout);
|
|
27678
|
-
renderer.root.add(graphics);
|
|
27679
|
-
graphicsRef.current = graphics;
|
|
27680
|
-
}
|
|
26662
|
+
const layout = computeStageLayout(renderer.width, renderer.height);
|
|
26663
|
+
const graphics = createGraphicsLayer(renderer, layout);
|
|
26664
|
+
renderer.root.add(graphics);
|
|
26665
|
+
graphicsRef.current = graphics;
|
|
27681
26666
|
return () => {
|
|
27682
|
-
|
|
27683
|
-
|
|
27684
|
-
if (graphics) {
|
|
26667
|
+
const g = graphicsRef.current;
|
|
26668
|
+
if (g) {
|
|
27685
26669
|
try {
|
|
27686
|
-
renderer.root.remove(
|
|
26670
|
+
renderer.root.remove(g.id);
|
|
27687
26671
|
} catch {}
|
|
27688
26672
|
}
|
|
27689
|
-
imageRef.current = null;
|
|
27690
26673
|
graphicsRef.current = null;
|
|
27691
26674
|
};
|
|
27692
26675
|
}, [renderer]);
|
|
27693
26676
|
useEffect(() => {
|
|
27694
|
-
const layout = computeStageLayout(renderer.width, renderer.height);
|
|
27695
|
-
const image = imageRef.current;
|
|
27696
26677
|
const graphics = graphicsRef.current;
|
|
26678
|
+
if (!graphics)
|
|
26679
|
+
return;
|
|
26680
|
+
const layout = computeStageLayout(renderer.width, renderer.height);
|
|
27697
26681
|
if (layout.tooSmall) {
|
|
27698
|
-
|
|
27699
|
-
if (graphics)
|
|
27700
|
-
clearGraphicsLayer(graphics);
|
|
26682
|
+
clearGraphicsLayer(graphics);
|
|
27701
26683
|
return;
|
|
27702
26684
|
}
|
|
27703
26685
|
const stats = fleetStatsFromState(props.state);
|
|
27704
|
-
const
|
|
27705
|
-
const animationTick = Math.floor(tick / ANIMATION_SLOWDOWN2);
|
|
26686
|
+
const animationTick = Math.floor(props.state.tick / ANIMATION_SLOWDOWN2);
|
|
27706
26687
|
const panels = (props.frame.panels ?? []).map((panel) => ({ ...panel }));
|
|
27707
26688
|
const terminalActive = props.frame.terminalActive ?? isTerminalScene(props.state.scene);
|
|
27708
26689
|
const fullScreen = Boolean(props.frame.fullScreen);
|
|
27709
|
-
|
|
27710
|
-
|
|
27711
|
-
|
|
27712
|
-
|
|
27713
|
-
|
|
27714
|
-
|
|
27715
|
-
pixelSize: pixelSizeForRenderer(renderer),
|
|
27716
|
-
panels,
|
|
27717
|
-
scene: props.state.scene,
|
|
27718
|
-
tick,
|
|
27719
|
-
load: stats.load,
|
|
27720
|
-
activeRuns: stats.active
|
|
27721
|
-
});
|
|
27722
|
-
}
|
|
27723
|
-
} else if (graphics) {
|
|
27724
|
-
resizeGraphicsLayer(graphics, layout);
|
|
27725
|
-
if (terminalActive || fullScreen) {
|
|
27726
|
-
clearGraphicsLayer(graphics);
|
|
27727
|
-
} else {
|
|
27728
|
-
drawAmbientField(graphics, layout, animationTick, props.state.scene, stats.load, stats.active);
|
|
27729
|
-
drawPanelChrome(graphics, layout, panels);
|
|
27730
|
-
}
|
|
26690
|
+
resizeGraphicsLayer(graphics, layout);
|
|
26691
|
+
if (terminalActive || fullScreen) {
|
|
26692
|
+
clearGraphicsLayer(graphics);
|
|
26693
|
+
} else {
|
|
26694
|
+
drawAmbientField(graphics, layout, animationTick, props.state.scene, stats.load, stats.active);
|
|
26695
|
+
drawPanelChrome(graphics, layout, panels);
|
|
27731
26696
|
}
|
|
27732
26697
|
});
|
|
27733
26698
|
return null;
|
|
@@ -27735,7 +26700,6 @@ function Backdrop(props) {
|
|
|
27735
26700
|
var ANIMATION_SLOWDOWN2 = 1;
|
|
27736
26701
|
var init_Backdrop = __esm(() => {
|
|
27737
26702
|
init_graphics();
|
|
27738
|
-
init_image_visual_layer();
|
|
27739
26703
|
init_fleet_stats();
|
|
27740
26704
|
});
|
|
27741
26705
|
|