From 8de96a86d292675eb383d15689cd429b9b4c62c1 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Fri, 24 Apr 2026 16:53:56 +0100 Subject: [PATCH] Reshuffle GUI workspace layout --- frontend/src/app.ts | 51 ++---- src/repixelizer/gui_static/app.js | 35 +---- src/repixelizer/gui_static/index.html | 218 +++++++++++++------------- src/repixelizer/gui_static/styles.css | 4 +- 4 files changed, 130 insertions(+), 178 deletions(-) diff --git a/frontend/src/app.ts b/frontend/src/app.ts index 7952b50..1a476f3 100644 --- a/frontend/src/app.ts +++ b/frontend/src/app.ts @@ -49,7 +49,6 @@ type AppState = { inputPreviewImage: ImageAsset | null; sourceImage: ImageAsset | null; preprocessedImage: ImageAsset | null; - edgeMapImage: ImageAsset | null; latticeImage: ImageAsset | null; guidanceImage: ImageAsset | null; inference: InferencePayload | null; @@ -67,7 +66,6 @@ type AppState = { altHeld: boolean; zoom: number; showGrid: boolean; - currentStage: string; }; type ViewportAnchor = { @@ -98,10 +96,8 @@ const stepSlider = byId("stepSlider"); const stepValue = byId("stepValue"); const lossCanvas = byId("lossCanvas"); const leftCanvas = byId("leftCanvas"); -const middleCanvas = byId("middleCanvas"); const rightCanvas = byId("rightCanvas"); const leftVizLabel = byId("leftVizLabel"); -const middleVizLabel = byId("middleVizLabel"); const rightVizLabel = byId("rightVizLabel"); const metricsPanel = byId("metricsPanel"); const paintSwatch = byId("paintSwatch"); @@ -161,7 +157,6 @@ const state: AppState = { inputPreviewImage: null, sourceImage: null, preprocessedImage: null, - edgeMapImage: null, latticeImage: null, guidanceImage: null, inference: null, @@ -179,7 +174,6 @@ const state: AppState = { altHeld: false, zoom: Number(zoomInput.value), showGrid: gridToggle.checked, - currentStage: "Idle", }; let currentEventSource: EventSource | null = null; @@ -249,7 +243,6 @@ function resetRunArtifacts(): void { state.jobId = null; state.sourceImage = null; state.preprocessedImage = null; - state.edgeMapImage = null; state.latticeImage = null; state.guidanceImage = null; state.inference = null; @@ -263,7 +256,6 @@ function resetRunArtifacts(): void { state.eventLog = []; state.editorBaseAsset = null; state.editorDirty = false; - state.currentStage = "Waiting"; } function parseOptionalInteger(input: HTMLInputElement): number | null { @@ -479,10 +471,8 @@ function renderSummary(): void { async function renderViewer(): Promise { const frame = getSelectedFrame(); let leftAsset = state.preprocessedImage ?? state.sourceImage; - let middleAsset = state.edgeMapImage; let rightAsset = state.finalOutputImage ?? state.cleanupImage ?? state.sourceImage; let leftLabel = "Source"; - let middleLabel = "Edge Scout"; let rightLabel = "Output"; if (state.latticeImage) { @@ -490,27 +480,26 @@ async function renderViewer(): Promise { leftLabel = "Lattice Prep"; } if (state.guidanceImage) { - middleAsset = state.guidanceImage; - middleLabel = "Guidance"; + leftAsset = state.guidanceImage; + leftLabel = "Guidance"; } if (frame) { leftAsset = frame.samplingOverlayImage; - middleAsset = frame.displacementImage; rightAsset = frame.outputImage; leftLabel = "Sampling Overlay"; - middleLabel = "Displacement"; rightLabel = "Current Output"; } else if (state.cleanupImage) { - middleAsset = state.heatmapImage ?? middleAsset; - middleLabel = "Cleanup Heatmap"; + if (state.heatmapImage) { + leftAsset = state.heatmapImage; + leftLabel = "Cleanup Heatmap"; + } rightAsset = state.cleanupImage; rightLabel = "Cleaned Output"; } leftVizLabel.textContent = leftLabel; - middleVizLabel.textContent = middleLabel; rightVizLabel.textContent = rightLabel; - await Promise.all([drawAsset(leftCanvas, leftAsset), drawAsset(middleCanvas, middleAsset), drawAsset(rightCanvas, rightAsset)]); + await Promise.all([drawAsset(leftCanvas, leftAsset), drawAsset(rightCanvas, rightAsset)]); renderMetrics(); } @@ -826,22 +815,18 @@ async function handleEvent(eventName: string, payload: JsonRecord): Promise a.step - b.step); } - if (state.autoFollow) { - state.selectedFrameIndex = Math.max(0, state.frames.findIndex((candidate) => candidate.step === frame.step)); + if (state.autoFollow) { + state.selectedFrameIndex = Math.max(0, state.frames.findIndex((candidate) => candidate.step === frame.step)); + } + if (eventName === "phase_field_final") { + addLog("Solver", "Final nearest-source sample committed."); + } + break; } - state.currentStage = frame.step === 0 ? "Initial placement" : `Solver step ${frame.step}/${frame.totalSteps}`; - if (eventName === "phase_field_final") { - addLog("Solver", "Final nearest-source sample committed."); - } - break; - } case "cleanup_completed": state.cleanupImage = payload.cleanedImage as ImageAsset; state.heatmapImage = payload.heatmapImage as ImageAsset; - state.currentStage = "Cleanup"; addLog("Cleanup", "Ran the local cleanup sweep."); break; case "palette_completed": state.finalOutputImage = payload.outputImage as ImageAsset; - state.currentStage = "Final output"; addLog("Output", "Final output image is ready."); break; case "pipeline_completed": state.finalOutputImage = payload.outputImage as ImageAsset; state.runSummary = (payload.runSummary as JsonRecord | null) ?? null; - state.currentStage = "Completed"; setStatus("completed", "Run finished. If the machine still did something stupid, fix it pixel by pixel."); addLog("Done", "Full pipeline completed."); runButton.disabled = false; diff --git a/src/repixelizer/gui_static/app.js b/src/repixelizer/gui_static/app.js index 0b6ef35..22d9051 100644 --- a/src/repixelizer/gui_static/app.js +++ b/src/repixelizer/gui_static/app.js @@ -21,10 +21,8 @@ const stepSlider = byId("stepSlider"); const stepValue = byId("stepValue"); const lossCanvas = byId("lossCanvas"); const leftCanvas = byId("leftCanvas"); -const middleCanvas = byId("middleCanvas"); const rightCanvas = byId("rightCanvas"); const leftVizLabel = byId("leftVizLabel"); -const middleVizLabel = byId("middleVizLabel"); const rightVizLabel = byId("rightVizLabel"); const metricsPanel = byId("metricsPanel"); const paintSwatch = byId("paintSwatch"); @@ -80,7 +78,6 @@ const state = { inputPreviewImage: null, sourceImage: null, preprocessedImage: null, - edgeMapImage: null, latticeImage: null, guidanceImage: null, inference: null, @@ -98,7 +95,6 @@ const state = { altHeld: false, zoom: Number(zoomInput.value), showGrid: gridToggle.checked, - currentStage: "Idle", }; let currentEventSource = null; let painting = false; @@ -159,7 +155,6 @@ function resetRunArtifacts() { state.jobId = null; state.sourceImage = null; state.preprocessedImage = null; - state.edgeMapImage = null; state.latticeImage = null; state.guidanceImage = null; state.inference = null; @@ -173,7 +168,6 @@ function resetRunArtifacts() { state.eventLog = []; state.editorBaseAsset = null; state.editorDirty = false; - state.currentStage = "Waiting"; } function parseOptionalInteger(input) { if (input.value.trim() === "") { @@ -377,37 +371,34 @@ function renderSummary() { async function renderViewer() { const frame = getSelectedFrame(); let leftAsset = state.preprocessedImage ?? state.sourceImage; - let middleAsset = state.edgeMapImage; let rightAsset = state.finalOutputImage ?? state.cleanupImage ?? state.sourceImage; let leftLabel = "Source"; - let middleLabel = "Edge Scout"; let rightLabel = "Output"; if (state.latticeImage) { leftAsset = state.latticeImage; leftLabel = "Lattice Prep"; } if (state.guidanceImage) { - middleAsset = state.guidanceImage; - middleLabel = "Guidance"; + leftAsset = state.guidanceImage; + leftLabel = "Guidance"; } if (frame) { leftAsset = frame.samplingOverlayImage; - middleAsset = frame.displacementImage; rightAsset = frame.outputImage; leftLabel = "Sampling Overlay"; - middleLabel = "Displacement"; rightLabel = "Current Output"; } else if (state.cleanupImage) { - middleAsset = state.heatmapImage ?? middleAsset; - middleLabel = "Cleanup Heatmap"; + if (state.heatmapImage) { + leftAsset = state.heatmapImage; + leftLabel = "Cleanup Heatmap"; + } rightAsset = state.cleanupImage; rightLabel = "Cleaned Output"; } leftVizLabel.textContent = leftLabel; - middleVizLabel.textContent = middleLabel; rightVizLabel.textContent = rightLabel; - await Promise.all([drawAsset(leftCanvas, leftAsset), drawAsset(middleCanvas, middleAsset), drawAsset(rightCanvas, rightAsset)]); + await Promise.all([drawAsset(leftCanvas, leftAsset), drawAsset(rightCanvas, rightAsset)]); renderMetrics(); } function renderSlider() { @@ -704,38 +695,30 @@ async function handleEvent(eventName, payload) { break; case "source_loaded": state.sourceImage = payload.sourceImage; - state.currentStage = "Loaded source"; setStatus("running", "Source loaded. Survey crew is measuring the mess."); addLog("Source", "Loaded the input image."); break; case "preprocess_completed": state.preprocessedImage = payload.sourceImage; - state.currentStage = "Preprocessed source"; addLog("Preprocess", "Stripped edge-connected background noise."); break; case "inference_candidates_ready": state.inference = payload.inference; - state.currentStage = "Scoring lattice candidates"; addLog("Inference", "Scored candidate grids and phase offsets."); break; case "phase_rerank_started": - state.currentStage = "Phase rerank preview"; addLog("Rerank", `Running ${String(payload.previewSteps)} preview steps across ${String(payload.candidateCount)} low-confidence candidates.`); break; case "phase_selection_completed": state.inference = payload.inference; - state.currentStage = "Selected lattice"; addLog("Selection", "Committed to a ruler and phase."); break; case "analysis_completed": - state.edgeMapImage = payload.edgeMapImage; - state.currentStage = "Edge scout"; addLog("Scout", "Built the edge map that tells the solver where the floorboards creak."); break; case "phase_field_prepared": state.latticeImage = payload.latticeImage; state.guidanceImage = payload.guidanceImage; - state.currentStage = "Prepared phase field"; addLog("Prep", `Locked ${String(payload.targetWidth)} x ${String(payload.targetHeight)} lattice centers.`); break; case "phase_field_initial": @@ -753,7 +736,6 @@ async function handleEvent(eventName, payload) { if (state.autoFollow) { state.selectedFrameIndex = Math.max(0, state.frames.findIndex((candidate) => candidate.step === frame.step)); } - state.currentStage = frame.step === 0 ? "Initial placement" : `Solver step ${frame.step}/${frame.totalSteps}`; if (eventName === "phase_field_final") { addLog("Solver", "Final nearest-source sample committed."); } @@ -762,18 +744,15 @@ async function handleEvent(eventName, payload) { case "cleanup_completed": state.cleanupImage = payload.cleanedImage; state.heatmapImage = payload.heatmapImage; - state.currentStage = "Cleanup"; addLog("Cleanup", "Ran the local cleanup sweep."); break; case "palette_completed": state.finalOutputImage = payload.outputImage; - state.currentStage = "Final output"; addLog("Output", "Final output image is ready."); break; case "pipeline_completed": state.finalOutputImage = payload.outputImage; state.runSummary = payload.runSummary ?? null; - state.currentStage = "Completed"; setStatus("completed", "Run finished. If the machine still did something stupid, fix it pixel by pixel."); addLog("Done", "Full pipeline completed."); runButton.disabled = false; diff --git a/src/repixelizer/gui_static/index.html b/src/repixelizer/gui_static/index.html index ada11eb..be86cd1 100644 --- a/src/repixelizer/gui_static/index.html +++ b/src/repixelizer/gui_static/index.html @@ -8,22 +8,114 @@
-
-
-
- -
-

Live Pipeline

-

Repixelizer

-

Take fake pixel art, force it onto a real lattice, then inspect the crime scene frame by frame.

-
-
-
-
-
+
+
+
+
+ +
+

Live Pipeline

+

Repixelizer

+

Take fake pixel art, force it onto a real lattice, then inspect the crime scene frame by frame.

+
+
+
+
+ +
+
+
+

Pipeline Stages

+
+
+
+
+ Idle +

Waiting for input.

+
+
+ + + No frames yet +
+
+ +
+
+
Source
+ +
+
+
Output
+ +
+
+
+ +
+
+
+

Pixel Fixes

+

Output Editor

+

Pencil the stragglers. Wheel zooms to cursor, middle mouse pans, Alt steals color.

+
+
+ + +
+
+ +
+
+
+
+ + + + +
+
+
+ + + 12x +
+ +
+ +
+
+ + +
+
+
+

Final output lands here once the solver finishes its little pilgrimage.

+
+
+
+
+
+
+ - -
-
-
-
-

Pipeline Stages

-
-
- -
-
-
Source
- -
-
-
Scout
- -
-
-
Output
- -
-
-
-
- Idle -

Waiting for input.

-
-
- - - No frames yet -
-
-
- -
-
-
-

Pixel Fixes

-

Output Editor

-

Pencil the stragglers. Wheel zooms to cursor, middle mouse pans, Alt steals color.

-
-
- - -
-
- -
-
-
-
- - - - -
-
-
- - - 12x -
- -
- -
-
- - -
-
-
-

Final output lands here once the solver finishes its little pilgrimage.

-
-
-
-
-
-
diff --git a/src/repixelizer/gui_static/styles.css b/src/repixelizer/gui_static/styles.css index 8b0c7f2..e03be2b 100644 --- a/src/repixelizer/gui_static/styles.css +++ b/src/repixelizer/gui_static/styles.css @@ -247,7 +247,7 @@ p { .app-grid { display: grid; gap: 12px; - grid-template-columns: minmax(320px, 390px) minmax(0, 1fr); + grid-template-columns: minmax(0, 1fr) minmax(320px, 390px); align-items: start; } @@ -569,7 +569,7 @@ p { .viewer-grid { display: grid; - grid-template-columns: repeat(3, minmax(0, 1fr)); + grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }