@thatopen/services 0.3.10 → 0.3.12

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.
Files changed (39) hide show
  1. package/dist/cli/commands/revit.d.ts +9 -0
  2. package/dist/cli/lib/revit-addin.d.ts +20 -0
  3. package/dist/cli.js +101 -0
  4. package/dist/cloud/LasToPotree.d.ts +59 -0
  5. package/dist/cloud/SplatToFq.d.ts +38 -0
  6. package/dist/cloud/index.d.ts +2 -0
  7. package/docs/builtin/paths.json +86 -86
  8. package/docs/cloud/GaussianSplatConverter.md +43 -0
  9. package/docs/cloud/PointCloudConverter.md +53 -0
  10. package/docs/revit-collab-quickstart.md +151 -0
  11. package/package.json +95 -95
  12. package/src/built-in/ClashesManager/example.ts +283 -283
  13. package/src/built-in/UIManager/src/clashes-panel/example.ts +160 -160
  14. package/src/built-in/UIManager/src/models-list/example.ts +122 -118
  15. package/src/cli/templates/app/README.md +217 -241
  16. package/src/cli/templates/app/package.json +33 -33
  17. package/src/cli/templates/app/src/setups/camera-tools.ts +0 -63
  18. package/src/cli/templates/app/src/setups/camera-views.ts +0 -201
  19. package/src/cli/templates/app/src/setups/card-header.ts +0 -35
  20. package/src/cli/templates/app/src/setups/clipper-tool.ts +0 -773
  21. package/src/cli/templates/app/src/setups/clipper.ts +0 -75
  22. package/src/cli/templates/app/src/setups/cloud-runner.ts +0 -13
  23. package/src/cli/templates/app/src/setups/exploded-view.ts +0 -246
  24. package/src/cli/templates/app/src/setups/helper-panel.ts +0 -88
  25. package/src/cli/templates/app/src/setups/hider.ts +0 -98
  26. package/src/cli/templates/app/src/setups/index.ts +0 -23
  27. package/src/cli/templates/app/src/setups/inspection.ts +0 -136
  28. package/src/cli/templates/app/src/setups/measurement-panel.ts +0 -188
  29. package/src/cli/templates/app/src/setups/measurement-tool.ts +0 -588
  30. package/src/cli/templates/app/src/setups/measurements.ts +0 -133
  31. package/src/cli/templates/app/src/setups/navigation-gizmo.ts +0 -316
  32. package/src/cli/templates/app/src/setups/plans-panel.ts +0 -619
  33. package/src/cli/templates/app/src/setups/right-sidebar.ts +0 -178
  34. package/src/cli/templates/app/src/setups/styles-panel.ts +0 -110
  35. package/src/cli/templates/app/src/setups/styles.ts +0 -375
  36. package/src/cli/templates/app/src/setups/tool-mode-manager.ts +0 -156
  37. package/src/cli/templates/app/src/setups/tool-mode.ts +0 -23
  38. package/src/cli/templates/app/src/setups/toolbar.ts +0 -229
  39. package/src/cli/templates/app/src/setups/ui-manager.ts +0 -27
