From e17344af63b8c4a5f29368533c585006b2228a93 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Sat, 23 May 2026 22:21:26 +0100 Subject: [PATCH] implements PLN-0083 --- discussion/index.ndjson | 2 +- ...ba8888-glyph-payload-emission-and-sizes.md | 16 +++---- .../FileSystemPackerWorkspaceService.java | 44 ++++++++++--------- 3 files changed, 33 insertions(+), 29 deletions(-) diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 5d67a3e2..478ea486 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,5 +1,5 @@ {"type":"meta","next_id":{"DSC":39,"AGD":42,"DEC":38,"PLN":87,"LSN":53,"CLSN":1}} -{"type":"discussion","id":"DSC-0038","status":"open","ticket":"studio-packer-rgba8888-asset-pipeline","title":"Studio and Packer RGBA8888 Asset Pipeline Alignment","created_at":"2026-05-23","updated_at":"2026-05-23","tags":["studio","packer","assets","glyph-bank","palette","rgba8888","runtime-alignment"],"agendas":[{"id":"AGD-0041","file":"AGD-0041-studio-packer-rgba8888-asset-pipeline.md","status":"accepted","created_at":"2026-05-23","updated_at":"2026-05-23"}],"decisions":[{"id":"DEC-0037","file":"DEC-0037-studio-packer-rgba8888-asset-pipeline.md","status":"accepted","created_at":"2026-05-23","updated_at":"2026-05-23","ref_agenda":"AGD-0041"}],"plans":[{"id":"PLN-0081","file":"PLN-0081-rgba8888-packer-and-studio-spec-propagation.md","status":"done","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0037"]},{"id":"PLN-0082","file":"PLN-0082-rgba8888-palette-model-and-argb-conversion.md","status":"done","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0037"]},{"id":"PLN-0083","file":"PLN-0083-rgba8888-glyph-payload-emission-and-sizes.md","status":"review","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0037"]},{"id":"PLN-0084","file":"PLN-0084-rgba8888-packer-projections-and-workspace-apis.md","status":"review","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0037"]},{"id":"PLN-0085","file":"PLN-0085-rgba8888-tests-fixtures-and-conformance.md","status":"review","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0037"]},{"id":"PLN-0086","file":"PLN-0086-rgba8888-final-integration-and-residue-removal.md","status":"review","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0037"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0038","status":"open","ticket":"studio-packer-rgba8888-asset-pipeline","title":"Studio and Packer RGBA8888 Asset Pipeline Alignment","created_at":"2026-05-23","updated_at":"2026-05-23","tags":["studio","packer","assets","glyph-bank","palette","rgba8888","runtime-alignment"],"agendas":[{"id":"AGD-0041","file":"AGD-0041-studio-packer-rgba8888-asset-pipeline.md","status":"accepted","created_at":"2026-05-23","updated_at":"2026-05-23"}],"decisions":[{"id":"DEC-0037","file":"DEC-0037-studio-packer-rgba8888-asset-pipeline.md","status":"accepted","created_at":"2026-05-23","updated_at":"2026-05-23","ref_agenda":"AGD-0041"}],"plans":[{"id":"PLN-0081","file":"PLN-0081-rgba8888-packer-and-studio-spec-propagation.md","status":"done","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0037"]},{"id":"PLN-0082","file":"PLN-0082-rgba8888-palette-model-and-argb-conversion.md","status":"done","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0037"]},{"id":"PLN-0083","file":"PLN-0083-rgba8888-glyph-payload-emission-and-sizes.md","status":"done","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0037"]},{"id":"PLN-0084","file":"PLN-0084-rgba8888-packer-projections-and-workspace-apis.md","status":"review","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0037"]},{"id":"PLN-0085","file":"PLN-0085-rgba8888-tests-fixtures-and-conformance.md","status":"review","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0037"]},{"id":"PLN-0086","file":"PLN-0086-rgba8888-final-integration-and-residue-removal.md","status":"review","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0037"]}],"lessons":[]} {"type":"discussion","id":"DSC-0037","status":"done","ticket":"pbs-autocomplete-parameter-names","title":"PBS autocomplete parameter names for stdlib and method calls","created_at":"2026-05-08","updated_at":"2026-05-14","tags":["compiler-pbs","studio","lsp","autocomplete","signature-help","stdlib"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0052","file":"discussion/lessons/DSC-0037-pbs-autocomplete-parameter-names/LSN-0052-canonical-callable-parameter-names-through-pbs-editor-assistance.md","status":"done","created_at":"2026-05-14","updated_at":"2026-05-14"}]} {"type":"discussion","id":"DSC-0036","status":"open","ticket":"pbs-symbol-documentation-and-hover-markdown","title":"Modelo de documentacao de simbolos em PBS e consumo markdown no hover","created_at":"2026-05-08","updated_at":"2026-05-08","tags":["compiler","compiler-pbs","studio","lsp","vscode","editor","hover","documentation","markdown"],"agendas":[{"id":"AGD-0039","file":"AGD-0039-pbs-symbol-documentation-and-hover-markdown.md","status":"open","created_at":"2026-05-08","updated_at":"2026-05-08"}],"decisions":[],"plans":[],"lessons":[]} {"type":"discussion","id":"DSC-0035","status":"done","ticket":"pbs-lsp-editor-assistance-wave-1","title":"Wave 1 de assistencia editorial via LSP para PBS no VS Code","created_at":"2026-05-08","updated_at":"2026-05-08","tags":["studio","lsp","vscode","compiler","compiler-pbs","editor","completion","hover","signature-help"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0051","file":"discussion/lessons/DSC-0035-pbs-lsp-editor-assistance-wave-1/LSN-0051-compiler-backed-editor-assistance-for-pbs.md","status":"done","created_at":"2026-05-08","updated_at":"2026-05-08"}]} diff --git a/discussion/workflow/plans/PLN-0083-rgba8888-glyph-payload-emission-and-sizes.md b/discussion/workflow/plans/PLN-0083-rgba8888-glyph-payload-emission-and-sizes.md index 36f4d493..8ada8be9 100644 --- a/discussion/workflow/plans/PLN-0083-rgba8888-glyph-payload-emission-and-sizes.md +++ b/discussion/workflow/plans/PLN-0083-rgba8888-glyph-payload-emission-and-sizes.md @@ -2,9 +2,9 @@ id: PLN-0083 ticket: studio-packer-rgba8888-asset-pipeline title: RGBA8888 Glyph Payload Emission and Size Accounting -status: review +status: done created: 2026-05-23 -completed: +completed: 2026-05-23 ref_decisions: - DEC-0037 tags: @@ -126,12 +126,12 @@ index into the referenced glyph palette. ## Acceptance Criteria -- [ ] Glyph payloads keep `GLYPH/indexed_v1`. -- [ ] Glyph palette blocks are 4096 bytes. -- [ ] Palette entries are emitted as RGBA bytes in runtime channel order. -- [ ] No synthetic magenta/color-key value is emitted. -- [ ] Size and decoded-size metadata match the new payload length. -- [ ] Scene `palette_id` payload shape is unchanged. +- [x] Glyph payloads keep `GLYPH/indexed_v1`. +- [x] Glyph palette blocks are 4096 bytes. +- [x] Palette entries are emitted as RGBA bytes in runtime channel order. +- [x] No synthetic magenta/color-key value is emitted. +- [x] Size and decoded-size metadata match the new payload length. +- [x] Scene `palette_id` payload shape is unchanged. ## Dependencies diff --git a/prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java b/prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java index b065946d..5bced46c 100644 --- a/prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java +++ b/prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java @@ -38,7 +38,11 @@ import java.util.*; import java.util.stream.Stream; public final class FileSystemPackerWorkspaceService implements PackerWorkspaceService { - private static final int GLYPH_BANK_COLOR_KEY_RGB565 = 0xF81F; + private static final int GLYPH_BANK_PALETTE_COUNT = 64; + private static final int GLYPH_BANK_COLORS_PER_PALETTE = 16; + private static final int GLYPH_BANK_RGBA8888_BYTES_PER_COLOR = 4; + private static final int GLYPH_BANK_PALETTE_BYTES = + GLYPH_BANK_PALETTE_COUNT * GLYPH_BANK_COLORS_PER_PALETTE * GLYPH_BANK_RGBA8888_BYTES_PER_COLOR; private static final String SCENE_BANK_SUPPORT_FILE = "scene-bank.studio.json"; private static final String SCENE_PACK_REQUEST_FILE = "scene-bank.pack-request.json"; @@ -1091,7 +1095,7 @@ public final class FileSystemPackerWorkspaceService implements PackerWorkspaceSe final byte[] sheetPixels = new byte[width * height]; final Map selectedByPath = new LinkedHashMap<>(); runtimeAsset.walkProjection().buildCandidateFiles().forEach(file -> selectedByPath.put(file.relativePath(), file)); - final Map declaredPaletteIndexByRgb = declaredPaletteIndexByRgb(declaration); + final Map declaredPaletteIndexByRgba = declaredPaletteIndexByRgba(declaration); declaration.artifacts().stream() .sorted(Comparator.comparingInt(PackerAssetArtifactSelection::index)) @@ -1108,7 +1112,7 @@ public final class FileSystemPackerWorkspaceService implements PackerWorkspaceSe tile, walkFile.metadata().get("palette"), artifact.file(), - declaredPaletteIndexByRgb); + declaredPaletteIndexByRgba); final int tileX = (artifact.index() % tilesPerRow) * tileSize; final int tileY = (artifact.index() / tilesPerRow) * tileSize; for (int localY = 0; localY < tile.height(); localY += 1) { @@ -1130,7 +1134,7 @@ public final class FileSystemPackerWorkspaceService implements PackerWorkspaceSe runtimeMetadata.put("tile_size", tileSize); runtimeMetadata.put("width", width); runtimeMetadata.put("height", height); - runtimeMetadata.put("palette_count", 64); + runtimeMetadata.put("palette_count", GLYPH_BANK_PALETTE_COUNT); runtimeMetadata.put("palette_authored", countAuthoredGlyphBankPalettes(declaration)); runtimeMetadata.put("codec", Map.of()); declaration.outputMetadata().forEach((key, value) -> { @@ -1150,7 +1154,7 @@ public final class FileSystemPackerWorkspaceService implements PackerWorkspaceSe "GLYPH", "NONE", payload, - width * height + 2048, + width * height + GLYPH_BANK_PALETTE_BYTES, runtimeMetadata, toolingMetadata, declaration.preloadEnabled()); @@ -1160,7 +1164,7 @@ public final class FileSystemPackerWorkspaceService implements PackerWorkspaceSe PackerTileIndexedV1 tile, Object paletteMetadata, String artifactFile, - Map declaredPaletteIndexByRgb) { + Map declaredPaletteIndexByRgba) { final int[] rgba8888 = paletteColors(paletteMetadata); if (rgba8888.length == 0) { throw new IllegalStateException("Selected tile artifact is missing palette metadata required for palette remapping: " + artifactFile); @@ -1172,7 +1176,7 @@ public final class FileSystemPackerWorkspaceService implements PackerWorkspaceSe throw new IllegalStateException("Tile palette index exceeds discovered palette size for artifact: " + artifactFile); } final int rgba = rgba8888[paletteIndex]; - final Integer materialIndex = declaredPaletteIndexByRgb.get(rgba); + final Integer materialIndex = declaredPaletteIndexByRgba.get(rgba); if (materialIndex == null || materialIndex < 0 || materialIndex > 15) { throw new IllegalStateException("Unable to resolve canonical palette index for artifact color in " + artifactFile); } @@ -1181,7 +1185,7 @@ public final class FileSystemPackerWorkspaceService implements PackerWorkspaceSe return remapped; } - private Map declaredPaletteIndexByRgb(PackerAssetDeclaration declaration) { + private Map declaredPaletteIndexByRgba(PackerAssetDeclaration declaration) { final JsonNode palettesNode = declaration.outputPipelineMetadata().get("palettes"); if (!(palettesNode instanceof ArrayNode palettesArray) || palettesArray.isEmpty()) { throw new IllegalStateException("Glyph packing requires at least one declared pipeline palette."); @@ -1272,7 +1276,7 @@ public final class FileSystemPackerWorkspaceService implements PackerWorkspaceSe } private byte[] emitGlyphBankPalettes(PackerAssetDeclaration declaration) { - final byte[] bytes = new byte[64 * 16 * 2]; + final byte[] bytes = new byte[GLYPH_BANK_PALETTE_BYTES]; final JsonNode palettesNode = declaration.outputPipelineMetadata().get("palettes"); if (!(palettesNode instanceof com.fasterxml.jackson.databind.node.ArrayNode palettesArray)) { return bytes; @@ -1284,21 +1288,21 @@ public final class FileSystemPackerWorkspaceService implements PackerWorkspaceSe continue; } final int paletteIndex = indexNode.intValue(); - if (paletteIndex < 0 || paletteIndex >= 64) { + if (paletteIndex < 0 || paletteIndex >= GLYPH_BANK_PALETTE_COUNT) { continue; } - final int paletteBaseOffset = (paletteIndex * 16) * 2; - bytes[paletteBaseOffset] = (byte) (GLYPH_BANK_COLOR_KEY_RGB565 & 0xFF); - bytes[paletteBaseOffset + 1] = (byte) ((GLYPH_BANK_COLOR_KEY_RGB565 >>> 8) & 0xFF); - final JsonNode convertedNode = paletteNode.path("convertedRgb565"); - if (!convertedNode.isArray()) { + final JsonNode rgbaNode = paletteNode.path("rgba8888"); + if (!rgbaNode.isArray()) { continue; } - for (int colorIndex = 0; colorIndex < Math.min(15, convertedNode.size()); colorIndex += 1) { - final int rgb565 = convertedNode.get(colorIndex).asInt(0); - final int baseOffset = ((paletteIndex * 16) + colorIndex + 1) * 2; - bytes[baseOffset] = (byte) (rgb565 & 0xFF); - bytes[baseOffset + 1] = (byte) ((rgb565 >>> 8) & 0xFF); + for (int colorIndex = 0; colorIndex < Math.min(GLYPH_BANK_COLORS_PER_PALETTE, rgbaNode.size()); colorIndex += 1) { + final int rgba = rgbaNode.get(colorIndex).asInt(0); + final int baseOffset = ((paletteIndex * GLYPH_BANK_COLORS_PER_PALETTE) + colorIndex) + * GLYPH_BANK_RGBA8888_BYTES_PER_COLOR; + bytes[baseOffset] = (byte) ((rgba >>> 24) & 0xFF); + bytes[baseOffset + 1] = (byte) ((rgba >>> 16) & 0xFF); + bytes[baseOffset + 2] = (byte) ((rgba >>> 8) & 0xFF); + bytes[baseOffset + 3] = (byte) (rgba & 0xFF); } } return bytes;