Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: LayoutitStudio/polycss
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: main
Choose a base ref
...
head repository: LayoutitStudio/polycss
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: feat/poly-iframe
Choose a head ref
Checking mergeability… Don’t worry, you can still create the pull request.
  • 17 commits
  • 24 files changed
  • 1 contributor

Commits on Jun 4, 2026

  1. feat(iframe): <poly-iframe> element + /television demo

    Adds a new public element across all three renderers for placing live
    iframes in 3D space, plus a five-TV demo page.
    
    - packages/polycss: PolyIframeElement (vanilla custom element). Mounts an
      iframe wrapper inside the parent <poly-scene>'s .polycss-scene so the
      CSS camera transform composes naturally with surrounding meshes. Same
      position/rotation/scale conventions as <poly-mesh> post-parity (world
      units, world-axis order, rotation conjugation rotateY(-rx) rotateX(-ry)
      rotateZ(-rz)). Width/height in world units; iframe centred at the
      wrapper's local origin so rotation/scale pivot at the visible centre.
    - packages/react: <PolyIframe> mirror with the same props.
    - packages/vue:   <PolyIframe> mirror with the same props.
    - 14/8/7 tests added per package; transform math + attribute forwarding
      pinned. AGENTS.md updated with the new element + naming entry.
    
    Bug fixes shipped alongside:
    - PolyPerspectiveCameraElement / PolyOrthographicCameraElement runtime
      attribute updates now mutate the camera handle in place and re-apply
      the scene transform. Before, the elements either recreated the handle
      (orphaning the scene's pointer) or updated but never called
      applyCamera, so rot-x/rot-y/zoom changes were ignored at runtime.
    - DocsHeader hides the floating search dock on /television (matches
      /gallery, /builder, /wordart).
    
    /television demo:
    - Vertical-rail TV picker (5 sets, hand-drawn SVG art per tile). ?tv=id
      query param + popstate sync so individual TVs are linkable.
    - Per-TV polygon indices identify which face(s) are the screen; the page
      derives the iframe's world-unit position, rotation, width, and height
      from those polygons' vertices at load time (area-weighted normal, bbox
      in the in-plane right/up basis, small lift along the normal so the
      iframe doesn't z-fight with the screen polygon itself). Per-TV rotY +
      zoom remain hand-tuned because GLB authoring orientations differ.
    - Retro Stack uses multiple screen entries — one <poly-iframe> per CRT
      is mounted dynamically and each is placed independently.
    apresmoi committed Jun 4, 2026
    Configuration menu
    Copy the full SHA
    42d17b1 View commit details
    Browse the repository at this point in the history
  2. feat(tv): rename /television → /tv, add header nav + floor + lighting

    - Rename /television route + public assets to /tv (shorter, link to it
      from the docs header next to WordArt).
    - Query param renamed to ?model=<id> (was ?tv=<id> — reads better
      alongside /tv).
    - Brighter scene lighting (directional 4.5→6.5, ambient 0.55→0.9) plus
      a ground <poly-plane> below each TV with cast-shadow on the mesh, so
      the bottom of every TV sits visibly on the floor.
    
    Element changes to support the floor:
    - PolyShapeElement now forwards `cast-shadow` / `receive-shadow` to
      scene.add (mirrors <poly-mesh>) and `exclude-from-auto-center` so
      ground planes don't skew the scene's auto-center calculation.
    - PolyShapeElement gains an attributeChangedCallback so transform attrs
      (position/scale/rotation/shadow) propagate after mount — the floor is
      re-positioned per TV from the script side once the mesh has loaded.
    - PolyPlaneElement: new `offset` attribute, defaulting to 0 so the
      plane is centered at the element's local origin. The underlying
      planePolygons helper defaulted to size*2 because it was authored as
      a transform-control drag handle.
    
    Camera-element runtime fix:
    - PolyPerspectiveCameraElement / PolyOrthographicCameraElement
      attributeChangedCallback now correctly locates the scene as a
      descendant (`this.querySelector('poly-scene')`) rather than an
      ancestor. The previous walk-up version always found null and
      applyCamera was never called, so runtime rot-x/rot-y/zoom changes
      were no-ops in vanilla.
    
    Tuning:
    - TV mesh gets `auto-center` so its bbox center IS mesh-local (0,0,0).
    - Floor's per-preset Z is derived from the mesh's minZ on load.
    - Per-TV cam.rotY/zoom dialed in by hand for each set (pixel TV at
      rotY 245 / zoom 10 for a 3/4 view that doesn't crop).
    apresmoi committed Jun 4, 2026
    Configuration menu
    Copy the full SHA
    9fee5e8 View commit details
    Browse the repository at this point in the history
  3. tv: add polygon 216 to retro stack's first screen + TODO for shadows

    - Retro stack screen 1: append poly 216 to the polyIndices array (user
      identified it as part of that CRT's bezel strip; was missing).
    - Floor shadow attempt: receiver-shadow on the floor + scene shadow
      config wired up cleanly, but the projected shadow SVG lands at wrong
      scene coords for our auto-centered TV + excludeFromAutoCenter floor
      combination. Vanilla dropped the legacy ground-shadow fallback for
      three.js parity, so a caster with no receiver draws nothing. Leaving
      the floor as a non-receiver for now with a TODO; lighting + floor
      geometry still ship.
    apresmoi committed Jun 4, 2026
    Configuration menu
    Copy the full SHA
    2fe3110 View commit details
    Browse the repository at this point in the history
  4. fix(tv): bump shadow.lift to 1 world unit so TV shadows clear the floor

    The receiver-shadow SVG sits at the floor plane plus `shadow.lift`
    (default 0.05 world units = 2.5 CSS px). On a big 400-world-unit floor
    viewed at a normal-angle camera (rotX 70), that razor-thin gap z-fought
    with the floor itself and the shadow only showed from straight overhead.
    A 1 world unit (50 CSS px) lift puts the shadow clearly in front at
    every angle the camera reaches.
    apresmoi committed Jun 4, 2026
    Configuration menu
    Copy the full SHA
    3b32528 View commit details
    Browse the repository at this point in the history
  5. fix(tv): drop poly 211 from retro stack's first screen

    The first CRT's actual screen polygons are 212–216 — 211 is an adjacent
    bezel face the iframe-placement code was averaging into the plane,
    shifting the iframe off the screen. Restricting to 212–216 lands the
    iframe on the visible glass.
    apresmoi committed Jun 4, 2026
    Configuration menu
    Copy the full SHA
    5f51765 View commit details
    Browse the repository at this point in the history
  6. tv: per-screen lift override; recess retro-stack iframes into bezels

    placementFromPolygons now takes an optional liftOverride; the TvScreen
    config exposes it as `lift`. The retro stack's CRT screens already
    model the front glass surface, so a small negative lift (−0.6 world
    units) seats the iframe inside the bezel instead of in front of it.
    
    The default lift formula (0.2 + 0.01 * max(w,h)) still applies for
    every other TV — those polygons mark the screen plane itself, so the
    iframe sitting slightly in front of them reads as the picture surface.
    apresmoi committed Jun 4, 2026
    Configuration menu
    Copy the full SHA
    5401d64 View commit details
    Browse the repository at this point in the history
  7. Configuration menu
    Copy the full SHA
    7d85e2d View commit details
    Browse the repository at this point in the history
  8. Configuration menu
    Copy the full SHA
    c62d2a5 View commit details
    Browse the repository at this point in the history
  9. Configuration menu
    Copy the full SHA
    b5e070a View commit details
    Browse the repository at this point in the history
  10. Configuration menu
    Copy the full SHA
    9ade7e3 View commit details
    Browse the repository at this point in the history
  11. Configuration menu
    Copy the full SHA
    4477e0a View commit details
    Browse the repository at this point in the history
  12. tv: re-enable receive-shadow on the TV mesh + bump shadow opacity

    The 'floating quad' I attributed to receive-shadow earlier turned out to
    be the monitor.glb's back panel authored at an offset position — present
    even without receive-shadow.
    
    Self-shadows on textured receivers are computed correctly but the
    texturedReceiver code reduces opacity to mimic three.js's 'darken to
    ambient-only' (`effOp = opacity * (1 - (ambient/total)^(1/2.4))`).
    With our bright light (dir 6.5, ambient 0.9) that pushed shadow alpha
    to ~0.32, which read as nearly-invisible 'white-ish' on textured TVs.
    Bumping the input opacity to 0.95 lands the effective alpha at ~0.55
    and the self-shadows now read as actually dark.
    apresmoi committed Jun 4, 2026
    Configuration menu
    Copy the full SHA
    e928b19 View commit details
    Browse the repository at this point in the history
  13. tv: shadow tweaks — lower lift back to 0.1, drop ambient so shadows r…

    …ead dark
    
    - Lift 1 → 0.1 world units. The bigger value was detaching shadows
      visibly from their receivers; 0.1 (5 CSS px) still clears z-fighting
      but reads as flush with the floor / bezel.
    - Ambient intensity 0.9 → 0.4. The texture-receiver code caps shadow
      alpha at `opacity * (1 - (ambient/total)^(1/2.4))` to mimic three.js's
      'darken to ambient-only' lighting model. With ambient=0.9 the cap
      pushed effective shadow alpha to ~0.32 — visibly faint / 'white-ish'
      on the TV's own faces. Lower ambient = darker possible shadows; 0.4
      hits the polycss default and lets self-shadows read as properly dark.
    apresmoi committed Jun 4, 2026
    Configuration menu
    Copy the full SHA
    59d94d6 View commit details
    Browse the repository at this point in the history
  14. Configuration menu
    Copy the full SHA
    59155ca View commit details
    Browse the repository at this point in the history
  15. tv: Orbit/FPV camera-mode pill + wider zoom range

    - Bottom-centre toggle switches between <poly-orbit-controls> and
      <poly-first-person-controls>. FPV mounts with WASD/jump/look and a
      hint label appears on the right side of the pill while active.
    - Orbit zoom range widened to [1, 200] so users can zoom out far past
      each TV's default zoom.
    apresmoi committed Jun 4, 2026
    Configuration menu
    Copy the full SHA
    9db0e88 View commit details
    Browse the repository at this point in the history
  16. tv: disable self-shadow + match gallery's FPV camera feel

    - Drop receive-shadow from the TV mesh: the texture-receiver darkening
      reads as 'white-ish' (capped at ambient brightness) and visible
      self-shadows weren't worth the cost.
    - FPV mode now matches the gallery's defaults: move-speed 30,
      jump-velocity 25, gravity 60, eye-height 6, look-sensitivity 0.15.
      Also switches camera perspective to 2000 while FPV is active (the
      same FPV_PERSPECTIVE the gallery and builder use) for a wider FOV;
      restores to 32000 when going back to Orbit.
    apresmoi committed Jun 4, 2026
    Configuration menu
    Copy the full SHA
    9345369 View commit details
    Browse the repository at this point in the history
  17. tv: FPV spawns BEHIND the TV looking at it (matches gallery's useFpvS…

    …pawn)
    
    Entering FPV used to drop the camera at scene origin (where the TV
    sits, since the scene is auto-centered) — so the player was INSIDE the
    TV with a face full of bezel.
    
    Now matching gallery's spawn behaviour:
    - Save + drop scene's auto-center attribute on entry, restore on exit.
    - Compute TV bbox from the loaded mesh handle, derive a spawn target
      one mesh-span behind the TV along the current rotY look direction,
      set it on the camera so the controls' initializeOriginFromTarget
      uses that as the seed.
    - Remove target on exit so orbit returns to its scene-origin pivot.
    apresmoi committed Jun 4, 2026
    Configuration menu
    Copy the full SHA
    82eca8b View commit details
    Browse the repository at this point in the history
Loading