@@ -1,241 +1,217 @@
1
- # ThatOpen BIM App
2
-
3
- This is a BIM (Building Information Modeling) app built for the That Open Platform.
4
- It runs in the browser inside the platform's iframe and has access to a 3D viewer,
5
- UI components, and the platform API.
6
-
7
- ## How this app works
8
-
9
- - **Entry point**: `src/main.ts` — runs as an IIFE when the platform loads the app.
10
- - **Build output**: `dist/bundle.js` — a single IIFE file built by Vite.
11
- - **Platform context**: The platform injects `window.__THATOPEN_CONTEXT__` with:
12
- - `appId` — this app's unique ID
13
- - `projectId` — the project this app belongs to
14
- - `accessToken` — Auth0 JWT for API calls
15
- - `apiUrl` — base URL for the That Open API
16
-
17
- ## Commands
18
-
19
- ```bash
20
- npm run dev # Start dev server (esbuild watch + serve on :4000)
21
- npm run build # Build dist/bundle.js (Vite/Rollup production build)
22
- npm run login # Authenticate with the platform (saves token locally)
23
- npm run publish # Publish to the platform
24
- ```
25
-
26
- ### Local development
27
-
28
- Apps run inside the That Open Platform (platform.thatopen.com) within a project —
29
- not as standalone websites. To develop locally:
30
-
31
- 1. Run `npm run dev` — this watches source files with esbuild and serves the bundle on port 4000.
32
- 2. Open your project on the platform and click the debug button.
33
- 3. Live reload is enabled — save a file to rebuild automatically.
34
-
35
- The dev server (`thatopen serve`) uses esbuild for near-instant incremental rebuilds.
36
- **Important**: Do NOT run `vite`, `vite build --watch`, or `npx vite` directly for development.
37
- Always use `npm run dev` which runs `thatopen serve` under the hood.
38
-
39
- ## Key libraries
40
-
41
- | Package | Import | Purpose |
42
- |---------|--------|---------|
43
- | `@thatopen/components` | `OBC` | BIM engine — components, fragments, worlds |
44
- | `@thatopen/components-front` | `OBF` | Front-end BIM components (Highlighter, measurements, etc.) |
45
- | `@thatopen/fragments` | `FRAGS` | Fragment geometry format |
46
- | `@thatopen/ui` | `BUI` | UI web components (`<bim-panel>`, `<bim-grid>`, etc.) |
47
- | `three` | `THREE` | 3D rendering engine |
48
- | `@thatopen/services` | `EngineServicesClient` | Platform API client + built-in components |
49
-
50
- ## Architecture pattern
51
-
52
- ```
53
- 1. Create EngineServicesClient from platform context
54
- 2. Call client.setup(globals, ...builtIns) — creates OBC.Components,
55
- inits BUI, loads built-in components, calls components.init()
56
- 3. Create viewport(s) and UI elements
57
- 4. Configure AppManager with elements + layouts
58
- 5. Call app.init()
59
- ```
60
-
61
- ## Built-in components
62
-
63
- Built-in components are platform-hosted UI modules loaded at runtime via the API client.
64
- They are fetched, evaluated, and registered with the OBC component system.
65
-
66
- | Component | Purpose |
67
- |-----------|---------|
68
- | **AppManager** | App shell — CSS grid layout system with sidebar for switching layouts |
69
- | **ViewportsManager** | Factory for 3D viewports with pre-configured world (scene, camera, renderer) |
70
- | **LoadModelButton** | Button + dropdown for loading IFC and Fragments files |
71
- | **ViewerToolbar** | Toolbar with Show/Hide/Focus/Isolate actions and color palette |
72
- | **ModelsPanel** | Panel listing loaded models with search bar and load button |
73
- | **ModelsDropdown** | Dropdown selector listing loaded models |
74
- | **ClassificationsList** | Hierarchical table of IFC classification data |
75
- | **ClashesList** | Interactive clash detection results with click-to-highlight |
76
- | **ClippingsList** | Panel listing clipping planes with enable/delete controls |
77
- | **LengthMeasuringsList** | Panel listing length measurements with cumulative total |
78
- | **AreaMeasuringsList** | Panel listing area measurements with area/perimeter totals |
79
- | **ColorsPalette** | Color picker grid with custom input and Highlighter styles |
80
- | **HighlightersList** | Panel listing Highlighter styles with manage/apply actions |
81
- | **QtoComparisonList** | Side-by-side quantity comparison for two selected elements |
82
- | **QueriesHierarchy** | Recursive multi-level query browser for IFC data |
83
- | **CustomViewLegend** | Color legend overlay with colored circles and labels |
84
- | **ScreenshotAnnotator** | Modal for annotating screenshots (arrows, text, freehand) via MarkerJS |
85
-
86
- **Full API reference**: Each component has detailed JSDoc with `@example` blocks in the
87
- `@thatopen/services` package source (`src/built-in/index.ts`). Read that file for config
88
- interfaces, method signatures, and code examples.
89
-
90
- ### Loading pattern
91
-
92
- Use `setup` to create the component system and load built-in components in one call:
93
-
94
- ```ts
95
- import { PlatformClient, AppManager, ViewportsManager } from "@thatopen/services";
96
-
97
- const client = PlatformClient.fromPlatformContext();
98
-
99
- // Creates OBC.Components, inits BUI, loads built-ins, calls components.init()
100
- const { components } = await client.setup(
101
- { OBC, OBF, BUI, THREE, FRAGS },
102
- AppManager, ViewportsManager,
103
- );
104
-
105
- const app = components.get(AppManager);
106
- const viewports = components.get(ViewportsManager);
107
- ```
108
-
109
- You can also load components individually if needed:
110
-
111
- ```ts
112
- // Batch load (parallel)
113
- await client.initBuiltInComponents(components, AppManager, ViewportsManager);
114
-
115
- // Or one at a time
116
- await client.initBuiltInComponent(AppManager, components);
117
- ```
118
-
119
- ### Required globals per component
120
-
121
- | Component | Globals to pass | Extra npm packages needed |
122
- |-----------|----------------|--------------------------|
123
- | AppManager | `{ OBC, BUI }` | — |
124
- | ViewportsManager | `{ OBC, BUI, THREE, FRAGS }` | — |
125
- | LoadModelButton | `{ OBC, BUI }` | — |
126
- | ModelsDropdown | `{ OBC, BUI }` | — |
127
- | ViewerToolbar | `{ OBC, OBF, BUI, THREE }` | `@thatopen/components-front` |
128
- | ColorsPalette | `{ OBC, OBF, BUI }` | `@thatopen/components-front` |
129
- | ClashesList | `{ OBC, OBF, BUI, THREE }` | `@thatopen/components-front` |
130
- | ClassificationsList | `{ OBC, OBF, BUI }` | `@thatopen/components-front` |
131
- | ClippingsList | `{ OBC, BUI }` | — |
132
- | HighlightersList | `{ OBC, OBF, BUI }` | `@thatopen/components-front` |
133
- | LengthMeasuringsList | `{ OBC, OBF, BUI, THREE }` | `@thatopen/components-front` |
134
- | AreaMeasuringsList | `{ OBC, OBF, BUI, THREE }` | `@thatopen/components-front` |
135
- | QtoComparisonList | `{ OBC, OBF, BUI }` | `@thatopen/components-front` |
136
- | QueriesHierarchy | `{ OBC, OBF, BUI }` | `@thatopen/components-front` |
137
- | CustomViewLegend | `{ OBC, BUI }` | — |
138
- | ScreenshotAnnotator | `{ OBC, BUI, MARKERJS }` | `@markerjs/markerjs3` |
139
-
140
- ### Global abbreviations
141
-
142
- ```ts
143
- import * as OBC from "@thatopen/components";
144
- import * as OBF from "@thatopen/components-front"; // needed for Toolbar, Highlighters, Clashes, etc.
145
- import * as BUI from "@thatopen/ui";
146
- import * as THREE from "three";
147
- import * as FRAGS from "@thatopen/fragments";
148
- import * as MARKERJS from "@markerjs/markerjs3"; // needed for ScreenshotAnnotator
149
- ```
150
-
151
- ### AppManager — app shell with CSS grid layouts
152
-
153
- Creates a grid-based layout system. Define named element slots and named layouts.
154
- A sidebar for switching layouts appears automatically when multiple layouts exist.
155
-
156
- ```ts
157
- const Layouts = ["Viewer", "Split"];
158
- const Elements = ["viewer", "panel"];
159
-
160
- await app.init({
161
- client,
162
- icons: undefined, // pass Record<K, string> when using typed App interface with icon keys
163
- grid: (grid: BUI.Grid<Layouts, Elements>) => {
164
- grid.elements = {
165
- viewer: viewportElement,
166
- panel: panelFunction, // Can be HTMLElement, () => BUI.TemplateResult, or { template, initialState }
167
- };
168
- grid.layouts = {
169
- Viewer: { template: `"viewer" 1fr / 1fr` },
170
- Split: {
171
- template: `"panel viewer" 1fr / 20rem 1fr`,
172
- icon: "solar:settings-bold",
173
- },
174
- };
175
- },
176
- });
177
- ```
178
-
179
- The `template` string uses CSS `grid-template` shorthand: `"areas" rows / columns`.
180
-
181
- ### ViewportsManager — 3D viewport factory
182
-
183
- Creates viewports with pre-configured world (scene, camera, renderer) and auto-initialized fragments.
184
-
185
- ```ts
186
- const viewports = components.get(ViewportsManager);
187
- const { element, world } = await viewports.create();
188
- // element is an HTMLElement to place in a layout slot
189
- // world has world.scene, world.camera, world.renderer
190
- ```
191
-
192
- ## Loading a BIM model
193
-
194
- ```ts
195
- const fragments = components.get(OBC.FragmentsManager);
196
-
197
- // From URL
198
- const response = await fetch("https://example.com/model.frag");
199
- const buffer = await response.arrayBuffer();
200
- await fragments.core.load(buffer, { modelId: "my-model" });
201
-
202
- // From platform storage
203
- const fileResponse = await client.downloadFile(fileId);
204
- const fileBuffer = await fileResponse.arrayBuffer();
205
- await fragments.core.load(fileBuffer, { modelId: "my-model" });
206
- ```
207
-
208
- ## EngineServicesClient API (commonly used in apps)
209
-
210
- ```ts
211
- // Recommended: auto-reads window.__THATOPEN_CONTEXT__ and sets useBearer: true
212
- const client = PlatformClient.fromPlatformContext();
213
- console.log(client.context.projectId); // access the platform context
214
-
215
- // Files
216
- const files = await client.listFiles();
217
- const file = await client.getFile(fileId);
218
- const response = await client.downloadFile(fileId);
219
- await client.createFile({ file: blob, name: "model.ifc", versionTag: "v1" });
220
-
221
- // Folders
222
- const folders = await client.listFolders();
223
- await client.createFolder("My Folder");
224
-
225
- // Execute cloud components
226
- const { executionId } = await client.executeComponent(componentId, { param: "value" });
227
- client.onExecutionProgress(executionId, (data) => {
228
- // data.progressUpdate — progress percentage
229
- // data.messageUpdate — status messages
230
- });
231
-
232
- // Test against a local cloud component (requires thatopen local-server running in the component project)
233
- client.localServerUrl = "http://localhost:4001";
234
- const local = await client.executeComponent("any-id", { param: "value" });
235
- client.localServerUrl = null; // reset to use the cloud API
236
- ```
237
-
238
- ## Configuration
239
-
240
- - `.thatopen` — local config (gitignored). Created by `npm run login`. Contains `accessToken`, `apiUrl`, and `appId` after first publish.
241
- - `vite.config.js` — builds to IIFE format as `dist/bundle.js`. All dependencies are bundled.
1
+ # ThatOpen BIM App
2
+
3
+ This is a BIM (Building Information Modeling) app built for the That Open Platform.
4
+ It runs in the browser inside the platform's iframe and has access to a 3D viewer,
5
+ UI components, and the platform API.
6
+
7
+ > IMPORTANT for AI assistants: the authoritative, always-current reference for the
8
+ > platform rules, the built-in components, and how to wire each one is shipped
9
+ > inside the installed package. Read these before writing code:
10
+ >
11
+ > - `node_modules/@thatopen/services/resources/AGENTS.md` — platform rules + the
12
+ > full navigation table.
13
+ > - `node_modules/@thatopen/services/docs/builtin/paths.json` — the index of every
14
+ > built-in component, with a one-line description and the path to its example.
15
+ > - `node_modules/@thatopen/services/src/built-in/<Component>/example.ts` — a
16
+ > complete, copy-adaptable integration example per component.
17
+ >
18
+ > This README explains the app's shape and the general pattern. For the exact API
19
+ > of any built-in, trust `paths.json` + the example files over any list here.
20
+
21
+ ## How this app works
22
+
23
+ - **Entry point**: `src/main.ts` — runs as an IIFE when the platform loads the app.
24
+ - **Build output**: `dist/bundle.js` — a single IIFE file.
25
+ - **Platform context**: the platform injects the app's context (project id, access
26
+ token, API url). `PlatformClient.fromPlatformContext()` reads it for you.
27
+
28
+ ## Commands
29
+
30
+ ```bash
31
+ npm run dev # Start the dev server (esbuild watch + serve on :4000)
32
+ npm run build # Build dist/bundle.js
33
+ npm run login # Authenticate with the platform (saves token locally)
34
+ npm run publish # Publish to the platform
35
+ ```
36
+
37
+ ### Local development
38
+
39
+ Apps run inside the That Open Platform within a project, not as standalone websites.
40
+ To develop locally:
41
+
42
+ 1. Run `npm run dev` — watches source with esbuild and serves the bundle on port 4000.
43
+ 2. Open your project on the platform and click the debug button.
44
+ 3. Live reload is enabled — save a file to rebuild automatically.
45
+
46
+ **Important**: use `npm run dev` (it runs `thatopen serve` under the hood). Do NOT run
47
+ `vite` / `vite build --watch` directly for development — `thatopen serve` applies the
48
+ correct build settings (including the beta engine-library aliases for beta projects).
49
+
50
+ ## Key libraries
51
+
52
+ | Package | Import as | Purpose |
53
+ |---------|-----------|---------|
54
+ | `@thatopen/components` | `OBC` | BIM engine — components, fragments, worlds |
55
+ | `@thatopen/components-front` | `OBF` | Front-end BIM components (Highlighter, measurements, …) |
56
+ | `@thatopen/fragments` | `FRAGS` | Fragment geometry format |
57
+ | `@thatopen/ui` | `BUI` | UI web components (`<bim-panel>`, `<bim-grid>`, …) |
58
+ | `three` | `THREE` | 3D rendering engine |
59
+ | `@markerjs/markerjs3` | `MARKERJS` | Screenshot annotation |
60
+ | `@thatopen/services` | (named exports) | Platform API client (`PlatformClient`) + built-in components |
61
+
62
+ ```ts
63
+ import * as OBC from "@thatopen/components";
64
+ import * as OBF from "@thatopen/components-front";
65
+ import * as FRAGS from "@thatopen/fragments";
66
+ import * as BUI from "@thatopen/ui";
67
+ import * as THREE from "three";
68
+ import * as MARKERJS from "@markerjs/markerjs3";
69
+ import { PlatformClient, UIManager } from "@thatopen/services";
70
+ ```
71
+
72
+ ## Architecture
73
+
74
+ The app boots on the **`UIManager`** built-in. `UIManager` registers the platform's
75
+ web components — the app shell and viewport plus every panel — as custom elements you
76
+ place with plain HTML/`BUI.html`:
77
+
78
+ - `<top-app>` — the app shell: a CSS-grid layout system with a sidebar (activity bar)
79
+ for switching named layouts.
80
+ - `<top-viewer>` — the 3D viewport (pre-configured world: scene, camera, renderer,
81
+ fragments), with its own tools baked in.
82
+ - `<top-viewer-toolbar>` — the bottom viewer toolbar (visibility/inspect, clip, measure).
83
+ - Side panels — `<top-model-tree>`, `<top-properties-panel>`, `<top-models-list>`,
84
+ `<top-data-table-panel>`, `<top-objects-panel>`, `<top-settings-panel>`, … — each
85
+ self-wires from the contexts `<top-app>` provides (no `components` plumbing needed).
86
+
87
+ The scaffolded `src/main.ts` already sets this up. The shape is:
88
+
89
+ ```ts
90
+ const client = PlatformClient.fromPlatformContext();
91
+
92
+ // 1. Register the platform web components. UIManager MUST be in setup — it
93
+ // defines <top-app>, <top-viewer>, the panels, etc. before the DOM renders.
94
+ const { components } = await client.setup<OBC.Components>(
95
+ { OBC, OBF, BUI, THREE, FRAGS, MARKERJS },
96
+ { uuid: UIManager.uuid },
97
+ );
98
+ components.get(UIManager).init();
99
+
100
+ // 2. Build the shell: <top-app> with named element slots + named layouts.
101
+ const app = document.createElement("top-app") as any;
102
+ app.elements = {
103
+ viewer: () => BUI.html`<top-viewer></top-viewer>`,
104
+ tree: () => BUI.html`<top-model-tree></top-model-tree>`,
105
+ // …more panels…
106
+ };
107
+ app.layouts = {
108
+ Explorer: { icon: "mdi:file-tree", template: `"tree viewer" 1fr / 22rem 1fr` },
109
+ // …more layouts…
110
+ };
111
+ app.layout = "Explorer";
112
+ app.sidebar = true;
113
+ document.getElementById("that-open-app")?.appendChild(app);
114
+ ```
115
+
116
+ A layout `template` is CSS `grid-template` shorthand: `"areas" rows / columns`, where
117
+ each area name maps to a key in `app.elements`. Each layout with an `icon` becomes a
118
+ sidebar (activity-bar) button.
119
+
120
+ Built-ins are loaded from the platform at runtime **by uuid** through the `setup`
121
+ call. You import each one as a named export from `@thatopen/services` (a ready
122
+ `{ uuid }` stub with types), never by a deep/internal path.
123
+
124
+ ## Built-in components
125
+
126
+ The current, authoritative list lives in
127
+ `node_modules/@thatopen/services/docs/builtin/paths.json` (index) with a full example
128
+ per component under `node_modules/@thatopen/services/src/built-in/`. At a high level:
129
+
130
+ - **`UIManager`** — the shell + viewport + all `top-*` panels above (already wired by
131
+ the scaffold).
132
+ - **`CDEManager`** — the platform CDE: files, folders, versions, metadata.
133
+ - **`ClashesManager`** + `<top-clashes-panel>` — clash detection and the ready-made
134
+ clash review UI (detection matrix, run controls, status filters, markers, highlights).
135
+ - **`FileList`** — a simple file list.
136
+
137
+ Read the matching `example.ts` for each before using it — the examples are the
138
+ source of truth for imports, ordering constraints, and wiring.
139
+
140
+ ### Adding a built-in feature (the general pattern)
141
+
142
+ Every manager-style built-in follows the same three steps. Example — adding clash
143
+ detection (see `ClashesManager/example.ts` and `UIManager/src/clashes-panel/example.ts`):
144
+
145
+ ```ts
146
+ // 1. Import the built-in as a named export from @thatopen/services.
147
+ import { PlatformClient, UIManager, ClashesManager } from "@thatopen/services";
148
+
149
+ // 2. Register it by uuid in the SAME setup call as UIManager.
150
+ const { components } = await client.setup<OBC.Components>(
151
+ { OBC, OBF, BUI, THREE, FRAGS, MARKERJS },
152
+ { uuid: UIManager.uuid },
153
+ { uuid: ClashesManager.uuid },
154
+ );
155
+
156
+ // 3a. Init the manager. Do this BEFORE its panel mounts — the panel reads its
157
+ // initial data in connectedCallback and only subscribes to changes afterward.
158
+ await components.get(ClashesManager).init(client);
159
+
160
+ // 3b. Mount the panel web component in a layout slot (UIManager registered it).
161
+ app.elements = {
162
+ // …existing elements…
163
+ clashes: () => BUI.html`<top-clashes-panel></top-clashes-panel>`,
164
+ };
165
+ app.layouts = {
166
+ // …existing layouts…
167
+ Clashes: { icon: "mdi:vector-intersection", template: `"clashes viewer" 1fr / 22rem 1fr` },
168
+ };
169
+ ```
170
+
171
+ The panel self-wires to its manager — you do not pass props or wire events by hand.
172
+
173
+ ## Loading a BIM model
174
+
175
+ ```ts
176
+ const fragments = components.get(OBC.FragmentsManager);
177
+
178
+ // From URL
179
+ const buffer = await (await fetch("https://example.com/model.frag")).arrayBuffer();
180
+ await fragments.core.load(buffer, { modelId: "my-model" });
181
+
182
+ // From platform storage
183
+ const fileBuffer = await (await client.downloadFile(fileId)).arrayBuffer();
184
+ await fragments.core.load(fileBuffer, { modelId: "my-model" });
185
+ ```
186
+
187
+ (The scaffold's `<top-models-list>` panel already loads models the user picks, so you
188
+ usually don't need to do this by hand.)
189
+
190
+ ## PlatformClient API (commonly used in apps)
191
+
192
+ ```ts
193
+ const client = PlatformClient.fromPlatformContext();
194
+ console.log(client.context.projectId);
195
+
196
+ // Files / folders
197
+ const files = await client.listFiles();
198
+ const response = await client.downloadFile(fileId);
199
+ await client.createFile({ file: blob, name: "model.ifc", versionTag: "v1" });
200
+ await client.createFolder("My Folder");
201
+
202
+ // Execute cloud components
203
+ const { executionId } = await client.executeComponent(componentId, { param: "value" });
204
+ client.onExecutionProgress(executionId, (data) => {
205
+ // data.progressUpdate — progress %, data.messageUpdate — status
206
+ });
207
+
208
+ // Test against a local cloud component (thatopen local-server running in that project)
209
+ client.localServerUrl = "http://localhost:4001";
210
+ ```
211
+
212
+ ## Configuration
213
+
214
+ - `.thatopen` — local config (gitignored). Created by `npm run login`; also holds
215
+ `beta: true` for beta projects and the `appId` after the first publish.
216
+ - `vite.config.js` — builds the IIFE `dist/bundle.js`; for beta projects it aliases
217
+ the `@thatopen/*` engine imports to their `@thatopen-platform/*-beta` packages.
@@ -1,33 +1,33 @@
1
- {
2
- "name": "{{PROJECT_NAME}}",
3
- "version": "1.0.0",
4
- "private": true,
5
- "scripts": {
6
- "dev": "thatopen serve",
7
- "build": "vite build",
8
- "login": "thatopen login --local",
9
- "publish": "thatopen publish"
10
- },
11
- "dependencies": {
12
- "@lit/context": "^1.1.6",
13
- "lit": "^3.0.0",
14
- "@markerjs/markerjs3": "^3.9.0",
15
- "@thatopen/components": "~3.4.0",
16
- "@thatopen/components-front": "~3.4.0",
17
- "@thatopen/fragments": "~3.4.0",
18
- "@thatopen/services": "file:../../../..",
19
- "@thatopen/ui": "~3.4.4",
20
- "three": "0.185.0",
21
- "@sparkjsdev/spark": "^0.1.10",
22
- "3d-tiles-renderer": "^0.4.28",
23
- "camera-controls": "^3.1.2",
24
- "opentype.js": "1.3.4",
25
- "potree-core": "^2.0.15",
26
- "web-ifc": "^0.0.77"
27
- },
28
- "devDependencies": {
29
- "@types/three": "^0.182.0",
30
- "typescript": "^5.2.0",
31
- "vite": "^5.2.0"
32
- }
33
- }
1
+ {
2
+ "name": "{{PROJECT_NAME}}",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "dev": "thatopen serve",
7
+ "build": "vite build",
8
+ "login": "thatopen login --local",
9
+ "publish": "thatopen publish"
10
+ },
11
+ "dependencies": {
12
+ "@lit/context": "^1.1.6",
13
+ "lit": "^3.0.0",
14
+ "@markerjs/markerjs3": "^3.9.0",
15
+ "@thatopen/components": "~3.4.0",
16
+ "@thatopen/components-front": "~3.4.0",
17
+ "@thatopen/fragments": "~3.4.0",
18
+ "@thatopen/services": "file:../../../..",
19
+ "@thatopen/ui": "~3.4.0",
20
+ "three": "0.185.0",
21
+ "@sparkjsdev/spark": "^0.1.10",
22
+ "3d-tiles-renderer": "^0.4.28",
23
+ "camera-controls": "^3.1.2",
24
+ "opentype.js": "1.3.4",
25
+ "potree-core": "^2.0.15",
26
+ "web-ifc": "^0.0.77"
27
+ },
28
+ "devDependencies": {
29
+ "@types/three": "^0.182.0",
30
+ "typescript": "^5.2.0",
31
+ "vite": "^5.2.0"
32
+ }
33
+ }
@@ -1,63 +0,0 @@
1
- import * as THREE from "three";
2
- import * as OBC from "@thatopen/components";
3
-
4
- /**
5
- * Camera tools for the viewer toolbar. Returns controllers matching the
6
- * toolbar's integration contract:
7
- * - `fitAll` — ACTION: fit the camera to the whole loaded model.
8
- * - `orthoToggle` — TOGGLE: switch the projection Perspective ⇄ Orthographic.
9
- */
10
-
11
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
- const firstWorld = (components: OBC.Components): any =>
13
- [...components.get(OBC.Worlds).list.values()][0];
14
-
15
- export interface CameraTools {
16
- fitAll: { label: string; icon: string; run(): Promise<void> };
17
- orthoToggle: {
18
- label: string;
19
- icon: string;
20
- active(): boolean;
21
- activate(): Promise<void>;
22
- deactivate(): Promise<void>;
23
- };
24
- }
25
-
26
- export const cameraTools = (components: OBC.Components): CameraTools => {
27
- const fragments = components.get(OBC.FragmentsManager);
28
-
29
- return {
30
- fitAll: {
31
- label: "Zoom to fit",
32
- icon: "mdi:fit-to-page-outline",
33
- async run() {
34
- const controls = firstWorld(components)?.camera?.controls;
35
- if (!controls) return;
36
- // Union every loaded model's bounding box, then frame its sphere —
37
- // fitToSphere preserves the current view direction (no rotation snap).
38
- const box = new THREE.Box3();
39
- for (const model of fragments.list.values()) {
40
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
41
- const b = (model as any).box as THREE.Box3 | undefined;
42
- if (b && !b.isEmpty()) box.union(b);
43
- }
44
- if (box.isEmpty()) return;
45
- const sphere = box.getBoundingSphere(new THREE.Sphere());
46
- await controls.fitToSphere(sphere, true);
47
- },
48
- },
49
- orthoToggle: {
50
- label: "Orthographic",
51
- icon: "mdi:angle-right",
52
- active() {
53
- return firstWorld(components)?.camera?.projection?.current === "Orthographic";
54
- },
55
- async activate() {
56
- await firstWorld(components)?.camera?.projection?.set?.("Orthographic");
57
- },
58
- async deactivate() {
59
- await firstWorld(components)?.camera?.projection?.set?.("Perspective");
60
- },
61
- },
62
- };
63
- };