@rr0/ufoathome 0.12.5 → 0.12.6

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/README.md CHANGED
@@ -100,7 +100,8 @@ mechanism.
100
100
  ## `<rr0-ufo-recorder>` — full editor
101
101
 
102
102
  The authoring component (~540KB gzip — see below for why): everything `<rr0-ufo>` has, plus a shape/appearance
103
- toolbar (oval/saucer/triangle presets, color, transparency, halo) and drag-to-record. It composes a nested
103
+ toolbar (oval/polygon presets, color, transparency, halo, and the object's real reported
104
+ size/distance — see [Apparent size](#apparent-size)) and drag-to-record. It composes a nested
104
105
  `<rr0-scene>` internally — not a bare `<rr0-ufo>` — so the shape being drawn is always seen against the
105
106
  sighting's own real sky, computed live from whatever latitude/longitude/heading/orientation/observation-time
106
107
  fields the toolbar currently holds (see [Architecture](#architecture)). This absorbs `<rr0-scene>`'s own
@@ -111,8 +112,23 @@ this heavier authoring component.
111
112
 
112
113
  ```html
113
114
  <rr0-ufo-recorder></rr0-ufo-recorder>
115
+ <rr0-ufo-recorder src="sighting.json"></rr0-ufo-recorder>
114
116
  ```
115
117
 
118
+ With `src`, the editor opens on an existing recording instead of an empty canvas — the same
119
+ attribute the three other elements take. That is what makes an editor URL per observation possible:
120
+ rr0.org's own editor page maps its `?sighting=` parameter onto it, and
121
+ [ufoathome.org](https://ufoathome.org) redirects any path it is given into that parameter, so
122
+
123
+ - `https://ufoathome.org/science/crypto/ufo/enquete/dossier/Socorro/sighting.json`, or simply
124
+ - `https://ufoathome.org/Socorro` for a case dossier of that site (a value with no `/` is expanded
125
+ to `/science/crypto/ufo/enquete/dossier/<name>/sighting.json`),
126
+
127
+ opens that observation for editing. The page only accepts recordings from its own origin: a shared
128
+ link must not be able to display a recording fabricated elsewhere inside an rr0.org page. To load
129
+ one from anywhere else, use the editor's own **Load from URL** field, which is an explicit gesture
130
+ by whoever is sitting at the keyboard.
131
+
116
132
  Usage: click **Record**, move the pointer over the canvas to draw the UFO's path, click **Stop**, then **Play** to
117
133
  replay it. The nested `<rr0-ufo>`'s `enableClickToPlay` is set to `false` here — a completed recording drag also
118
134
  fires a native "click" on the canvas, which would otherwise spuriously toggle playback right after recording.
@@ -123,8 +139,9 @@ Duration) are translated (English/French) the same way `<rr0-ufo>`'s own labels
123
139
 
124
140
  | Member | Kind | Description |
125
141
  |---|---|---|
142
+ | `src` | attribute | URL of a `SightingRecordingJson` to open in the editor, fetched on connect and whenever the attribute changes |
126
143
  | `sightingData` | property (get/set) | Delegates to the nested `<rr0-ufo>`'s `sightingData` |
127
- | `appearance` | property (get/set, accepts a partial object on set) | `{ presetId: "oval" \| "saucer" \| "triangle", color: string, transparency: number, haloScale: number }` — the UFO's appearance used for the next recording |
144
+ | `appearance` | property (get/set, accepts a partial object on set) | `{ presetId: "oval" \| "polygon", color: string, transparency: number, haloScale: number }` — the UFO's appearance used for the next recording |
128
145
 
129
146
  ## `<rr0-scene>` — 3D decor
130
147
 
@@ -208,10 +225,10 @@ URL (typically relative to the case's own page, same as `<rr0-ufo>`'s own `src`)
208
225
 
209
226
  The two shapes are told apart automatically — a fetched JSON array is a manifest, a plain object is one witness's
210
227
  own recording. No labels or ids are duplicated in a manifest itself — each witness's display name and the shared
211
- case id grouping them together are read from that witness's *own* file (`witnessName`/`caseId`, see
228
+ case id grouping them together are read from that witness's *own* file (`witness`/`caseId`, see
212
229
  [Data format](#data-format)), so there's a single source of truth and nothing to drift out of sync. This means
213
230
  every listed witness's recording is fetched upfront (to read its name), not lazily on selection — fine at the
214
- scale a case's witness list actually has. If a witness has no `witnessName`, its `witnessId` is shown instead, or
231
+ scale a case's witness list actually has. If a witness has no `witness.title`, its `witness.id` is shown instead, or
215
232
  the URL itself as a last resort. A mismatched `caseId` across the listed witnesses logs a console warning (doesn't
216
233
  block) — likely means unrelated recordings got listed together by mistake.
217
234
 
@@ -229,13 +246,35 @@ selector loads that witness's already-fetched recording into the nested `<rr0-sc
229
246
  `witnessUrls` again (e.g. a manifest refresh) keeps the current selection if that witness is still present, instead
230
247
  of resetting back to the first.
231
248
 
232
- Clicking "?" opens a panel, anchored to the button as a floating overlay (it never shifts the canvas below it).
233
- Its main content is the currently-selected witness's observation metadata (date, location, case id whichever are
234
- actually present in that witness's own `sighting.json`; the witness's own name isn't repeated here, since it's
235
- already in the toolbar's testimony line). Below that, a smaller footer row holds the app's own name/version on the
236
- left, linking to [ufoathome.org](https://ufoathome.org), and a "Credits" link on the right that reveals third-party
237
- credits on click (the live terrain imagery attribution, once a real relief patch has resolved, plus the bundled
238
- thunder sound's own required attribution see [`CREDITS.md`](CREDITS.md)).
249
+ Clicking "?" opens a panel anchored under the button (it never shifts the canvas below it). Where the browser has
250
+ the popover API the panel is a top-layer `popover="auto"` the one placement a host page's own `overflow: hidden`
251
+ wrapper cannot clip, which is what rr0.org's layout was doing to it kept under the button by CSS anchor
252
+ positioning, flipping above it or centring in the viewport when that side is too short, and closing on Escape or a
253
+ click outside. Browsers without the API get the plain absolutely-positioned overlay instead.
254
+
255
+ Its main content is the currently-selected witness's observation metadata (date, location, case id, description,
256
+ tags — whichever are actually present in that witness's own `sighting.json`; the witness's own name isn't repeated
257
+ here, since it's already in the toolbar's testimony line). The date is shown on the WITNESS's own clock, never
258
+ converted into the reader's time zone (see `utcOffsetHours` in [Data format](#data-format)).
259
+
260
+ A footer row holds the app's own name/version on the left — linking to that very observation in the editor (see
261
+ [`<rr0-ufo-recorder>`](#rr0-ufo-recorder--full-editor)'s own `src`), not to the application's home page — and two
262
+ fold-outs on the right, both closed until asked for:
263
+
264
+ - **Embed** hands out the two self-contained lines it takes to put this observation on any other page, either as a
265
+ replay (`<rr0-eyewitness>`) or as the editor (`<rr0-ufo-recorder>`), with absolute URLs and a copy button:
266
+
267
+ ```html
268
+ <script type="module" src="https://rr0.org/science/crypto/ufo/rr0-eyewitness.mjs"></script>
269
+ <rr0-eyewitness src="https://rr0.org/science/crypto/ufo/enquete/dossier/Socorro/sighting.json"></rr0-eyewitness>
270
+ ```
271
+
272
+ The script URL is derived from where the running bundle was itself loaded from (`import.meta.url`), never
273
+ hardcoded, so a snippet generated from a local or staging copy points back at that copy. Pasting it into a site
274
+ of your own needs the bundle and the recording to be readable cross-origin (rr0.org serves
275
+ `/science/crypto/ufo/*` with `Access-Control-Allow-Origin: *` for exactly this).
276
+ - **Credits** reveals third-party credits (the live terrain imagery attribution, once a real relief patch has
277
+ resolved, plus the bundled thunder sound's own required attribution — see [`CREDITS.md`](CREDITS.md)).
239
278
 
240
279
  All of this component's own labels (Testimony by, About, Close, Observation/Date/Location/Case, Credits) are
241
280
  translated (English/French) the same way as `<rr0-ufo>`'s own labels.
@@ -250,10 +289,12 @@ interface SightingRecordingJson {
250
289
  time?: { year?: number, month?: number, day?: number, hour?: number, minute?: number, second?: number }
251
290
  endTime?: { year?: number, month?: number, day?: number, hour?: number, minute?: number, second?: number } // alternative to durationSeconds
252
291
  durationSeconds?: number // alternative to endTime; takes precedence if both are set
292
+ utcOffsetHours?: number // the LEGAL time zone the witness's clock was on (+1 for France in 1965, -7 for New Mexico in April 1964). Absent = approximated from the longitude, which cannot know legal time or a daylight-saving switch
253
293
  place?: { lat: number, lng: number }[]
254
- witnessId?: string // opaque internal referenceno PII beyond a display name (see witnessName)
255
- witnessName?: string // for cases where the witness is already publicly named in the published material (e.g. Chiles-Whitted) — omit for anonymous witnesses
294
+ witness?: { id?: string, dirName?: string, title?: string, lastName?: string, firstNames?: string[] } // every field optionalsupply whichever is known; omit entirely for an anonymous witness
256
295
  caseId?: string // shared by every witness's own sighting.json for the same case — see <rr0-eyewitness>
296
+ description?: string
297
+ tags?: string[]
257
298
  timeline: {
258
299
  keyframes: Array<{
259
300
  t: number // milliseconds since recording start
@@ -267,14 +308,35 @@ interface SightingRecordingJson {
267
308
  transparency: number // 0 = opaque, 1 = fully transparent
268
309
  haloScale: number // 0 = no glow
269
310
  selected: boolean
311
+ title?: string // shown as an on-canvas tooltip when hovered
312
+ physical?: { sizeM: number, distanceM: number } // what the witness reported — see Apparent size
270
313
  points?: { x: number, y: number }[] // "polygon" shapes only
271
314
  }
272
315
  }>
273
316
  }>
317
+ order?: string[] // back-to-front paint/hit-test order; absent = first-appearance order
318
+ groups?: string[][] // each inner array is one group's member sourceIds
274
319
  }
320
+ witnessTrack?: { keyframes: Array<{ t: number, pose: { lat?: number, lng?: number, elevationM: number, headingDeg?: number, pitchDeg: number, fovDeg: number } }> }
321
+ weatherTrack?: { keyframes: Array<{ t: number, weather: Weather }> }
322
+ weather?: Weather // legacy static fallback for recordings predating weatherTrack
323
+ decor?: DecorObject[] // buildings, trees, streetlights, vehicles, other witnesses — see src/engine/model/Decor.ts
275
324
  }
276
325
  ```
277
326
 
327
+ A shape left out of a later keyframe is **held** at its last recorded state, not hidden — and one whose first
328
+ keyframe is at `t=5000` is already painted, in that state, from `t=0` (hold-first/hold-last at both ends of a
329
+ source's own range). To make something stop being visible, keyframe it with `transparency: 1`.
330
+
331
+ ### Apparent size
332
+
333
+ `physical` is the witness's own reported size and distance, and the on-screen `bounds.width` is derived from it
334
+ rather than drawn by eye: on the 640x360 canvas at the default 60° vertical field of view, one degree is about
335
+ 5.4px and the full Moon about 2.8px, so an object of 3.5m at 90m is 12px wide — not the 90px an author reaches for
336
+ unaided. `ApparentSize` (`src/engine/shape/ApparentSize.ts`) does the conversion both ways, and the editor's own
337
+ **Real size** / **Distance** fields apply it and read back what the current drawing actually spans, in degrees and
338
+ in full Moons.
339
+
278
340
  This format is deliberately independent of [`@rr0/data`](https://github.com/RR0/data)'s `RR0Event`/`@rr0/time`'s
279
341
  `Level2Date`/`@rr0/place`'s `Place` classes, even though its `time`/`place` fields are structurally aligned with
280
342
  them — importing those classes into browser-bundled code pulls in Node-only file-scanning dependencies that break a