@vcmap/core 5.1.6 → 5.2.0

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 (59) hide show
  1. package/dist/src/interaction/abstractInteraction.d.ts +5 -0
  2. package/dist/src/interaction/abstractInteraction.js.map +1 -1
  3. package/dist/src/interaction/eventHandler.d.ts +5 -1
  4. package/dist/src/interaction/eventHandler.js +29 -12
  5. package/dist/src/interaction/eventHandler.js.map +1 -1
  6. package/dist/src/map/baseOLMap.d.ts +2 -1
  7. package/dist/src/map/baseOLMap.js +1 -1
  8. package/dist/src/map/baseOLMap.js.map +1 -1
  9. package/dist/src/map/cesiumMap.d.ts +2 -1
  10. package/dist/src/map/cesiumMap.js +7 -4
  11. package/dist/src/map/cesiumMap.js.map +1 -1
  12. package/dist/src/map/obliqueMap.js +3 -3
  13. package/dist/src/map/obliqueMap.js.map +1 -1
  14. package/dist/src/map/openlayersMap.js +1 -1
  15. package/dist/src/map/openlayersMap.js.map +1 -1
  16. package/dist/src/map/vcsMap.d.ts +17 -6
  17. package/dist/src/map/vcsMap.js +46 -8
  18. package/dist/src/map/vcsMap.js.map +1 -1
  19. package/dist/src/util/clipping/clippingObject.js +10 -1
  20. package/dist/src/util/clipping/clippingObject.js.map +1 -1
  21. package/dist/src/util/clipping/clippingObjectManager.js +6 -0
  22. package/dist/src/util/clipping/clippingObjectManager.js.map +1 -1
  23. package/dist/src/util/clipping/clippingPlaneHelper.d.ts +3 -2
  24. package/dist/src/util/clipping/clippingPlaneHelper.js +14 -7
  25. package/dist/src/util/clipping/clippingPlaneHelper.js.map +1 -1
  26. package/dist/src/util/editor/editFeaturesSession.js +56 -4
  27. package/dist/src/util/editor/editFeaturesSession.js.map +1 -1
  28. package/dist/src/util/editor/editGeometrySession.d.ts +6 -1
  29. package/dist/src/util/editor/editGeometrySession.js +51 -44
  30. package/dist/src/util/editor/editGeometrySession.js.map +1 -1
  31. package/dist/src/util/editor/interactions/editGeometryMouseOverInteraction.d.ts +1 -1
  32. package/dist/src/util/editor/interactions/editGeometryMouseOverInteraction.js +4 -2
  33. package/dist/src/util/editor/interactions/editGeometryMouseOverInteraction.js.map +1 -1
  34. package/dist/src/util/editor/interactions/rightClickInteraction.d.ts +9 -0
  35. package/dist/src/util/editor/interactions/rightClickInteraction.js +31 -0
  36. package/dist/src/util/editor/interactions/rightClickInteraction.js.map +1 -0
  37. package/dist/src/util/flight/flightInstance.d.ts +1 -1
  38. package/dist/src/util/flight/flightPlayer.js +16 -13
  39. package/dist/src/util/flight/flightPlayer.js.map +1 -1
  40. package/dist/src/util/mapCollection.d.ts +14 -0
  41. package/dist/src/util/mapCollection.js +33 -0
  42. package/dist/src/util/mapCollection.js.map +1 -1
  43. package/package.json +3 -2
  44. package/src/interaction/abstractInteraction.ts +5 -0
  45. package/src/interaction/eventHandler.ts +30 -13
  46. package/src/map/baseOLMap.ts +3 -2
  47. package/src/map/cesiumMap.ts +11 -4
  48. package/src/map/obliqueMap.ts +3 -3
  49. package/src/map/openlayersMap.ts +1 -1
  50. package/src/map/vcsMap.ts +63 -10
  51. package/src/util/clipping/clippingObject.ts +10 -1
  52. package/src/util/clipping/clippingObjectManager.ts +6 -0
  53. package/src/util/clipping/clippingPlaneHelper.ts +14 -6
  54. package/src/util/editor/editFeaturesSession.ts +72 -10
  55. package/src/util/editor/editGeometrySession.ts +61 -39
  56. package/src/util/editor/interactions/editGeometryMouseOverInteraction.ts +7 -2
  57. package/src/util/editor/interactions/rightClickInteraction.ts +42 -0
  58. package/src/util/flight/flightPlayer.ts +21 -15
  59. package/src/util/mapCollection.ts +47 -0
@@ -19,6 +19,7 @@ import {
19
19
  setupScratchLayer,
20
20
  } from './editorSessionHelpers.js';
21
21
  import InteractionChain from '../../interaction/interactionChain.js';
22
+ import type AbstractInteraction from '../../interaction/abstractInteraction.js';
22
23
  import VcsEvent from '../../vcsEvent.js';
23
24
  import TranslateVertexInteraction from './interactions/translateVertexInteraction.js';
24
25
  import RemoveVertexInteraction from './interactions/removeVertexInteraction.js';
@@ -59,6 +60,11 @@ function assignVectorProperty<
59
60
  props[key] = value;
60
61
  }
61
62
 
63
+ type EditGeometrySessionOptions = {
64
+ denyInsertion?: boolean;
65
+ denyRemoval?: boolean;
66
+ };
67
+
62
68
  /**
63
69
  * Create the editing interaction for a feature with a line geometry
64
70
  * @param feature
@@ -68,6 +74,7 @@ function assignVectorProperty<
68
74
  function createEditLineStringGeometryInteraction(
69
75
  feature: Feature<LineString>,
70
76
  scratchLayer: VectorLayer,
77
+ options: EditGeometrySessionOptions,
71
78
  ): EditGeometryInteraction {
72
79
  const geometry =
73
80
  feature[obliqueGeometry] ?? (feature.getGeometry() as LineString);
@@ -84,28 +91,32 @@ function createEditLineStringGeometryInteraction(
84
91
  const translateVertex = new TranslateVertexInteraction(feature);
85
92
  translateVertex.vertexChanged.addEventListener(resetGeometry);
86
93
 
87
- const insertVertex = new InsertVertexInteraction(feature, geometry);
88
- insertVertex.vertexInserted.addEventListener(({ vertex, index }) => {
89
- scratchLayer.addFeatures([vertex]);
90
- vertices.splice(index, 0, vertex);
91
- resetGeometry();
92
- });
94
+ const interactions: AbstractInteraction[] = [translateVertex];
93
95
 
94
- const removeVertex = new RemoveVertexInteraction();
95
- removeVertex.vertexRemoved.addEventListener((vertex) => {
96
- scratchLayer.removeFeaturesById([vertex.getId() as string]);
97
- const index = vertices.indexOf(vertex);
98
- if (index > -1) {
99
- vertices.splice(index, 1);
96
+ if (!options.denyInsertion) {
97
+ const insertVertex = new InsertVertexInteraction(feature, geometry);
98
+ insertVertex.vertexInserted.addEventListener(({ vertex, index }) => {
99
+ scratchLayer.addFeatures([vertex]);
100
+ vertices.splice(index, 0, vertex);
100
101
  resetGeometry();
101
- }
102
- });
102
+ });
103
+ interactions.push(insertVertex);
104
+ }
105
+
106
+ if (!options.denyRemoval) {
107
+ const removeVertex = new RemoveVertexInteraction();
108
+ removeVertex.vertexRemoved.addEventListener((vertex) => {
109
+ scratchLayer.removeFeaturesById([vertex.getId() as string]);
110
+ const index = vertices.indexOf(vertex);
111
+ if (index > -1) {
112
+ vertices.splice(index, 1);
113
+ resetGeometry();
114
+ }
115
+ });
116
+ interactions.push(removeVertex);
117
+ }
103
118
 
104
- const interactionChain = new InteractionChain([
105
- translateVertex,
106
- insertVertex,
107
- removeVertex,
108
- ]);
119
+ const interactionChain = new InteractionChain(interactions);
109
120
 
110
121
  return {
111
122
  interactionChain,
@@ -250,6 +261,7 @@ function createEditBBoxGeometryInteraction(
250
261
  function createEditSimplePolygonInteraction(
251
262
  feature: Feature<Polygon>,
252
263
  scratchLayer: VectorLayer,
264
+ options: EditGeometrySessionOptions,
253
265
  ): EditGeometryInteraction {
254
266
  const geometry =
255
267
  feature[obliqueGeometry] ?? (feature.getGeometry() as Polygon);
@@ -271,28 +283,32 @@ function createEditSimplePolygonInteraction(
271
283
  const translateVertex = new TranslateVertexInteraction(feature);
272
284
  translateVertex.vertexChanged.addEventListener(resetGeometry);
273
285
 
274
- const insertVertex = new InsertVertexInteraction(feature, linearRing);
275
- insertVertex.vertexInserted.addEventListener(({ vertex, index }) => {
276
- scratchLayer.addFeatures([vertex]);
277
- vertices.splice(index, 0, vertex);
278
- resetGeometry();
279
- });
286
+ const interactions: AbstractInteraction[] = [translateVertex];
280
287
 
281
- const removeVertex = new RemoveVertexInteraction();
282
- removeVertex.vertexRemoved.addEventListener((vertex) => {
283
- scratchLayer.removeFeaturesById([vertex.getId() as string]);
284
- const index = vertices.indexOf(vertex);
285
- if (index > -1) {
286
- vertices.splice(index, 1);
288
+ if (!options.denyInsertion) {
289
+ const insertVertex = new InsertVertexInteraction(feature, linearRing);
290
+ insertVertex.vertexInserted.addEventListener(({ vertex, index }) => {
291
+ scratchLayer.addFeatures([vertex]);
292
+ vertices.splice(index, 0, vertex);
287
293
  resetGeometry();
288
- }
289
- });
294
+ });
295
+ interactions.push(insertVertex);
296
+ }
297
+
298
+ if (!options.denyRemoval) {
299
+ const removeVertex = new RemoveVertexInteraction();
300
+ removeVertex.vertexRemoved.addEventListener((vertex) => {
301
+ scratchLayer.removeFeaturesById([vertex.getId() as string]);
302
+ const index = vertices.indexOf(vertex);
303
+ if (index > -1) {
304
+ vertices.splice(index, 1);
305
+ resetGeometry();
306
+ }
307
+ });
308
+ interactions.push(removeVertex);
309
+ }
290
310
 
291
- const interactionChain = new InteractionChain([
292
- translateVertex,
293
- insertVertex,
294
- removeVertex,
295
- ]);
311
+ const interactionChain = new InteractionChain(interactions);
296
312
 
297
313
  return {
298
314
  interactionChain,
@@ -350,11 +366,13 @@ function createEditPointInteraction(
350
366
  * @param app
351
367
  * @param layer
352
368
  * @param [interactionId] id for registering mutliple exclusive interaction. Needed to run a selection session at the same time as a edit features session.
369
+ * @param [editVertexOptions={}]
353
370
  */
354
371
  function startEditGeometrySession(
355
372
  app: VcsApp,
356
373
  layer: VectorLayer,
357
374
  interactionId?: string,
375
+ editVertexOptions: EditGeometrySessionOptions = {},
358
376
  ): EditGeometrySession {
359
377
  const {
360
378
  interactionChain,
@@ -367,7 +385,9 @@ function startEditGeometrySession(
367
385
  const mapInteractionController = new MapInteractionController();
368
386
  interactionChain.addInteraction(mapInteractionController);
369
387
 
370
- const mouseOverInteraction = new EditGeometryMouseOverInteraction();
388
+ const mouseOverInteraction = new EditGeometryMouseOverInteraction(
389
+ editVertexOptions.denyRemoval,
390
+ );
371
391
  interactionChain.addInteraction(mouseOverInteraction);
372
392
 
373
393
  const stopped = new VcsEvent<void>();
@@ -463,12 +483,14 @@ function startEditGeometrySession(
463
483
  currentInteractionSet = createEditSimplePolygonInteraction(
464
484
  feature as Feature<Polygon>,
465
485
  scratchLayer,
486
+ editVertexOptions,
466
487
  );
467
488
  }
468
489
  } else if (geometryType === GeometryType.LineString) {
469
490
  currentInteractionSet = createEditLineStringGeometryInteraction(
470
491
  feature as Feature<LineString>,
471
492
  scratchLayer,
493
+ editVertexOptions,
472
494
  );
473
495
  } else if (geometryType === GeometryType.Point) {
474
496
  currentInteractionSet = createEditPointInteraction(
@@ -43,8 +43,13 @@ class EditGeometryMouseOverInteraction extends AbstractInteraction {
43
43
 
44
44
  cursorStyle: CSSStyleDeclaration | undefined;
45
45
 
46
- constructor() {
47
- super(EventType.MOVE, ModificationKeyType.NONE | ModificationKeyType.SHIFT);
46
+ constructor(denyRemoval?: boolean) {
47
+ super(
48
+ EventType.MOVE,
49
+ denyRemoval
50
+ ? ModificationKeyType.NONE
51
+ : ModificationKeyType.NONE | ModificationKeyType.SHIFT,
52
+ );
48
53
 
49
54
  this.setActive();
50
55
  }
@@ -0,0 +1,42 @@
1
+ import AbstractInteraction, {
2
+ InteractionEvent,
3
+ } from '../../../interaction/abstractInteraction.js';
4
+ import {
5
+ EventType,
6
+ ModificationKeyType,
7
+ PointerKeyType,
8
+ } from '../../../interaction/interactionType.js';
9
+ import VcsEvent from '../../../vcsEvent.js';
10
+
11
+ function timeout(ms: number): Promise<void> {
12
+ return new Promise((resolve) => {
13
+ setTimeout(resolve, ms);
14
+ });
15
+ }
16
+
17
+ export default class RightClickInteraction extends AbstractInteraction {
18
+ rightClicked = new VcsEvent<void>();
19
+
20
+ eventChainFinished = new VcsEvent<void>();
21
+
22
+ constructor() {
23
+ super(EventType.CLICK, ModificationKeyType.NONE, PointerKeyType.RIGHT);
24
+ }
25
+
26
+ async pipe(event: InteractionEvent): Promise<InteractionEvent> {
27
+ this.rightClicked.raiseEvent();
28
+ event.chainEnded?.addEventListener(() => {
29
+ this.eventChainFinished.raiseEvent();
30
+ });
31
+ // we need to wait a bit, otherwise the changing features in the rightClicked Event do not take effect before
32
+ // the next interaction.
33
+ await timeout(0);
34
+ return event;
35
+ }
36
+
37
+ destroy(): void {
38
+ this.rightClicked.destroy();
39
+ this.eventChainFinished.destroy();
40
+ super.destroy();
41
+ }
42
+ }
@@ -5,7 +5,6 @@ import {
5
5
  LinearSpline,
6
6
  QuaternionSpline,
7
7
  Scene,
8
- ScreenSpaceCameraController,
9
8
  } from '@vcmap-cesium/engine';
10
9
  import { getLogger } from '@vcsuite/logger';
11
10
  import { check } from '@vcsuite/check';
@@ -86,9 +85,9 @@ export async function createFlightPlayer(
86
85
 
87
86
  let postRenderListener: (() => void) | undefined;
88
87
 
89
- let backedBeforeTimeout: number | undefined;
88
+ let resetMapControls: (() => void) | undefined;
90
89
 
91
- let screenSpaceCameraController: ScreenSpaceCameraController | undefined;
90
+ let backedBeforeTimeout: number | undefined;
92
91
 
93
92
  const stop = (): void => {
94
93
  if (playerState !== 'stopped') {
@@ -97,8 +96,9 @@ export async function createFlightPlayer(
97
96
  postRenderListener = undefined;
98
97
  }
99
98
 
100
- if (screenSpaceCameraController) {
101
- screenSpaceCameraController.enableInputs = true;
99
+ if (resetMapControls) {
100
+ resetMapControls();
101
+ resetMapControls = undefined;
102
102
  }
103
103
 
104
104
  setState('stopped');
@@ -167,8 +167,9 @@ export async function createFlightPlayer(
167
167
  const seconds = time - clock.currentSystemTime;
168
168
  clock.currentSystemTime = time;
169
169
  if (playerState === 'paused') {
170
- if (screenSpaceCameraController) {
171
- screenSpaceCameraController.enableInputs = true;
170
+ if (resetMapControls) {
171
+ resetMapControls();
172
+ resetMapControls = undefined;
172
173
  }
173
174
  return;
174
175
  }
@@ -196,10 +197,11 @@ export async function createFlightPlayer(
196
197
  scene.camera.setView(view);
197
198
  }
198
199
 
199
- if (playerState === 'playing') {
200
- if (screenSpaceCameraController) {
201
- screenSpaceCameraController.enableInputs = false;
202
- }
200
+ if (playerState === 'playing' && !resetMapControls) {
201
+ resetMapControls = app.maps.requestExclusiveMapControls(
202
+ { apiCalls: true, keyEvents: true, pointerEvents: true },
203
+ stop,
204
+ );
203
205
  }
204
206
  };
205
207
 
@@ -228,11 +230,15 @@ export async function createFlightPlayer(
228
230
  postRenderListener = undefined;
229
231
  }
230
232
 
233
+ if (resetMapControls) {
234
+ resetMapControls();
235
+ resetMapControls = undefined;
236
+ }
237
+
231
238
  const scene = cesiumMap.getScene();
232
239
  if (!scene) {
233
240
  return;
234
241
  }
235
- ({ screenSpaceCameraController } = scene);
236
242
  postRenderListener = scene.postRender.addEventListener(cesiumPostRender);
237
243
  clock.currentSystemTime = undefined;
238
244
 
@@ -266,9 +272,9 @@ export async function createFlightPlayer(
266
272
  postRenderListener = undefined;
267
273
  }
268
274
 
269
- if (screenSpaceCameraController) {
270
- screenSpaceCameraController.enableInputs = true;
271
- screenSpaceCameraController = undefined;
275
+ if (resetMapControls) {
276
+ resetMapControls();
277
+ resetMapControls = undefined;
272
278
  }
273
279
 
274
280
  if (backedBeforeTimeout != null) {
@@ -17,6 +17,12 @@ export type MapCollectionInitializationError = {
17
17
  map: VcsMap;
18
18
  };
19
19
 
20
+ export type DisableMapControlOptions = {
21
+ apiCalls: boolean;
22
+ pointerEvents: boolean;
23
+ keyEvents: boolean;
24
+ };
25
+
20
26
  async function setCesiumToOLViewpoint(
21
27
  cesiumMap: CesiumMap,
22
28
  olMap: OpenlayersMap,
@@ -119,6 +125,10 @@ class MapCollection extends Collection<VcsMap> {
119
125
  // eslint-disable-next-line class-methods-use-this
120
126
  private _postRenderListener: () => void = () => {};
121
127
 
128
+ /** Callback function that is passed when calling requestExclusiveMapControls and called when exclusive map controls are forcefully removed. */
129
+ // eslint-disable-next-line class-methods-use-this
130
+ private _exclusiveMapControlsRemoved: () => void = () => {};
131
+
122
132
  constructor() {
123
133
  super();
124
134
 
@@ -342,6 +352,7 @@ class MapCollection extends Collection<VcsMap> {
342
352
  }
343
353
  }
344
354
 
355
+ const previousMap = this._activeMap;
345
356
  this._activeMap = map;
346
357
  await this._activeMap.activate();
347
358
  this._setActiveMapCSSClass();
@@ -350,6 +361,14 @@ class MapCollection extends Collection<VcsMap> {
350
361
  await this._activeMap.gotoViewpoint(viewpoint);
351
362
  }
352
363
 
364
+ const disableMapControlOptions: DisableMapControlOptions = {
365
+ apiCalls: !!previousMap?.movementApiCallsDisabled,
366
+ keyEvents: !!previousMap?.movementKeyEventsDisabled,
367
+ pointerEvents: !!previousMap?.movementPointerEventsDisabled,
368
+ };
369
+ map.disableMovement(disableMapControlOptions);
370
+ previousMap?.disableMovement(false);
371
+
353
372
  this.clippingObjectManager.mapActivated(map);
354
373
  this._postRenderListener();
355
374
  this._postRenderListener = this._activeMap.postRender.addEventListener(
@@ -368,6 +387,34 @@ class MapCollection extends Collection<VcsMap> {
368
387
  return this._array.filter((m) => m.className === type);
369
388
  }
370
389
 
390
+ /**
391
+ * Manages the disabling of map navigation controls. By calling this function the map navigation controls passed in the options are disabled. The remove function passed by the previous caller is executed.
392
+ * @param options - which of the movement controls should be disabled.
393
+ * @param removed - the callback for when the interaction is forcefully removed.
394
+ * @returns function to reset map controls.
395
+ */
396
+ requestExclusiveMapControls(
397
+ options: DisableMapControlOptions,
398
+ removed: () => void,
399
+ ): () => void {
400
+ this._exclusiveMapControlsRemoved();
401
+ if (this._activeMap) {
402
+ this._activeMap.disableMovement(options);
403
+ }
404
+
405
+ this._exclusiveMapControlsRemoved = removed;
406
+
407
+ return () => {
408
+ // only reset if this function is called by the current exclusiveMapControls owner.
409
+ if (removed === this._exclusiveMapControlsRemoved) {
410
+ this._exclusiveMapControlsRemoved = (): void => {};
411
+ if (this._activeMap) {
412
+ this._activeMap.disableMovement(false);
413
+ }
414
+ }
415
+ };
416
+ }
417
+
371
418
  destroy(): void {
372
419
  super.destroy();
373
420
  [...this._layerCollection].forEach((l) => {