From b3a55172a2f6587083218313e80acca8cf8a14bc Mon Sep 17 00:00:00 2001 From: cdricms <36056008+cdricms@users.noreply.github.com> Date: Sun, 9 Aug 2026 18:16:02 +0200 Subject: [PATCH] docs(apple): document Mac target in screenshot studio README --- packaging/apple/studio/README.md | 46 +++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/packaging/apple/studio/README.md b/packaging/apple/studio/README.md index c1736ce..7f8cde3 100644 --- a/packaging/apple/studio/README.md +++ b/packaging/apple/studio/README.md @@ -15,7 +15,10 @@ swift run studio # all locales × screens -> generated/ ..// (ships to App Store) LOCALES="fr de" SCREENS="share-securely" swift run studio # subset PLATFORM=ipad swift run studio # iPad set -> generated//iPad/ +PLATFORM=mac swift run studio # Mac set -> generated//Mac/ ``` +`PLATFORM` must match between `capture.sh` and `swift run studio` (they read the same +`generated/shots//` tree). Run from this directory (it reads `strings.json` and `assets/` relative to cwd). ## Full pipeline @@ -26,37 +29,48 @@ swift run studio # composite everything -> generated//[iPad/] ``` `capture.sh` drives the app into each screen via the DEBUG `-VniScreenshot` launch argument (see `apple/VniDrop/App/ScreenshotSupport.swift`), once per locale via -`-AppleLanguages`, in dark mode with a 9:41 status bar. Screenshots are transient -(git-ignored, regenerated per run) — during layout iteration, capture once then re-run -`swift run studio` on its own. +`-AppleLanguages`, in dark mode. Screenshots are transient (git-ignored, regenerated per +run) — during layout iteration, capture once then re-run `swift run studio` on its own. +- **iPhone / iPad** run in the simulator (9:41 status-bar override) via `simctl`. +- **Mac** has no simulator: `capture.sh` builds the native app, launches the binary + directly, sizes its window with `osascript`, and grabs it with `screencapture`. Grant + the terminal **Accessibility + Screen Recording** permission the first time. ## Platforms -`PLATFORM=iphone` (default) or `ipad`. Each `Platform` (`Sources/studio/Platform.swift`) -carries its canvas size, capture simulator, output subfolder, and a `DeviceModel` — the -`.usdz`, its screen material, the orientation fix (yaw so the screen faces the camera), -optional front-glass mesh to hide, and whether to tint the body graphite. Adding a device -(e.g. Mac) is a new `DeviceModel` + `Platform` case + a layout set. +`PLATFORM=iphone` (default), `ipad`, or `mac`. Each `Platform` +(`Sources/studio/Platform.swift`) carries its canvas size, capture target, output +subfolder, and a `DeviceModel` — the `.usdz`, its screen material, the orientation fix +(yaw so the screen faces the camera), optional front-glass mesh to hide, whether to tint +the body graphite, a `fillFraction` (how much of the frame the device fills; lower for +wide 3/4 poses that would otherwise clip), and a `screenPad` (black margin baked around +the shot so the window clears the display's rounded corners). Adding a device is a new +`DeviceModel` + `Platform` case + a layout set. (The studio is Apple-only today; the +same SwiftUI/SceneKit approach is intended to extend to Android and Windows later.) ## Device rendering `SceneKitDeviceRenderer` textures the captured screenshot onto the model's screen mesh and renders it off-screen. Curvature, bezel and body are the model's real geometry; poses (pitch/yaw/roll) and a studio environment (IBL + bloom) are applied in the scene. It -auto-generates planar UVs for screen meshes that ship without them. +auto-generates planar `[0,1]` UVs for screen meshes that ship without them, and mattes the +shot onto a slightly larger black canvas (`screenPad`) so the display edge stays black +instead of smearing the capture's corner pixels. ## Assets (`assets/`) -- `iphone-17-pro-max.usdz`, `ipad-pro.usdz` — the 3D devices (committed; CC BY 4.0, see - `ATTRIBUTION.md`). +- `iphone-17-pro-max.usdz`, `ipad-pro.usdz`, `macbook-air.usdz` — the 3D devices + (committed; CC BY 4.0, see `ATTRIBUTION.md`). - `globe.png` — for the send-anywhere hero (committed). - `generated/shots///*.png` — captured app screens (transient). ## Layout & tuning -- `Sources/studio/ScreenSpec.swift` — per-platform layouts (`iphone` / `ipad`): gradient, - device pose/position/size, globe + route (send-anywhere), the encryption flow - (stay-private: `beams` → `lock` → `stream` + `banners`), caption placement. +- `Sources/studio/ScreenSpec.swift` — per-platform layouts (`iphone` / `ipad` / `mac`): + gradient, device pose/position/size, globe + route (send-anywhere), the encryption flow + (stay-private: `beams` → `lock` → `stream` + `banners`), caption placement. `beams` and + `stream` take a `horizontal` flag for side-by-side devices (used by Mac stay-private). - `Sources/studio/ScreenFrame.swift` — the composition (layer order, caption fitting, generated artwork). ## Screens `share-securely`, `choose-receivers`, `send-anywhere` (globe + Paris→LA route arc, -reuses the share screenshot), `stay-private` (two stacked phones + encryption beams → -padlock → binary protection stream, with localized CHIFFREMENT/PROTECTION banners). +reuses the share screenshot), `stay-private` (encryption beams → padlock → binary +protection stream, with localized CHIFFREMENT/PROTECTION banners; two stacked phones on +iPhone/iPad, two side-by-side laptops with a horizontal flow on Mac).