Skip to content
Docs
Open Promoeyes
app-tour

app-tour

APP-TOUR primitives — how a promo POINTS AT one thing on a screen.

Read the rig's notes
Product tours are made of four tags and one rule.

  ui                    the app itself, rasterised onto the device glass.
                        Cheap, sharp, and completely FLAT: its items are
                        pixels in a canvas, so nothing in here can be lifted
                        off, framed by the camera, or lit. Everything the
                        tour does NOT touch lives here.

  ui3d(overlay=screen)  the tour layer. Real plane meshes, surface-anchored
                        flush on that same glass in the SAME coordinate
                        space — an item authored at the same x/y sits
                        pixel-exact on its texture twin. Being real
                        geometry, it can leave the display (+z), be framed
                        by id, and cast into the scene's light.

  mouse                 the pointer. Its move keyframes address UI items BY
                        ID — texture items included — so a click tracks its
                        button while the phone is still turning.

  ui3d (free-standing)  the callout. A panel that belongs to the SCENE
                        rather than to the screen, met by a leader line in
                        world millimetres.

THE RULE: author the thing TWICE. Once in the texture, where it is just part
of the app, and once in an overlay, where it is the subject. At rest the two
are one image; the overlay is the only thing that ever moves.

STACKING. `lift` is millimetres off the glass and doubles as the paint order
of the tour: base app 0 · scrim 0.02 · popped card 0.04 · hero control 0.06.
Give every overlay in a scene its own lift or they z-fight on the display.

SCREEN mm -> WORLD mm. A leader line, a world label or a floating panel has
to meet the popout in world space. For an UNROTATED device at (px, py, pz)
with a W x H glass, a screen point (sx, sy) is:

    world = (px + sx - W/2,  py + H/2 - sy,  pz + glassZ + lift + dz)

Screen y runs DOWN and world y runs UP, hence the flip. The iphone glass
sits at z = +6.3 in the device's own frame. Rotate the device and this stops
being arithmetic — which is why scene 05 keeps its phone square-on.

FIVE TRAPS, every one of them found the hard way:

  1. iphone safe-top pushes every TEXTURE item down ~4.6mm to clear the
     Dynamic Island, and does NOT touch the overlays. A flush twin is then
     4.6mm out of register. Author `safe-top=off` and your own top margin.
  2. Overlay stage size. `width`/`height` on the overlay IS the glass in mm
     (iphone 71x154, ipad 197x262, laptop 346x223, chrome 480x300). Leave it
     off and every coordinate inside is read against 1920x1080 instead.
  3. Cursor coordinate keyframes are RELATIVE to the mouse's authored
     `position` — its home. `value="0 0 0"` means "at home"; repeating the
     home coordinates in a kf puts the pointer at twice the distance. Only
     `absolute=true` reads a value as a world point. (Camera keyframes are
     the opposite: a camera is never rebased, so its values are absolute.)
  4. Framing. A texture item has no world bounds, so `node=<texture item>`
     never resolves. A device-mounted overlay IS real geometry and is the
     documented way to frame a region of a screen — but its framed pose only
     resolves in the FIRST scene of a reel today; seek into any later scene
     and the solve reads the overlay's un-anchored stage coordinates and the
     shot lands off the device. (camera-framing-devices scene 08 has the same
     symptom.) Until that is fixed, frame the DEVICE or a FREE-STANDING ui3d
     panel — both are ordinary scene nodes and both are exact. Keep the first
     framed beat a couple of seconds in, and use `bounds=union side=front`.
  5. `scroll` moves the TEXTURE's children only. An overlay does not ride it,
     so pop the twin AFTER the scroll parks, at the row's settled y.

One app throughout — Flowlet, a light UI on a dark stage, so a scrim reads as
a scrim and a popout reads as a card in the air.

