Skip to content

Improve WPM pathing paint editor - #104

Merged
Frotty merged 6 commits into
masterfrom
codex/wpm-paint-editor
Aug 25, 2026
Merged

Improve WPM pathing paint editor#104
Frotty merged 6 commits into
masterfrom
codex/wpm-paint-editor

Conversation

@Frotty

@Frotty Frotty commented Aug 25, 2026

Copy link
Copy Markdown
Member

What changed

  • Reworked the editable .wpm preview into a compact paint-style workspace with a side palette.
  • Added Brush, Line, Fill, Erase, configurable brush size, swatches, and Alt-click sampling of the complete raw flag byte.
  • Kept edits on the existing central host-side pipeline with grouped undo/redo and serialize/reparse save validation.
  • Replaced ambiguous Water/Unknown labels with the documented WC3 pathing meanings, including an explicit version warning for nonzero WPM versions.
  • Added WPM flag semantics tests and end-to-end coverage for brush size, line, fill, sampling, undo/redo, and round-trip saving.
  • Documented that .imp is intentionally not an editing target.

Validation

  • npm test — passed.
  • npx tsc -p . --noEmit — passed.
  • npm run lint — passed with one pre-existing warning in webpack.config.js (CopyFilePlugin unused).
  • npm run test:e2e — 70 passed.

Notes

The WPM fixture examined locally is version 0 and uses 0x40 for ordinary interior ground, so the UI now calls it No Water / Unfloatable rather than presenting it as visible water. Nonzero versions are preserved but marked as unverified because only version 0 has a documented layout.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6c4c9a5061

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/features/wpmPreview.ts Outdated
Comment on lines +423 to +426
while (stack.length) {
const index = stack.pop();
const x = index % W, y = Math.floor(index / W);
paintCell(x, y, replacement);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Batch flood-fill updates before refreshing the canvas

When Fill targets a large uniform region, this synchronous loop invokes paintCell for every matching cell; each invocation updates the canvas with putImageData and adds an entry to gestureChanges, after which an object per cell is posted to the extension host. Real WPM grids can contain hundreds of thousands of cells, so filling an ordinary blank region can block the webview or exhaust memory. Accumulate the affected cells and refresh/post them in batches or a compact representation.

Useful? React with 👍 / 👎.

Comment thread src/features/wpmFlags.ts Outdated
/** The only WPM header version with a documented byte layout. */
export const WPM_KNOWN_VERSION = 0;

export const WPM_FLAG_DEFS: readonly WpmFlagDefinition[] = [

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep the WPM flag helpers in the existing preview module

This new helper module has only one production consumer, wpmPreview.ts, so it creates a one-off abstraction solely for this viewer. Keep the definitions and color helpers in the existing WPM preview module rather than adding a separate utility file, as required by the repository's localization convention.

AGENTS.md reference: AGENTS.md:L43-L43

Useful? React with 👍 / 👎.

@Frotty

Frotty commented Aug 25, 2026

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 43023546f5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/features/wpmPreview.ts Outdated
runs.forEach((run) => {
if (!Number.isInteger(run.start) || !Number.isInteger(run.length) || !Number.isInteger(run.value) ||
run.start < 0 || run.length < 1 || run.start + run.length > data.length) return;
for (let index = run.start; index < run.start + run.length; index++) changes.push({ index, value: run.value });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep compact fill runs compact when applying them

On a large uniform WPM region, each compact run is expanded back into one { index, value } object per cell before applyChanges, while collectWpmRunRequests similarly expands it into a per-cell Map; a million-cell fill therefore still creates millions of allocations and can block or exhaust the webview and extension host. Fresh evidence after the earlier flood-fill comment is that the new run protocol compacts only the message transport, then reconstructs the original per-cell representation at both endpoints; apply and retain the runs without this expansion.

Useful? React with 👍 / 👎.

document.querySelectorAll('[data-brush-bit]').forEach((input) => input.addEventListener('change', updateBrushValue));
const brushSizeInput = document.getElementById('brushSize');
const brushSizeValue = document.getElementById('brushSizeValue');
brushSizeInput.value = String(brushSize);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Initialize the brush-size readout from restored state

When VS Code recreates a webview whose saved brushSize is greater than 1, this updates the range input and the actual painting size but leaves #brushSizeValue at the hard-coded 1 × 1 until the user moves the slider. The editor can therefore display a 1-cell brush while applying an unexpectedly large restored brush; initialize the output here or call updateBrushSize() during setup.

Useful? React with 👍 / 👎.

@Frotty

Frotty commented Aug 25, 2026

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 90778ae382

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/features/wpmPreview.ts Outdated
Comment on lines +436 to +438
if (!gestureChanges.has(index)) gestureChanges.set(index, data[index]);
data[index] = next;
if (refresh) refreshCell(index);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Batch brush pixel uploads per pointer update

With a large brush or a long Line gesture, every stamped cell calls refreshCell, which immediately invokes putImageData; a size-32 brush therefore performs 1,024 canvas uploads for a single point, including repeated uploads where adjacent stamps overlap, and a drag across a normal WPM can multiply this into hundreds of thousands of synchronous calls that freeze the webview. Update the backing pixels while stamping, then upload the image once per pointer update or completed line.

Useful? React with 👍 / 👎.

@Frotty

Frotty commented Aug 25, 2026

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2f03b49bc5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

let lineStart = null, lineCurrent = null;

function eventCell(e) {
const rect = viewport.getBoundingClientRect();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restrict batched uploads to the dirty rectangle

When painting a large WPM, every pointer movement that reaches another cell calls paintLine, which calls this function and synchronously uploads the entire W × H image even if only a few pixels changed; a 1920 × 1920 grid copies roughly 14 MiB per event and can still freeze brush drags. Fresh evidence after the earlier brush-upload comment is that batching replaced the one-cell dirty upload with this unconditional full-image upload; retain one upload per pointer update, but pass the accumulated dirty bounds to putImageData.

Useful? React with 👍 / 👎.

@Frotty

Frotty commented Aug 25, 2026

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c7a3fbe281

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/features/wpmPreview.ts Outdated
refreshCell(index);
}
});
offCtx.putImageData(img, 0, 0);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Flush only the dirty run rectangle

On large WPM grids, every completed gesture and every undo/redo receives an applyRuns acknowledgement that reaches this unconditional full-image upload, even when the runs changed only one cell; it also leaves the dirty bounds set by refreshCell, so the next brush flush may upload the bounding rectangle of both edits. Fresh evidence after the earlier full-image-upload comment is that pointer updates now use flushImage(), but this acknowledgement path still copies the entire W × H image; call flushImage() here as well so the upload is bounded and the dirty state is reset.

Useful? React with 👍 / 👎.

@Frotty

Frotty commented Aug 25, 2026

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Nice work!

Reviewed commit: 056a955d64

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@Frotty

Frotty commented Aug 25, 2026

Copy link
Copy Markdown
Member Author

Codex review loop complete: 6 review rounds were run. All actionable findings were addressed, the final review of 056a955 was clean, and the GitHub build check passes. Local validation: tsc, npm test, lint, and the WPM e2e spec pass; no merge performed.

@Frotty
Frotty merged commit e110490 into master Aug 25, 2026
1 check passed
@Frotty
Frotty deleted the codex/wpm-paint-editor branch August 25, 2026 11:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant