@shapediver/viewer.features.drawing-tools 3.12.16 → 3.12.18

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 (53) hide show
  1. package/package.json +10 -10
  2. package/dist/business/implementation/managers/interaction/InteractionManagerAdapter.d.ts +0 -36
  3. package/dist/business/implementation/managers/interaction/InteractionManagerAdapter.d.ts.map +0 -1
  4. package/dist/business/implementation/managers/interaction/InteractionManagerAdapter.js +0 -77
  5. package/dist/business/implementation/managers/interaction/InteractionManagerAdapter.js.map +0 -1
  6. package/dist/business/implementation/managers/interaction/InteractionManagerRefactored.d.ts +0 -82
  7. package/dist/business/implementation/managers/interaction/InteractionManagerRefactored.d.ts.map +0 -1
  8. package/dist/business/implementation/managers/interaction/InteractionManagerRefactored.js +0 -406
  9. package/dist/business/implementation/managers/interaction/InteractionManagerRefactored.js.map +0 -1
  10. package/dist/business/implementation/managers/interaction/actions/InteractionActions.d.ts +0 -107
  11. package/dist/business/implementation/managers/interaction/actions/InteractionActions.d.ts.map +0 -1
  12. package/dist/business/implementation/managers/interaction/actions/InteractionActions.js +0 -191
  13. package/dist/business/implementation/managers/interaction/actions/InteractionActions.js.map +0 -1
  14. package/dist/business/implementation/managers/interaction/config/InteractionConfig.d.ts +0 -134
  15. package/dist/business/implementation/managers/interaction/config/InteractionConfig.d.ts.map +0 -1
  16. package/dist/business/implementation/managers/interaction/config/InteractionConfig.js +0 -218
  17. package/dist/business/implementation/managers/interaction/config/InteractionConfig.js.map +0 -1
  18. package/dist/business/implementation/managers/interaction/gestures/GestureRecognition.d.ts +0 -118
  19. package/dist/business/implementation/managers/interaction/gestures/GestureRecognition.d.ts.map +0 -1
  20. package/dist/business/implementation/managers/interaction/gestures/GestureRecognition.js +0 -352
  21. package/dist/business/implementation/managers/interaction/gestures/GestureRecognition.js.map +0 -1
  22. package/dist/business/implementation/managers/interaction/index.d.ts +0 -13
  23. package/dist/business/implementation/managers/interaction/index.d.ts.map +0 -1
  24. package/dist/business/implementation/managers/interaction/index.js +0 -49
  25. package/dist/business/implementation/managers/interaction/index.js.map +0 -1
  26. package/dist/business/implementation/managers/interaction/interfaces/IInteractionManagerForStrategy.d.ts +0 -24
  27. package/dist/business/implementation/managers/interaction/interfaces/IInteractionManagerForStrategy.d.ts.map +0 -1
  28. package/dist/business/implementation/managers/interaction/interfaces/IInteractionManagerForStrategy.js +0 -3
  29. package/dist/business/implementation/managers/interaction/interfaces/IInteractionManagerForStrategy.js.map +0 -1
  30. package/dist/business/implementation/managers/interaction/mobile-detection-example.d.ts +0 -24
  31. package/dist/business/implementation/managers/interaction/mobile-detection-example.d.ts.map +0 -1
  32. package/dist/business/implementation/managers/interaction/mobile-detection-example.js +0 -112
  33. package/dist/business/implementation/managers/interaction/mobile-detection-example.js.map +0 -1
  34. package/dist/business/implementation/managers/interaction/strategies/DesktopInteractionStrategy.d.ts +0 -37
  35. package/dist/business/implementation/managers/interaction/strategies/DesktopInteractionStrategy.d.ts.map +0 -1
  36. package/dist/business/implementation/managers/interaction/strategies/DesktopInteractionStrategy.js +0 -301
  37. package/dist/business/implementation/managers/interaction/strategies/DesktopInteractionStrategy.js.map +0 -1
  38. package/dist/business/implementation/managers/interaction/strategies/IInteractionStrategy.d.ts +0 -52
  39. package/dist/business/implementation/managers/interaction/strategies/IInteractionStrategy.d.ts.map +0 -1
  40. package/dist/business/implementation/managers/interaction/strategies/IInteractionStrategy.js +0 -21
  41. package/dist/business/implementation/managers/interaction/strategies/IInteractionStrategy.js.map +0 -1
  42. package/dist/business/implementation/managers/interaction/strategies/MobileInteractionStrategy.d.ts +0 -80
  43. package/dist/business/implementation/managers/interaction/strategies/MobileInteractionStrategy.d.ts.map +0 -1
  44. package/dist/business/implementation/managers/interaction/strategies/MobileInteractionStrategy.js +0 -671
  45. package/dist/business/implementation/managers/interaction/strategies/MobileInteractionStrategy.js.map +0 -1
  46. package/dist/business/implementation/managers/interaction/test-mobile-detection.d.ts +0 -24
  47. package/dist/business/implementation/managers/interaction/test-mobile-detection.d.ts.map +0 -1
  48. package/dist/business/implementation/managers/interaction/test-mobile-detection.js +0 -136
  49. package/dist/business/implementation/managers/interaction/test-mobile-detection.js.map +0 -1
  50. package/dist/business/implementation/managers/interaction/test-refactored.d.ts +0 -9
  51. package/dist/business/implementation/managers/interaction/test-refactored.d.ts.map +0 -1
  52. package/dist/business/implementation/managers/interaction/test-refactored.js +0 -57
  53. package/dist/business/implementation/managers/interaction/test-refactored.js.map +0 -1
