@inweb/viewer-three 26.10.6 → 26.11.1
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/dist/plugins/components/AxesHelperComponent.js +23 -1
- package/dist/plugins/components/AxesHelperComponent.js.map +1 -1
- package/dist/plugins/components/AxesHelperComponent.min.js +1 -1
- package/dist/plugins/components/AxesHelperComponent.module.js +24 -2
- package/dist/plugins/components/AxesHelperComponent.module.js.map +1 -1
- package/dist/plugins/components/ExtentsHelperComponent.js +18 -0
- package/dist/plugins/components/ExtentsHelperComponent.js.map +1 -1
- package/dist/plugins/components/ExtentsHelperComponent.min.js +1 -1
- package/dist/plugins/components/ExtentsHelperComponent.module.js +19 -1
- package/dist/plugins/components/ExtentsHelperComponent.module.js.map +1 -1
- package/dist/plugins/loaders/GLTFCloudLoader.js +2 -3
- package/dist/plugins/loaders/GLTFCloudLoader.js.map +1 -1
- package/dist/plugins/loaders/GLTFCloudLoader.min.js +1 -1
- package/dist/plugins/loaders/GLTFCloudLoader.module.js +2 -3
- package/dist/plugins/loaders/GLTFCloudLoader.module.js.map +1 -1
- package/dist/plugins/loaders/GLTFFileLoader.js +2499 -0
- package/dist/plugins/loaders/GLTFFileLoader.js.map +1 -0
- package/dist/plugins/loaders/GLTFFileLoader.min.js +24 -0
- package/dist/plugins/loaders/GLTFFileLoader.module.js +74 -0
- package/dist/plugins/loaders/GLTFFileLoader.module.js.map +1 -0
- package/dist/plugins/loaders/IFCXLoader.js +5 -7
- package/dist/plugins/loaders/IFCXLoader.js.map +1 -1
- package/dist/plugins/loaders/IFCXLoader.min.js +1 -1
- package/dist/plugins/loaders/IFCXLoader.module.js +5 -7
- package/dist/plugins/loaders/IFCXLoader.module.js.map +1 -1
- package/dist/plugins/loaders/PotreeLoader.js +1 -2
- package/dist/plugins/loaders/PotreeLoader.js.map +1 -1
- package/dist/plugins/loaders/PotreeLoader.min.js +1 -1
- package/dist/plugins/loaders/PotreeLoader.module.js +1 -2
- package/dist/plugins/loaders/PotreeLoader.module.js.map +1 -1
- package/dist/viewer-three.js +770 -2777
- package/dist/viewer-three.js.map +1 -1
- package/dist/viewer-three.min.js +3 -3
- package/dist/viewer-three.module.js +609 -206
- package/dist/viewer-three.module.js.map +1 -1
- package/lib/Viewer/Viewer.d.ts +27 -20
- package/lib/Viewer/commands/GetSelected2.d.ts +2 -0
- package/lib/Viewer/commands/SelectModel.d.ts +1 -1
- package/lib/Viewer/commands/SetSelected2.d.ts +2 -0
- package/lib/Viewer/components/index.d.ts +6 -6
- package/lib/Viewer/loaders/DynamicGltfLoader/DynamicModelImpl.d.ts +0 -1
- package/lib/Viewer/loaders/GLTFBinaryExtension.d.ts +5 -0
- package/lib/Viewer/loaders/GLTFCloudDynamicLoader.d.ts +2 -2
- package/lib/Viewer/loaders/{GLTFFileLoader.d.ts → GLTFFileDynamicLoader.d.ts} +7 -1
- package/lib/Viewer/loaders/GLTFLoadingManager.d.ts +4 -3
- package/lib/Viewer/loaders/RangesLoader.d.ts +15 -0
- package/lib/Viewer/loaders/index.d.ts +22 -14
- package/lib/Viewer/models/IModelImpl.d.ts +6 -8
- package/lib/Viewer/models/ModelImpl.d.ts +3 -5
- package/package.json +5 -5
- package/plugins/components/AxesHelperComponent.ts +31 -2
- package/plugins/components/ExtentsHelperComponent.ts +25 -0
- package/plugins/loaders/GLTFCloudLoader.ts +2 -3
- package/{src/Viewer → plugins}/loaders/GLTFFileLoader.ts +21 -12
- package/plugins/loaders/IFCX/IFCXCloudLoader.ts +5 -5
- package/plugins/loaders/IFCX/IFCXFileLoader.ts +3 -4
- package/plugins/loaders/Potree/PotreeFileLoader.ts +3 -4
- package/src/Viewer/Viewer.ts +120 -88
- package/src/Viewer/commands/ClearSelected.ts +3 -1
- package/src/Viewer/commands/GetModels.ts +1 -1
- package/src/Viewer/commands/GetSelected.ts +2 -2
- package/src/Viewer/commands/GetSelected2.ts +34 -0
- package/src/Viewer/commands/HideSelected.ts +3 -1
- package/src/Viewer/commands/SelectModel.ts +5 -5
- package/src/Viewer/commands/SetSelected.ts +9 -10
- package/src/Viewer/commands/SetSelected2.ts +42 -0
- package/src/Viewer/commands/ZoomToObjects.ts +5 -6
- package/src/Viewer/commands/ZoomToSelected.ts +3 -1
- package/src/Viewer/commands/index.ts +4 -0
- package/src/Viewer/components/CameraComponent.ts +6 -1
- package/src/Viewer/components/ExtentsComponent.ts +4 -1
- package/src/Viewer/components/SelectionComponent.ts +2 -0
- package/src/Viewer/components/index.ts +6 -6
- package/src/Viewer/loaders/DynamicGltfLoader/DynamicGltfLoader.js +253 -22
- package/src/Viewer/loaders/DynamicGltfLoader/DynamicModelImpl.ts +20 -10
- package/src/Viewer/loaders/DynamicGltfLoader/GltfStructure.js +3 -1
- package/src/Viewer/loaders/GLTFBinaryExtension.ts +91 -0
- package/src/Viewer/loaders/GLTFCloudDynamicLoader.ts +13 -19
- package/src/Viewer/loaders/GLTFFileDynamicLoader.ts +145 -0
- package/src/Viewer/loaders/GLTFLoadingManager.ts +5 -4
- package/src/Viewer/loaders/RangesLoader.ts +95 -0
- package/src/Viewer/loaders/index.ts +24 -16
- package/src/Viewer/models/IModelImpl.ts +8 -9
- package/src/Viewer/models/ModelImpl.ts +30 -17
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
// acknowledge and accept the above terms.
|
|
22
22
|
///////////////////////////////////////////////////////////////////////////////
|
|
23
23
|
|
|
24
|
+
import { Scene } from "three";
|
|
24
25
|
import { Loader, ModelImpl, Viewer } from "@inweb/viewer-three";
|
|
25
26
|
import { parse, clear } from "./render.js";
|
|
26
27
|
|
|
@@ -52,18 +53,17 @@ export class IFCXCloudLoader extends Loader {
|
|
|
52
53
|
const textDecoder = new TextDecoder();
|
|
53
54
|
const json = JSON.parse(textDecoder.decode(arrayBuffer));
|
|
54
55
|
|
|
55
|
-
const scene = await parse(json);
|
|
56
|
+
const scene: Scene = await parse(json);
|
|
56
57
|
clear();
|
|
57
58
|
|
|
58
59
|
let handle = 0;
|
|
59
|
-
scene.traverse((object
|
|
60
|
-
object.userData = { handle, ...object.userData };
|
|
60
|
+
scene.traverse((object) => {
|
|
61
|
+
object.userData = { handle: handle + "", ...object.userData };
|
|
61
62
|
handle++;
|
|
62
63
|
});
|
|
63
64
|
|
|
64
65
|
const modelImpl = new ModelImpl(scene);
|
|
65
|
-
modelImpl.
|
|
66
|
-
modelImpl.viewer = this.viewer;
|
|
66
|
+
modelImpl.id = file.id;
|
|
67
67
|
|
|
68
68
|
this.viewer.scene.add(scene);
|
|
69
69
|
this.viewer.models.push(modelImpl);
|
|
@@ -39,7 +39,7 @@ export class IFCXFileLoader extends Loader {
|
|
|
39
39
|
);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
override async load(file: any, format?: string, params
|
|
42
|
+
override async load(file: any, format?: string, params: GLTFLoadParams = {}): Promise<this> {
|
|
43
43
|
const manager = new GLTFLoadingManager(file, params);
|
|
44
44
|
|
|
45
45
|
const loader = new IFCXLoader(manager);
|
|
@@ -58,13 +58,12 @@ export class IFCXFileLoader extends Loader {
|
|
|
58
58
|
|
|
59
59
|
let handle = 0;
|
|
60
60
|
scene.traverse((object) => {
|
|
61
|
-
object.userData = { handle, ...object.userData };
|
|
61
|
+
object.userData = { handle: handle + "", ...object.userData };
|
|
62
62
|
handle++;
|
|
63
63
|
});
|
|
64
64
|
|
|
65
65
|
const modelImpl = new ModelImpl(scene);
|
|
66
|
-
modelImpl.
|
|
67
|
-
modelImpl.viewer = this.viewer;
|
|
66
|
+
modelImpl.id = params.modelId || this.extractFileName(file);
|
|
68
67
|
|
|
69
68
|
this.viewer.scene.add(scene);
|
|
70
69
|
this.viewer.models.push(modelImpl);
|
|
@@ -23,11 +23,11 @@
|
|
|
23
23
|
|
|
24
24
|
import { Euler, Vector3 } from "three";
|
|
25
25
|
import { PointColorType, PointCloudOctree, PointSizeType, PointShape, Potree } from "potree-core";
|
|
26
|
-
import { Loader, Viewer } from "@inweb/viewer-three";
|
|
26
|
+
import { Loader, LoadParams, Viewer } from "@inweb/viewer-three";
|
|
27
27
|
|
|
28
28
|
import { PotreeModelImpl } from "./PotreeModelImpl";
|
|
29
29
|
|
|
30
|
-
export type PotreeLoadParams = {
|
|
30
|
+
export type PotreeLoadParams = LoadParams & {
|
|
31
31
|
path?: string;
|
|
32
32
|
position?: Vector3;
|
|
33
33
|
rotation?: Euler;
|
|
@@ -83,8 +83,7 @@ export class PotreeFileLoader extends Loader {
|
|
|
83
83
|
this.pointClouds.push(pco);
|
|
84
84
|
|
|
85
85
|
const modelImpl = new PotreeModelImpl(pco);
|
|
86
|
-
modelImpl.
|
|
87
|
-
modelImpl.viewer = this.viewer;
|
|
86
|
+
modelImpl.id = params.modelId || this.extractFileName(file);
|
|
88
87
|
modelImpl.pco = pco;
|
|
89
88
|
|
|
90
89
|
this.viewer.scene.add(pco);
|
package/src/Viewer/Viewer.ts
CHANGED
|
@@ -50,8 +50,8 @@ import {
|
|
|
50
50
|
FileSource,
|
|
51
51
|
IClippingPlane,
|
|
52
52
|
IComponent,
|
|
53
|
-
IEntity,
|
|
54
53
|
IDragger,
|
|
54
|
+
IEntity,
|
|
55
55
|
ILoader,
|
|
56
56
|
IOptions,
|
|
57
57
|
IOrthogonalCamera,
|
|
@@ -80,12 +80,13 @@ export class Viewer
|
|
|
80
80
|
implements IViewer, IWorldTransform
|
|
81
81
|
{
|
|
82
82
|
public client: Client | undefined;
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
private canvaseventlistener: (event: any) => void;
|
|
86
|
-
|
|
83
|
+
public options: IOptions;
|
|
87
84
|
public canvas: HTMLCanvasElement | undefined;
|
|
88
85
|
public canvasEvents: string[];
|
|
86
|
+
public loaders: ILoader[];
|
|
87
|
+
public models: IModelImpl[];
|
|
88
|
+
|
|
89
|
+
private canvaseventlistener: (event: any) => void;
|
|
89
90
|
|
|
90
91
|
public scene: Scene | undefined;
|
|
91
92
|
public helpers: Helpers | undefined;
|
|
@@ -98,9 +99,6 @@ export class Viewer
|
|
|
98
99
|
public ssaaRenderPass: SSAARenderPass | undefined;
|
|
99
100
|
public outputPass: OutputPass | undefined;
|
|
100
101
|
public composer: EffectComposer | undefined;
|
|
101
|
-
|
|
102
|
-
public loaders: ILoader[];
|
|
103
|
-
public models: IModelImpl[];
|
|
104
102
|
public selected: Object3D[];
|
|
105
103
|
public extents: Box3;
|
|
106
104
|
public target: Vector3;
|
|
@@ -120,22 +118,22 @@ export class Viewer
|
|
|
120
118
|
*/
|
|
121
119
|
constructor(client?: Client) {
|
|
122
120
|
super();
|
|
123
|
-
this._options = new Options(this);
|
|
124
|
-
|
|
125
121
|
this.client = client;
|
|
122
|
+
this.options = new Options(this);
|
|
123
|
+
this.loaders = [];
|
|
124
|
+
this.models = [];
|
|
126
125
|
|
|
127
|
-
this.canvasEvents = CANVAS_EVENTS;
|
|
126
|
+
this.canvasEvents = CANVAS_EVENTS.slice();
|
|
128
127
|
this.canvaseventlistener = (event: Event) => this.emit(event);
|
|
129
128
|
|
|
130
|
-
this.loaders = [];
|
|
131
|
-
this.models = [];
|
|
132
129
|
this.selected = [];
|
|
133
130
|
this.extents = new Box3();
|
|
134
|
-
this.target = new Vector3();
|
|
131
|
+
this.target = new Vector3(0, 0, 0);
|
|
135
132
|
|
|
136
133
|
this._activeDragger = null;
|
|
137
134
|
this._components = [];
|
|
138
135
|
|
|
136
|
+
this._renderNeeded = false;
|
|
139
137
|
this._renderTime = 0;
|
|
140
138
|
|
|
141
139
|
this.render = this.render.bind(this);
|
|
@@ -144,10 +142,17 @@ export class Viewer
|
|
|
144
142
|
this._markup = new Markup();
|
|
145
143
|
}
|
|
146
144
|
|
|
147
|
-
|
|
148
|
-
|
|
145
|
+
/**
|
|
146
|
+
* 2D markup core instance used to create markups.
|
|
147
|
+
*
|
|
148
|
+
* @readonly
|
|
149
|
+
*/
|
|
150
|
+
get markup(): IMarkup {
|
|
151
|
+
return this._markup;
|
|
149
152
|
}
|
|
150
153
|
|
|
154
|
+
// IViewer
|
|
155
|
+
|
|
151
156
|
get draggers(): string[] {
|
|
152
157
|
return [...draggers.getDraggers().keys()];
|
|
153
158
|
}
|
|
@@ -156,21 +161,11 @@ export class Viewer
|
|
|
156
161
|
return [...components.getComponents().keys()];
|
|
157
162
|
}
|
|
158
163
|
|
|
159
|
-
/**
|
|
160
|
-
* 2D markup core instance used to create markups.
|
|
161
|
-
*
|
|
162
|
-
* @readonly
|
|
163
|
-
*/
|
|
164
|
-
get markup(): IMarkup {
|
|
165
|
-
return this._markup;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
164
|
initialize(canvas: HTMLCanvasElement, onProgress?: (event: ProgressEvent<EventTarget>) => void): Promise<this> {
|
|
169
165
|
this.addEventListener("optionschange", (event) => this.syncOptions(event.data));
|
|
170
166
|
|
|
171
167
|
this.scene = new Scene();
|
|
172
168
|
this.helpers = new Helpers();
|
|
173
|
-
this.target = new Vector3(0, 0, 0);
|
|
174
169
|
|
|
175
170
|
const pixelRatio = window.devicePixelRatio;
|
|
176
171
|
const rect = canvas.parentElement.getBoundingClientRect();
|
|
@@ -319,6 +314,8 @@ export class Viewer
|
|
|
319
314
|
this.emitEvent({ type: "update", data: force });
|
|
320
315
|
}
|
|
321
316
|
|
|
317
|
+
// Internal render routines
|
|
318
|
+
|
|
322
319
|
render(time?: DOMHighResTimeStamp, force = false): void {
|
|
323
320
|
if (!this.renderer) return;
|
|
324
321
|
if (!this._renderNeeded && !force) return;
|
|
@@ -341,6 +338,8 @@ export class Viewer
|
|
|
341
338
|
this.emitEvent({ type: "render", time, deltaTime });
|
|
342
339
|
}
|
|
343
340
|
|
|
341
|
+
// Internal loading routines
|
|
342
|
+
|
|
344
343
|
loadReferences(model: Model | File | Assembly): Promise<this> {
|
|
345
344
|
// todo: load reference as text fonts
|
|
346
345
|
return Promise.resolve(this);
|
|
@@ -357,18 +356,20 @@ export class Viewer
|
|
|
357
356
|
* exception will be thrown.
|
|
358
357
|
*
|
|
359
358
|
* For files from Open Cloud Server, the default model will be loaded. If there is no default model,
|
|
360
|
-
* first
|
|
359
|
+
* the first available model will be loaded. If no models are found in the file, an exception will be
|
|
361
360
|
* thrown.
|
|
362
361
|
*
|
|
363
362
|
* For URLs, the file extension is used to determine the file format. For a `ArrayBuffer` and `Data
|
|
364
|
-
* URL`, a file format must be specified using `params.format` parameter
|
|
365
|
-
*
|
|
363
|
+
* URL`, a file format must be specified using `params.format` parameter. If no appropriate loader is
|
|
364
|
+
* found for the specified format, an exception will be thrown.
|
|
366
365
|
*
|
|
367
366
|
* If there was an active dragger before opening the file, it will be deactivated. After opening the
|
|
368
367
|
* file, you must manually activate the required dragger.
|
|
369
368
|
*
|
|
370
369
|
* Fires:
|
|
371
370
|
*
|
|
371
|
+
* - {@link CancelEvent | cancel}
|
|
372
|
+
* - {@link ClearEvent | clear}
|
|
372
373
|
* - {@link OpenEvent | open}
|
|
373
374
|
* - {@link GeometryStartEvent | geometrystart}
|
|
374
375
|
* - {@link GeometryProgressEvent | geometryprogress}
|
|
@@ -377,23 +378,26 @@ export class Viewer
|
|
|
377
378
|
* - {@link GeometryEndEvent | geometryend}
|
|
378
379
|
* - {@link GeometryErrorEvent | geometryerror}
|
|
379
380
|
*
|
|
380
|
-
* @param file - File to load. Can be
|
|
381
|
+
* @param file - File to load. Can be:
|
|
381
382
|
*
|
|
382
383
|
* - `File`, `Assembly` or `Model` instance from the Open Cloud Server
|
|
383
|
-
* -
|
|
384
|
+
* - `URL` string
|
|
384
385
|
* - {@link https://developer.mozilla.org/docs/Web/HTTP/Basics_of_HTTP/Data_URIs | Data URL} string
|
|
385
386
|
* - {@link https://developer.mozilla.org/docs/Web/API/File | Web API File} object
|
|
386
387
|
* - {@link https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer | ArrayBuffer}
|
|
387
388
|
* object
|
|
388
389
|
*
|
|
389
390
|
* @param params - Loading parameters.
|
|
390
|
-
* @param params.format - File format
|
|
391
|
-
* URL`.
|
|
391
|
+
* @param params.format - File format. Can be `gltf`, `glb` or format from a plugin. Required when
|
|
392
|
+
* loading a file as `ArrayBuffer` or `Data URL`.
|
|
392
393
|
* @param params.mode - File opening mode. Can be one of:
|
|
393
394
|
*
|
|
394
|
-
* - `
|
|
395
|
-
* - `
|
|
395
|
+
* - `file` - Single file mode. Unloads an open file and opens a new one. This is default mode.
|
|
396
|
+
* - `assembly` - Assembly mode. Appends a file to an already open file.
|
|
396
397
|
*
|
|
398
|
+
* @param params.modelId - Unique model ID in the assembly (multi-model scene). Used as a model prefix
|
|
399
|
+
* when selecting objects (see {@link getSelected2}). Must not contain the ":" (colon). Required when
|
|
400
|
+
* loading a file as `ArrayBuffer` or `Data URL`.
|
|
397
401
|
* @param params.requestHeader - The
|
|
398
402
|
* {@link https://developer.mozilla.org/docs/Glossary/Request_header | request header} used in HTTP
|
|
399
403
|
* request.
|
|
@@ -415,6 +419,7 @@ export class Viewer
|
|
|
415
419
|
params: {
|
|
416
420
|
format?: string;
|
|
417
421
|
mode?: string;
|
|
422
|
+
modelId?: string;
|
|
418
423
|
requestHeader?: HeadersInit;
|
|
419
424
|
withCredentials?: boolean;
|
|
420
425
|
path?: string;
|
|
@@ -424,22 +429,27 @@ export class Viewer
|
|
|
424
429
|
): Promise<this> {
|
|
425
430
|
if (!this.renderer) return this;
|
|
426
431
|
|
|
427
|
-
|
|
432
|
+
const mode = params.mode || "file";
|
|
433
|
+
|
|
434
|
+
if (mode !== "assembly" && mode !== "a" && mode !== "append") {
|
|
428
435
|
this.cancel();
|
|
429
436
|
this.clear();
|
|
430
437
|
}
|
|
431
438
|
|
|
432
|
-
this.emitEvent({ type: "open", file });
|
|
439
|
+
this.emitEvent({ type: "open", mode, file });
|
|
433
440
|
|
|
434
441
|
let model: any = file;
|
|
435
442
|
if (model && typeof model.getModels === "function") {
|
|
436
443
|
const models = await model.getModels();
|
|
437
444
|
model = models.find((model: Model) => model.default) || models[0] || file;
|
|
438
445
|
}
|
|
446
|
+
if (model && typeof model.database === "string") {
|
|
447
|
+
file = model.file;
|
|
448
|
+
}
|
|
439
449
|
if (!model) throw new Error(`Format not supported`);
|
|
440
450
|
|
|
441
451
|
let format = params.format;
|
|
442
|
-
if (!format && typeof
|
|
452
|
+
if (!format && typeof file["type"] === "string") format = file["type"].split(".").pop();
|
|
443
453
|
if (!format && typeof file === "string") format = file.split(".").pop();
|
|
444
454
|
if (!format && file instanceof globalThis.File) format = file.name.split(".").pop();
|
|
445
455
|
|
|
@@ -483,7 +493,7 @@ export class Viewer
|
|
|
483
493
|
"Viewer.loadGltfFile() has been deprecated since 26.4 and will be removed in a future release, use Viewer.open() instead."
|
|
484
494
|
);
|
|
485
495
|
|
|
486
|
-
return this.open(file, { ...params, format: "gltf", externalFiles, mode: "
|
|
496
|
+
return this.open(file, { ...params, format: "gltf", externalFiles, mode: "assembly" });
|
|
487
497
|
}
|
|
488
498
|
|
|
489
499
|
cancel(): this {
|
|
@@ -510,6 +520,9 @@ export class Viewer
|
|
|
510
520
|
this.scene.clear();
|
|
511
521
|
this.helpers.clear();
|
|
512
522
|
|
|
523
|
+
this.extents.makeEmpty();
|
|
524
|
+
this.target.set(0, 0, 0);
|
|
525
|
+
|
|
513
526
|
this.syncOptions();
|
|
514
527
|
this.syncOverlay();
|
|
515
528
|
this.update(true);
|
|
@@ -519,6 +532,10 @@ export class Viewer
|
|
|
519
532
|
return this;
|
|
520
533
|
}
|
|
521
534
|
|
|
535
|
+
is3D(): boolean {
|
|
536
|
+
return true;
|
|
537
|
+
}
|
|
538
|
+
|
|
522
539
|
syncOptions(options: IOptions = this.options): void {
|
|
523
540
|
if (!this.renderer) return;
|
|
524
541
|
|
|
@@ -557,10 +574,18 @@ export class Viewer
|
|
|
557
574
|
return this.executeCommand("getSelected");
|
|
558
575
|
}
|
|
559
576
|
|
|
577
|
+
getSelected2(): string[] {
|
|
578
|
+
return this.executeCommand("getSelected2");
|
|
579
|
+
}
|
|
580
|
+
|
|
560
581
|
setSelected(handles?: string[]): void {
|
|
561
582
|
this.executeCommand("setSelected", handles);
|
|
562
583
|
}
|
|
563
584
|
|
|
585
|
+
setSelected2(handles?: string[]): void {
|
|
586
|
+
this.executeCommand("setSelected2", handles);
|
|
587
|
+
}
|
|
588
|
+
|
|
564
589
|
clearSelected(): void {
|
|
565
590
|
this.executeCommand("clearSelected");
|
|
566
591
|
}
|
|
@@ -630,44 +655,6 @@ export class Viewer
|
|
|
630
655
|
return this._components.find((component) => component.name === name);
|
|
631
656
|
}
|
|
632
657
|
|
|
633
|
-
is3D(): boolean {
|
|
634
|
-
return true;
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
screenToWorld(position: { x: number; y: number }): { x: number; y: number; z: number } {
|
|
638
|
-
if (!this.renderer) return { x: position.x, y: position.y, z: 0 };
|
|
639
|
-
|
|
640
|
-
const rect = this.canvas.getBoundingClientRect();
|
|
641
|
-
const x = position.x / (rect.width / 2) - 1;
|
|
642
|
-
const y = -position.y / (rect.height / 2) + 1;
|
|
643
|
-
|
|
644
|
-
const point = new Vector3(x, y, -1);
|
|
645
|
-
point.unproject(this.camera);
|
|
646
|
-
|
|
647
|
-
return { x: point.x, y: point.y, z: point.z };
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
worldToScreen(position: { x: number; y: number; z: number }): { x: number; y: number } {
|
|
651
|
-
if (!this.renderer) return { x: position.x, y: position.y };
|
|
652
|
-
|
|
653
|
-
const point = new Vector3(position.x, position.y, position.z);
|
|
654
|
-
point.project(this.camera);
|
|
655
|
-
|
|
656
|
-
const rect = this.canvas.getBoundingClientRect();
|
|
657
|
-
const x = (point.x + 1) * (rect.width / 2);
|
|
658
|
-
const y = (-point.y + 1) * (rect.height / 2);
|
|
659
|
-
|
|
660
|
-
return { x, y };
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
getScale(): { x: number; y: number; z: number } {
|
|
664
|
-
return { x: 1, y: 1, z: 1 };
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
executeCommand(id: string, ...args: any[]): any {
|
|
668
|
-
return commands.executeCommand(id, this, ...args);
|
|
669
|
-
}
|
|
670
|
-
|
|
671
658
|
drawViewpoint(viewpoint: IViewpoint): void {
|
|
672
659
|
if (!this.renderer) return;
|
|
673
660
|
|
|
@@ -731,15 +718,17 @@ export class Viewer
|
|
|
731
718
|
};
|
|
732
719
|
|
|
733
720
|
const setClippingPlanes = (clipping_planes: IClippingPlane[]) => {
|
|
734
|
-
clipping_planes
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
721
|
+
if (clipping_planes) {
|
|
722
|
+
clipping_planes.forEach((clipping_plane) => {
|
|
723
|
+
const plane = new Plane();
|
|
724
|
+
plane.setFromNormalAndCoplanarPoint(
|
|
725
|
+
getVector3FromPoint3d(clipping_plane.direction),
|
|
726
|
+
getVector3FromPoint3d(clipping_plane.location)
|
|
727
|
+
);
|
|
728
|
+
|
|
729
|
+
this.renderer.clippingPlanes.push(plane);
|
|
730
|
+
});
|
|
731
|
+
}
|
|
743
732
|
};
|
|
744
733
|
|
|
745
734
|
const setSelection = (selection: IEntity[]) => {
|
|
@@ -759,10 +748,10 @@ export class Viewer
|
|
|
759
748
|
setOrthogonalCamera(viewpoint.orthogonal_camera);
|
|
760
749
|
setPerspectiveCamera(viewpoint.perspective_camera);
|
|
761
750
|
setClippingPlanes(viewpoint.clipping_planes);
|
|
762
|
-
setSelection(viewpoint.selection);
|
|
751
|
+
setSelection(viewpoint.custom_fields?.selection2 || viewpoint.selection);
|
|
763
752
|
this._markup.setViewpoint(viewpoint);
|
|
764
753
|
|
|
765
|
-
this.target
|
|
754
|
+
this.target.copy(getVector3FromPoint3d(viewpoint.custom_fields?.camera_target ?? this.target));
|
|
766
755
|
|
|
767
756
|
this.setActiveDragger(draggerName);
|
|
768
757
|
this.emitEvent({ type: "drawviewpoint", data: viewpoint });
|
|
@@ -814,6 +803,10 @@ export class Viewer
|
|
|
814
803
|
return this.getSelected().map((handle) => ({ handle }));
|
|
815
804
|
};
|
|
816
805
|
|
|
806
|
+
const getSelection2 = (): IEntity[] => {
|
|
807
|
+
return this.getSelected2().map((handle) => ({ handle }));
|
|
808
|
+
};
|
|
809
|
+
|
|
817
810
|
const viewpoint: IViewpoint = { custom_fields: {} };
|
|
818
811
|
|
|
819
812
|
viewpoint.orthogonal_camera = getOrthogonalCamera();
|
|
@@ -824,9 +817,48 @@ export class Viewer
|
|
|
824
817
|
this._markup.getViewpoint(viewpoint);
|
|
825
818
|
|
|
826
819
|
viewpoint.custom_fields.camera_target = getPoint3dFromVector3(this.target);
|
|
820
|
+
viewpoint.custom_fields.selection2 = getSelection2();
|
|
827
821
|
|
|
828
822
|
this.emitEvent({ type: "createviewpoint", data: viewpoint });
|
|
829
823
|
|
|
830
824
|
return viewpoint;
|
|
831
825
|
}
|
|
826
|
+
|
|
827
|
+
// IWorldTransform
|
|
828
|
+
|
|
829
|
+
screenToWorld(position: { x: number; y: number }): { x: number; y: number; z: number } {
|
|
830
|
+
if (!this.renderer) return { x: position.x, y: position.y, z: 0 };
|
|
831
|
+
|
|
832
|
+
const rect = this.canvas.getBoundingClientRect();
|
|
833
|
+
const x = position.x / (rect.width / 2) - 1;
|
|
834
|
+
const y = -position.y / (rect.height / 2) + 1;
|
|
835
|
+
|
|
836
|
+
const point = new Vector3(x, y, -1);
|
|
837
|
+
point.unproject(this.camera);
|
|
838
|
+
|
|
839
|
+
return { x: point.x, y: point.y, z: point.z };
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
worldToScreen(position: { x: number; y: number; z: number }): { x: number; y: number } {
|
|
843
|
+
if (!this.renderer) return { x: position.x, y: position.y };
|
|
844
|
+
|
|
845
|
+
const point = new Vector3(position.x, position.y, position.z);
|
|
846
|
+
point.project(this.camera);
|
|
847
|
+
|
|
848
|
+
const rect = this.canvas.getBoundingClientRect();
|
|
849
|
+
const x = (point.x + 1) * (rect.width / 2);
|
|
850
|
+
const y = (-point.y + 1) * (rect.height / 2);
|
|
851
|
+
|
|
852
|
+
return { x, y };
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
getScale(): { x: number; y: number; z: number } {
|
|
856
|
+
return { x: 1, y: 1, z: 1 };
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
// ICommandService
|
|
860
|
+
|
|
861
|
+
executeCommand(id: string, ...args: any[]): any {
|
|
862
|
+
return commands.executeCommand(id, this, ...args);
|
|
863
|
+
}
|
|
832
864
|
}
|
|
@@ -29,5 +29,7 @@ export function clearSelected(viewer: Viewer): void {
|
|
|
29
29
|
selection.clearSelection();
|
|
30
30
|
|
|
31
31
|
viewer.update();
|
|
32
|
-
|
|
32
|
+
|
|
33
|
+
viewer.emitEvent({ type: "select", handles: [] });
|
|
34
|
+
viewer.emitEvent({ type: "select2", handles: [] });
|
|
33
35
|
}
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
import type { Viewer } from "../Viewer";
|
|
25
25
|
|
|
26
26
|
export function getSelected(viewer: Viewer): string[] {
|
|
27
|
-
const
|
|
28
|
-
|
|
27
|
+
const handles2 = viewer.executeCommand("getSelected2");
|
|
28
|
+
const handles = handles2.map((handle) => handle.slice(handle.indexOf(":") + 1));
|
|
29
29
|
return handles;
|
|
30
30
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2002-2025, Open Design Alliance (the "Alliance").
|
|
3
|
+
// All rights reserved.
|
|
4
|
+
//
|
|
5
|
+
// This software and its documentation and related materials are owned by
|
|
6
|
+
// the Alliance. The software may only be incorporated into application
|
|
7
|
+
// programs owned by members of the Alliance, subject to a signed
|
|
8
|
+
// Membership Agreement and Supplemental Software License Agreement with the
|
|
9
|
+
// Alliance. The structure and organization of this software are the valuable
|
|
10
|
+
// trade secrets of the Alliance and its suppliers. The software is also
|
|
11
|
+
// protected by copyright law and international treaty provisions. Application
|
|
12
|
+
// programs incorporating this software must include the following statement
|
|
13
|
+
// with their copyright notices:
|
|
14
|
+
//
|
|
15
|
+
// This application incorporates Open Design Alliance software pursuant to a
|
|
16
|
+
// license agreement with Open Design Alliance.
|
|
17
|
+
// Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance.
|
|
18
|
+
// All rights reserved.
|
|
19
|
+
//
|
|
20
|
+
// By use of this software, its documentation or related materials, you
|
|
21
|
+
// acknowledge and accept the above terms.
|
|
22
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
23
|
+
|
|
24
|
+
import type { Viewer } from "../Viewer";
|
|
25
|
+
|
|
26
|
+
export function getSelected2(viewer: Viewer): string[] {
|
|
27
|
+
const handles2 = [];
|
|
28
|
+
|
|
29
|
+
viewer.models.forEach((model) => {
|
|
30
|
+
handles2.push(...model.getHandlesByObjects(viewer.selected));
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return handles2;
|
|
34
|
+
}
|
|
@@ -31,6 +31,8 @@ export function hideSelected(viewer: Viewer): void {
|
|
|
31
31
|
selection.clearSelection();
|
|
32
32
|
|
|
33
33
|
viewer.update();
|
|
34
|
+
|
|
34
35
|
viewer.emitEvent({ type: "hide" });
|
|
35
|
-
viewer.emitEvent({ type: "select",
|
|
36
|
+
viewer.emitEvent({ type: "select", handles: [] });
|
|
37
|
+
viewer.emitEvent({ type: "select2", handles: [] });
|
|
36
38
|
}
|
|
@@ -24,14 +24,14 @@
|
|
|
24
24
|
import type { Viewer } from "../Viewer";
|
|
25
25
|
import type { SelectionComponent } from "../components/SelectionComponent";
|
|
26
26
|
|
|
27
|
-
export function selectModel(viewer: Viewer,
|
|
27
|
+
export function selectModel(viewer: Viewer, id: string): void {
|
|
28
28
|
const selection = viewer.getComponent("SelectionComponent") as SelectionComponent;
|
|
29
29
|
selection.clearSelection();
|
|
30
30
|
|
|
31
|
-
viewer.models
|
|
32
|
-
.filter((model) => model.handle === handle)
|
|
33
|
-
.forEach((model) => selection.select(model.getObjects(), model));
|
|
31
|
+
viewer.models.filter((model) => model.id === id).forEach((model) => selection.select(model.getObjects(), model));
|
|
34
32
|
|
|
35
33
|
viewer.update();
|
|
36
|
-
|
|
34
|
+
|
|
35
|
+
viewer.emitEvent({ type: "select", handles: viewer.getSelected() });
|
|
36
|
+
viewer.emitEvent({ type: "select2", handles: viewer.getSelected2() });
|
|
37
37
|
}
|
|
@@ -22,19 +22,18 @@
|
|
|
22
22
|
///////////////////////////////////////////////////////////////////////////////
|
|
23
23
|
|
|
24
24
|
import type { Viewer } from "../Viewer";
|
|
25
|
-
import type { SelectionComponent } from "../components/SelectionComponent";
|
|
26
25
|
|
|
27
26
|
export function setSelected(viewer: Viewer, handles: string[] = []): void {
|
|
28
|
-
const
|
|
29
|
-
selection.clearSelection();
|
|
27
|
+
const handles2 = [];
|
|
30
28
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
handles.forEach((handle) => {
|
|
30
|
+
if (handle.includes(":")) {
|
|
31
|
+
handles2.push(handle);
|
|
32
|
+
} else
|
|
33
|
+
viewer.models.forEach((model) => {
|
|
34
|
+
handles2.push(`${model.id}:${handle}`);
|
|
35
|
+
});
|
|
35
36
|
});
|
|
36
37
|
|
|
37
|
-
viewer.
|
|
38
|
-
viewer.emitEvent({ type: "show" });
|
|
39
|
-
viewer.emitEvent({ type: "select", data: undefined, handles });
|
|
38
|
+
viewer.executeCommand("setSelected2", handles2);
|
|
40
39
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2002-2025, Open Design Alliance (the "Alliance").
|
|
3
|
+
// All rights reserved.
|
|
4
|
+
//
|
|
5
|
+
// This software and its documentation and related materials are owned by
|
|
6
|
+
// the Alliance. The software may only be incorporated into application
|
|
7
|
+
// programs owned by members of the Alliance, subject to a signed
|
|
8
|
+
// Membership Agreement and Supplemental Software License Agreement with the
|
|
9
|
+
// Alliance. The structure and organization of this software are the valuable
|
|
10
|
+
// trade secrets of the Alliance and its suppliers. The software is also
|
|
11
|
+
// protected by copyright law and international treaty provisions. Application
|
|
12
|
+
// programs incorporating this software must include the following statement
|
|
13
|
+
// with their copyright notices:
|
|
14
|
+
//
|
|
15
|
+
// This application incorporates Open Design Alliance software pursuant to a
|
|
16
|
+
// license agreement with Open Design Alliance.
|
|
17
|
+
// Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance.
|
|
18
|
+
// All rights reserved.
|
|
19
|
+
//
|
|
20
|
+
// By use of this software, its documentation or related materials, you
|
|
21
|
+
// acknowledge and accept the above terms.
|
|
22
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
23
|
+
|
|
24
|
+
import type { Viewer } from "../Viewer";
|
|
25
|
+
import type { SelectionComponent } from "../components/SelectionComponent";
|
|
26
|
+
|
|
27
|
+
export function setSelected2(viewer: Viewer, handles: string[] = []): void {
|
|
28
|
+
const selectionComponent = viewer.getComponent("SelectionComponent") as SelectionComponent;
|
|
29
|
+
selectionComponent.clearSelection();
|
|
30
|
+
|
|
31
|
+
viewer.models.forEach((model) => {
|
|
32
|
+
const objects = model.getObjectsByHandles(handles);
|
|
33
|
+
model.showObjects(objects);
|
|
34
|
+
selectionComponent.select(objects, model);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
viewer.update();
|
|
38
|
+
|
|
39
|
+
viewer.emitEvent({ type: "show" });
|
|
40
|
+
viewer.emitEvent({ type: "select", data: undefined, handles: viewer.getSelected() });
|
|
41
|
+
viewer.emitEvent({ type: "select2", data: undefined, handles });
|
|
42
|
+
}
|