Repository navigation
Add Panel Mapper Pro Phase 1: Electron shell scaffold - #1
Open
asaptrap99 wants to merge 7 commits into
Open
asaptrap99 wants to merge 7 commits into
asaptrap99 wants to merge 7 commits into
Conversation
New standalone Electron/React/TypeScript app under panel-mapper-pro/, separate from the existing Java/Processing Shape Mapper library at the repo root. Implements the Electron shell phase from the projection mapping app spec: control window + fullscreen output window, display enumeration/picker, IPC scaffold (typed contextBridge preload, main process handlers), and empty .pmproj project new/open/save via native dialogs. WebGL rendering pipeline, shape types, and layer system land in later phases.
Ports the unit-square-to-quad projective mapping (Heckbert's closed-form homography) into core/geometry/homography.ts, and builds a WebGL render pipeline (Three.js) that evaluates the homography exactly at every vertex of a fine internal grid so affine per-cell interpolation reproduces a true projective warp without a custom shader. The same grid-warp primitive is shared with the future mesh shape type. Adds a Zustand store as the single source of truth for shapes, a draggable Stage with numeric-fallback corner fields and arrow-key nudging (Shift for fine-step), and live control-to-output IPC sync so the projector output window mirrors the control window's WebGL scene. A built-in checkerboard test pattern stands in for the content library, which lands in a later phase. Also fixes a real preload-loading bug hit during smoke testing: Electron's default sandboxed preload environment cannot resolve local multi-file require()s, so window.panelMapper was silently undefined at runtime. Fixed by disabling the OS-level preload sandbox (contextIsolation remains the security boundary) and standardizing electron/ on CommonJS instead of mixing ESM/CJS module formats across main/preload. Verified via Playwright driving the packaged Electron build under Xvfb: zero console/page errors, quad renders and drags correctly with live perspective warp.
Wires up the full multi-shape layer stack on top of the Phase 2 quad MVP: - Layer list shows all shapes ordered by z (Photoshop-style, top of list = top of stack), with drag-and-drop reorder, per-shape visibility and lock toggles, and delete. Locked shapes reject drag/point edits in the Stage. - Shape Inspector now actually wires opacity and blend mode (normal/add/ screen) to the store instead of being read-only, plus a content-crop window (x/y/w/h fractions) so a shape can show a sub-region of its assigned content. - Content Library: import images/video via a native file dialog, list imported sources, assign one to the selected shape. - ShapeSceneRenderer now loads real per-shape textures (image via THREE.TextureLoader, video via THREE.VideoTexture) instead of always using the shared test pattern, with a cache keyed by content id. - Media loads through a newly registered `pmfile://` protocol rather than raw `file://` URLs, since a page served from the Vite dev server (http) can't reliably load `file://` resources; the custom privileged scheme works consistently in both dev and packaged builds and normalizes Windows drive-letter paths in one shared helper (core/project/contentUrl.ts). Verified via Playwright driving the packaged Electron build under Xvfb: multiple overlapping quads composite and z-order correctly, opacity and screen blend render correctly against the black stage background, and per-shape visibility toggling hides/shows only the intended shape without affecting others.
Adds the five remaining shape types on top of the quad-only MVP, each with its own real math foundation module under core/geometry/: - triangleWarp.ts: the affine map a single triangle always has (three point pairs fully determine it) — rendered by handing the 3 vertices straight to Three.js with corner UVs, since hardware barycentric interpolation reproduces the affine warp exactly with no subdivision needed. - Polygon: fan-triangulated from the centroid, each fan triangle using the same affine/hardware-interpolation trick, with UVs from a canonical regular polygon inscribed in the crop rect. - meshWarp.ts: per-cell bilinear interpolation (not per-cell homography) — bilinear reduces to a plain linear interpolation along any shared edge, so adjacent cells always agree exactly with no seams, by construction. - ellipseWarp.ts: parametric unit-disk-to-ellipse map (center, independent x/y radii, rotation), fanned into flat triangles from the center so the radial UV mapping is exact per triangle. - Line: a constant-width ribbon built by offsetting each polyline vertex along its local perpendicular, with along-length/across-width UVs. Generalizes Stage.tsx (drag handles) and ShapeInspector.tsx (numeric fields) across all point-array shape types (quad/triangle/polygon/mesh/ line), adds dedicated ellipse handles (center, and a radiusX handle that doubles as a rotate+resize control, matching how corner-drag rotate affordances work in other design tools), and polygon vertex add/remove. ToolPalette now creates all six shape types via a generic addShape(type) store action instead of the quad-only addQuad. Fixes a real rendering bug caught during visual smoke testing: non-quad shapes with user-drawn point order weren't guaranteed to wind counter-clockwise in Three.js's coordinate space, so triangles/polygons were silently backface-culled (invisible) despite their handles rendering correctly. Fixed by setting side: THREE.DoubleSide on the shared shape material. Verified via Playwright driving the packaged Electron build under Xvfb: each of the six shape types renders its warped test pattern correctly in isolation, the ellipse's rotate+resize handle and a dragged mesh interior point (bilinear bulge, zero seam at the mesh boundary) both behave correctly, and no console/page errors occur across the whole flow.
Builds out the .pmproj file lifecycle beyond the basic new/open/save from Phase 1: - Content paths are relativized to the project file's directory on save (electron/pathUtils.ts) when the media lives underneath it, so a project folder stays portable and git-diffable; falls back to an absolute path otherwise. Resolved back to absolute for the running session on open. - Relink missing media: opening a project checks every content source's resolved path on disk and reports which ones are missing (OpenProjectResult.missingContentIds). ContentLibrary surfaces a warning badge and a Relink button that opens a file picker and repoints just that content source. - Autosave: a debounced (3s) background save to a dedicated crash-recovery slot in userData, independent of explicit Save. On launch, if an autosave is found the user is offered a restore prompt. - Recent projects: a "Recent…" dropdown in the top bar backed by the existing recent-projects.json list, opening a project directly by path (electron: project:openPath) instead of requiring the native file dialog every time. Verified via Playwright driving the packaged Electron build under Xvfb, with the native save/open dialogs monkey-patched in the main process so the flow could be scripted end-to-end: Save As writes a valid .pmproj, New clears the canvas, Open restores the saved shapes, the recent-projects dropdown lists the saved path, the autosave file appears after the debounce window, content paths are stored relative when possible, and deleting a referenced media file and reopening the project correctly surfaces the missing-content badge with no console/page errors.
Undo/redo across all shape edits: every project-mutating store action now funnels through a single applyProjectChange helper that debounces history commits by 500ms, so a burst of rapid edits (dragging a point, scrubbing an opacity slider, retyping a number) coalesces into one undo step instead of one per intermediate event. Wired to Ctrl/Cmd+Z and Ctrl/Cmd+Shift+Z, skipped while a text field/select has focus so native input undo and typing aren't hijacked, plus Undo/Redo buttons in the top bar. Adds a Delete/Backspace shortcut to remove the selected shape, and a "?" keyboard-shortcuts overlay (ShortcutsOverlay.tsx) summarizing all of the above plus the existing arrow-key nudge controls. Expands the built-in test pattern library beyond the single hardcoded checkerboard: grid, color bars, and a per-shape "ID card" pattern that bakes the shape's own label into the texture (useful for telling shapes apart once there are many). Patterns are selectable per-shape from the Content dropdown via reserved "pattern:*" contentId values, resolved and cached in ShapeSceneRenderer without needing fake ContentSource entries in the project schema. Verified via Playwright driving the packaged Electron build under Xvfb: two adds + two undos empties the layer list, two redos restores both shapes, Delete removes the selected shape and is itself undoable, the "?" overlay opens and closes, and the shape-ID pattern renders the correct per-shape label and color — all with zero console/page errors.
Gets electron-builder actually producing a working Windows installer: - electron-builder.yml: disable publish/update-feed generation (publish: null) — this app has no auto-update and no networking by design (see spec non-goals), and electron-builder crashed trying to build update metadata without a configured publish provider. - package.json: add an `author` field to silence electron-builder's missing-author warning. - README: document that building the Windows target from Linux/macOS requires Wine (electron-builder shells out to `rcedit` via Wine to set the exe's icon/version metadata) plus the apt packages needed, and that building on Windows itself needs no extra setup. Verified end-to-end in this Linux sandbox by installing wine + wine32:i386 and running `npm run package`: electron-builder downloads the real win32-x64 Electron binary, produces "Panel Mapper Pro Setup 0.1.0.exe" (an NSIS installer, confirmed via `file` as a genuine PE32 Windows executable) alongside a win-unpacked/ build whose main executable is a genuine PE32+ x64 Electron binary with a proper app.asar resource bundle, and exits cleanly with no errors or warnings.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
New standalone Electron/React/TypeScript app under panel-mapper-pro/, separate from the existing Java/Processing Shape Mapper library at the repo root. Implements the Electron shell phase from the projection mapping app spec: control window + fullscreen output window, display enumeration/picker, IPC scaffold (typed contextBridge preload, main process handlers), and empty .pmproj project new/open/save via native dialogs. WebGL rendering pipeline, shape types, and layer system land in later phases.