@@ -1,671 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MobileInteractionStrategy = void 0;
4
- const viewer_1 = require("@shapediver/viewer");
5
- const viewer_shared_services_1 = require("@shapediver/viewer.shared.services");
6
- const IInteractionStrategy_1 = require("./IInteractionStrategy");
7
- /**
8
- * Mobile-specific interaction strategy using touch gestures
9
- */
10
- class MobileInteractionStrategy {
11
- constructor(drawingToolsManager, interactionManager, config) {
12
- // Touch-specific state
13
- this.touchStartTime = 0;
14
- this.touchStartPosition = { x: 0, y: 0 };
15
- this.isLongPress = false;
16
- this.touchHasMoved = false;
17
- this.isPotentialInsertion = false;
18
- this.isDraggingPoint = false; // Track if we're dragging a point
19
- this.lastTapTime = 0;
20
- this.tapCount = 0;
21
- this.drawingToolsManager = drawingToolsManager;
22
- this.interactionManager = interactionManager;
23
- this.config = config;
24
- }
25
- canHandle(event) {
26
- // Handle all pointer types on mobile devices (touch, pen, mouse on tablets)
27
- // Note: Strategy selection is now done via SystemInfo.isMobile,
28
- // so this method is primarily for compatibility
29
- return (event.pointerType === "touch" ||
30
- event.pointerType === "pen" ||
31
- event.pointerType === "mouse");
32
- }
33
- onPointerDown(event, ray) {
34
- if (this.drawingToolsManager.closed) {
35
- return { handled: false };
36
- }
37
- this.touchStartTime = Date.now();
38
- this.touchStartPosition = { x: event.clientX, y: event.clientY };
39
- this.isLongPress = false;
40
- this.longPressPoint = undefined; // Reset long press point
41
- this.touchHasMoved = false;
42
- this.isPotentialInsertion = false;
43
- this.isDraggingPoint = false; // Reset drag state
44
- // Start long press detection
45
- this.startLongPressDetection(event, ray);
46
- // Handle multi-touch for different actions
47
- if (this.isMultiTouch(event)) {
48
- return this.handleMultiTouch(event, ray);
49
- }
50
- // Handle insertion immediately in onPointerDown (like desktop strategy)
51
- // Only if we're not near an existing point (which would be for dragging)
52
- const distances = this.drawingToolsManager.geometryMathManager.checkPointDistances(ray, this.drawingToolsManager.positionArray);
53
- const nearPoint = this.findNearestTouchTarget(distances);
54
- // IMPORTANT: Check for closing FIRST, before any other logic that might change insertion state
55
- // Special case: If we're in insertion mode and touching the first point, close immediately
56
- if (nearPoint === 0 &&
57
- this.interactionManager.insertionInteractionHandler
58
- .insertionActive &&
59
- this.canCloseDrawing()) {
60
- // Close the drawing immediately when touching the first point
61
- this.interactionManager.insertionInteractionHandler.stopInsertion();
62
- this.drawingToolsManager.geometryState.closeLoop = true;
63
- this.disableMobileContinuousRendering();
64
- // Emit GEOMETRY_CHANGED event
65
- viewer_shared_services_1.EventEngine.instance.emitEvent(viewer_shared_services_1.EVENTTYPE_DRAWING_TOOLS.GEOMETRY_CHANGED, {
66
- viewportId: this.drawingToolsManager.viewport.id,
67
- drawingToolId: this.drawingToolsManager.uuid,
68
- points: this.drawingToolsManager.geometryState.getPointsData(),
69
- temporary: false,
70
- fromHistory: false,
71
- });
72
- this.drawingToolsManager.viewport.render(); // Force immediate render after closing
73
- return {
74
- handled: true,
75
- action: IInteractionStrategy_1.InteractionAction.INSERT_END,
76
- };
77
- }
78
- if (nearPoint === undefined) {
79
- // Not near a point, this could be an insertion tap
80
- // Check if insertion is allowed before proceeding
81
- if (!this.canInsertPoint()) {
82
- return {
83
- handled: true,
84
- action: IInteractionStrategy_1.InteractionAction.NONE,
85
- };
86
- }
87
- // Handle insertion finalization (exactly like desktop strategy)
88
- if (this.interactionManager.insertionInteractionHandler
89
- .insertionActive) {
90
- const result = this.interactionManager.insertionInteractionHandler.finalizeInsertion();
91
- if (result) {
92
- this.drawingToolsManager.update();
93
- this.disableMobileContinuousRendering();
94
- this.drawingToolsManager.viewport.render(); // Force immediate render after closing
95
- return {
96
- handled: true,
97
- action: IInteractionStrategy_1.InteractionAction.INSERT_END,
98
- };
99
- }
100
- else {
101
- // Only continue insertion if we can still insert points
102
- if (this.canInsertPoint()) {
103
- this.enableMobileContinuousRendering();
104
- this.interactionManager.insertionInteractionHandler.startInsertion(event);
105
- this.drawingToolsManager.update();
106
- return {
107
- handled: true,
108
- action: IInteractionStrategy_1.InteractionAction.INSERT_START,
109
- };
110
- }
111
- else {
112
- // Can't insert more points, stop insertion
113
- this.disableMobileContinuousRendering();
114
- return {
115
- handled: true,
116
- action: IInteractionStrategy_1.InteractionAction.NONE,
117
- };
118
- }
119
- }
120
- }
121
- // Set last event in manager (important for insertion logic)
122
- this.interactionManager.setLastEvent(event);
123
- // Check if insertion is already active (need to finalize previous insertion)
124
- if (this.interactionManager.insertionInteractionHandler
125
- .insertionActive) {
126
- const result = this.interactionManager.insertionInteractionHandler.finalizeInsertion();
127
- if (result) {
128
- // Drawing was closed
129
- this.disableMobileContinuousRendering();
130
- this.drawingToolsManager.update();
131
- this.drawingToolsManager.viewport.render(); // Force immediate render after closing
132
- return {
133
- handled: true,
134
- action: IInteractionStrategy_1.InteractionAction.INSERT_END,
135
- };
136
- }
137
- else {
138
- // Only continue insertion if we can still insert points
139
- if (this.canInsertPoint()) {
140
- // Continue with new insertion
141
- this.interactionManager.startInsertion();
142
- this.drawingToolsManager.update();
143
- return {
144
- handled: true,
145
- action: IInteractionStrategy_1.InteractionAction.INSERT_START,
146
- };
147
- }
148
- else {
149
- // Can't insert more points, stop insertion
150
- this.disableMobileContinuousRendering();
151
- return {
152
- handled: true,
153
- action: IInteractionStrategy_1.InteractionAction.NONE,
154
- };
155
- }
156
- }
157
- }
158
- // Start insertion immediately (like desktop strategy) - but only if allowed
159
- if (this.canInsertPoint()) {
160
- this.isPotentialInsertion = true; // Track that we started an insertion
161
- this.enableMobileContinuousRendering();
162
- this.interactionManager.startInsertion();
163
- return {
164
- handled: true,
165
- action: IInteractionStrategy_1.InteractionAction.INSERT_START,
166
- };
167
- }
168
- else {
169
- // Can't insert points, return without action
170
- return {
171
- handled: true,
172
- action: IInteractionStrategy_1.InteractionAction.NONE,
173
- };
174
- }
175
- }
176
- return this.handleSingleTouch(event, ray);
177
- }
178
- onPointerMove(event, ray) {
179
- if (this.drawingToolsManager.closed) {
180
- return { handled: false };
181
- }
182
- // Handle different move scenarios - check dragging FIRST
183
- if (this.isDragging()) {
184
- return this.handleTouchDrag(event, ray);
185
- }
186
- // Cancel long press if moved too far
187
- if (this.hasTouchMovedBeyondThreshold(event)) {
188
- this.touchHasMoved = true;
189
- // If we have a selected point and aren't dragging yet, start dragging
190
- if (!this.isDragging() &&
191
- this.interactionManager.interactionManagerHelper
192
- .selectedPointIndices.length > 0) {
193
- const selectedPoints = this.interactionManager.interactionManagerHelper
194
- .selectedPointIndices;
195
- if (selectedPoints.length > 0) {
196
- // Start dragging the selected point(s)
197
- const draggingStarted = this.interactionManager.interactionManagerHelper.startDragging();
198
- if (draggingStarted) {
199
- this.isDraggingPoint = true;
200
- this.enableMobileCameraFreeze();
201
- this.cancelLongPress(); // Cancel long press since we're now dragging
202
- return this.handleTouchDrag(event, ray);
203
- }
204
- }
205
- }
206
- // Cancel insertion if this was a potential insertion and we've started dragging
207
- // (indicating user wants to drag, not insert)
208
- if (this.isPotentialInsertion &&
209
- this.interactionManager.insertionInteractionHandler
210
- .insertionActive) {
211
- // Check if we've started dragging - if so, cancel the insertion
212
- if (this.isDragging() || this.isDraggingPoint) {
213
- this.interactionManager.insertionInteractionHandler.stopInsertion();
214
- this.disableMobileContinuousRendering();
215
- this.isPotentialInsertion = false;
216
- }
217
- }
218
- this.cancelLongPress();
219
- }
220
- if (this.interactionManager.insertionInteractionHandler.insertionActive) {
221
- return this.handleInsertionMove(event, ray);
222
- }
223
- // Update cursor for hover feedback
224
- this.updateCursor();
225
- return this.handleTouchHover(event, ray);
226
- }
227
- onPointerUp(event, ray) {
228
- if (this.drawingToolsManager.closed) {
229
- return { handled: false };
230
- }
231
- this.cancelLongPress();
232
- // Clean up drag state
233
- if (this.isDraggingPoint) {
234
- // Call helper.onUp() to handle closing logic (like desktop)
235
- this.interactionManager.interactionManagerHelper.onUp();
236
- this.isDraggingPoint = false;
237
- this.disableMobileCameraFreeze(); // Remove mobile camera freeze
238
- // Camera freeze will be automatically removed by the interaction manager
239
- }
240
- const touchDuration = Date.now() - this.touchStartTime;
241
- const touchDistance = this.getTouchDistance(event);
242
- // Determine gesture type
243
- if (this.isLongPress) {
244
- return this.handleLongPress(event, ray);
245
- }
246
- if (touchDistance < this.config.touchSettings.tapThreshold) {
247
- return this.handleTap(event, ray, touchDuration);
248
- }
249
- if (this.isDragging()) {
250
- return this.handleDragEnd(event, ray);
251
- }
252
- // Clean up camera freeze if still active from point selection but no drag occurred
253
- // (This handles cases where user touches a point but just taps without moving)
254
- if (!this.isDraggingPoint) {
255
- this.disableMobileCameraFreeze();
256
- }
257
- return { handled: true, action: IInteractionStrategy_1.InteractionAction.NONE };
258
- }
259
- onPointerOut() {
260
- this.cancelLongPress();
261
- // Clean up camera freeze if pointer leaves the area
262
- this.disableMobileCameraFreeze();
263
- return {
264
- handled: true,
265
- action: IInteractionStrategy_1.InteractionAction.NONE,
266
- };
267
- }
268
- startLongPressDetection(event, ray) {
269
- // Check if we're starting long press on a point
270
- const distances = this.drawingToolsManager.geometryMathManager.checkPointDistances(ray, this.drawingToolsManager.positionArray);
271
- const nearPoint = this.findNearestTouchTarget(distances);
272
- this.longPressPoint = nearPoint; // Store the point for potential deletion
273
- this.longPressTimer = window.setTimeout(() => {
274
- this.isLongPress = true;
275
- this.handleLongPressStart(event, ray);
276
- }, this.config.touchSettings.longPressDuration);
277
- }
278
- cancelLongPress() {
279
- if (this.longPressTimer) {
280
- clearTimeout(this.longPressTimer);
281
- this.longPressTimer = undefined;
282
- }
283
- this.longPressPoint = undefined; // Reset the long press point
284
- }
285
- isMultiTouch(event) {
286
- // Check if there are multiple active pointers
287
- // This would require tracking active pointers
288
- return false; // Simplified for now
289
- }
290
- handleSingleTouch(event, ray) {
291
- // Check if touching near a point for potential drag
292
- const distances = this.drawingToolsManager.geometryMathManager.checkPointDistances(ray, this.drawingToolsManager.positionArray);
293
- // Mobile-specific point selection with larger touch targets
294
- const nearPoint = this.findNearestTouchTarget(distances);
295
- if (nearPoint !== undefined) {
296
- // Check if this is the first point and we can close
297
- if (nearPoint === 0 && this.canCloseDrawing()) {
298
- // Close the drawing by setting closeLoop and calling update
299
- this.drawingToolsManager.geometryState.closeLoop = true;
300
- // Emit GEOMETRY_CHANGED event for closing
301
- viewer_shared_services_1.EventEngine.instance.emitEvent(viewer_shared_services_1.EVENTTYPE_DRAWING_TOOLS.GEOMETRY_CHANGED, {
302
- viewportId: this.drawingToolsManager.viewport.id,
303
- drawingToolId: this.drawingToolsManager.uuid,
304
- points: this.drawingToolsManager.geometryState.getPointsData(),
305
- temporary: false,
306
- fromHistory: false,
307
- });
308
- this.disableMobileContinuousRendering();
309
- this.disableMobileCameraFreeze(); // Clean up camera freeze since interaction is complete
310
- this.drawingToolsManager.viewport.render(); // Force immediate render after closing
311
- return {
312
- handled: true,
313
- action: IInteractionStrategy_1.InteractionAction.INSERT_END,
314
- };
315
- }
316
- else {
317
- // Not first point or can't close, just select for interaction (drag/delete)
318
- // Select the point but don't start dragging yet
319
- // This allows taps and long press to still work
320
- this.selectPointForInteraction(nearPoint, ray);
321
- return {
322
- handled: true,
323
- action: IInteractionStrategy_1.InteractionAction.SELECT,
324
- preventDefault: true,
325
- };
326
- }
327
- }
328
- return { handled: true, action: IInteractionStrategy_1.InteractionAction.NONE };
329
- }
330
- handleMultiTouch(event, ray) {
331
- // Handle two-finger gestures for camera control or multi-select
332
- return {
333
- handled: true,
334
- action: IInteractionStrategy_1.InteractionAction.NONE,
335
- stopPropagation: true,
336
- };
337
- }
338
- handleTap(event, ray, duration) {
339
- const now = Date.now();
340
- // Check for double tap
341
- if (now - this.lastTapTime <
342
- this.config.touchSettings.doubleTapInterval) {
343
- this.tapCount++;
344
- }
345
- else {
346
- this.tapCount = 1;
347
- }
348
- this.lastTapTime = now;
349
- if (this.tapCount === 2) {
350
- return this.handleDoubleTap(event, ray);
351
- }
352
- return this.handleSingleTap(event, ray);
353
- }
354
- handleSingleTap(event, ray) {
355
- // Check if we're tapping on an existing point first
356
- const distances = this.drawingToolsManager.geometryMathManager.checkPointDistances(ray, this.drawingToolsManager.positionArray);
357
- const nearPoint = this.findNearestTouchTarget(distances);
358
- // Get selected points from the touch down event
359
- const selectedPoints = this.interactionManager.interactionManagerHelper
360
- .selectedPointIndices;
361
- // If we're in insertion mode and tapped on the first point, close the drawing
362
- // Use nearPoint instead of selectedPoints since selectedPoints might be cleared
363
- if (nearPoint !== undefined &&
364
- nearPoint === 0 &&
365
- this.interactionManager.insertionInteractionHandler
366
- .insertionActive &&
367
- this.canCloseDrawing()) {
368
- // Close the drawing by tapping the first point
369
- this.interactionManager.insertionInteractionHandler.stopInsertion();
370
- this.drawingToolsManager.geometryState.closeLoop = true;
371
- this.disableMobileContinuousRendering();
372
- // Emit GEOMETRY_CHANGED event instead of calling update directly
373
- viewer_shared_services_1.EventEngine.instance.emitEvent(viewer_shared_services_1.EVENTTYPE_DRAWING_TOOLS.GEOMETRY_CHANGED, {
374
- viewportId: this.drawingToolsManager.viewport.id,
375
- drawingToolId: this.drawingToolsManager.uuid,
376
- points: this.drawingToolsManager.geometryState.getPointsData(),
377
- temporary: false,
378
- fromHistory: false,
379
- });
380
- this.drawingToolsManager.viewport.render(); // Force immediate render after closing
381
- return {
382
- handled: true,
383
- action: IInteractionStrategy_1.InteractionAction.INSERT_END,
384
- };
385
- }
386
- // Handle insertion finalization (mobile modification of desktop strategy)
387
- // On mobile, we need to finalize points but keep insertion active for continuous drawing
388
- if (this.interactionManager.insertionInteractionHandler.insertionActive) {
389
- const result = this.interactionManager.insertionInteractionHandler.finalizeInsertion();
390
- if (result) {
391
- // Drawing was completed/closed
392
- // Emit GEOMETRY_CHANGED event instead of calling update directly
393
- viewer_shared_services_1.EventEngine.instance.emitEvent(viewer_shared_services_1.EVENTTYPE_DRAWING_TOOLS.GEOMETRY_CHANGED, {
394
- viewportId: this.drawingToolsManager.viewport.id,
395
- drawingToolId: this.drawingToolsManager.uuid,
396
- points: this.drawingToolsManager.geometryState.getPointsData(),
397
- temporary: false,
398
- fromHistory: false,
399
- });
400
- this.disableMobileContinuousRendering();
401
- this.drawingToolsManager.viewport.render(); // Force immediate render after closing
402
- return {
403
- handled: true,
404
- action: IInteractionStrategy_1.InteractionAction.INSERT_END,
405
- };
406
- }
407
- else {
408
- // Point was added but drawing not complete
409
- // On mobile: restart insertion immediately to keep continuous drawing
410
- if (this.canInsertPoint()) {
411
- try {
412
- this.enableMobileContinuousRendering();
413
- this.interactionManager.insertionInteractionHandler.startInsertion(event);
414
- // Don't call update() here - let GEOMETRY_CHANGED events handle it
415
- return {
416
- handled: true,
417
- action: IInteractionStrategy_1.InteractionAction.NONE, // Avoid triggering action system that might reset state
418
- };
419
- }
420
- catch (error) {
421
- console.warn("Failed to restart insertion:", error);
422
- // Insertion restart failed, continue with fallback
423
- }
424
- }
425
- else {
426
- // Can't insert more points, stop insertion
427
- this.disableMobileContinuousRendering();
428
- return {
429
- handled: true,
430
- action: IInteractionStrategy_1.InteractionAction.NONE,
431
- };
432
- }
433
- }
434
- }
435
- // Start insertion if not active (like desktop strategy) - but only if allowed
436
- if (!this.interactionManager.insertionInteractionHandler
437
- .insertionActive &&
438
- this.canInsertPoint()) {
439
- try {
440
- this.enableMobileContinuousRendering();
441
- this.interactionManager.insertionInteractionHandler.startInsertion(event);
442
- this.drawingToolsManager.update();
443
- return {
444
- handled: true,
445
- action: IInteractionStrategy_1.InteractionAction.NONE, // Avoid triggering action system that might reset state
446
- };
447
- }
448
- catch (error) {
449
- // Insertion failed, return default action
450
- }
451
- }
452
- return { handled: true, action: IInteractionStrategy_1.InteractionAction.SELECT };
453
- }
454
- handleDoubleTap(event, ray) {
455
- // Double tap for special actions like finishing insertion or deleting
456
- this.tapCount = 0;
457
- const distances = this.drawingToolsManager.geometryMathManager.checkPointDistances(ray, this.drawingToolsManager.positionArray);
458
- const nearPoint = this.findNearestTouchTarget(distances);
459
- if (nearPoint !== undefined) {
460
- // Double tap on point could delete it
461
- return this.handlePointDeletion(nearPoint);
462
- }
463
- // Double tap in empty space could finish current operation
464
- if (this.interactionManager.insertionInteractionHandler.insertionActive) {
465
- this.interactionManager.stopInsertion();
466
- this.disableMobileContinuousRendering();
467
- return {
468
- handled: true,
469
- action: IInteractionStrategy_1.InteractionAction.INSERT_END,
470
- };
471
- }
472
- return { handled: true, action: IInteractionStrategy_1.InteractionAction.NONE };
473
- }
474
- handleLongPressStart(event, ray) {
475
- // Long press could start context menu or multi-select mode
476
- // Provide haptic feedback if available and enabled
477
- this.triggerHapticFeedback();
478
- }
479
- handleLongPress(event, ray) {
480
- // Long press actions - delete point if on existing point
481
- this.triggerHapticFeedback();
482
- // Check if we have a stored point from the long press start
483
- if (this.longPressPoint !== undefined) {
484
- // Delete the point by index directly to avoid ray precision issues
485
- this.interactionManager.deletionInteractionHandler.deletePointByIndex(this.longPressPoint);
486
- // Reset long press state
487
- this.longPressPoint = undefined;
488
- this.isLongPress = false;
489
- // Remove camera freeze since long press interaction is complete
490
- this.disableMobileCameraFreeze();
491
- return {
492
- handled: true,
493
- action: IInteractionStrategy_1.InteractionAction.DELETE,
494
- preventDefault: true,
495
- };
496
- }
497
- // If no point to delete, remove camera freeze and return context menu action
498
- this.disableMobileCameraFreeze();
499
- return { handled: true, action: IInteractionStrategy_1.InteractionAction.CONTEXT_MENU };
500
- }
501
- triggerHapticFeedback() {
502
- if (this.config.touchSettings.enableHapticFeedback &&
503
- "vibrate" in navigator) {
504
- navigator.vibrate(this.config.touchSettings.hapticPattern);
505
- }
506
- }
507
- handleTouchDrag(event, ray) {
508
- // Touch drag for moving points - similar to mouse drag but with touch-specific behavior
509
- this.moveDraggedPoints(ray);
510
- return {
511
- handled: true,
512
- action: IInteractionStrategy_1.InteractionAction.DRAG_MOVE,
513
- preventDefault: true,
514
- };
515
- }
516
- handleInsertionMove(event, ray) {
517
- // Handle moving insertion point on mobile
518
- this.interactionManager.insertionInteractionHandler.onMove(ray);
519
- return {
520
- handled: true,
521
- action: IInteractionStrategy_1.InteractionAction.INSERT_MOVE,
522
- };
523
- }
524
- handleTouchHover(event, ray) {
525
- // Mobile doesn't have true hover, but we can update visual feedback
526
- return { handled: true, action: IInteractionStrategy_1.InteractionAction.HOVER };
527
- }
528
- handleDragEnd(event, ray) {
529
- // End drag operation - the interaction manager will handle cleanup
530
- return {
531
- handled: true,
532
- action: IInteractionStrategy_1.InteractionAction.DRAG_END,
533
- };
534
- }
535
- handlePointDeletion(pointIndex) {
536
- // Handle point deletion with confirmation or undo option
537
- return {
538
- handled: true,
539
- action: IInteractionStrategy_1.InteractionAction.DELETE,
540
- };
541
- }
542
- hasTouchMovedBeyondThreshold(event) {
543
- const distance = this.getTouchDistance(event);
544
- return distance > this.config.touchSettings.tapMovementThreshold;
545
- }
546
- getTouchDistance(event) {
547
- const dx = event.clientX - this.touchStartPosition.x;
548
- const dy = event.clientY - this.touchStartPosition.y;
549
- return Math.sqrt(dx * dx + dy * dy);
550
- }
551
- findNearestTouchTarget(distances) {
552
- // Find nearest point with larger touch target area for mobile
553
- // Use a larger threshold for point selection to make it easier to grab points
554
- const touchThreshold = this.config.touchSettings.minTouchTargetSize * 2; // Double the touch target for easier point selection
555
- if (distances && distances.length > 0) {
556
- // Find the closest point within the mobile touch threshold
557
- for (let i = 0; i < distances.length; i++) {
558
- if (distances[i] && distances[i].distance < touchThreshold) {
559
- return distances[i].index; // Return the actual point index, not the array index
560
- }
561
- }
562
- }
563
- return undefined;
564
- }
565
- isDragging() {
566
- return this.interactionManager.interactionManagerHelper.dragging;
567
- }
568
- selectPointForInteraction(pointIndex, ray) {
569
- const helper = this.interactionManager.interactionManagerHelper;
570
- // Just select the point for potential interaction, but don't start dragging
571
- const distances = [{ index: pointIndex, distance: 0 }];
572
- // Set the hovered point and select it
573
- helper.checkHover(distances, ray);
574
- helper.selectPoint(distances);
575
- // Enable camera freeze immediately when touching a point since user might move it
576
- this.enableMobileCameraFreeze();
577
- // Don't start dragging here - that will happen on movement
578
- }
579
- moveDraggedPoints(ray) {
580
- const helper = this.interactionManager.interactionManagerHelper;
581
- helper.moveSelectedPoints(ray);
582
- }
583
- updateCursor() {
584
- // Mobile devices don't typically show cursor changes, but we can update
585
- // for hybrid devices (tablets with mouse support)
586
- if (this.interactionManager.interactionManagerHelper.dragging) {
587
- document.body.style.cursor = "grabbing";
588
- }
589
- else if (this.interactionManager.interactionManagerHelper.hoveredPoint !==
590
- undefined) {
591
- document.body.style.cursor = "pointer";
592
- }
593
- else {
594
- document.body.style.cursor = "default";
595
- }
596
- }
597
- /**
598
- * Enable continuous rendering for mobile insertions to ensure immediate visual feedback
599
- */
600
- enableMobileContinuousRendering() {
601
- if (!this.mobileContinuousRenderingFlag) {
602
- this.mobileContinuousRenderingFlag =
603
- this.drawingToolsManager.viewport.addFlag(viewer_1.FLAG_TYPE.CONTINUOUS_RENDERING);
604
- }
605
- }
606
- /**
607
- * Disable continuous rendering for mobile insertions to save performance
608
- */
609
- disableMobileContinuousRendering() {
610
- if (this.mobileContinuousRenderingFlag) {
611
- this.drawingToolsManager.viewport.removeFlag(this.mobileContinuousRenderingFlag);
612
- this.mobileContinuousRenderingFlag = undefined;
613
- }
614
- }
615
- /**
616
- * Check if the drawing can be closed (same logic as InsertionInteractionHandler)
617
- */
618
- canCloseDrawing() {
619
- const geometryState = this.drawingToolsManager.geometryState;
620
- const settings = this.drawingToolsManager.settings;
621
- const pointCount = geometryState.getPointCount();
622
- // For closing, check current point count, not point count - 1
623
- const checkNumberOfPointsResult = geometryState.checkNumberOfPoints(pointCount);
624
- const canBeClosed = settings.geometry.mode === "lines" &&
625
- pointCount > 3 &&
626
- checkNumberOfPointsResult;
627
- const shouldBeClosed = settings.geometry.close === true &&
628
- geometryState.closeLoop === false &&
629
- settings.geometry.autoClose === false;
630
- return canBeClosed && shouldBeClosed;
631
- }
632
- /**
633
- * Check if insertion should be allowed
634
- * Returns false if drawing is closed or max points reached
635
- */
636
- canInsertPoint() {
637
- // Don't allow insertion if drawing tools manager is closed
638
- if (this.drawingToolsManager.closed) {
639
- return false;
640
- }
641
- // Don't allow insertion if the loop is already closed
642
- if (this.drawingToolsManager.geometryState.closeLoop) {
643
- return false;
644
- }
645
- // Don't allow insertion if we can't add more points (max points reached)
646
- if (!this.drawingToolsManager.geometryManager.canAddPoint()) {
647
- return false;
648
- }
649
- return true;
650
- }
651
- /**
652
- * Enable camera freeze for mobile point dragging
653
- */
654
- enableMobileCameraFreeze() {
655
- if (!this.mobileCameraFreezeFlag) {
656
- this.mobileCameraFreezeFlag =
657
- this.drawingToolsManager.viewport.addFlag(viewer_1.FLAG_TYPE.CAMERA_FREEZE);
658
- }
659
- }
660
- /**
661
- * Disable camera freeze for mobile point dragging
662
- */
663
- disableMobileCameraFreeze() {
664
- if (this.mobileCameraFreezeFlag) {
665
- this.drawingToolsManager.viewport.removeFlag(this.mobileCameraFreezeFlag);
666
- this.mobileCameraFreezeFlag = undefined;
667
- }
668
- }
669
- }
670
- exports.MobileInteractionStrategy = MobileInteractionStrategy;
671
- //# sourceMappingURL=MobileInteractionStrategy.js.map