Skip to content
Docs
Open Promoeyes
peripherals

peripherals

PERIPHERALS — the code-built keyboard and mouse (scripts/device-models/keyboard.mts, mouse.mts), and every way their `state` channel drives them. npm run models:devices -- keyboard --out <promo dir>/models/keyboard.glb npm run models:devices -- mouse --out <promo dir>/models/mouse.glb Both are 1 unit = 1 mm, stand on y = 0, centred, the user's side toward +z: place them with `position` = the surface point under their centre and no scale.

Read the rig's notes
KEYBOARD clips: press-<id> · down-<id> (with hold) · press-cmd+<id> · press-shift+<id> · rest.
  ids: esc f1…f12 eject · grave 1…0 minus equal delete · tab q…p lbracket rbracket backslash ·
       caps a…l semicolon quote return · lshift z…m comma period slash rshift ·
       fn ctrl lopt lcmd space rcmd ropt left up down right   (aliases: cmd, shift, option)
MOUSE clips: click-left · click-right · double-click-left · down-left · down-right (with hold) · rest.
Write every row as `TIME <clip> 0 hold`: 0 = no crossfade (a keystroke is 0.17 s), hold = park on
the last frame (a press ends up, a down- ends down) instead of looping. One clip plays at a time.

s1 · the keyboard types "hello", then ⌘K, then holds space down and lets it go.
s2 · the mouse: left click, right click, a double click, a press held.
Topic
devices
Scenes
2
Kind
reference rig
//
    PERIPHERALS — the code-built keyboard and mouse (scripts/device-models/keyboard.mts, mouse.mts),
    and every way their `state` channel drives them.
      npm run models:devices -- keyboard --out <promo dir>/models/keyboard.glb
      npm run models:devices -- mouse    --out <promo dir>/models/mouse.glb
    Both are 1 unit = 1 mm, stand on y = 0, centred, the user's side toward +z: place them with
    `position` = the surface point under their centre and no scale.

    KEYBOARD clips: press-<id> · down-<id> (with hold) · press-cmd+<id> · press-shift+<id> · rest.
      ids: esc f1…f12 eject · grave 1…0 minus equal delete · tab q…p lbracket rbracket backslash ·
           caps a…l semicolon quote return · lshift z…m comma period slash rshift ·
           fn ctrl lopt lcmd space rcmd ropt left up down right   (aliases: cmd, shift, option)
    MOUSE clips: click-left · click-right · double-click-left · down-left · down-right (with hold) · rest.
    Write every row as `TIME <clip> 0 hold`: 0 = no crossfade (a keystroke is 0.17 s), hold = park on
    the last frame (a press ends up, a down- ends down) instead of looping. One clip plays at a time.

    s1 · the keyboard types "hello", then ⌘K, then holds space down and lets it go.
    s2 · the mouse: left click, right click, a double click, a press held.
promo#peripherals(width=1920 height=1080 fps=30)
  materials
    physical#slab(color=#0b0b0d metalness=0.2 roughness=0.18 clearcoat=1 clearcoat-roughness=0.06 envmap-intensity=1)

  template#studio
    primitive#table(position="0 -10 0" receive_shadow=true)
      geometry(type=rounded-box width=1400 height=20 depth=900 radius=4 segments=3)
      material(ref=slab)

  // ═══ S1 · KEYBOARD ═══════════════════════════════════════════════════════════════════════════
  scene#s1-keyboard(duration=6)
    renderer(tone_mapping=None exposure=1 shadow_map=true shadow_map_type=pcf-soft)
    camera(dof_pass=three type=perspective fov=30 near=5 far=20000 position="-40 95 175" look_at="-25 6 20" dof_range=120 dof_blur=6)
    postprocessing
      step(name=render)
      step(name=unreal_bloom strength=0.12 radius=0.4 threshold=0.92)
      step(name=film_grain grain=0.02 scanlines=0 vignette=0.35 vignette_start=0.4 output_transform=2 exposure=1)
      step(name=aa method=ssaa samples=4)
    background(top=#16181c bottom=#08090b)
    environment(hdr="studio_small_04_2k" as_background=false background_color=#0b0c0e intensity=0.45 blurriness=0.4 environment_rotation_y_deg=40)
    lights
      light(type=ambient color=#8d96a8 intensity=0.05)
      light(type=directional color=#fff6ea intensity=1.6 position="-400 900 500" target="0 0 0" cast_shadow=true)
        shadow(map_size="4096 4096" bias=-0.0003 normal_bias=0.6 radius=3)
          camera(near=10 far=3000 left=-400 right=400 top=400 bottom=-400)
      light(type=area color=#dfe7f5 intensity=1.4 width=900 height=500 position="0 700 0" rotation="-90 0 0")
      light(type=spot color=#bcd4ff intensity=120000 angle=0.5 penumbra=1 position="300 120 -500" target="0 10 0")
    template(ref=studio)
    asset#kb(asset="model:keyboard" position="0 0 0")
      state
        0 rest
        1.00 press-h 0 hold
        1.16 press-e 0 hold
        1.32 press-l 0 hold
        1.48 press-l 0 hold
        1.64 press-o 0 hold
        2.60 press-cmd+k 0 hold
        3.60 down-space 0 hold
        4.60 rest 0 hold

  // ═══ S2 · MOUSE ═══════════════════════════════════════════════════════════════════════════════
  scene#s2-mouse(duration=6)
    renderer(tone_mapping=None exposure=1 shadow_map=true shadow_map_type=pcf-soft)
    camera(dof_pass=three type=perspective fov=30 near=5 far=20000 position="-130 60 150" look_at="0 9 0" dof_range=90 dof_blur=6)
    postprocessing
      step(name=render)
      step(name=unreal_bloom strength=0.12 radius=0.4 threshold=0.92)
      step(name=film_grain grain=0.02 scanlines=0 vignette=0.35 vignette_start=0.4 output_transform=2 exposure=1)
      step(name=aa method=ssaa sample