Loading…
a327ex.com

Anchor Website 14

Opus 4.8

Summary

Continued the Anchor Website renderer (a327ex.com reimplemented inside the Anchor 2 engine). Three arcs: (1) full MOBILE SUPPORT for the engine renderer; (2) wiring the content-adding skills to sync the engine renderer (not just the Lua server); (3) building the BOX2D LETTER-DROP announcement effect — in progress, local-only.

Mobile support (Anchor2 engine committed 1825c77, renderer prod 5677ef1), 3 device-tested increments:

  • Increment 1 (touch): SDL_FINGER* → the existing mouse/scroll model in SHARED Anchor2/engine/src/anchor.c. Tap = a 2-step synthetic click (press one fixed-step, release the next, so update-time mouse_is_pressed/released edges fire); one-finger drag = 1:1 scroll into touch_scroll_dy, drained by new engine_get_touch_scroll(), routed to the pane under the finger. Disabled SDL touch→mouse emulation (SDL_HINT_TOUCH_MOUSE_EVENTS=0). New engine_get_css_size()/engine_get_dpr(). Removed the engine-boot.js mobile bail. Temporary green DEV_HUD. Device test found game == css (384×696, dpr 2.81) — Emscripten defaults to a CSS-px backing store; the previous instance's "phone reports 1170 physical px" assumption was WRONG (breakpoint already worked, text was DPR-1 soft).
  • Increment 2 (crisp DPR): web_native_resolution now sizes the canvas BACKING STORE to physical px (CSS×DPR via emscripten_set_canvas_element_size, factored into web_target_backing()), DPR capped at 2.0 (WEB_DPR_CAP). Compositor + mouse_to_game_coords made backing-authoritative on web (window_w = game_width; mouse identity since Emscripten scales mouse to the backing) — fixed a left-shift/black-bar blit bug (compositor had trusted SDL's stale CSS window size). Renderer: global px(n)=round(n*UI_S), UI_S = width/css (dpr on web, 1 on desktop → byte-identical), defined before the content modules are required; wrapped theme fonts/metrics/gaps (theme_set_dpr), main.lua consts, homepage hp, sidebar, elements, canvas. Breakpoint width < MOBILE_BP*UI_S.
  • PERF (the big win): homepage was 27fps / dc=1622 (a text post was 60fps/dc=17). Cause: the feed drew ALL ~330 link rows + 87 message date-rows every frame, each font switch breaking the batch. Fix (1) cull off-screen feed items → dc ~47, 60fps. Fix (2) VIRTUALIZED feed — homepage_build stores metadata only (no doc load / no media fetch); message docs build lazily in homepage_draw (ensure_message_built) within a screen of the viewport, MSG_EST_H=260 for the unbuilt tail, build budget 2/frame. Scales to thousands + fixes the cold-load (only newest/on-screen media fetches). The video "15fps" was this draw-storm compounding — gone (60fps in playback). web_video_pump1 also skips texImage2D for a paused/ended video.
  • Increment 3 (live-resize): web_check_resize() polls the CSS viewport each frame → re-fit backing + game_width/height + layer_resize() over all layers (in-place color-tex + stencil-rbo realloc, drops the lazy effect buffer). sync_engine_globals refreshes width/height. DESKTOP browser resize WORKS; PHONE ROTATION does NOT (owner: "absolutely not necessary" — likely innerWidth stale on orientationchange). DEV_HUD off (local DEV_HUD=false). Owner kept the DPR cap at 2.0 (the fps fix was the culling, not the resolution).

Claude Code mobile access (research): owner wanted to feed phone screenshots into the session. Claude Code Remote Control does this, BUT is NOT available from the Claude Code DESKTOP app (only CLI + VS Code extension; issues #29006/#48949). Owner runs the Desktop app, so continued with the email round-trip.

Content skills sync the renderer (committed a5011fe): /msg, /draft publish, /end-session (normal+sealed), /unseal now append bash renderer/tools/deploy.sh --content after their prod push, so content syncs the ENGINE site too. Option A (always --content, non-aborting) + a gating tweak: new tools/uncached_tweets.py (mirrors uncached_media.py) so deploy.sh runs fetch_tweets --ids only for new tweets → a text-only post hits X zero times. Found a pre-existing drift (uncached YT id jr_Fzl2XwKU) the next sync will pull.

BOX2D LETTER-DROP effect — IN PROGRESS, LOCAL ONLY (engine bindings desktop-built only, NOTHING deployed/committed): clicking a [this](#drop) link turns the visible page into Box2D physics. Owner's iterated design: loose text = individual letters; video/image/gallery/embed = single rigid bodies; TWEETS = containers (4 wall fixtures = the card border, with text + portrait + media all tumbling as separate objects INSIDE, contained by the walls); separators = thin lines; sidebar letters fall but its bg tint stays; non-letter objects barely rotate; restitution/bounce; [this] stays static and clicking again = the reset (tween back).

  • Engine (SHARED anchor.c, DESKTOP-built only, NOT committed): engine_glyph_capture(on) / engine_glyph_capture_read() (records every glyph layer_draw_text draws into a buffer — enumerates visible letters); layer_draw_glyph_c(layerHANDLE, cp, font, cx, cy, r, sx, sy, color) (draw a glyph CENTERED + rotated — physics body → draw). Confirmed layer_push composes (current = parent*m) for nested transforms; reused the existing physics_shape_set_restitution (no engine change for bounce).
  • Renderer (main.lua "drop section" + hooks in elements.lua/homepage.lua, LOCAL): #drop/F9 → capture → build → fall; update() short-circuits (scroll off). Solid frames re-drawn rotated via a nested layer_push transform. Tweets = 4-wall containers + inner-tagged contents (inner↔inner/inner↔frame). drop_box helper sets restitution 0.5 on every shape (walls too). Tuned live: gravity 1700, letter spin ~±7, non-letter spin ~±0.4, tweet spin ±2.25, restitution 0.5, TW_WALL=6, DROP_MAX=2000.
  • WHAT'S LEFT (full detail in renderer/PLAN.md "▶ LETTER-DROP" section): (1) VIDEO in the drop — owner deciding (A) tap-to-play in place via rotated hit-test vs (B) click → the existing fullscreen player w/ controls (clicking a fallen video currently does nothing since update short-circuits; controls are axis-aligned so they don't fit a rotated card); (2) the RESET (increment 3) — static re-clickable this link + tween-back; (3) ship prep — rebuild the WEB engine w/ the 2 new bindings, real-phone test, remove the F9 trigger, commit anchor.c to Anchor2; (4) the announcement post (owner writes it + the video + [this](#drop), /msg it) then the FULL FLIP cutover.

Commits: Anchor2 1825c77 (mobile engine → GitHub); a327ex-site 5677ef1 (mobile renderer → prod), a5011fe (content-skill tooling → prod). Letter-drop engine + renderer are UNCOMMITTED + local. renderer/PLAN.md updated with the "Anchor Website 14" mobile section + the "▶ LETTER-DROP … IN PROGRESS" handoff (also uncommitted, local).

🔒 Only the summary of this log is public. Private because it contains too many website internal details.