@realsee/vr-cli 0.1.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/NOTICE.md +7 -0
- package/README.md +216 -0
- package/TERMS.txt +54 -0
- package/agent-assets/AGENTS.md +113 -0
- package/agent-assets/adapters/.cursor/rules/realsee-vr.mdc +7 -0
- package/agent-assets/adapters/.github/copilot-instructions.md +1 -0
- package/agent-assets/adapters/.kiro/steering/realsee-vr.md +6 -0
- package/agent-assets/adapters/CLAUDE.md +3 -0
- package/bin/vr-cli.mjs +3 -0
- package/dist/cli.mjs +24 -0
- package/package.json +38 -0
- package/skills/realsee-image-resources/SKILL.md +82 -0
- package/skills/realsee-image-resources/references/cors-and-three-textures.md +50 -0
- package/skills/realsee-image-resources/references/data-wanxiang.md +57 -0
- package/skills/realsee-image-resources/references/five-image-url-transform.md +81 -0
- package/skills/realsee-image-resources/references/source-and-domain-policy.md +63 -0
- package/skills/realsee-vr-app/SKILL.md +157 -0
- package/skills/realsee-vr-app/references/continuous-improvement.md +24 -0
- package/skills/realsee-vr-app/references/dnalogel-api-capabilities.md +241 -0
- package/skills/realsee-vr-app/references/dnalogel-openapi-recipes.md +818 -0
- package/skills/realsee-vr-app/references/five-api-capabilities.md +119 -0
- package/skills/realsee-vr-app/references/five-runtime.md +83 -0
- package/skills/realsee-vr-app/references/official-docs.md +61 -0
- package/skills/realsee-vr-app/references/plugin-lifecycle.md +65 -0
- package/skills/realsee-vr-app/references/ui-and-validation.md +57 -0
- package/skills/realsee-vr-app/references/vapor-dom-layer.md +186 -0
- package/skills/realsee-vr-app/scripts/verify-project.mjs +1566 -0
- package/skills/threejs-r117-five/SKILL.md +71 -0
- package/skills/threejs-r117-five/references/five-ownership.md +70 -0
- package/skills/threejs-r117-five/references/r117-capabilities.md +82 -0
- package/skills/threejs-r117-five/references/r117-version-guards.md +60 -0
- package/templates/base/.editorconfig +12 -0
- package/templates/base/.env.example +12 -0
- package/templates/base/.gitignore.template +6 -0
- package/templates/base/.node-version +1 -0
- package/templates/base/.npmrc.template +3 -0
- package/templates/base/.nvmrc +1 -0
- package/templates/base/.prettierignore +12 -0
- package/templates/base/README.md +160 -0
- package/templates/base/eslint.config.mjs +75 -0
- package/templates/base/index.html +13 -0
- package/templates/base/package-lock.json +6444 -0
- package/templates/base/package.json +55 -0
- package/templates/base/prettier.config.mjs +5 -0
- package/templates/base/server/app.ts +54 -0
- package/templates/base/server/check-config.ts +4 -0
- package/templates/base/server/config.ts +54 -0
- package/templates/base/server/index.ts +31 -0
- package/templates/base/server/realsee-open-api.ts +316 -0
- package/templates/base/server/types.ts +64 -0
- package/templates/base/server/work-route.ts +80 -0
- package/templates/base/server/work-service.ts +54 -0
- package/templates/base/shared/model-floorplan.ts +242 -0
- package/templates/base/src/main.tsx +11 -0
- package/templates/base/src/shared/useElementSize.ts +28 -0
- package/templates/base/src/styles.css +91 -0
- package/templates/base/src/vr/five/SpatialRuntimeProvider.tsx +234 -0
- package/templates/base/src/vr/five/api.ts +10 -0
- package/templates/base/src/vr/five/fiveConfig.ts +42 -0
- package/templates/base/src/vr/five/initialState.ts +48 -0
- package/templates/base/src/vr/plugins/SpatialPluginRegistry.ts +104 -0
- package/templates/base/src/vr/plugins/dnalogel.ts +2 -0
- package/templates/base/src/vr/plugins/examples/FeatureOwnedMeshPlugin.ts +73 -0
- package/templates/base/src/vr/work/WorkSource.ts +247 -0
- package/templates/base/tsconfig.json +27 -0
- package/templates/base/tsconfig.server.json +25 -0
- package/templates/base/vite.config.ts +21 -0
- package/templates/viewer/src/app/App.tsx +182 -0
- package/templates/viewer/src/features/floorplan/ModelFloorplanFeature.ts +141 -0
- package/templates/viewer/src/features/navigation/ModeSwitcher.tsx +111 -0
- package/templates/viewer/src/features/tags/PanoTagFeature.ts +110 -0
- package/templates/viewer/src/ui/ViewerOverlay.tsx +141 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: realsee-vr-app
|
|
3
|
+
description: Build, extend, or review Realsee spatial applications with the complete native @realsee/five and @realsee/dnalogel capabilities, using @realsee/vapor only for the DOM layer above the native Five canvas. Use for Work, rendering, models, state, camera, coordinates, events, plugins, VR spatial tags and annotations, floorplans, measurement, routes, media, effects, overlays, cleanup, and browser validation.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Realsee spatial application workflow
|
|
7
|
+
|
|
8
|
+
The generated product is currently a read-only Viewer, but its SDK boundary is not a reduced Viewer API. Five is the complete spatial runtime; dnalogel supplies a preset plugin collection, while application-defined plugins may integrate directly with Five through the same local plugin infrastructure. Vapor is a React DOM component layer above it. React may own local composition, Context and lifecycle effects, but the generated runtime must not use the delayed `@realsee/five/react` adapter.
|
|
9
|
+
|
|
10
|
+
## 1. Classify the change by layer
|
|
11
|
+
|
|
12
|
+
- `server`: replaceable BFF example; OpenAPI authentication/adaptation, framework-neutral Work and plugin-data services, Fastify HTTP routes and production static hosting.
|
|
13
|
+
- `src/vr/five`: native Five construction, renderer/canvas ownership, Work/State and full public SDK access.
|
|
14
|
+
- `src/vr/plugins`: vendor-neutral registration and lifecycle infrastructure for dnalogel presets and application-defined Five plugins; `dnalogel.ts` is only the preset package capability barrel.
|
|
15
|
+
- `src/vr/work`: injectable Work acquisition, identity and explicit preset-data boundary.
|
|
16
|
+
- `src/features`: small lifecycle-owning compositions such as navigation or a selected spatial-annotation renderer.
|
|
17
|
+
- `src/ui`: Vapor/React DOM only; no independent spatial source of truth.
|
|
18
|
+
- `src/app`: composition of the spatial stage, features and DOM overlay.
|
|
19
|
+
|
|
20
|
+
Apply these stable capability and data-source rules before implementation:
|
|
21
|
+
|
|
22
|
+
- Spatial capability resolution order: installed @realsee/dnalogel preset -> native Five -> Three.js.
|
|
23
|
+
- Tags, hotspots, and anchors default to PanoTagPlugin with GET /open/v3/hot/list.
|
|
24
|
+
- Tours use Five State snapshots with GET /open/v3/observerpicture/search.
|
|
25
|
+
- Model annotations default to ModelMakerPlugin with GET /open/v3/annotation/search.
|
|
26
|
+
- Routes use GuideLinePlugin for rendering and shape-selected CruisePlugin or MovePlugin playback with GET /open/v3/route/search.
|
|
27
|
+
- SDK-shaped custom data requires an explicit developer opt-out from Open Platform data.
|
|
28
|
+
|
|
29
|
+
For every spatial, VR or 3D request, inspect the installed `@realsee/dnalogel` catalog and the candidate plugin declarations first. Only when no preset matches or the matching preset has a documented capability gap may the feature fall back to native Five and then to Three through Five's ownership boundaries. Record the missing preset capability rather than silently beginning with custom Three code.
|
|
30
|
+
|
|
31
|
+
When a custom fallback is justified, inspect `src/vr/plugins/examples/FeatureOwnedMeshPlugin.ts` first. Treat it as the preferred opt-in pattern: reuse the existing Five instance, own one removable scene root, roll back failed registration, set `five.needsRender`, and dispose only feature-owned resources. Do not import or register the example from the default App; enable an adapted plugin explicitly from a focused feature and pair it with `SpatialRuntimeLifetime.own()` plus identity-safe `plugins.unregister(name, expected)`.
|
|
32
|
+
|
|
33
|
+
Do not add an AI provider to the runtime core. Optional AI adapters may propose typed actions but must not silently mutate persistent data.
|
|
34
|
+
|
|
35
|
+
## 2. Retrieve exact version knowledge
|
|
36
|
+
|
|
37
|
+
Start with [references/official-docs.md](references/official-docs.md), then load only the references matching the task:
|
|
38
|
+
|
|
39
|
+
- Complete Five native surface: [references/five-api-capabilities.md](references/five-api-capabilities.md)
|
|
40
|
+
- Image sources, approved CDN hosts, Five URL transforms, 数据万象 and CORS: [realsee-image-resources/SKILL.md](../realsee-image-resources/SKILL.md)
|
|
41
|
+
- Three.js r117 capabilities and Five ownership: [threejs-r117-five/SKILL.md](../threejs-r117-five/SKILL.md)
|
|
42
|
+
- Five Work/State/modes/rendering invariants: [references/five-runtime.md](references/five-runtime.md)
|
|
43
|
+
- Complete dnalogel plugin families and spatial-annotation routing: [references/dnalogel-api-capabilities.md](references/dnalogel-api-capabilities.md)
|
|
44
|
+
- Self-contained prompt → OpenAPI/BFF → SDK implementation recipes for projects without SDK source: [references/dnalogel-openapi-recipes.md](references/dnalogel-openapi-recipes.md)
|
|
45
|
+
- Plugin lifecycle and registration: [references/plugin-lifecycle.md](references/plugin-lifecycle.md)
|
|
46
|
+
- Vapor's DOM-only boundary: [references/vapor-dom-layer.md](references/vapor-dom-layer.md)
|
|
47
|
+
- DOM layering and browser validation: [references/ui-and-validation.md](references/ui-and-validation.md)
|
|
48
|
+
|
|
49
|
+
For Vapor, start with the target project's installed `node_modules/@realsee/vapor/AI_CONTEXT.md` and `llms.txt`, use `ai_guides/README.md` plus the relevant component or recipe only to discover candidates, then confirm the public export in `vapor.d.ts` and the exact props in installed declarations.
|
|
50
|
+
|
|
51
|
+
External generated projects are not expected to have the Five or dnalogel source repositories. Start from the bundled [OpenAPI-to-SDK recipes](references/dnalogel-openapi-recipes.md) to map the user's prompt to an authoritative API, adapter, plugin and cleanup flow; never require cloning SDK source or locating repository examples.
|
|
52
|
+
|
|
53
|
+
Installed package declarations are authoritative for the versions actually resolved by `package-lock.json`. The generated minimums are Five 6.8.9 and dnalogel 3.81.2, but an intentional update may install newer releases. For Five, read its packaged `AI_CONTEXT.md` and `llms.txt` before feature guides. For dnalogel, start with its installed `package.json`/`exports`, `libs/index.d.ts`, then the selected plugin declaration barrel; template source, dnalogel repository examples, and online examples are supporting evidence only. For Three-based features, load the sibling `threejs-r117-five` Skill and verify against the exact r117 declarations. Never infer a method, content discriminator or plugin name from an online example without checking the installed version.
|
|
54
|
+
|
|
55
|
+
Apply these Vapor component fidelity rules whenever the request names Vapor or asks for its component library:
|
|
56
|
+
|
|
57
|
+
- When the user explicitly requests Vapor components, use matching named exports from the installed `@realsee/vapor` package for every applicable DOM control; importing `Vapor` or `vapor.css` alone does not satisfy the request.
|
|
58
|
+
- Do not replace an available Vapor component with raw HTML or a locally styled replica; use raw DOM only for semantics or capabilities absent from the installed Vapor declarations, and record that gap.
|
|
59
|
+
- Before implementing Vapor UI, read `node_modules/@realsee/vapor/AI_CONTEXT.md`, `llms.txt`, `vapor.d.ts`, and the selected component declarations; never invent component names or props.
|
|
60
|
+
- Use the installed `ai_guides` only for component discovery and composition recipes; the target project's root `vapor.d.ts` and selected component declarations are the API contract, and conflicts resolve in favor of installed declarations.
|
|
61
|
+
- Keep the Five canvas in its dedicated sibling host outside `Vapor`; Vapor layout components own DOM chrome only, even when an external recipe nests a placeholder VR component inside a stack.
|
|
62
|
+
|
|
63
|
+
## 3. Classify spatial intent, then apply the preferred capability
|
|
64
|
+
|
|
65
|
+
**VR spatial tag (spatial annotation) is the umbrella concept.** It includes text, images, image-text, video, audio, links, models, virtual/VR content, media/model screens, room or item labels, marketing cards and custom spatial content. PanoTag is not a synonym for every annotation, but `PanoTagPlugin` is the default preset after a request is classified as a tag, hotspot or anchor.
|
|
66
|
+
|
|
67
|
+
**Classify content, renderer, anchor, and lifecycle/data ownership before adapting OpenAPI or SDK data.**
|
|
68
|
+
|
|
69
|
+
1. Content/purpose: text, image, image-text, video, audio, link, model, virtual/VR link, media model, marketing, room/item label or custom content.
|
|
70
|
+
2. Renderer: DOM/popover, CSS3D, Three mesh/texture/video texture, GLTF, dedicated label renderer or pano-video projection.
|
|
71
|
+
3. Anchor: Five/pano state, 2D point, 3D point plus normal, four-point plane, model matrix, room/item identity, 3D box, polygon or mask.
|
|
72
|
+
4. Lifecycle/data ownership: Work/model readiness, visibility/fold state, media autoplay and stop, hooks, cleanup, runtime-only state and the authoritative persistence owner.
|
|
73
|
+
|
|
74
|
+
Use the BFF to fetch OpenAPI data with `resource_code` and server-side authorization, validate the envelope, then adapt it to installed SDK declarations:
|
|
75
|
+
|
|
76
|
+
- Tag/hotspot/anchor data: adapt `/open/v3/hot/list` `data` to the exact PanoTag `Tags` contract, preserving `globalConfig`, `contentTypeConfig` and typed `tagList` entries.
|
|
77
|
+
- Normalize optional OpenAPI configuration fields such as `version`, `globalConfig` and `contentTypeConfig`: treat `null` as absent before validating the installed SDK contract.
|
|
78
|
+
- Load ordinary PanoTag point/plane tags after `five.load` without waiting for `five.model.loaded`; gate only model-dependent tag content or anchors on model readiness.
|
|
79
|
+
- Tour data: convert `/open/v3/observerpicture/search` records into Five `State` snapshots with Work identity; apply them through `five.setState`.
|
|
80
|
+
- Model annotation data: adapt `/open/v3/annotation/search` records to `ModelMakerPlugin` `ServerData` (`box`, `triangles` or `prism`) only after validating `object_data`.
|
|
81
|
+
- Route data: read `/open/v3/route/search` `data.list`, then select point-route or custom-curve semantics before adapting separate GuideLine rendering and playback inputs.
|
|
82
|
+
- Tour adapters read `data.list`, map each validated record to `Partial<State>` with the active `workCode`, and never cast an observer-picture record directly to `State`.
|
|
83
|
+
- Model annotation adapters read `data.list`, validate `object_data` for `box`, `triangles` or `prism`, and pass `{ list }` to ModelMaker only for a model-capable Work.
|
|
84
|
+
- dnalogel 3.81.2 route playback is shape-selected: a validated pano group uses `CruisePlugin` `{ panoIndexList }`, while a validated model-space curve uses `MovePlugin` `{ path }`; `GuideLinePlugin` renders route geometry and is not playback input.
|
|
85
|
+
- Do not invent `RoutePlugin`, `PanoRove`, `stop()`, or a universal route controller; use only the exports and methods declared by the installed package.
|
|
86
|
+
- The complete route playback contract lives in [references/dnalogel-api-capabilities.md](references/dnalogel-api-capabilities.md): the `panoIndexList`/`keyframes` union, raw-record prohibitions, ambiguous `pano_group`+`path` records, per-plugin readiness gates, rejection rules and cleanup order.
|
|
87
|
+
- Feature API, schema, or plugin failures disable only the affected feature; keep the base Viewer usable and never runtime-fallback to raw data or a custom Three implementation.
|
|
88
|
+
- Scope tour, ModelMaker, GuideLine, Cruise and Move work to an active `workCode`/generation token; abort fetches, ignore stale continuations, pause the owned playback controller, remove hooks, clear GuideLine data, wait for pending loads, then let identity-safe unregister dispose each registered controller exactly once before `five.dispose()`.
|
|
89
|
+
|
|
90
|
+
If the developer explicitly opts out of Open Platform data, construct data only in the installed SDK's exact shape. This exception does not authorize generic field guessing, browser credentials, customer Work mutation or invented media URLs.
|
|
91
|
+
|
|
92
|
+
Never infer PanoTag from a generic `tags`, `tagList` or `tag_list` field, Panorama mode, or a screenshot. OpenAPI `/open/v3/hot/list` is an explicit authoritative source only after validation; application input still requires a named typed contract such as `presetData.panoTagList`. PanoTag 3.81.2 canonical content types include `Text`, `Audio`, `ImageText`, `Image`, `Video`, `Panorama`, `Link`, `VRLink`, `Sticker`, `PanoLink`, `Marketing`, `MediaPlane`, `MediaModel`, `Model`, `Custom` and `Unknown`; `model_file` is not canonical.
|
|
93
|
+
|
|
94
|
+
“Virtual screen” is a behavior, not a declared `VirtualScreenPlugin`. Choose by behavior and installed type:
|
|
95
|
+
|
|
96
|
+
- model television/screen video on four-point surfaces: `ModelTVVideoPlugin`;
|
|
97
|
+
- PanoTag-owned image/video plane: PanoTag `MediaPlane`;
|
|
98
|
+
- a model carrying a media plane: PanoTag `MediaModel`;
|
|
99
|
+
- interactive four-point DOM screen: `CSS3DRenderPlugin`;
|
|
100
|
+
- video aligned to pano indexes: `PanoVideoPlugin`;
|
|
101
|
+
- no matching preset or a documented preset gap: a focused application-defined Five/Three plugin.
|
|
102
|
+
|
|
103
|
+
The default Viewer is read-only. Never directly edit `work.json`, downloaded Work, or customer Work. Persistent mutations require an explicit authoritative editor/API/BFF/source contract and user confirmation; otherwise provide a typed patch proposal or implement a runtime-only feature. Media/model URLs must come from the Work, an approved API/CDN, or user-authorized project assets—never invent or import an unrelated third-party URL.
|
|
104
|
+
|
|
105
|
+
For every image consumer, also apply these sibling image-resource rules:
|
|
106
|
+
|
|
107
|
+
- Image resources use approved Realsee CDN domains only; never use `ljcdn.com`, `lianjia.com` or their subdomains.
|
|
108
|
+
- Prefer Five `defaultImageURLTransform` over hand-built 数据万象 query strings when its installed contract satisfies the request.
|
|
109
|
+
- URL transformation does not grant CORS access.
|
|
110
|
+
- Ordinary images use the deployment's approved image-4 host.
|
|
111
|
+
- Feature media from OpenAPI or Work data is displayed through a derived sized variant, never the original: pass ordinary images through the reviewed `defaultImageURLTransform` adapter with a bounded `size`, and do not hand a full-resolution URL to a tag, tour, card or DOM thumbnail.
|
|
112
|
+
|
|
113
|
+
## 4. Preserve spatial runtime invariants
|
|
114
|
+
|
|
115
|
+
1. Keep Three locked at the generated version, since Five targets that release; Five, dnalogel and Vapor may be updated together with browser validation.
|
|
116
|
+
2. Keep one Three instance and use public Five/dnalogel exports rather than copied SDK code.
|
|
117
|
+
3. Construct `Five` directly from `@realsee/five`; never import `@realsee/five/react`, `createFiveProvider`, `FiveCanvas` or its hooks.
|
|
118
|
+
4. Keep the native `Five` instance available through `useSpatialRuntime`; feature adapters must not narrow away SDK capabilities.
|
|
119
|
+
5. Create and append Five only after its host has non-zero dimensions; call `five.refresh` for later positive resizes.
|
|
120
|
+
6. Resolve `/{resourceCode}` in the browser and call only same-origin `/api/work/{resourceCode}`. Parse Work with explicit `workCode` and optional `baseURL`; keep AK/SK, tokens and OpenAPI calls server-only. AK/SK authorize BFF upstream access; internet-facing caller or tenant authorization belongs before the Work route and must never expose AK/SK to the browser.
|
|
121
|
+
7. Keep the generated TypeScript BFF replaceable: `server/types.ts` owns the contracts, the Realsee client owns token exchange/cache and upstream calls, the Work service owns the framework-neutral envelope, and Fastify only adapts HTTP. A Go or other backend must preserve the browser endpoint and response contract.
|
|
122
|
+
8. Treat Work loaded, model refined and feature ready as separate gates.
|
|
123
|
+
9. Use Five `State` as the authoritative spatial snapshot with Work identity.
|
|
124
|
+
10. Pair every plugin registration, event subscription, request, loop, media operation and Three resource with cleanup.
|
|
125
|
+
11. On teardown, dispose dynamic features/plugins before `five.dispose()`, then remove the unmanaged canvas; do not assume `dispose` is idempotent.
|
|
126
|
+
12. Treat dnalogel lifecycles per installed plugin type; there is no universal `load` or `dispose` contract.
|
|
127
|
+
13. Keep Vapor as a sibling DOM overlay above the native Five surface. Transparent roots never intercept the spatial stage.
|
|
128
|
+
|
|
129
|
+
## 5. Extend without narrowing
|
|
130
|
+
|
|
131
|
+
The default Viewer demonstrates Work loading, Panorama/Mapview navigation, an explicitly supplied PanoTag preset and an optional validated ModelFloorplan capability. New capabilities belong in focused `features/` adapters, but may use any supported native Five API, any installed dnalogel preset, or an application-defined Five plugin. Import directly for tree shaking; use `src/vr/five/api.ts` and `src/vr/plugins/dnalogel.ts` as discoverable capability barrels, not mandatory wrappers.
|
|
132
|
+
|
|
133
|
+
`five.load` has no public AbortSignal/cancel contract in 6.8.9. Abort the upstream fetch, ignore stale continuations, and serialize or replace instance ownership when dynamic Work changes require strict ordering. Do not invent `start`, `destroy`, canvas-detach or load-cancel methods.
|
|
134
|
+
|
|
135
|
+
## 6. Validate
|
|
136
|
+
|
|
137
|
+
Run the pinned Node/npm toolchain (`.nvmrc`, `.node-version`, `packageManager`) with the committed lockfile. Both the browser app and the Fastify BFF are TypeScript: `typecheck:web` uses `tsconfig.json`, `typecheck:bff` uses `tsconfig.server.json`, and lint is type-aware with `--max-warnings=0`. The server runs through Node native type stripping, so keep `server/` erasable-only (no `enum`, `namespace`, parameter properties) with explicit `.ts` import extensions:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
npm ci
|
|
141
|
+
npm run check
|
|
142
|
+
npm run build
|
|
143
|
+
node .agents/skills/realsee-vr-app/scripts/verify-project.mjs .
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Then validate in a real browser at `http://127.0.0.1:8087/{resourceCode}` (the template uses local IPv4 loopback and the non-privileged port 8087; do not change it to port 517): native canvas dimensions, Work and model readiness, relevant modes/events/coordinates, spatial-annotation anchor and renderer behavior, plugin cleanup across remounts, DOM/canvas hit targets and the absence of AK/SK, tokens and `REALSEE_GATEWAY_APP_SECRET` from browser requests and built assets.
|
|
147
|
+
|
|
148
|
+
## 7. Keep the capability contract maintainable
|
|
149
|
+
|
|
150
|
+
Treat the capability map, SDK versions, OpenAPI adapters and generated template as one versioned contract. For a changed SDK or OpenAPI field, first add a narrow contract fixture or regression case, then update the adapter and its reference; do not solve the drift only in prompt text. Record the preset capability gap and fallback rationale in the feature's review/decision record. Read [references/continuous-improvement.md](references/continuous-improvement.md) when adding a new feature family, changing SDK baselines, or planning a release.
|
|
151
|
+
|
|
152
|
+
## 8. Model floorplan contract
|
|
153
|
+
|
|
154
|
+
- Floorplans default to ModelFloorplanPlugin with GET /open/v3/floorplan/plugins.
|
|
155
|
+
- `data.format_floorplan_url`, not `format_model_url`, resolves to the preferred `{ version, data: FloorplanServerData }` plugin input.
|
|
156
|
+
- Expose `capabilities.modelFloorplan` only after validating the complete wrapper and nested floorplan shape; missing, empty, malformed or failed floorplan data must leave the base Viewer usable.
|
|
157
|
+
- The complete model floorplan contract lives in [references/dnalogel-api-capabilities.md](references/dnalogel-api-capabilities.md): tab naming, `autoShowEnable`/opacity ownership, `appendTo` mounting, multi-floor authority and cleanup order.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Persistent improvement loop
|
|
2
|
+
|
|
3
|
+
Use this reference for a new feature family, an SDK/OpenAPI upgrade, or a generator release. It prevents the prompt, template and executable checks from drifting apart.
|
|
4
|
+
|
|
5
|
+
## Contract ownership
|
|
6
|
+
|
|
7
|
+
Keep these artifacts aligned and versioned together:
|
|
8
|
+
|
|
9
|
+
- the machine-readable `src/core/spatial-policy.mjs` capability map;
|
|
10
|
+
- `AGENTS.md` and this skill, which express the agent decision rules;
|
|
11
|
+
- BFF adapters and their `unknown`-to-SDK validation boundaries;
|
|
12
|
+
- generated template, verifier/doctor checks and a small fixture for every past regression.
|
|
13
|
+
|
|
14
|
+
The OpenAPI response is not an SDK contract. Retain a sanitized representative fixture per endpoint and validate it before adapting it. Include empty, null optional-field, malformed and stale-work cases. Never store real Work, access tokens, AK/SK or customer media in a fixture.
|
|
15
|
+
|
|
16
|
+
## Change gate
|
|
17
|
+
|
|
18
|
+
For an added or changed capability, capture: requested intent, selected preset, exact installed declaration reviewed, OpenAPI/local-data authority, readiness gate, cleanup owner, fallback reason, and browser acceptance evidence. A Five/Three fallback must state the unavailable dnalogel behavior; it does not become the next feature's default merely because it exists.
|
|
19
|
+
|
|
20
|
+
## Release and learning signals
|
|
21
|
+
|
|
22
|
+
Run `vr-cli policy --json`, `vr-cli doctor`, generated-project checks, typecheck/build and focused browser tests before release. Track only aggregated, non-sensitive signals: adapter validation failures by endpoint/schema version, plugin initialization/cleanup failures, capability fallbacks and browser/runtime compatibility failures. Attach the generator, policy and SDK versions to each signal. Do not collect resource codes, coordinates, customer Work, URLs containing credentials or raw OpenAPI payloads.
|
|
23
|
+
|
|
24
|
+
Turn a confirmed production issue into the smallest durable artifact: a fixture, an adapter test, a doctor rule, or a skill clarification. Review the compatibility matrix on every SDK baseline change and deprecate rules only after generated projects have a documented migration path.
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
# dnalogel 3.81.2 capability map
|
|
2
|
+
|
|
3
|
+
This reference defines generated-project product policy for the reviewed `@realsee/dnalogel` 3.81.2 baseline. The manifest declares `>=3.81.2`, and the initial lockfile resolves 3.81.2; it is not a replacement for the target project's actual installed declarations. This dnalogel source workspace may use a different version, so do not copy its imports or controller methods into a generated project without checking the target installation.
|
|
4
|
+
|
|
5
|
+
The current template deliberately uses version-bound declaration paths such as `@realsee/dnalogel/libs/PanoTagPlugin` and `@realsee/dnalogel/libs/floorplan/ModelFloorplanPlugin`. Keep that approach only while those paths remain declared by the installed 3.81.2 package; an SDK baseline change requires re-validating every import and its lifecycle.
|
|
6
|
+
|
|
7
|
+
`@realsee/dnalogel` is the preferred preset capability layer above Five, not the boundary of everything an application may build. For every spatial, VR or 3D request, inspect the installed catalog and the candidate plugin declarations before writing custom Five/Three code. Do not assume a source-tree root export, online snippet, or another package version exists in this target.
|
|
8
|
+
|
|
9
|
+
## Source-of-truth order
|
|
10
|
+
|
|
11
|
+
1. `node_modules/@realsee/dnalogel/package.json` and `libs/index.d.ts`.
|
|
12
|
+
2. The selected plugin's barrel and controller declarations under `libs/`.
|
|
13
|
+
3. The matching installed docs under `docs/` when needed.
|
|
14
|
+
4. The authoritative Realsee OpenAPI specification for server-side feature data.
|
|
15
|
+
|
|
16
|
+
Do not assume all plugins share one data shape or lifecycle. The root package exports no universal plugin controller interface.
|
|
17
|
+
|
|
18
|
+
## Capability and data-source policy
|
|
19
|
+
|
|
20
|
+
Spatial capability resolution order: installed @realsee/dnalogel preset -> native Five -> Three.js.
|
|
21
|
+
|
|
22
|
+
| Product intent | Preferred implementation | Default authoritative data | Installed SDK boundary |
|
|
23
|
+
| --------------------------------------------------------------- | --------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
|
|
24
|
+
| Text/image/video/audio/model/virtual tags, hotspots and anchors | `PanoTagPlugin` | `GET /open/v3/hot/list` | PanoTag `Tags`, including typed `tagList` and configuration |
|
|
25
|
+
| Tour points | Five `State` snapshots | `GET /open/v3/observerpicture/search` | `five.getCurrentState()` / `five.setState()` with Work identity |
|
|
26
|
+
| Model-space annotations | `ModelMakerPlugin` | `GET /open/v3/annotation/search` | `ServerData` with `box`, `triangles` or `prism` items |
|
|
27
|
+
| Floorplan / house layout | `ModelFloorplanPlugin` | `GET /open/v3/floorplan/plugins` descriptor, then `data.format_floorplan_url` | Fully validated `{ version, data: FloorplanServerData }` |
|
|
28
|
+
| Routes and route playback | `GuideLinePlugin` rendering plus shape-selected `CruisePlugin` or `MovePlugin` playback | `GET /open/v3/route/search` | GuideLine `lines`, Cruise `{ panoIndexList }`/keyframes, or Move `{ path }` after separate validation |
|
|
29
|
+
|
|
30
|
+
Tags, hotspots, and anchors default to PanoTagPlugin with GET /open/v3/hot/list.
|
|
31
|
+
|
|
32
|
+
Tours use Five State snapshots with GET /open/v3/observerpicture/search.
|
|
33
|
+
|
|
34
|
+
Model annotations default to ModelMakerPlugin with GET /open/v3/annotation/search.
|
|
35
|
+
|
|
36
|
+
Routes use GuideLinePlugin for rendering and shape-selected CruisePlugin or MovePlugin playback with GET /open/v3/route/search.
|
|
37
|
+
|
|
38
|
+
SDK-shaped custom data requires an explicit developer opt-out from Open Platform data.
|
|
39
|
+
|
|
40
|
+
The five authenticated OpenAPI GET requests require `resource_code` and server-side `Authorization`. Fetch them through a typed BFF/data port, validate each OpenAPI envelope, then adapt to the exact installed SDK declaration. The floorplan descriptor's external `format_floorplan_url` fetch is a separate redirect-free HTTPS request without gateway authorization and must validate the complete plugin wrapper. Never put access tokens or AK/SK in browser code. The custom-data opt-out permits SDK-shaped application data only; it does not permit guessing generic fields, bypassing validation, modifying customer Work, or inventing external media.
|
|
41
|
+
|
|
42
|
+
A matching preset remains preferred even when an adapter is required. Fall back to native Five and then Three only when no preset matches or a concrete preset capability is insufficient; document that gap in the feature adapter.
|
|
43
|
+
|
|
44
|
+
## VR spatial annotation decision workflow
|
|
45
|
+
|
|
46
|
+
**VR spatial tag (spatial annotation) is the umbrella concept.** PanoTag is not the synonym for every text, image, video, model, room/item label, model annotation or virtual screen placed in a VR space. First classify four independent axes:
|
|
47
|
+
|
|
48
|
+
1. **Content/purpose:** text, image, image-text, audio, video, link, model, virtual/VR link, media model, marketing card, room/item label or custom content.
|
|
49
|
+
2. **Renderer:** DOM/popover, CSS3D, Three mesh/texture/video texture, GLTF, dedicated label renderer or pano-video projection.
|
|
50
|
+
3. **Anchor:** Five/pano state, 2D point, 3D point plus normal, four-point plane, model matrix, item/room identity, 3D box, polygon or mask.
|
|
51
|
+
4. **Lifecycle/data ownership:** Work/model readiness, visible/folded state, autoplay/stop policy, hooks, cleanup, runtime-only state and the authoritative persistence owner.
|
|
52
|
+
|
|
53
|
+
After classification, requests for tags, hotspots or anchors default to `PanoTagPlugin`. Requests for model-space geometric annotations default to `ModelMakerPlugin`. This routing does not authorize a blind conversion: never infer PanoTag from generic `tags`, `tagList` and `tag_list` fields, Panorama mode or a screenshot. Require `/open/v3/hot/list` through a validated BFF adapter or another explicit typed source such as `presetData.panoTagList`.
|
|
54
|
+
|
|
55
|
+
### PanoTag 3.81.2 contract
|
|
56
|
+
|
|
57
|
+
`PanoTagPlugin(five, params?)` returns `PanoTagPluginController`. Its controller declares typed data loading, add/update/remove operations, visibility and enablement state, hooks and disposal.
|
|
58
|
+
|
|
59
|
+
Installed `PanoTagPlugin/typings/tag/TagData.d.ts` declares these canonical content types: `Text`, `Audio`, `ImageText`, `Image`, `Video`, `Panorama`, `Link`, `VRLink`, `Sticker`, `PanoLink`, `Marketing`, `MediaPlane`, `MediaModel`, `Model`, `Custom` and `Unknown`. `model_file` is not canonical and must not be introduced as a default discriminator.
|
|
60
|
+
|
|
61
|
+
Installed `Tag.d.ts` and `Utils.d.ts` declare `2DPoint`, `3DPoint`, `Plane`, `Model`, `3DBox`, `Polygon` and `Mask` stick types. Their required position, normal, matrix, box, polygon and mask data differs; do not flatten every anchor into one point shape. `/open/v3/hot/list` returns `data.globalConfig`, `data.contentTypeConfig` and `data.tagList`; validate and adapt each record before calling `load`.
|
|
62
|
+
|
|
63
|
+
Normalize optional OpenAPI configuration fields such as `version`, `globalConfig` and `contentTypeConfig`: treat `null` as absent before validating the installed SDK contract.
|
|
64
|
+
|
|
65
|
+
Load ordinary PanoTag point/plane tags after `five.load` without waiting for `five.model.loaded`; gate only model-dependent tag content or anchors on model readiness.
|
|
66
|
+
|
|
67
|
+
### Five State tour contract
|
|
68
|
+
|
|
69
|
+
The OpenAPI transport succeeds only when the HTTP response is successful, `code === 0`, and `data.list` is an array. An empty list is a valid ready-empty result, not a schema failure. Each observer-picture item contains display metadata plus a nested `data` pose; keep those layers separate.
|
|
70
|
+
|
|
71
|
+
Tour adapters read `data.list`, map each validated record to `Partial<State>` with the active `workCode`, and never cast an observer-picture record directly to `State`.
|
|
72
|
+
|
|
73
|
+
Use the nested `data.pano_index`, `longitude`, `latitude` and `fov` as the pose source. If top-level `pano_index` is also present, require it to agree. Validate finite values and confirm the pano belongs to the active `five.observers`; a `derived_id` is not a `panoIndex`. Set `mode: 'Panorama'` explicitly instead of forwarding an untrusted OpenAPI mode string. Treat `offset: null` as absent; if an offset is intentionally supported, reconstruct a Three `Vector3` from three finite numbers. `five.setState` returns `void`, so do not `await` it; use `state.synced` or `five.ready()` only when the product needs a completion signal.
|
|
74
|
+
|
|
75
|
+
### ModelMaker 3.81.2 contract
|
|
76
|
+
|
|
77
|
+
The OpenAPI transport succeeds only when the HTTP response is successful, `code === 0`, and `data.list` is an array. Records include identity/labels/space metadata plus `type` and `object_data`; do not pass the HTTP envelope or raw list directly to the plugin.
|
|
78
|
+
|
|
79
|
+
Model annotation adapters read `data.list`, validate `object_data` for `box`, `triangles` or `prism`, and pass `{ list }` to ModelMaker only for a model-capable Work.
|
|
80
|
+
|
|
81
|
+
`ModelMakerPlugin(five, config?)` returns its installed controller and `load` accepts `ServerData = { list: ServerItem[] }`. Validate finite geometry per discriminator: `box` needs start/end points, `triangles` needs point triangles, and `prism` needs points plus finite height. Preserve only reviewed metadata and choose a stable non-zero id. Reject malformed records with indexed diagnostics; distinguish an upstream empty list from a non-empty list with no valid records.
|
|
82
|
+
|
|
83
|
+
The installed controller waits for the active Five model internally. Verify that the Work declares a usable model and guard model readiness with cancellation/stale-generation handling before calling `load`; do not invoke it for a panorama-only Work and wait forever. On cleanup, disable and clear as declared, remove hooks, wait for pending load, then call identity-safe unregister once; unregister performs disposal of the registered controller before Five teardown.
|
|
84
|
+
|
|
85
|
+
### GuideLine, Cruise and Move 3.81.2 contracts
|
|
86
|
+
|
|
87
|
+
The OpenAPI transport succeeds only when the HTTP response is successful, `code === 0`, and `data.list` is an array. An empty upstream list is ready-empty. Route records may expose ids, `pano_group`, `path`, `panorama_style_config`, `model_style_config` and `visible_floor_indexes`; nullable or absent optional fields must be omitted rather than invented. The OpenAPI record, GuideLine line, Cruise action and Move action are four separate types even when they describe one product route.
|
|
88
|
+
|
|
89
|
+
dnalogel 3.81.2 route playback is shape-selected: a validated pano group uses `CruisePlugin` `{ panoIndexList }`, while a validated model-space curve uses `MovePlugin` `{ path }`; `GuideLinePlugin` renders route geometry and is not playback input.
|
|
90
|
+
|
|
91
|
+
`CruisePlugin` accepts exactly one of `panoIndexList` or `keyframes`; its installed union has no type discriminator.
|
|
92
|
+
|
|
93
|
+
OpenAPI route records are never passed raw: rename validated style config only for GuideLine `lines`, and never pass GuideLine `PathItem` arrays or style objects to `CruisePlugin` or `MovePlugin`.
|
|
94
|
+
|
|
95
|
+
If a source record contains both `pano_group` and `path`, the route adapter must choose product semantics explicitly and pass only the selected geometry branch to GuideLine.
|
|
96
|
+
|
|
97
|
+
#### Select and validate one route branch
|
|
98
|
+
|
|
99
|
+
Do not infer a route-kind discriminator that is absent from the installed declarations. The product adapter must select exactly one branch before constructing any plugin data:
|
|
100
|
+
|
|
101
|
+
- **Point route:** require a non-empty ordered `pano_group`; validate each index against the active Work's observers. Preserve route order. Repeated indexes, cross-floor transitions and floor visibility require explicit product policy—never silently deduplicate, sort, flatten floors or substitute a nearby pano. Build a GuideLine line with only the selected `pano_group`, stable `id`/`render_id` and reviewed styles; omit `path`. Build a separate Cruise action exactly as `{ panoIndexList }`.
|
|
102
|
+
- **Custom curve:** first prove that the source coordinates are model-space under the product/OpenAPI contract. Require exactly one supported path segment (`CatmullRomCurve3` in the installed GuideLine declaration) with at least two finite, usable positions. Build a GuideLine line with only `path: PathItem[]`, stable `id`/`render_id` and reviewed styles; omit `pano_group` entirely because even a truthy empty array takes precedence over `path` in the installed renderer. Separately reconstruct a Move-compatible `AnyPosition[]` or reviewed one-curve `THREE.CurvePath<THREE.Vector3>` and call `load({ path })`; never pass the GuideLine `PathItem[]` wrapper.
|
|
103
|
+
- **Cruise keyframes:** these remain a separate Cruise action made only from the installed `Move`/`Rotate` action frames. They are not arbitrary model-space curves and do not turn a custom `path` into Cruise data.
|
|
104
|
+
|
|
105
|
+
Rename `panorama_style_config` to `panorama_style` and `model_style_config` to `model_style` only inside a validated GuideLine line. Omit empty optional styles and `lines`; never forward styling to playback. If coordinate-space provenance, route semantics or a referenced pano cannot be proved, mark that route unavailable instead of guessing.
|
|
106
|
+
|
|
107
|
+
Reject empty routes, unknown pano indexes, unsupported curves, non-finite coordinates, timing or speed, and ambiguous multi-segment Move paths before plugin load.
|
|
108
|
+
|
|
109
|
+
An array passed to Move with fewer than two positions is invalid. The installed Move implementation consumes only `CurvePath.curves[0]`, so a multi-segment path must be rejected, explicitly merged under a reviewed geometric rule, or delegated to a dedicated reviewed playback layer; never claim that every segment will play. Degenerate repeated curve positions must likewise be rejected or normalized by an explicit product rule before plugin load.
|
|
110
|
+
|
|
111
|
+
#### Readiness, visibility, playback and cleanup
|
|
112
|
+
|
|
113
|
+
`GuideLinePlugin.load` waits for model readiness; `CruisePlugin` waits only for Work and observers; `MovePlugin` enters Model and awaits Five readiness when playback starts.
|
|
114
|
+
|
|
115
|
+
GuideLine starts hidden: after a successful model-gated load, call `show()` only when line rendering is requested. Loading or showing GuideLine never starts playback. On a panorama-only Work, skip GuideLine load and expose line rendering as unavailable while retaining independently validated point-route Cruise playback. Move custom-curve playback is model-only. Do not use `GuideLineItem.walk()` as the owned production playback path: it creates temporary Cruise/Move controllers whose completion and disposal ownership are not reliable enough for cancellation.
|
|
116
|
+
|
|
117
|
+
Call only declared playback methods such as `play`, `pause` or `playFromStart`; listen to the concrete controller's hooks for completion/interruption. An empty Cruise keyframe action can remain playing without completion and must be rejected before load.
|
|
118
|
+
|
|
119
|
+
Route cleanup pauses the owned playback controller before hook removal and disposal; `clear` belongs to GuideLine, is not a public Cruise operation, and GuideLine disposal does not own an external or embedded Cruise controller automatically.
|
|
120
|
+
|
|
121
|
+
Do not invent `RoutePlugin`, `PanoRove`, `stop()`, or a universal route controller; use only the exports and methods declared by the installed package.
|
|
122
|
+
|
|
123
|
+
Feature API, schema, or plugin failures disable only the affected feature; keep the base Viewer usable and never runtime-fallback to raw data or a custom Three implementation. Keep rendering and playback state/errors independent so a GuideLine failure cannot destroy valid Cruise playback and a playback failure cannot remove an already rendered line.
|
|
124
|
+
|
|
125
|
+
Scope tour, ModelMaker, GuideLine, Cruise and Move work to an active `workCode`/generation token; abort fetches, ignore stale continuations, pause the owned playback controller, remove hooks, clear GuideLine data, wait for pending loads, then let identity-safe unregister dispose each registered controller exactly once before `five.dispose()`.
|
|
126
|
+
|
|
127
|
+
### Virtual-screen routing
|
|
128
|
+
|
|
129
|
+
“Virtual screen” describes behavior; dnalogel 3.81.2 does not declare a `VirtualScreenPlugin`.
|
|
130
|
+
|
|
131
|
+
| Required behavior | Candidate implementation |
|
|
132
|
+
| ------------------------------------------------------------------- | --------------------------------------------------------- |
|
|
133
|
+
| Video on a model television/screen described by four-point surfaces | `ModelTVVideoPlugin` (`video_src`, poster and point sets) |
|
|
134
|
+
| Image/video plane owned by a PanoTag record | PanoTag `MediaPlane` |
|
|
135
|
+
| Model plus an attached four-point media plane | PanoTag `MediaModel` |
|
|
136
|
+
| Interactive DOM mounted to four spatial points | `CSS3DRenderPlugin.create3DDomContainer` |
|
|
137
|
+
| Video regions aligned to pano indexes | `PanoVideoPlugin` |
|
|
138
|
+
| No preset matches or a declared preset capability is insufficient | Focused application-defined Five/Three plugin |
|
|
139
|
+
|
|
140
|
+
Use only Work-provided, approved API/CDN or user-authorized media/model URLs. The generated Viewer is read-only: never directly edit `work.json`, downloaded Work or customer Work. Persistent changes require an authoritative editor/API/BFF/source contract and user confirmation; otherwise return a typed patch proposal or keep the feature runtime-only.
|
|
141
|
+
|
|
142
|
+
## Capability families — resolve each against installed declarations
|
|
143
|
+
|
|
144
|
+
### View, camera and spatial interaction
|
|
145
|
+
|
|
146
|
+
- `ModelViewPlugin`
|
|
147
|
+
- `CameraMovementPlugin`
|
|
148
|
+
- `PanoCursorRaycasterPlugin`
|
|
149
|
+
- `CSS3DRenderPlugin`
|
|
150
|
+
- `Object3DHelperPlugin`
|
|
151
|
+
- `ModelChassisCompassPlugin`
|
|
152
|
+
- `ModelEntryDoorGuidePlugin`
|
|
153
|
+
|
|
154
|
+
### Tags, labels and annotations
|
|
155
|
+
|
|
156
|
+
- `PanoTagPlugin`
|
|
157
|
+
- `PanoSpatialTagPlugin`
|
|
158
|
+
- `ModelRoomLabelPlugin`
|
|
159
|
+
- `ModelItemLabelPlugin`
|
|
160
|
+
- `ItemLabelPlugin`
|
|
161
|
+
- `PanoDoorLabelPlugin`
|
|
162
|
+
- `ModelMakerPlugin`
|
|
163
|
+
- `AreaMakerPlugin`
|
|
164
|
+
|
|
165
|
+
### Floorplan and spatial structure
|
|
166
|
+
|
|
167
|
+
- `ModelFloorplanPlugin`
|
|
168
|
+
- `MapviewFloorplanPlugin`
|
|
169
|
+
- `TopviewFloorplanPlugin`
|
|
170
|
+
- `PanoFloorplanRadarPlugin`
|
|
171
|
+
- `FloorplanGuidePlugin`
|
|
172
|
+
- floorplan server/data types exported by the `floorplan` barrel
|
|
173
|
+
|
|
174
|
+
### Measurement, drawing and geometry
|
|
175
|
+
|
|
176
|
+
- `PanoRulerPlugin`
|
|
177
|
+
- `PanoRulerProPlugin`
|
|
178
|
+
- `PanoMeasurePlugin`
|
|
179
|
+
- `MeasurePlugin`
|
|
180
|
+
- `SculptPlugin`
|
|
181
|
+
- `SculptPluginForFive`
|
|
182
|
+
- `PaintBrush` component and its state/action types
|
|
183
|
+
|
|
184
|
+
### Route, movement and infrastructure
|
|
185
|
+
|
|
186
|
+
- `GuideLinePlugin`
|
|
187
|
+
- `CruisePlugin`
|
|
188
|
+
- `MovePlugin`
|
|
189
|
+
- `PipelinePlugin`
|
|
190
|
+
|
|
191
|
+
### Media, compass and capture
|
|
192
|
+
|
|
193
|
+
- `PanoCompassPlugin`
|
|
194
|
+
- `ModelTVVideoPlugin`
|
|
195
|
+
- `PanoVideoPlugin`
|
|
196
|
+
- `CurrentPanoImagePlugin`
|
|
197
|
+
|
|
198
|
+
### Version-sensitive capabilities
|
|
199
|
+
|
|
200
|
+
- `DigitalPerformancePlugin` and `DigitalPerformanceV2` are not assumed to be root exports. Resolve their public import path, data input, and lifecycle only from the installed 3.81.2 declarations before proposing their use.
|
|
201
|
+
- Treat every family above as a product-routing candidate, not proof of a stable root import. The selected package declaration remains authoritative.
|
|
202
|
+
|
|
203
|
+
## Lifecycle contract
|
|
204
|
+
|
|
205
|
+
Plugins are factories receiving a `Five` instance and optional parameters. Return values vary:
|
|
206
|
+
|
|
207
|
+
- many modern controllers expose `hooks`, `state`, `enable`, `disable` and `dispose`;
|
|
208
|
+
- data-driven plugins may add `load`;
|
|
209
|
+
- media, route and cruise controllers expose only their concrete declared playback operations;
|
|
210
|
+
- older plugin return objects may not expose `dispose`;
|
|
211
|
+
- some exports are classes or namespaces rather than `FivePlugin<P, R>` values.
|
|
212
|
+
|
|
213
|
+
Each feature adapter must inspect its installed return type and own its exact lifecycle. The shared `SpatialPluginRegistry` rejects names already owned outside the registry, performs identity-safe `five.plugins` registration, and calls `dispose` when present. It does not invent `load`, `disable`, `stop` or media cleanup. Replacement/dispose failures are reported without preventing the remaining registry entries from being drained.
|
|
214
|
+
|
|
215
|
+
## Registration and cleanup
|
|
216
|
+
|
|
217
|
+
For a dynamic feature:
|
|
218
|
+
|
|
219
|
+
1. Create the plugin for the active native Five instance.
|
|
220
|
+
2. Register only when cross-feature lookup is needed, using a stable scoped name. If registration fails, directly dispose the candidate because the registry never owned it.
|
|
221
|
+
3. Load validated, adapted plugin-specific data only after its required Work/model/readiness gate.
|
|
222
|
+
4. Subscribe once and retain every unsubscribe callback.
|
|
223
|
+
5. On cleanup: invalidate and abort, unsubscribe hooks, stop or pause declared media/animation, clear owned data, wait for pending loads, then call identity-safe unregister once. `SpatialPluginRegistry.unregister` disposes the registered instance; do not explicitly dispose it afterward.
|
|
224
|
+
|
|
225
|
+
Constructor plugins configured in `FiveInitArgs.plugins` are owned by Five; do not also register or dispose them through `SpatialPluginRegistry`.
|
|
226
|
+
|
|
227
|
+
## Multi-Work rule
|
|
228
|
+
|
|
229
|
+
A plugin instance belongs to a Five viewport and usually an active Work. Comparison, sandbox and multi-Work features must include viewport/Work identity in their ownership model. Never use an unscoped process-global plugin singleton.
|
|
230
|
+
|
|
231
|
+
## Model floorplan contract
|
|
232
|
+
|
|
233
|
+
- Floorplans default to ModelFloorplanPlugin with GET /open/v3/floorplan/plugins.
|
|
234
|
+
- `data.format_floorplan_url`, not `format_model_url`, resolves to the preferred `{ version, data: FloorplanServerData }` plugin input.
|
|
235
|
+
- Expose `capabilities.modelFloorplan` only after validating the complete wrapper and nested floorplan shape; missing, empty, malformed or failed floorplan data must leave the base Viewer usable.
|
|
236
|
+
- The default tabs are `漫游` for `Panorama` and `三维模型` for `Mapview`; do not expose `Topview` as `地图`.
|
|
237
|
+
- Add the `平面图` tab only after the capability validates and `ModelFloorplanPlugin.load` succeeds.
|
|
238
|
+
- Configure `ModelFloorplanPlugin` with `autoShowEnable: false`; the application tab owns explicit `show()`/`hide()`, uses `modelOpacity: 0` while the floorplan is visible, and restores the Five model surface on hide, failure, and disposal.
|
|
239
|
+
- Resolve the Five canvas parent and call `ModelFloorplanPlugin.appendTo(wrapper)` before `load`; `five.addExtraElement` registers input handling but does not mount the plugin DOM.
|
|
240
|
+
- For multi-floor Work, ModelFloorplanPlugin and Five pano/model floor synchronization are the floor source of truth; do not invent a React-only `floorIndex`.
|
|
241
|
+
- Floorplan show/hide, hooks, pending load and identity-safe disposal must finish before `five.dispose()`.
|