Scene map, one idea each:
  01 LIFT       a card leaves the glass, and the slot it left behind
  02 SPOTLIGHT  a scrim under the tour layer, one button above it
  03 POINTER    the cursor addresses a button by id, then the pop fires
  04 FRAME      the row hands off to a world panel, and the camera names it
  05 CALLOUT    a world panel and a leader line, met in world millimetres
  06 STEPS      a three-stop chain on one screen, one scrim throughout
  07 SCROLL     reach a row deep in a list, park, then pop its twin
  08 DESKTOP    the same four tags on a chrome window
  09 ATLAS      every layer at once, labelled with its lift

Capture: nx run tools:capture:webgl -- --project promos/primitives/app-tour/app-tour.promo
Preview: /packages/runtime/index.html?project=promos/primitives/app-tour/app-tour.promo
Topic
uis
Scenes
9
Kind
reference rig
//
    APP-TOUR primitives — how a promo POINTS AT one thing on a screen.

    Product tours are made of four tags and one rule.

      ui                    the app itself, rasterised onto the device glass.
                            Cheap, sharp, and completely FLAT: its items are
                            pixels in a canvas, so nothing in here can be lifted
                            off, framed by the camera, or lit. Everything the
                            tour does NOT touch lives here.

      ui3d(overlay=screen)  the tour layer. Real plane meshes, surface-anchored
                            flush on that same glass in the SAME coordinate
                            space — an item authored at the same x/y sits
                            pixel-exact on its texture twin. Being real
                            geometry, it can leave the display (+z), be framed
                            by id, and cast into the scene's light.

      mouse                 the pointer. Its move keyframes address UI items BY
                            ID — texture items included — so a click tracks its
                            button while the phone is still turning.

      ui3d (free-standing)  the callout. A panel that belongs to the SCENE
                            rather than to the screen, met by a leader line in
                            world millimetres.

    THE RULE: author the thing TWICE. Once in the texture, where it is just part
    of the app, and once in an overlay, where it is the subject. At rest the two
    are one image; the overlay is the only thing that ever moves.

    STACKING. `lift` is millimetres off the glass and doubles as the paint order
    of the tour: base app 0 · scrim 0.02 · popped card 0.04 · hero control 0.06.
    Give every overlay in a scene its own lift or they z-fight on the display.

    SCREEN mm -> WORLD mm. A leader line, a world label or a floating panel has
    to meet the popout in world space. For an UNROTATED device at (px, py, pz)
    with a W x H glass, a screen point (sx, sy) is:

        world = (px + sx - W/2,  py + H/2 - sy,  pz + glassZ + lift + dz)

    Screen y runs DOWN and world y runs UP, hence the flip. The iphone glass
    sits at z = +6.3 in the device's own frame. Rotate the device and this stops
    being arithmetic — which is why scene 05 keeps its phone square-on.

    FIVE TRAPS, every one of them found the hard way:

      1. iphone safe-top pushes every TEXTURE item down ~4.6mm to clear the
         Dynamic Island, and does NOT touch the overlays. A flush twin is then
         4.6mm out of register. Author `safe-top=off` and your own top margin.
      2. Overlay stage size. `width`/`height` on the overlay IS the glass in mm
         (iphone 71x154, ipad 197x262, laptop 346x223, chrome 480x300). Leave it
         off and every coordinate inside is read against 1920x1080 instead.
      3. Cursor coordinate keyframes are RELATIVE to the mouse's authored
         `position` — its home. `value="0 0 0"` means "at home"; repeating the
         home coordinates in a kf puts the pointer at twice the distance. Only
         `absolute=true` reads a value as a world point. (Camera keyframes are
         the opposite: a camera is never rebased, so its values are absolute.)
      4. Framing. A texture item has no world bounds, so `node=<texture item>`
         never resolves. A device-mounted overlay IS real geometry and is the
         documented way to frame a region of a screen — but its framed pose only
         resolves in the FIRST scene of a reel today; seek into any later scene
         and the solve reads the overlay's un-anchored stage coordinates and the
         shot lands off the device. (camera-framing-devices scene 08 has the same
         symptom.) Until that is fixed, frame the DEVICE or a FREE-STANDING ui3d
         panel — both are ordinary scene nodes and both are exact. Keep the first
         framed beat a couple of seconds in, and use `bounds=uni