@uptimizr/unreal 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md ADDED
@@ -0,0 +1,137 @@
1
+ # AGENTS.md — @uptimizr/unreal
2
+
3
+ > Packaged agent guide. For the human reference see [README.md](./README.md); for design
4
+ > rationale see the project ADRs at https://github.com/RaananW/Uptimizr/tree/main/docs/adr.
5
+
6
+ ## What this package is
7
+
8
+ The **Unreal Engine (web export)** connector for Uptimizr (ADR 0045). Unreal renders into a
9
+ `<canvas>` via WebAssembly, so there is no live JS scene to duck-type. This package is a thin
10
+ engine-flavoured wrapper over [`@uptimizr/web-export`](../web-export) and works in **two tiers**:
11
+
12
+ | Tier | Engine code? | Captures |
13
+ | ----------- | ----------------------------------------------- | --------------------------------------------------------------- |
14
+ | **JS-only** | none | pointer move/click heatmaps, FPS / long frames, JS errors |
15
+ | **Bridged** | a thin copy-in shim (see [`bridge/`](./bridge)) | camera pose → view-direction heatmap, world-space picks, replay |
16
+
17
+ Unreal's native world frame is **left-handed, z-up, centimeters** (`UNREAL_FRAME`,
18
+ `unitScale: 100`). It is the only engine that exercises the non-`y` up-axis and non-1 unit-scale
19
+ paths: the connector rebases **z-up → y-up** and converts **cm → m** before reaching the canonical
20
+ wire frame (ADR 0018 / ADR 0045 §5). The engine-side shim does **no** coordinate math.
21
+
22
+ **Status — best-effort by design.** Epic deprecated the official HTML5/Emscripten target after
23
+ UE 4.24, and Pixel Streaming renders server-side (no client WASM scene to read), so neither fits
24
+ this model. The shim targets the real Emscripten-based, client-side web exports — community HTML5
25
+ forks (UE 4.24–4.27, WebGL2) and Wonder Interactive / SimplyStream (UE 5.1–5.4, WASM + WebGPU).
26
+ Every viable target is experimental or community-maintained, so the **bridged tier is best-effort**;
27
+ the JS-only tier always works on any web export that renders into a `<canvas>`.
28
+
29
+ ## Install
30
+
31
+ ```bash
32
+ pnpm add @uptimizr/unreal
33
+ ```
34
+
35
+ The engine-side bridge is a **copy-in asset**, not an npm dependency — see [`bridge/`](./bridge).
36
+
37
+ ## Canonical usage — the web side
38
+
39
+ ```ts
40
+ import { trackUnreal } from "@uptimizr/unreal";
41
+
42
+ const { client, bridge } = trackUnreal({
43
+ projectId: "your-project",
44
+ endpoint: "https://collect.example.com",
45
+ canvas: () => document.querySelector("#unreal-canvas"),
46
+ });
47
+
48
+ // ... later, on teardown
49
+ await client.stop("manual");
50
+ ```
51
+
52
+ `trackUnreal` creates the client, registers the JS-only tier collector, publishes the engine
53
+ `bridge` (default `window.__uptimizr_unreal__`), and starts the session with Unreal's connector
54
+ provenance. Run it **before** the export boots so the bridge global exists when the shim
55
+ initializes. `client` is the `@uptimizr/sdk-core` `UptimizrClient` — read `client.sessionId`,
56
+ `client.track(name, props)`, `client.setScene(sceneId)`, `client.stop(reason)`.
57
+
58
+ ### Advanced (compose it yourself)
59
+
60
+ ```ts
61
+ import { UptimizrClient } from "@uptimizr/sdk-core";
62
+ import { unrealCollector, UNREAL_FRAME } from "@uptimizr/unreal";
63
+
64
+ const client = new UptimizrClient({ projectId: "your-project", endpoint: "..." });
65
+ client.use(unrealCollector({ canvas: () => document.querySelector("#unreal-canvas") }));
66
+ client.start();
67
+ ```
68
+
69
+ Options are `@uptimizr/web-export`'s `TrackWebExportOptions` with `name` and `frame` omitted
70
+ (they are fixed to `"unreal"` / `UNREAL_FRAME`): `canvas`, `capture`, `pointerMoveThrottleMs`,
71
+ `perfWindowMs`, `jankFrameMs`, `sceneId`, `bridgeGlobal`, `onSceneProxy`, `version`,
72
+ `flushIntervalMs`, `transport`, `disabled`, `debug`, `user`, `meta`.
73
+
74
+ ## Canonical usage — the engine side
75
+
76
+ The bridged tier needs a thin copy-in Emscripten shim: [`bridge/Uptimizr.h`](./bridge/Uptimizr.h)
77
+ and [`bridge/Uptimizr.cpp`](./bridge/Uptimizr.cpp).
78
+
79
+ 1. Copy both into your project's `Source/<Module>/` (or a plugin) so they build with your **web**
80
+ target.
81
+ 2. Load `@uptimizr/unreal` in the export's host page and call `trackUnreal({...})`.
82
+ 3. Drive the sampler from C++:
83
+
84
+ ```cpp
85
+ #include "Uptimizr.h"
86
+
87
+ UptimizrTelemetry().Initialize(); // once, after the page connector is up
88
+ UptimizrTelemetry().Tick(GetWorld(), DeltaSeconds); // every frame
89
+ UptimizrTelemetry().TraceAndReportPick(GetWorld()); // from your click handler
90
+ ```
91
+
92
+ …or drive `Init` / `Shutdown` from JS by symbol via `cwrap`
93
+ (`Module.cwrap('UptimizrBridge_Init', 'number', [])`).
94
+
95
+ `Initialize()` reads the live bridge's `protocolVersion` and asserts it equals
96
+ `UPTIMIZR_BRIDGE_PROTOCOL_VERSION` (`1`), staying disabled on a mismatch. `Tick` reads the active
97
+ `APlayerCameraManager` pose and accumulates FPS, pushing a pose every frame and a perf sample about
98
+ once per second. Outside Emscripten (e.g. the desktop editor) every entry point compiles to a
99
+ **no-op**, so the shim is safe to leave wired into every build target.
100
+
101
+ ## Rules for agents
102
+
103
+ - **Push raw Unreal values — centimeters, z-up, left-handed.** Do **not** pre-convert in the shim;
104
+ the TypeScript connector owns the single normalization path so every engine stays consistent
105
+ (ADR 0045 §4/§5).
106
+ - **The shim does no schema mapping.** Events live once in `@uptimizr/schema` and are emitted by
107
+ the connector.
108
+ - **Never invent identifiers engine-side** and never forward raw input text (ADR 0003/0045 §6).
109
+ Only poses, FPS and developer-assigned **named** objects cross the bridge (a pick sends the
110
+ actor's `GetName()` and the world hit point). No client-side persistent IDs; the server assigns
111
+ the cookieless visitor hash.
112
+ - `UNREAL_FRAME` is `{ handedness: "left", upAxis: "z", unitScale: 100 }` — it is the regression
113
+ canary for the non-y / non-1 normalization paths. Changing it silently corrupts every
114
+ world-space aggregate.
115
+ - Capture channels that need the engine (camera pose, world-space picks, scene proxy, replay) are
116
+ simply **absent** without the shim — do not fake them from the DOM.
117
+ - `registerRegions(sceneId, regions, { endpoint, apiKey })` (from `@uptimizr/sdk-core`) declares a
118
+ scene's named regions. It **replaces** the scene's set and needs an **`annotate`**-capable key —
119
+ never ship that key in a public bundle; call it from build/deploy/admin code.
120
+ - Native (non-web) Unreal builds and **Pixel Streaming** are out of scope (ADR 0045): server-side
121
+ rendering has no client WASM scene to read.
122
+
123
+ ## Export / build caveats
124
+
125
+ - You need an **Emscripten-based, client-side** web target (a community HTML5 fork, or Wonder
126
+ Interactive / SimplyStream). There is no official Epic web target to build against.
127
+ - The shim compiles to no-ops off Emscripten, so it can stay in the module for every target.
128
+ - Point `canvas` at the export's real canvas element and start `trackUnreal` before the export
129
+ boots.
130
+
131
+ ## More
132
+
133
+ - Package reference: [README.md](./README.md)
134
+ - Engine-side bridge: [`bridge/README.md`](./bridge/README.md)
135
+ - Unreal guide: https://uptimizr.com/docs/connectors/unreal/
136
+ - Shared foundation: [`@uptimizr/web-export`](../web-export/AGENTS.md)
137
+ - Integration guide: https://github.com/RaananW/Uptimizr/blob/main/docs/integration.md
package/README.md CHANGED
@@ -61,9 +61,14 @@ client.start();
61
61
  ## Engine-side bridge
62
62
 
63
63
  The bridged tier needs a thin copy-in shim that pushes world-space pose / picks / FPS
64
- across Unreal's Emscripten glue. The contract and an `EM_JS` sketch live in
65
- [`bridge/README.md`](./bridge/README.md). The full shim is authored in the Unreal
66
- web-export sub-issue (umbrella #111).
64
+ across Unreal's Emscripten glue. It ships in [`bridge/`](./bridge) as
65
+ [`Uptimizr.h`](./bridge/Uptimizr.h) + [`Uptimizr.cpp`](./bridge/Uptimizr.cpp): copy both
66
+ into your project's `Source/<Module>/` (or a plugin) so they build with your **web**
67
+ target, then drive `UptimizrTelemetry().Initialize()` / `.Tick(World, DeltaSeconds)` /
68
+ `.TraceAndReportPick(World)` from C++ (or `Init` / `Shutdown` from JS via `cwrap`). Off
69
+ Emscripten every entry point compiles to a no-op. `Initialize()` asserts the live bridge's
70
+ `protocolVersion` matches `UPTIMIZR_BRIDGE_PROTOCOL_VERSION` (1). The full contract, the
71
+ viable web targets, and an `EM_JS` sketch are in [`bridge/README.md`](./bridge/README.md).
67
72
 
68
73
  ## Privacy
69
74