Skip to content

[feat] 40-image: big photos as textures + the Image editor (F13) - #353

Open
AlexZ005 wants to merge 4 commits into
feat/40from
feat/40-image
Open

AlexZ005 wants to merge 4 commits into
feat/40from
feat/40-image

Conversation

@AlexZ005

Copy link
Copy Markdown
Collaborator

Roadmap 40 F13 (lane 40-image).

What changes

  • A big photo becomes a texture instead of being refused with "Image is too large (max 8 MB)": it is scaled to fit 1024 px (aspect kept). Only a file over 64 MB is turned away.
  • Image editor (floating window in the UV editor's WindowShell shape; a stacked sheet on a phone): crop (mouse, touch, typed X/Y/W/H, Free/1:1/Original), rotate/flip, resize (50 % / 200 % / power of 2), brightness/contrast/saturation, its own undo/redo, Save, Save as copy, and per-image Versions with Restore original (local idb: the original + the last 19 saves).
  • Opened from the Explorer's image menu (Edit image…), the preview window's edit button, and Edit beside a texture in the Inspector.
  • Textures follow their image: a texture applied from the Explorer remembers its library image (additive source on the map message, mapSources in materials); Save updates every such texture for everyone in the session. Inspector Edit on an unlinked texture first files it into the library.
  • Storage breakdown: a new "Image versions" category, reclaimable.

Proof

  • e2e image-editor: 53/53 (two peers + a 390×844 touch phone), GPU backend; counterfactuals for the phone fixes (run9, run15).
  • vitest imageOps; svelte-check 300/41 = main; check:tokens clean.
  • Regression battery green except two checks that fail identically on pristine 1.31.0 (file-preview window resize, explorer-drop DOM viewport drop).
  • Before/after shots (390×844 + 1440×900, dark + light) and summary: ~/.code/lanes-30/after-40/40-image/.

🤖 Generated with Claude Code

AlexZ005 and others added 4 commits October 8, 2026 13:55
…s remember their image

- setObjectsTexture no longer refuses files over 8 MB: the path already downscales to
  1024 px, so the cap only refused photos it was built to shrink (roadmap 40 F13,
  image-large). The one limit left is a 64 MB decode-safety cap.
- material.userData.mapSource = the content hash of the Explorer image a texture was
  made from (Explorer drop, UV slot drop). It rides the `map` message as an additive
  `source` field, the `materials` payload as `mapSources`, and a material-type switch.
  Any write without one (paint, undo, a file from disk, an older peer) drops the link.
- texturesFromSource(hash) / linkTextureSource(uuid, slot, hash): the seams the Image
  editor's Save uses to re-texture every material made from an image.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ersions (WIP)

- src/lib/image/imageOps.js: pure raster maths (crop/rotate/flip/area+bilinear resize/
  brightness-contrast-saturation), vitest imageOps (19 green)
- src/lib/image/imageVersions.js: per-image version history in idb (Original always kept, cap 20)
- src/lib/image/imageEditor.js: open/close, decode/encode, saveImage (same record, version kept,
  linked textures re-textured as one undo), restoreImageVersion, saveImageCopy, editMaterialTexture
- ImageEditorWindow.svelte: WindowShell canvas + right sidebar (Edit / Versions), zoom/pan/pinch,
  crop drag, editor-local undo, phone sheet above Play
- entry points: Explorer "Edit image...", preview #preview-edit, Inspector #texture-edit
- storage breakdown: "Image versions" category
- e2e image-editor (WIP: sections 1-8 pass; save is slow on a janky page, being profiled)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…d Play; suite green

- the phone shell's top bar (64 px) covered the editor's header and close button: the
  sheet now starts under it and ends at the bottom bar (--ps-bar-h), so Play stays tappable
- canvas and sidebar no longer squeeze side by side at 390 px (232 px canvas, a sidebar
  clipping its own labels): the Edit/Versions panel stacks under a full-width canvas,
  its tabs a row of 44 px touch targets
- image-editor suite: GPU backend (on software GL two pages + the 14 MB photo starved the
  compositor, ~1 s per round trip, profiled: JS idle), wider post-Save waits, diagnostic
  logging removed, the phone section finds the shell's #ps-play and asserts the close
  button and the stacked panel (counterfactual: both red with the CSS removed)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… view

- the sidebar's scroller is shared by Edit and Versions, so after scrolling down in Edit the
  short Versions list opened scrolled out of sight and read as empty (measured on a phone:
  the list 525 px above the visible area). Each panel resets the scroller when it mounts.
- on a phone the stacked panel showed Apply crop half under the bottom bar after Crop...;
  entering crop mode scrolls it into the panel's view
- suite: phone checks for both, the touch drag's crop box asserted directly, the first-draw
  canvas read polls instead of sampling once (counterfactual run15: three checks red)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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