@shapediver/viewer.features.drawing-tools 3.13.20 → 3.14.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.
- package/dist/api/implementation/DrawingToolsApi.d.ts +5 -2
- package/dist/api/implementation/DrawingToolsApi.d.ts.map +1 -1
- package/dist/api/implementation/DrawingToolsApi.js.map +1 -1
- package/dist/api/interfaces/IDrawingToolsApi.d.ts +5 -2
- package/dist/api/interfaces/IDrawingToolsApi.d.ts.map +1 -1
- package/dist/business/implementation/DrawingToolsManager.d.ts +12 -9
- package/dist/business/implementation/DrawingToolsManager.d.ts.map +1 -1
- package/dist/business/implementation/DrawingToolsManager.js +20 -14
- package/dist/business/implementation/DrawingToolsManager.js.map +1 -1
- package/dist/business/implementation/managers/HistoryManager.d.ts +2 -0
- package/dist/business/implementation/managers/HistoryManager.d.ts.map +1 -1
- package/dist/business/implementation/managers/HistoryManager.js +3 -1
- package/dist/business/implementation/managers/HistoryManager.js.map +1 -1
- package/dist/business/implementation/managers/geometry/GeometryManager.d.ts +3 -2
- package/dist/business/implementation/managers/geometry/GeometryManager.d.ts.map +1 -1
- package/dist/business/implementation/managers/geometry/GeometryManager.js +4 -4
- package/dist/business/implementation/managers/geometry/GeometryManager.js.map +1 -1
- package/dist/business/implementation/managers/geometry/GeometryState.d.ts +4 -2
- package/dist/business/implementation/managers/geometry/GeometryState.d.ts.map +1 -1
- package/dist/business/implementation/managers/geometry/GeometryState.js +15 -7
- package/dist/business/implementation/managers/geometry/GeometryState.js.map +1 -1
- package/dist/business/implementation/managers/geometry/helpers/GeometryManagerHelper.d.ts +3 -2
- package/dist/business/implementation/managers/geometry/helpers/GeometryManagerHelper.d.ts.map +1 -1
- package/dist/business/implementation/managers/geometry/helpers/GeometryManagerHelper.js +20 -6
- package/dist/business/implementation/managers/geometry/helpers/GeometryManagerHelper.js.map +1 -1
- package/dist/business/implementation/managers/interaction/InteractionManager.d.ts +1 -1
- package/dist/business/implementation/managers/interaction/InteractionManager.d.ts.map +1 -1
- package/dist/business/implementation/managers/interaction/InteractionManager.js +2 -2
- package/dist/business/implementation/managers/interaction/InteractionManager.js.map +1 -1
- package/dist/business/implementation/managers/interaction/handlers/InsertionInteractionHandler.d.ts.map +1 -1
- package/dist/business/implementation/managers/interaction/handlers/InsertionInteractionHandler.js +10 -10
- package/dist/business/implementation/managers/interaction/handlers/InsertionInteractionHandler.js.map +1 -1
- package/dist/business/implementation/managers/interaction/helpers/InteractionManagerHelper.d.ts +1 -0
- package/dist/business/implementation/managers/interaction/helpers/InteractionManagerHelper.d.ts.map +1 -1
- package/dist/business/implementation/managers/interaction/helpers/InteractionManagerHelper.js +24 -8
- package/dist/business/implementation/managers/interaction/helpers/InteractionManagerHelper.js.map +1 -1
- package/dist/business/implementation/managers/interaction/interfaces/IStrategy.d.ts +1 -1
- package/dist/business/implementation/managers/interaction/interfaces/IStrategy.d.ts.map +1 -1
- package/dist/business/implementation/managers/interaction/strategies/DesktopStrategy.d.ts +349 -6
- package/dist/business/implementation/managers/interaction/strategies/DesktopStrategy.d.ts.map +1 -1
- package/dist/business/implementation/managers/interaction/strategies/DesktopStrategy.js +631 -147
- package/dist/business/implementation/managers/interaction/strategies/DesktopStrategy.js.map +1 -1
- package/dist/business/implementation/managers/interaction/strategies/MobileStategy.d.ts +1 -1
- package/dist/business/implementation/managers/interaction/strategies/MobileStategy.d.ts.map +1 -1
- package/dist/business/implementation/managers/interaction/strategies/MobileStategy.js +7 -5
- package/dist/business/implementation/managers/interaction/strategies/MobileStategy.js.map +1 -1
- package/dist/business/interfaces/IDrawingToolsManager.d.ts +8 -5
- package/dist/business/interfaces/IDrawingToolsManager.d.ts.map +1 -1
- package/dist/business/interfaces/IDrawingToolsManager.js.map +1 -1
- package/dist/business/interfaces/events/IDrawingToolsEvent.d.ts +2 -0
- package/dist/business/interfaces/events/IDrawingToolsEvent.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +11 -10
|
@@ -10,12 +10,71 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
10
10
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11
11
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
12
|
};
|
|
13
|
-
var _DesktopStrategy_drawingToolsManager, _DesktopStrategy_geometryMathManager, _DesktopStrategy_insertionInteractionHandler, _DesktopStrategy_interactionManager, _DesktopStrategy_interactionManagerHelper, _DesktopStrategy_midPointInteractionHandler, _DesktopStrategy_restrictionManager, _DesktopStrategy_viewport, _DesktopStrategy_cameraFreezeFlag, _DesktopStrategy_lastEvent, _DesktopStrategy_onDownPointer;
|
|
13
|
+
var _DesktopStrategy_instances, _DesktopStrategy_drawingToolsManager, _DesktopStrategy_geometryMathManager, _DesktopStrategy_insertionInteractionHandler, _DesktopStrategy_interactionManager, _DesktopStrategy_interactionManagerHelper, _DesktopStrategy_midPointInteractionHandler, _DesktopStrategy_restrictionManager, _DesktopStrategy_selectionBox, _DesktopStrategy_viewport, _DesktopStrategy_boxHoveredPoints, _DesktopStrategy_cameraFreezeFlag, _DesktopStrategy_isBoxSelecting, _DesktopStrategy_lastEvent, _DesktopStrategy_lastMoveEvent, _DesktopStrategy_onDownPointer, _DesktopStrategy_updateAllPointMaterials;
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.DesktopStrategy = void 0;
|
|
16
|
+
const viewer_rendering_engine_intersection_engine_1 = require("@shapediver/viewer.rendering-engine.intersection-engine");
|
|
16
17
|
const viewer_shared_types_1 = require("@shapediver/viewer.shared.types");
|
|
18
|
+
const gl_matrix_1 = require("gl-matrix");
|
|
19
|
+
const IDrawingToolsManager_1 = require("../../../../interfaces/IDrawingToolsManager");
|
|
20
|
+
/**
|
|
21
|
+
* ## Quick Reference - Main Event Flow:
|
|
22
|
+
*
|
|
23
|
+
* **Mouse Down** → Initiate interaction (box selection, insertion, point selection)
|
|
24
|
+
* **Mouse Move** → Update previews, handle dragging, provide feedback
|
|
25
|
+
* **Mouse Up** → Finalize operations, apply changes, cleanup state
|
|
26
|
+
* **Mouse Out** → Pause operations, cleanup visual feedback
|
|
27
|
+
* **Key Down** → Execute commands (insert, confirm, cancel, delete)
|
|
28
|
+
*
|
|
29
|
+
* ## Interaction State Priority:
|
|
30
|
+
* 1. **Box Selection** (Alt + drag) - Highest priority, blocks other interactions
|
|
31
|
+
* 2. **Active Insertion** - Continuous point placement mode
|
|
32
|
+
* 3. **Point Dragging** - Moving selected points
|
|
33
|
+
* 4. **Point Selection** - Single/multi-point selection
|
|
34
|
+
* 5. **Mid-point Insertion** - Insert between existing points
|
|
35
|
+
* 6. **Hover Detection** - Visual feedback only
|
|
36
|
+
*
|
|
37
|
+
* See DesktopStrategy.md for detailed workflow documentation.
|
|
38
|
+
*/
|
|
39
|
+
/**
|
|
40
|
+
* DesktopStrategy - Handles desktop mouse and keyboard interactions for drawing tools
|
|
41
|
+
*
|
|
42
|
+
* This class implements the Strategy pattern to provide desktop-specific interaction handling
|
|
43
|
+
* for drawing tools. It manages various interaction modes including point insertion, selection,
|
|
44
|
+
* dragging, and box selection.
|
|
45
|
+
*
|
|
46
|
+
* ## Main Interaction Workflows:
|
|
47
|
+
*
|
|
48
|
+
* ### 1. Point Insertion Workflow:
|
|
49
|
+
* - User clicks to start insertion mode
|
|
50
|
+
* - Mouse movements update the insertion preview
|
|
51
|
+
* - Click again to finalize point placement
|
|
52
|
+
* - Supports auto-start for empty drawings
|
|
53
|
+
*
|
|
54
|
+
* ### 2. Point Selection & Dragging Workflow:
|
|
55
|
+
* - Click on existing points to select them
|
|
56
|
+
* - Drag selected points to move them
|
|
57
|
+
* - Multiple selection support with modifier keys
|
|
58
|
+
*
|
|
59
|
+
* ### 3. Box Selection Workflow:
|
|
60
|
+
* - Alt + drag to create selection box
|
|
61
|
+
* - Shift = additive selection, Ctrl = removal selection
|
|
62
|
+
* - All points within box are selected/deselected
|
|
63
|
+
*
|
|
64
|
+
* ### 4. Mid-point Insertion Workflow:
|
|
65
|
+
* - Hover over line segments to show mid-point preview
|
|
66
|
+
* - Click to insert point between existing points
|
|
67
|
+
*
|
|
68
|
+
* ## Key Features:
|
|
69
|
+
* - Camera freeze during interactions
|
|
70
|
+
* - Visual feedback through cursor changes
|
|
71
|
+
* - Material updates for hover/selection states
|
|
72
|
+
* - Keyboard shortcuts for common operations
|
|
73
|
+
* - Restriction-based point placement
|
|
74
|
+
*/
|
|
17
75
|
class DesktopStrategy {
|
|
18
76
|
constructor(drawingToolsManager, interactionManager) {
|
|
77
|
+
_DesktopStrategy_instances.add(this);
|
|
19
78
|
_DesktopStrategy_drawingToolsManager.set(this, void 0);
|
|
20
79
|
_DesktopStrategy_geometryMathManager.set(this, void 0);
|
|
21
80
|
_DesktopStrategy_insertionInteractionHandler.set(this, void 0);
|
|
@@ -23,9 +82,13 @@ class DesktopStrategy {
|
|
|
23
82
|
_DesktopStrategy_interactionManagerHelper.set(this, void 0);
|
|
24
83
|
_DesktopStrategy_midPointInteractionHandler.set(this, void 0);
|
|
25
84
|
_DesktopStrategy_restrictionManager.set(this, void 0);
|
|
85
|
+
_DesktopStrategy_selectionBox.set(this, void 0);
|
|
26
86
|
_DesktopStrategy_viewport.set(this, void 0);
|
|
87
|
+
_DesktopStrategy_boxHoveredPoints.set(this, []);
|
|
27
88
|
_DesktopStrategy_cameraFreezeFlag.set(this, "");
|
|
89
|
+
_DesktopStrategy_isBoxSelecting.set(this, false);
|
|
28
90
|
_DesktopStrategy_lastEvent.set(this, void 0);
|
|
91
|
+
_DesktopStrategy_lastMoveEvent.set(this, void 0);
|
|
29
92
|
_DesktopStrategy_onDownPointer.set(this, void 0);
|
|
30
93
|
__classPrivateFieldSet(this, _DesktopStrategy_drawingToolsManager, drawingToolsManager, "f");
|
|
31
94
|
__classPrivateFieldSet(this, _DesktopStrategy_interactionManager, interactionManager, "f");
|
|
@@ -35,142 +98,202 @@ class DesktopStrategy {
|
|
|
35
98
|
__classPrivateFieldSet(this, _DesktopStrategy_insertionInteractionHandler, __classPrivateFieldGet(this, _DesktopStrategy_interactionManager, "f").insertionInteractionHandler, "f");
|
|
36
99
|
__classPrivateFieldSet(this, _DesktopStrategy_midPointInteractionHandler, __classPrivateFieldGet(this, _DesktopStrategy_interactionManager, "f").midPointInteractionHandler, "f");
|
|
37
100
|
__classPrivateFieldSet(this, _DesktopStrategy_interactionManagerHelper, __classPrivateFieldGet(this, _DesktopStrategy_interactionManager, "f").interactionManagerHelper, "f");
|
|
101
|
+
__classPrivateFieldSet(this, _DesktopStrategy_selectionBox, new viewer_rendering_engine_intersection_engine_1.SelectionBox(__classPrivateFieldGet(this, _DesktopStrategy_viewport, "f").canvas), "f");
|
|
38
102
|
}
|
|
39
103
|
get cameraFreezeFlag() {
|
|
40
104
|
return __classPrivateFieldGet(this, _DesktopStrategy_cameraFreezeFlag, "f");
|
|
41
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Handles mouse/pointer down events - Entry point for most interaction workflows
|
|
108
|
+
*
|
|
109
|
+
* ## Workflow Priority:
|
|
110
|
+
* 1. **Box Selection** (Alt + Click): Initiates rectangular selection mode
|
|
111
|
+
* 2. **Insertion Finalization**: If insertion is active, finalizes current point and starts new insertion
|
|
112
|
+
* 3. **Point Interaction**: Handles hover detection, selection, and dragging initiation
|
|
113
|
+
* 4. **Right Click**: Cancels current operation
|
|
114
|
+
*
|
|
115
|
+
* ## State Changes:
|
|
116
|
+
* - Sets camera freeze flag for dragging/box selection
|
|
117
|
+
* - Updates selection state
|
|
118
|
+
* - Triggers mid-point insertion completion
|
|
119
|
+
* - Starts dragging mode for selected points
|
|
120
|
+
*
|
|
121
|
+
* @param event - Pointer event containing mouse button and modifier key information
|
|
122
|
+
* @param ray - 3D ray from camera through mouse position for intersection testing
|
|
123
|
+
*/
|
|
42
124
|
onDown(event, ray) {
|
|
43
125
|
if (event.button === 0) {
|
|
44
126
|
__classPrivateFieldSet(this, _DesktopStrategy_onDownPointer, event, "f");
|
|
45
127
|
__classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").moving = false;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
*/
|
|
50
|
-
if (__classPrivateFieldGet(this, _DesktopStrategy_insertionInteractionHandler, "f").insertionActive === true) {
|
|
51
|
-
const result = __classPrivateFieldGet(this, _DesktopStrategy_insertionInteractionHandler, "f").finalizeInsertion();
|
|
52
|
-
const distances = __classPrivateFieldGet(this, _DesktopStrategy_geometryMathManager, "f").checkPointDistances(ray, __classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").positionArray);
|
|
53
|
-
__classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").checkHover(distances, ray);
|
|
54
|
-
if (result) {
|
|
55
|
-
__classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").update();
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
__classPrivateFieldGet(this, _DesktopStrategy_insertionInteractionHandler, "f").startInsertion(event);
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
128
|
+
// Handle box selection initiation
|
|
129
|
+
if (this.handleBoxSelectionStart(event)) {
|
|
130
|
+
return;
|
|
62
131
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
* FINISH MID POINT INSERTION IF THE CURRENT INDEX IS THE MID POINT INSERTION INDEX
|
|
67
|
-
*/
|
|
68
|
-
if (__classPrivateFieldGet(this, _DesktopStrategy_midPointInteractionHandler, "f").midPointInsertionActive ===
|
|
69
|
-
true) {
|
|
70
|
-
__classPrivateFieldGet(this, _DesktopStrategy_midPointInteractionHandler, "f").finishMidPointInsertion(distances);
|
|
71
|
-
__classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").midPointInserted = true;
|
|
132
|
+
// Handle insertion finalization and restart
|
|
133
|
+
if (this.handleInsertionFinalization(event, ray)) {
|
|
134
|
+
return;
|
|
72
135
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
136
|
+
// Calculate point distances for hover and selection logic
|
|
137
|
+
const distances = __classPrivateFieldGet(this, _DesktopStrategy_geometryMathManager, "f").checkPointDistances(ray, __classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").positionArray);
|
|
138
|
+
// Handle mid-point insertion
|
|
139
|
+
this.handleMidPointInsertion(distances);
|
|
140
|
+
// Check hover state
|
|
76
141
|
__classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").checkHover(distances, ray);
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
*/
|
|
80
|
-
__classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").selectPoint(distances);
|
|
81
|
-
/**
|
|
82
|
-
* IF THE CURRENTLY HOVERED POINT IS SELECTED
|
|
83
|
-
* START DRAGGING
|
|
84
|
-
*/
|
|
85
|
-
const draggingStarted = __classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").startDragging();
|
|
86
|
-
if (draggingStarted && !__classPrivateFieldGet(this, _DesktopStrategy_cameraFreezeFlag, "f"))
|
|
87
|
-
__classPrivateFieldSet(this, _DesktopStrategy_cameraFreezeFlag, __classPrivateFieldGet(this, _DesktopStrategy_viewport, "f").addFlag(viewer_shared_types_1.FLAG_TYPE.CAMERA_FREEZE), "f");
|
|
142
|
+
// Handle point selection and dragging
|
|
143
|
+
this.handlePointSelection(distances);
|
|
88
144
|
}
|
|
89
145
|
else if (event.button === 2) {
|
|
90
|
-
|
|
91
|
-
* WHEN RIGHT MOUSE BUTTON IS PRESSED
|
|
92
|
-
*/
|
|
146
|
+
// Right mouse button - cancel current operation
|
|
93
147
|
this.onOut();
|
|
94
148
|
}
|
|
95
149
|
}
|
|
96
150
|
/**
|
|
97
|
-
*
|
|
151
|
+
* Handles keyboard input for drawing tool controls
|
|
98
152
|
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
153
|
+
* ## Supported Operations:
|
|
154
|
+
*
|
|
155
|
+
* ### Confirm Key (typically Enter):
|
|
156
|
+
* - **During Insertion**: Finalizes insertion and updates drawing
|
|
157
|
+
* - **Normal Mode**: Updates/commits current drawing state
|
|
158
|
+
*
|
|
159
|
+
* ### Cancel Key (typically Escape):
|
|
160
|
+
* - **During Insertion**: Stops insertion mode
|
|
161
|
+
* - **Normal Mode**: Cancels entire drawing operation
|
|
162
|
+
*
|
|
163
|
+
* ### Insert Key (typically Space):
|
|
164
|
+
* - Starts insertion mode at current mouse position
|
|
165
|
+
* - Shows restriction visualization
|
|
166
|
+
*
|
|
167
|
+
* ### Delete Key (typically Delete/Backspace):
|
|
168
|
+
* - Removes currently selected points from drawing
|
|
169
|
+
*
|
|
170
|
+
* ## Workflow Integration:
|
|
171
|
+
* These keyboard shortcuts provide alternative ways to control the drawing workflow
|
|
172
|
+
* without relying solely on mouse interactions.
|
|
101
173
|
*/
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
//
|
|
105
|
-
if (
|
|
106
|
-
__classPrivateFieldGet(this,
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
174
|
+
onKeyDown() {
|
|
175
|
+
const keys = this.getKeyStates();
|
|
176
|
+
// Handle confirm key
|
|
177
|
+
if (keys.confirm) {
|
|
178
|
+
if (__classPrivateFieldGet(this, _DesktopStrategy_interactionManager, "f").insertionInteractionHandler
|
|
179
|
+
.insertionActive) {
|
|
180
|
+
this.stopInsertion();
|
|
181
|
+
__classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").update();
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
__classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").update();
|
|
185
|
+
}
|
|
111
186
|
}
|
|
112
|
-
//
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
187
|
+
// Handle cancel key
|
|
188
|
+
if (keys.cancel) {
|
|
189
|
+
if (__classPrivateFieldGet(this, _DesktopStrategy_interactionManager, "f").insertionInteractionHandler
|
|
190
|
+
.insertionActive) {
|
|
191
|
+
this.stopInsertion();
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
__classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").cancel();
|
|
195
|
+
}
|
|
118
196
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
197
|
+
// Handle insert key
|
|
198
|
+
if (keys.insert) {
|
|
199
|
+
this.startInsertion();
|
|
200
|
+
}
|
|
201
|
+
// Handle delete key
|
|
202
|
+
if (keys.delete) {
|
|
203
|
+
__classPrivateFieldGet(this, _DesktopStrategy_interactionManager, "f").deleteSelection();
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Handles mouse/pointer movement - Core interaction processing for all movement-based workflows
|
|
208
|
+
*
|
|
209
|
+
* ## Primary Workflows:
|
|
210
|
+
*
|
|
211
|
+
* ### 1. Box Selection Mode (when #isBoxSelecting = true):
|
|
212
|
+
* - Updates selection rectangle bounds
|
|
213
|
+
* - Provides real-time hover feedback for points within selection
|
|
214
|
+
* - Respects modifier keys (Shift=add, Ctrl=remove)
|
|
215
|
+
*
|
|
216
|
+
* ### 2. Insertion Workflows:
|
|
217
|
+
* - **Auto-start**: Automatically begins insertion for empty drawings
|
|
218
|
+
* - **Resume**: Restarts paused insertions when mouse re-enters valid area
|
|
219
|
+
* - **Active insertion**: Updates insertion preview position
|
|
220
|
+
* - **Pause**: Pauses insertion when mouse leaves restricted area
|
|
221
|
+
*
|
|
222
|
+
* ### 3. Point Manipulation:
|
|
223
|
+
* - **Dragging**: Moves selected points when dragging is active
|
|
224
|
+
* - **Hover detection**: Updates hover state for visual feedback
|
|
225
|
+
* - **Mid-point insertion**: Shows preview for inserting points between existing ones
|
|
226
|
+
*
|
|
227
|
+
* ### 4. Visual Feedback:
|
|
228
|
+
* - **Cursor updates**: Changes cursor based on interaction state (grab, pointer, default)
|
|
229
|
+
* - **Material updates**: Updates point colors for hover/selection states
|
|
230
|
+
* - **Text visualization**: Updates position indicator text
|
|
231
|
+
*
|
|
232
|
+
* ## Movement Detection:
|
|
233
|
+
* Uses CLICK_THRESHOLD_SQUARED to distinguish between clicks and drags,
|
|
234
|
+
* preventing accidental dragging on small mouse movements.
|
|
235
|
+
*
|
|
236
|
+
* @param event - Pointer event with current mouse position and modifier keys
|
|
237
|
+
* @param ray - 3D ray for intersection testing and point placement
|
|
238
|
+
*/
|
|
239
|
+
onMove(event, ray) {
|
|
240
|
+
// Track the last move event for modifier key states
|
|
241
|
+
__classPrivateFieldSet(this, _DesktopStrategy_lastMoveEvent, event, "f");
|
|
242
|
+
// Handle box selection movement
|
|
243
|
+
if (__classPrivateFieldGet(this, _DesktopStrategy_isBoxSelecting, "f")) {
|
|
244
|
+
// Pass the current shift/ctrl state to determine selection behavior
|
|
245
|
+
const isAdditive = event.shiftKey;
|
|
246
|
+
const isRemoval = event.ctrlKey;
|
|
247
|
+
__classPrivateFieldGet(this, _DesktopStrategy_selectionBox, "f").onMove(event, isAdditive, isRemoval);
|
|
248
|
+
// Update hover effects for points inside the selection box
|
|
249
|
+
this.updateBoxSelectionHover();
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
let currentRestrictedPoint;
|
|
253
|
+
// Handle automatic start and insertion resume
|
|
254
|
+
currentRestrictedPoint =
|
|
255
|
+
this.handleAutoStart(event) || currentRestrictedPoint;
|
|
256
|
+
currentRestrictedPoint =
|
|
257
|
+
this.handleInsertionResume(event) || currentRestrictedPoint;
|
|
258
|
+
const pointerMoved = this.hasPointerMoved(event);
|
|
125
259
|
__classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").moving = pointerMoved;
|
|
126
260
|
if (pointerMoved) {
|
|
127
261
|
__classPrivateFieldSet(this, _DesktopStrategy_lastEvent, event, "f");
|
|
128
|
-
|
|
129
|
-
* IF WE ARE DRAGGING A POINT
|
|
130
|
-
* MOVE THE SELECTED POINTS
|
|
131
|
-
*/
|
|
262
|
+
// Handle point dragging
|
|
132
263
|
currentRestrictedPoint =
|
|
133
264
|
__classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").moveSelectedPoints(ray) ||
|
|
134
265
|
currentRestrictedPoint;
|
|
135
266
|
}
|
|
267
|
+
// Check point distances and hover state
|
|
136
268
|
const distances = __classPrivateFieldGet(this, _DesktopStrategy_geometryMathManager, "f").checkPointDistances(ray, __classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").positionArray);
|
|
137
269
|
__classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").checkHover(distances, ray);
|
|
138
270
|
if (pointerMoved) {
|
|
139
|
-
|
|
140
|
-
* IF INSERT KEY IS PRESSED
|
|
141
|
-
* ADD POINT AT RAY INTERSECTION IF THERE IS NONE WAS ADDED
|
|
142
|
-
* MOVE LAST ADDED POINT IF THERE IS ONE
|
|
143
|
-
*/
|
|
271
|
+
// Handle insertion movement
|
|
144
272
|
currentRestrictedPoint =
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
* IF INSERT KEY IS NOT PRESSED AND DRAGGING IS NOT ACTIVE
|
|
149
|
-
* CHECK IF THERE IS A LINE CLOSE TO THE RAY AND ADD A MID POINT TO IT
|
|
150
|
-
*/
|
|
151
|
-
if (__classPrivateFieldGet(this, _DesktopStrategy_insertionInteractionHandler, "f").insertionActive === false &&
|
|
152
|
-
__classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").dragging === false &&
|
|
153
|
-
__classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").selectedPointIndices.length === 0) {
|
|
154
|
-
__classPrivateFieldGet(this, _DesktopStrategy_midPointInteractionHandler, "f").onMove(ray, __classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").hoveredPoint);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
if (__classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").dragging) {
|
|
158
|
-
document.body.style.cursor = "grabbing";
|
|
159
|
-
}
|
|
160
|
-
else if (__classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").hoveredPoint !== undefined) {
|
|
161
|
-
document.body.style.cursor = "pointer";
|
|
162
|
-
}
|
|
163
|
-
else {
|
|
164
|
-
document.body.style.cursor = "default";
|
|
273
|
+
this.handleInsertionMove(ray) || currentRestrictedPoint;
|
|
274
|
+
// Handle mid-point insertion
|
|
275
|
+
this.handleMidPointMove(ray);
|
|
165
276
|
}
|
|
166
|
-
//
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
__classPrivateFieldGet(this, _DesktopStrategy_insertionInteractionHandler, "f").pauseInsertion();
|
|
277
|
+
// Update cursor and handle insertion pause
|
|
278
|
+
this.updateCursor();
|
|
279
|
+
this.handleInsertionPause(currentRestrictedPoint);
|
|
170
280
|
__classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").textVisualizationManager.updatePointerPosition(currentRestrictedPoint);
|
|
171
281
|
}
|
|
172
282
|
/**
|
|
173
|
-
*
|
|
283
|
+
* Handles mouse leave/out events - Cleanup and state reset
|
|
284
|
+
*
|
|
285
|
+
* ## Cleanup Operations:
|
|
286
|
+
* - **Restriction visualization**: Hides visual guides for point placement restrictions
|
|
287
|
+
* - **Insertion pause**: Temporarily stops insertion mode (can be resumed on mouse re-enter)
|
|
288
|
+
* - **Hover state**: Clears any hovered point indicators
|
|
289
|
+
* - **General reset**: Calls reset() to clean up interaction state
|
|
290
|
+
*
|
|
291
|
+
* ## Use Cases:
|
|
292
|
+
* - Mouse leaves the drawing area/viewport
|
|
293
|
+
* - Right-click cancellation
|
|
294
|
+
* - Focus loss events
|
|
295
|
+
*
|
|
296
|
+
* This ensures the UI returns to a clean state when interaction is interrupted.
|
|
174
297
|
*/
|
|
175
298
|
onOut() {
|
|
176
299
|
__classPrivateFieldGet(this, _DesktopStrategy_restrictionManager, "f").showRestrictionVisualization = false;
|
|
@@ -178,11 +301,304 @@ class DesktopStrategy {
|
|
|
178
301
|
__classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").onOut();
|
|
179
302
|
this.reset();
|
|
180
303
|
}
|
|
181
|
-
|
|
304
|
+
/**
|
|
305
|
+
* Handles mouse/pointer up events - Finalization of click/drag operations
|
|
306
|
+
*
|
|
307
|
+
* ## Primary Operations:
|
|
308
|
+
*
|
|
309
|
+
* ### Box Selection Completion:
|
|
310
|
+
* When box selection is active (#isBoxSelecting = true):
|
|
311
|
+
* 1. **Finalize selection**: Ends the selection rectangle operation
|
|
312
|
+
* 2. **Process intersections**: Determines which points are within the selection box
|
|
313
|
+
* 3. **Apply selection logic**: Handles modifier keys for add/remove/toggle selection
|
|
314
|
+
* 4. **Visual cleanup**: Updates material indices and resets hover states
|
|
315
|
+
* 5. **State reset**: Clears box selection flags and data
|
|
316
|
+
*
|
|
317
|
+
* ### General Cleanup:
|
|
318
|
+
* For all other operations:
|
|
319
|
+
* - **End dragging**: Stops any active point dragging operations
|
|
320
|
+
* - **Camera unfreeze**: Removes camera movement restrictions
|
|
321
|
+
* - **State reset**: Returns to default interaction state
|
|
322
|
+
*
|
|
323
|
+
* ## Workflow Integration:
|
|
324
|
+
* This method completes the interaction cycle started by onDown(),
|
|
325
|
+
* ensuring proper cleanup and state transitions for all operation types.
|
|
326
|
+
*
|
|
327
|
+
* @param event - Pointer event with final mouse position and modifier key states
|
|
328
|
+
*/
|
|
329
|
+
onUp(event) {
|
|
330
|
+
// Handle box selection completion
|
|
331
|
+
if (__classPrivateFieldGet(this, _DesktopStrategy_isBoxSelecting, "f")) {
|
|
332
|
+
__classPrivateFieldGet(this, _DesktopStrategy_selectionBox, "f").onEnd(event);
|
|
333
|
+
this.handleBoxSelection(event);
|
|
334
|
+
// Clear box hovered points, last move event, and update material indices for all points
|
|
335
|
+
__classPrivateFieldSet(this, _DesktopStrategy_boxHoveredPoints, [], "f");
|
|
336
|
+
__classPrivateFieldGet(this, _DesktopStrategy_instances, "m", _DesktopStrategy_updateAllPointMaterials).call(this);
|
|
337
|
+
__classPrivateFieldSet(this, _DesktopStrategy_lastMoveEvent, undefined, "f");
|
|
338
|
+
__classPrivateFieldSet(this, _DesktopStrategy_isBoxSelecting, false, "f");
|
|
339
|
+
__classPrivateFieldGet(this, _DesktopStrategy_selectionBox, "f").reset();
|
|
340
|
+
}
|
|
182
341
|
__classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").onUp();
|
|
183
342
|
this.reset();
|
|
184
343
|
}
|
|
344
|
+
/**
|
|
345
|
+
* Convert position array to array of vec3 points
|
|
346
|
+
*/
|
|
347
|
+
convertPositionArrayToPoints() {
|
|
348
|
+
if (!__classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").positionArray ||
|
|
349
|
+
__classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").positionArray.length === 0) {
|
|
350
|
+
return [];
|
|
351
|
+
}
|
|
352
|
+
const points = [];
|
|
353
|
+
for (let i = 0; i < __classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").positionArray.length; i += DesktopStrategy.COORDINATE_STEP) {
|
|
354
|
+
points.push(gl_matrix_1.vec3.fromValues(__classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").positionArray[i], __classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").positionArray[i + 1], __classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").positionArray[i + 2]));
|
|
355
|
+
}
|
|
356
|
+
return points;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Get the current state of control keys
|
|
360
|
+
*/
|
|
361
|
+
getKeyStates() {
|
|
362
|
+
return {
|
|
363
|
+
insert: __classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").keyPressed(__classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").settings.controls.insert),
|
|
364
|
+
cancel: __classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").keyPressed(__classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").settings.controls.cancel),
|
|
365
|
+
confirm: __classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").keyPressed(__classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").settings.controls.confirm),
|
|
366
|
+
delete: __classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").keyPressed(__classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").settings.controls.delete),
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Enables automatic insertion start for empty drawings to improve user experience
|
|
371
|
+
*
|
|
372
|
+
* ## Auto-start Conditions:
|
|
373
|
+
* 1. **Setting enabled**: `autoStart` setting must be enabled
|
|
374
|
+
* 2. **No active insertion**: Insertion mode is not currently active
|
|
375
|
+
* 3. **Empty drawing**: No points exist in the current drawing
|
|
376
|
+
*
|
|
377
|
+
* ## Workflow Benefits:
|
|
378
|
+
* - Eliminates need to press insert key for first point
|
|
379
|
+
* - Creates smoother initial user experience
|
|
380
|
+
* - Reduces friction for starting new drawings
|
|
381
|
+
*
|
|
382
|
+
* @param event - Pointer event to cache for insertion start
|
|
383
|
+
* @returns Restricted point position if insertion started, undefined otherwise
|
|
384
|
+
*/
|
|
385
|
+
handleAutoStart(event) {
|
|
386
|
+
if (__classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").settings.general.autoStart &&
|
|
387
|
+
__classPrivateFieldGet(this, _DesktopStrategy_insertionInteractionHandler, "f").insertionActive === false &&
|
|
388
|
+
__classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").getPointsData().length === 0) {
|
|
389
|
+
__classPrivateFieldSet(this, _DesktopStrategy_lastEvent, event, "f");
|
|
390
|
+
return this.startInsertion();
|
|
391
|
+
}
|
|
392
|
+
return undefined;
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Processes box selection completion and applies selection logic based on modifier keys
|
|
396
|
+
*
|
|
397
|
+
* ## Selection Logic Workflow:
|
|
398
|
+
* 1. **Point conversion**: Converts position array to 3D points for intersection testing
|
|
399
|
+
* 2. **Intersection calculation**: Determines which points are within the selection box
|
|
400
|
+
* 3. **Modifier key handling**:
|
|
401
|
+
* - **Shift**: Additive selection (adds points to existing selection)
|
|
402
|
+
* - **Ctrl**: Removal selection (removes points from existing selection)
|
|
403
|
+
* - **None**: Toggle selection (default behavior - toggles each point's selection state)
|
|
404
|
+
*
|
|
405
|
+
* ## Integration with Selection System:
|
|
406
|
+
* - Uses InteractionManagerHelper methods for consistent selection behavior
|
|
407
|
+
* - Maintains selection state across different interaction modes
|
|
408
|
+
* - Respects existing selection when using modifier keys
|
|
409
|
+
*
|
|
410
|
+
* @param event - Optional pointer event for modifier key state (fallback to last move event)
|
|
411
|
+
*/
|
|
412
|
+
handleBoxSelection(event) {
|
|
413
|
+
const points = this.convertPositionArrayToPoints();
|
|
414
|
+
if (points.length === 0) {
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
// Get intersected point indices
|
|
418
|
+
const intersectedIndices = __classPrivateFieldGet(this, _DesktopStrategy_selectionBox, "f").intersectPoints(points);
|
|
419
|
+
// Use the last move event for modifier key state, fallback to provided event
|
|
420
|
+
const currentEvent = __classPrivateFieldGet(this, _DesktopStrategy_lastMoveEvent, "f") || event;
|
|
421
|
+
// Handle selection based on modifier keys from the last move event
|
|
422
|
+
if (currentEvent === null || currentEvent === void 0 ? void 0 : currentEvent.shiftKey) {
|
|
423
|
+
// Shift key: add to selection
|
|
424
|
+
intersectedIndices.forEach((index) => {
|
|
425
|
+
__classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").selectPoint([
|
|
426
|
+
{ index, distance: 0 },
|
|
427
|
+
]);
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
else if (currentEvent === null || currentEvent === void 0 ? void 0 : currentEvent.ctrlKey) {
|
|
431
|
+
// Ctrl key: remove from selection
|
|
432
|
+
intersectedIndices.forEach((index) => {
|
|
433
|
+
__classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").deselectPoint(index);
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
else {
|
|
437
|
+
// No modifier key: replace selection (default behavior)
|
|
438
|
+
intersectedIndices.forEach((index) => {
|
|
439
|
+
__classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").toggleSelection(index);
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Initiates box selection mode when Alt key is pressed during mouse down
|
|
445
|
+
*
|
|
446
|
+
* ## Workflow:
|
|
447
|
+
* 1. **Validation**: Checks if Alt key is pressed
|
|
448
|
+
* 2. **State setup**: Sets box selection flag and initializes selection box
|
|
449
|
+
* 3. **Camera control**: Freezes camera to prevent viewport movement during selection
|
|
450
|
+
* 4. **Event binding**: Connects selection box to camera projection for accurate 3D selection
|
|
451
|
+
*
|
|
452
|
+
* ## Visual Feedback:
|
|
453
|
+
* - Selection rectangle appears on screen
|
|
454
|
+
* - Camera movement is disabled
|
|
455
|
+
* - Cursor indicates selection mode
|
|
456
|
+
*
|
|
457
|
+
* @param event - Pointer event to check for Alt key modifier
|
|
458
|
+
* @returns true if box selection was initiated, false otherwise
|
|
459
|
+
*/
|
|
460
|
+
handleBoxSelectionStart(event) {
|
|
461
|
+
if (!event.altKey)
|
|
462
|
+
return false;
|
|
463
|
+
__classPrivateFieldSet(this, _DesktopStrategy_isBoxSelecting, true, "f");
|
|
464
|
+
if (__classPrivateFieldGet(this, _DesktopStrategy_viewport, "f").camera) {
|
|
465
|
+
__classPrivateFieldGet(this, _DesktopStrategy_selectionBox, "f").onDown(event, __classPrivateFieldGet(this, _DesktopStrategy_viewport, "f").camera.project.bind(__classPrivateFieldGet(this, _DesktopStrategy_viewport, "f").camera));
|
|
466
|
+
}
|
|
467
|
+
if (!__classPrivateFieldGet(this, _DesktopStrategy_cameraFreezeFlag, "f")) {
|
|
468
|
+
__classPrivateFieldSet(this, _DesktopStrategy_cameraFreezeFlag, __classPrivateFieldGet(this, _DesktopStrategy_viewport, "f").addFlag(viewer_shared_types_1.FLAG_TYPE.CAMERA_FREEZE), "f");
|
|
469
|
+
}
|
|
470
|
+
return true;
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Manages the insertion workflow when insertion mode is already active
|
|
474
|
+
*
|
|
475
|
+
* ## Insertion Finalization Workflow:
|
|
476
|
+
* 1. **Completion attempt**: Tries to finalize the current insertion point
|
|
477
|
+
* 2. **Success path**: If successful, updates the drawing and exits
|
|
478
|
+
* 3. **Continuation path**: If not finalized, starts a new insertion at click location
|
|
479
|
+
* 4. **Hover management**: Updates hover state after point distance calculations
|
|
480
|
+
*
|
|
481
|
+
* ## Use Cases:
|
|
482
|
+
* - User clicks while in insertion mode to place a point
|
|
483
|
+
* - Handles both successful point placement and insertion continuation
|
|
484
|
+
* - Maintains smooth insertion workflow for multiple point placement
|
|
485
|
+
*
|
|
486
|
+
* @param event - Pointer event for the new insertion location
|
|
487
|
+
* @param ray - 3D ray for intersection testing and point placement
|
|
488
|
+
* @returns true if insertion was processed, false if insertion mode is not active
|
|
489
|
+
*/
|
|
490
|
+
handleInsertionFinalization(event, ray) {
|
|
491
|
+
if (!__classPrivateFieldGet(this, _DesktopStrategy_insertionInteractionHandler, "f").insertionActive)
|
|
492
|
+
return false;
|
|
493
|
+
const result = __classPrivateFieldGet(this, _DesktopStrategy_insertionInteractionHandler, "f").finalizeInsertion();
|
|
494
|
+
const distances = __classPrivateFieldGet(this, _DesktopStrategy_geometryMathManager, "f").checkPointDistances(ray, __classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").positionArray);
|
|
495
|
+
__classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").checkHover(distances, ray);
|
|
496
|
+
if (result) {
|
|
497
|
+
__classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").update();
|
|
498
|
+
return true;
|
|
499
|
+
}
|
|
500
|
+
else {
|
|
501
|
+
__classPrivateFieldGet(this, _DesktopStrategy_insertionInteractionHandler, "f").startInsertion(event);
|
|
502
|
+
return true;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Handle mouse move during insertion mode
|
|
507
|
+
*/
|
|
508
|
+
handleInsertionMove(ray) {
|
|
509
|
+
return __classPrivateFieldGet(this, _DesktopStrategy_insertionInteractionHandler, "f").onMove(ray);
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* Handle insertion pause when point is not restricted
|
|
513
|
+
*/
|
|
514
|
+
handleInsertionPause(currentRestrictedPoint) {
|
|
515
|
+
if (!currentRestrictedPoint &&
|
|
516
|
+
__classPrivateFieldGet(this, _DesktopStrategy_insertionInteractionHandler, "f").insertionActive) {
|
|
517
|
+
__classPrivateFieldGet(this, _DesktopStrategy_insertionInteractionHandler, "f").pauseInsertion();
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Handle resuming paused insertion
|
|
522
|
+
*/
|
|
523
|
+
handleInsertionResume(event) {
|
|
524
|
+
if (__classPrivateFieldGet(this, _DesktopStrategy_insertionInteractionHandler, "f").insertionPaused) {
|
|
525
|
+
__classPrivateFieldSet(this, _DesktopStrategy_lastEvent, event, "f");
|
|
526
|
+
return this.startInsertion();
|
|
527
|
+
}
|
|
528
|
+
return undefined;
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Handle mid-point insertion completion
|
|
532
|
+
*/
|
|
533
|
+
handleMidPointInsertion(distances) {
|
|
534
|
+
if (__classPrivateFieldGet(this, _DesktopStrategy_midPointInteractionHandler, "f").midPointInsertionActive &&
|
|
535
|
+
distances) {
|
|
536
|
+
__classPrivateFieldGet(this, _DesktopStrategy_midPointInteractionHandler, "f").finishMidPointInsertion(distances);
|
|
537
|
+
__classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").midPointInserted = true;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Handle mid-point insertion logic during movement
|
|
542
|
+
*/
|
|
543
|
+
handleMidPointMove(ray) {
|
|
544
|
+
if (__classPrivateFieldGet(this, _DesktopStrategy_insertionInteractionHandler, "f").insertionActive === false &&
|
|
545
|
+
__classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").dragging === false &&
|
|
546
|
+
__classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").selectedPointIndices.length === 0) {
|
|
547
|
+
__classPrivateFieldGet(this, _DesktopStrategy_midPointInteractionHandler, "f").onMove(ray, __classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").hoveredPoint);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Handle point selection and dragging initiation
|
|
552
|
+
*/
|
|
553
|
+
handlePointSelection(distances) {
|
|
554
|
+
if (!distances)
|
|
555
|
+
return;
|
|
556
|
+
__classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").selectPoint(distances);
|
|
557
|
+
const draggingStarted = __classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").startDragging();
|
|
558
|
+
if (draggingStarted && !__classPrivateFieldGet(this, _DesktopStrategy_cameraFreezeFlag, "f")) {
|
|
559
|
+
__classPrivateFieldSet(this, _DesktopStrategy_cameraFreezeFlag, __classPrivateFieldGet(this, _DesktopStrategy_viewport, "f").addFlag(viewer_shared_types_1.FLAG_TYPE.CAMERA_FREEZE), "f");
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* Check if pointer has moved beyond the click threshold
|
|
564
|
+
*/
|
|
565
|
+
hasPointerMoved(event) {
|
|
566
|
+
const distanceSquared = __classPrivateFieldGet(this, _DesktopStrategy_onDownPointer, "f")
|
|
567
|
+
? Math.pow(event.clientX - __classPrivateFieldGet(this, _DesktopStrategy_onDownPointer, "f").clientX, 2) +
|
|
568
|
+
Math.pow(event.clientY - __classPrivateFieldGet(this, _DesktopStrategy_onDownPointer, "f").clientY, 2)
|
|
569
|
+
: Infinity;
|
|
570
|
+
return distanceSquared > DesktopStrategy.CLICK_THRESHOLD_SQUARED;
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Comprehensive state reset for interaction cleanup
|
|
574
|
+
*
|
|
575
|
+
* ## Reset Workflow:
|
|
576
|
+
* ```
|
|
577
|
+
* Box Selection Reset → Insertion State Check → Camera Unfreeze → Helper Reset
|
|
578
|
+
* ↓ ↓ ↓ ↓
|
|
579
|
+
* Clear box flags Check if insertion Remove freeze Reset selection
|
|
580
|
+
* Reset hover states is still active flag if safe and drag states
|
|
581
|
+
* Clear tracking Keep freeze if Restore camera Clean temp data
|
|
582
|
+
* ```
|
|
583
|
+
*
|
|
584
|
+
* ## Safety Measures:
|
|
585
|
+
* - Only unfreezes camera if insertion is not active
|
|
586
|
+
* - Properly cleans up visual states for all tracked points
|
|
587
|
+
* - Ensures no orphaned state remains after interactions
|
|
588
|
+
*/
|
|
185
589
|
reset() {
|
|
590
|
+
// Reset box selection if active
|
|
591
|
+
if (__classPrivateFieldGet(this, _DesktopStrategy_isBoxSelecting, "f")) {
|
|
592
|
+
__classPrivateFieldSet(this, _DesktopStrategy_isBoxSelecting, false, "f");
|
|
593
|
+
__classPrivateFieldGet(this, _DesktopStrategy_selectionBox, "f").reset();
|
|
594
|
+
__classPrivateFieldSet(this, _DesktopStrategy_lastMoveEvent, undefined, "f");
|
|
595
|
+
// Clear hover effects from box hovered points
|
|
596
|
+
__classPrivateFieldGet(this, _DesktopStrategy_boxHoveredPoints, "f").forEach((index) => {
|
|
597
|
+
const isSelected = __classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").selectedPointIndices.includes(index);
|
|
598
|
+
this.updatePointMaterial(index, isSelected, false);
|
|
599
|
+
});
|
|
600
|
+
__classPrivateFieldSet(this, _DesktopStrategy_boxHoveredPoints, [], "f");
|
|
601
|
+
}
|
|
186
602
|
if (__classPrivateFieldGet(this, _DesktopStrategy_insertionInteractionHandler, "f").insertionActive === false) {
|
|
187
603
|
__classPrivateFieldGet(this, _DesktopStrategy_restrictionManager, "f").showRestrictionVisualization = false;
|
|
188
604
|
__classPrivateFieldGet(this, _DesktopStrategy_viewport, "f").removeFlag(__classPrivateFieldGet(this, _DesktopStrategy_cameraFreezeFlag, "f"));
|
|
@@ -190,67 +606,135 @@ class DesktopStrategy {
|
|
|
190
606
|
}
|
|
191
607
|
__classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").reset();
|
|
192
608
|
}
|
|
609
|
+
/**
|
|
610
|
+
* Initiates insertion mode with proper state setup
|
|
611
|
+
*
|
|
612
|
+
* ## Insertion Start Workflow:
|
|
613
|
+
* ```
|
|
614
|
+
* Enable Restrictions → Stop Mid-point → Start Insertion → Return Position
|
|
615
|
+
* ↓ ↓ ↓ ↓
|
|
616
|
+
* Show visual Clear any existing Begin insertion Validate and
|
|
617
|
+
* guides for mid-point preview at cached event return position
|
|
618
|
+
* valid placement operations location or undefined
|
|
619
|
+
* ```
|
|
620
|
+
*
|
|
621
|
+
* @returns Restricted point position if insertion started successfully, undefined if restricted
|
|
622
|
+
*/
|
|
193
623
|
startInsertion() {
|
|
194
624
|
__classPrivateFieldGet(this, _DesktopStrategy_restrictionManager, "f").showRestrictionVisualization = true;
|
|
195
625
|
__classPrivateFieldGet(this, _DesktopStrategy_midPointInteractionHandler, "f").stopMidPointInsertion();
|
|
196
626
|
return __classPrivateFieldGet(this, _DesktopStrategy_insertionInteractionHandler, "f").startInsertion(__classPrivateFieldGet(this, _DesktopStrategy_lastEvent, "f"));
|
|
197
627
|
}
|
|
628
|
+
/**
|
|
629
|
+
* Cleanly exits insertion mode with proper cleanup
|
|
630
|
+
*
|
|
631
|
+
* ## Insertion Stop Workflow:
|
|
632
|
+
* ```
|
|
633
|
+
* Hide Restrictions → Stop Insertion → Unfreeze Camera → Clear Flags
|
|
634
|
+
* ↓ ↓ ↓ ↓
|
|
635
|
+
* Remove visual End insertion Restore camera Reset freeze
|
|
636
|
+
* guides and handler state movement flag state
|
|
637
|
+
* feedback capability
|
|
638
|
+
* ```
|
|
639
|
+
*/
|
|
198
640
|
stopInsertion() {
|
|
199
641
|
__classPrivateFieldGet(this, _DesktopStrategy_restrictionManager, "f").showRestrictionVisualization = false;
|
|
200
642
|
__classPrivateFieldGet(this, _DesktopStrategy_insertionInteractionHandler, "f").stopInsertion();
|
|
201
643
|
__classPrivateFieldGet(this, _DesktopStrategy_viewport, "f").removeFlag(__classPrivateFieldGet(this, _DesktopStrategy_cameraFreezeFlag, "f"));
|
|
202
644
|
__classPrivateFieldSet(this, _DesktopStrategy_cameraFreezeFlag, "", "f");
|
|
203
645
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
646
|
+
/**
|
|
647
|
+
* Provides real-time visual feedback during box selection by updating hover states
|
|
648
|
+
*
|
|
649
|
+
* ## Dynamic Hover Management:
|
|
650
|
+
* 1. **Current intersection**: Calculates which points are currently in the selection box
|
|
651
|
+
* 2. **Hover removal**: Points that left the box lose their hover effect
|
|
652
|
+
* 3. **Hover addition**: Points that entered the box gain hover effect
|
|
653
|
+
* 4. **State preservation**: Maintains existing selection states while adding hover effects
|
|
654
|
+
*
|
|
655
|
+
* ## Visual Feedback:
|
|
656
|
+
* - Points inside selection box show hover material (different color/highlight)
|
|
657
|
+
* - Selected + hovered points show combined visual state
|
|
658
|
+
* - Provides immediate feedback during box drag operation
|
|
659
|
+
*
|
|
660
|
+
* ## Performance Optimization:
|
|
661
|
+
* - Only updates materials for points that changed state
|
|
662
|
+
* - Tracks previous hover state to minimize unnecessary updates
|
|
663
|
+
*/
|
|
664
|
+
updateBoxSelectionHover() {
|
|
665
|
+
const points = this.convertPositionArrayToPoints();
|
|
666
|
+
if (points.length === 0) {
|
|
667
|
+
return;
|
|
223
668
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
669
|
+
// Get current intersected point indices
|
|
670
|
+
const currentBoxIntersectedIndices = __classPrivateFieldGet(this, _DesktopStrategy_selectionBox, "f").intersectPoints(points);
|
|
671
|
+
// Find points that were previously hovered but are no longer in the box
|
|
672
|
+
const pointsToUnhover = __classPrivateFieldGet(this, _DesktopStrategy_boxHoveredPoints, "f").filter((index) => !currentBoxIntersectedIndices.includes(index));
|
|
673
|
+
// Find points that are newly in the box
|
|
674
|
+
const pointsToHover = currentBoxIntersectedIndices.filter((index) => !__classPrivateFieldGet(this, _DesktopStrategy_boxHoveredPoints, "f").includes(index));
|
|
675
|
+
// Remove hover effect from points no longer in the box
|
|
676
|
+
pointsToUnhover.forEach((index) => {
|
|
677
|
+
const isSelected = __classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").selectedPointIndices.includes(index);
|
|
678
|
+
this.updatePointMaterial(index, isSelected, false);
|
|
679
|
+
});
|
|
680
|
+
// Add hover effect to points newly in the box
|
|
681
|
+
pointsToHover.forEach((index) => {
|
|
682
|
+
const isSelected = __classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").selectedPointIndices.includes(index);
|
|
683
|
+
this.updatePointMaterial(index, isSelected, true);
|
|
684
|
+
});
|
|
685
|
+
// Update the tracked hovered points
|
|
686
|
+
__classPrivateFieldSet(this, _DesktopStrategy_boxHoveredPoints, currentBoxIntersectedIndices, "f");
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Update cursor based on current interaction state
|
|
690
|
+
*/
|
|
691
|
+
updateCursor() {
|
|
692
|
+
if (__classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").dragging) {
|
|
693
|
+
document.body.style.cursor = "grabbing";
|
|
237
694
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
* - START INSERTION
|
|
241
|
-
*/
|
|
242
|
-
if (insertKeyPressed) {
|
|
243
|
-
this.startInsertion();
|
|
695
|
+
else if (__classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").hoveredPoint !== undefined) {
|
|
696
|
+
document.body.style.cursor = "pointer";
|
|
244
697
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
* - DELETE SELECTION
|
|
248
|
-
*/
|
|
249
|
-
if (deleteKeyPressed) {
|
|
250
|
-
__classPrivateFieldGet(this, _DesktopStrategy_interactionManager, "f").deleteSelection();
|
|
698
|
+
else {
|
|
699
|
+
document.body.style.cursor = "default";
|
|
251
700
|
}
|
|
252
701
|
}
|
|
702
|
+
/**
|
|
703
|
+
* Update material index for a single point based on its state
|
|
704
|
+
*/
|
|
705
|
+
updatePointMaterial(index, isSelected, isHovered) {
|
|
706
|
+
let materialIndex;
|
|
707
|
+
if (isSelected && isHovered) {
|
|
708
|
+
materialIndex = IDrawingToolsManager_1.MATERIAL_INDEX.SELECTED_HOVERED;
|
|
709
|
+
}
|
|
710
|
+
else if (isSelected) {
|
|
711
|
+
materialIndex = IDrawingToolsManager_1.MATERIAL_INDEX.SELECTED;
|
|
712
|
+
}
|
|
713
|
+
else if (isHovered) {
|
|
714
|
+
materialIndex = IDrawingToolsManager_1.MATERIAL_INDEX.HOVERED;
|
|
715
|
+
}
|
|
716
|
+
else {
|
|
717
|
+
materialIndex = IDrawingToolsManager_1.MATERIAL_INDEX.DEFAULT;
|
|
718
|
+
}
|
|
719
|
+
__classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").updateMaterialIndex(index, materialIndex);
|
|
720
|
+
}
|
|
253
721
|
}
|
|
254
722
|
exports.DesktopStrategy = DesktopStrategy;
|
|
255
|
-
_DesktopStrategy_drawingToolsManager = new WeakMap(), _DesktopStrategy_geometryMathManager = new WeakMap(), _DesktopStrategy_insertionInteractionHandler = new WeakMap(), _DesktopStrategy_interactionManager = new WeakMap(), _DesktopStrategy_interactionManagerHelper = new WeakMap(), _DesktopStrategy_midPointInteractionHandler = new WeakMap(), _DesktopStrategy_restrictionManager = new WeakMap(), _DesktopStrategy_viewport = new WeakMap(), _DesktopStrategy_cameraFreezeFlag = new WeakMap(), _DesktopStrategy_lastEvent = new WeakMap(), _DesktopStrategy_onDownPointer = new WeakMap()
|
|
723
|
+
_DesktopStrategy_drawingToolsManager = new WeakMap(), _DesktopStrategy_geometryMathManager = new WeakMap(), _DesktopStrategy_insertionInteractionHandler = new WeakMap(), _DesktopStrategy_interactionManager = new WeakMap(), _DesktopStrategy_interactionManagerHelper = new WeakMap(), _DesktopStrategy_midPointInteractionHandler = new WeakMap(), _DesktopStrategy_restrictionManager = new WeakMap(), _DesktopStrategy_selectionBox = new WeakMap(), _DesktopStrategy_viewport = new WeakMap(), _DesktopStrategy_boxHoveredPoints = new WeakMap(), _DesktopStrategy_cameraFreezeFlag = new WeakMap(), _DesktopStrategy_isBoxSelecting = new WeakMap(), _DesktopStrategy_lastEvent = new WeakMap(), _DesktopStrategy_lastMoveEvent = new WeakMap(), _DesktopStrategy_onDownPointer = new WeakMap(), _DesktopStrategy_instances = new WeakSet(), _DesktopStrategy_updateAllPointMaterials = function _DesktopStrategy_updateAllPointMaterials() {
|
|
724
|
+
if (!__classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").positionArray ||
|
|
725
|
+
__classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").positionArray.length === 0) {
|
|
726
|
+
return;
|
|
727
|
+
}
|
|
728
|
+
const pointCount = __classPrivateFieldGet(this, _DesktopStrategy_drawingToolsManager, "f").positionArray.length /
|
|
729
|
+
DesktopStrategy.COORDINATE_STEP;
|
|
730
|
+
const selectedIndices = __classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").selectedPointIndices;
|
|
731
|
+
const hoveredPoint = __classPrivateFieldGet(this, _DesktopStrategy_interactionManagerHelper, "f").hoveredPoint;
|
|
732
|
+
for (let i = 0; i < pointCount; i++) {
|
|
733
|
+
const isSelected = selectedIndices.includes(i);
|
|
734
|
+
const isHovered = hoveredPoint === i;
|
|
735
|
+
this.updatePointMaterial(i, isSelected, isHovered);
|
|
736
|
+
}
|
|
737
|
+
};
|
|
738
|
+
DesktopStrategy.CLICK_THRESHOLD_SQUARED = 25; // 5px threshold squared
|
|
739
|
+
DesktopStrategy.COORDINATE_STEP = 3; // Number of coordinates per point (x, y, z)
|
|
256
740
|
//# sourceMappingURL=DesktopStrategy.js.map
|