@itwin/editor-frontend 3.5.0-dev.8 → 3.6.0-dev.3

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 (103) hide show
  1. package/CHANGELOG.md +58 -1
  2. package/lib/cjs/DeleteElementsTool.d.ts +0 -2
  3. package/lib/cjs/DeleteElementsTool.d.ts.map +1 -1
  4. package/lib/cjs/DeleteElementsTool.js +3 -5
  5. package/lib/cjs/DeleteElementsTool.js.map +1 -1
  6. package/lib/cjs/EditTool.d.ts +0 -1
  7. package/lib/cjs/EditTool.d.ts.map +1 -1
  8. package/lib/cjs/EditTool.js +7 -7
  9. package/lib/cjs/EditTool.js.map +1 -1
  10. package/lib/cjs/EditToolIpc.d.ts +18 -0
  11. package/lib/cjs/EditToolIpc.d.ts.map +1 -0
  12. package/lib/cjs/EditToolIpc.js +28 -0
  13. package/lib/cjs/EditToolIpc.js.map +1 -0
  14. package/lib/cjs/ElementGeometryTool.d.ts +2 -3
  15. package/lib/cjs/ElementGeometryTool.d.ts.map +1 -1
  16. package/lib/cjs/ElementGeometryTool.js +8 -10
  17. package/lib/cjs/ElementGeometryTool.js.map +1 -1
  18. package/lib/cjs/ModifyCurveTools.d.ts +64 -43
  19. package/lib/cjs/ModifyCurveTools.d.ts.map +1 -1
  20. package/lib/cjs/ModifyCurveTools.js +318 -202
  21. package/lib/cjs/ModifyCurveTools.js.map +1 -1
  22. package/lib/cjs/ModifyElementTool.d.ts +48 -0
  23. package/lib/cjs/ModifyElementTool.d.ts.map +1 -0
  24. package/lib/cjs/ModifyElementTool.js +178 -0
  25. package/lib/cjs/ModifyElementTool.js.map +1 -0
  26. package/lib/cjs/ProjectLocation/ProjectExtentsDecoration.d.ts +0 -2
  27. package/lib/cjs/ProjectLocation/ProjectExtentsDecoration.d.ts.map +1 -1
  28. package/lib/cjs/ProjectLocation/ProjectExtentsDecoration.js +3 -5
  29. package/lib/cjs/ProjectLocation/ProjectExtentsDecoration.js.map +1 -1
  30. package/lib/cjs/SketchTools.d.ts +2 -4
  31. package/lib/cjs/SketchTools.d.ts.map +1 -1
  32. package/lib/cjs/SketchTools.js +8 -10
  33. package/lib/cjs/SketchTools.js.map +1 -1
  34. package/lib/cjs/SolidModelingTools.d.ts +3 -3
  35. package/lib/cjs/SolidModelingTools.d.ts.map +1 -1
  36. package/lib/cjs/SolidModelingTools.js +30 -29
  37. package/lib/cjs/SolidModelingTools.js.map +1 -1
  38. package/lib/cjs/SolidPrimitiveTools.d.ts +69 -5
  39. package/lib/cjs/SolidPrimitiveTools.d.ts.map +1 -1
  40. package/lib/cjs/SolidPrimitiveTools.js +291 -8
  41. package/lib/cjs/SolidPrimitiveTools.js.map +1 -1
  42. package/lib/cjs/TransformElementsTool.d.ts +3 -5
  43. package/lib/cjs/TransformElementsTool.d.ts.map +1 -1
  44. package/lib/cjs/TransformElementsTool.js +10 -12
  45. package/lib/cjs/TransformElementsTool.js.map +1 -1
  46. package/lib/cjs/UndoRedoTool.js +1 -1
  47. package/lib/cjs/UndoRedoTool.js.map +1 -1
  48. package/lib/cjs/editor-frontend.d.ts +5 -3
  49. package/lib/cjs/editor-frontend.d.ts.map +1 -1
  50. package/lib/cjs/editor-frontend.js +5 -3
  51. package/lib/cjs/editor-frontend.js.map +1 -1
  52. package/lib/esm/DeleteElementsTool.d.ts +0 -2
  53. package/lib/esm/DeleteElementsTool.d.ts.map +1 -1
  54. package/lib/esm/DeleteElementsTool.js +3 -5
  55. package/lib/esm/DeleteElementsTool.js.map +1 -1
  56. package/lib/esm/EditTool.d.ts +0 -1
  57. package/lib/esm/EditTool.d.ts.map +1 -1
  58. package/lib/esm/EditTool.js +8 -8
  59. package/lib/esm/EditTool.js.map +1 -1
  60. package/lib/esm/EditToolIpc.d.ts +18 -0
  61. package/lib/esm/EditToolIpc.d.ts.map +1 -0
  62. package/lib/esm/EditToolIpc.js +24 -0
  63. package/lib/esm/EditToolIpc.js.map +1 -0
  64. package/lib/esm/ElementGeometryTool.d.ts +2 -3
  65. package/lib/esm/ElementGeometryTool.d.ts.map +1 -1
  66. package/lib/esm/ElementGeometryTool.js +8 -10
  67. package/lib/esm/ElementGeometryTool.js.map +1 -1
  68. package/lib/esm/ModifyCurveTools.d.ts +64 -43
  69. package/lib/esm/ModifyCurveTools.d.ts.map +1 -1
  70. package/lib/esm/ModifyCurveTools.js +317 -202
  71. package/lib/esm/ModifyCurveTools.js.map +1 -1
  72. package/lib/esm/ModifyElementTool.d.ts +48 -0
  73. package/lib/esm/ModifyElementTool.d.ts.map +1 -0
  74. package/lib/esm/ModifyElementTool.js +173 -0
  75. package/lib/esm/ModifyElementTool.js.map +1 -0
  76. package/lib/esm/ProjectLocation/ProjectExtentsDecoration.d.ts +0 -2
  77. package/lib/esm/ProjectLocation/ProjectExtentsDecoration.d.ts.map +1 -1
  78. package/lib/esm/ProjectLocation/ProjectExtentsDecoration.js +3 -5
  79. package/lib/esm/ProjectLocation/ProjectExtentsDecoration.js.map +1 -1
  80. package/lib/esm/SketchTools.d.ts +2 -4
  81. package/lib/esm/SketchTools.d.ts.map +1 -1
  82. package/lib/esm/SketchTools.js +8 -10
  83. package/lib/esm/SketchTools.js.map +1 -1
  84. package/lib/esm/SolidModelingTools.d.ts +3 -3
  85. package/lib/esm/SolidModelingTools.d.ts.map +1 -1
  86. package/lib/esm/SolidModelingTools.js +30 -29
  87. package/lib/esm/SolidModelingTools.js.map +1 -1
  88. package/lib/esm/SolidPrimitiveTools.d.ts +69 -5
  89. package/lib/esm/SolidPrimitiveTools.d.ts.map +1 -1
  90. package/lib/esm/SolidPrimitiveTools.js +289 -8
  91. package/lib/esm/SolidPrimitiveTools.js.map +1 -1
  92. package/lib/esm/TransformElementsTool.d.ts +3 -5
  93. package/lib/esm/TransformElementsTool.d.ts.map +1 -1
  94. package/lib/esm/TransformElementsTool.js +10 -12
  95. package/lib/esm/TransformElementsTool.js.map +1 -1
  96. package/lib/esm/UndoRedoTool.js +1 -1
  97. package/lib/esm/UndoRedoTool.js.map +1 -1
  98. package/lib/esm/editor-frontend.d.ts +5 -3
  99. package/lib/esm/editor-frontend.d.ts.map +1 -1
  100. package/lib/esm/editor-frontend.js +5 -3
  101. package/lib/esm/editor-frontend.js.map +1 -1
  102. package/lib/public/locales/en/Editor.json +42 -0
  103. package/package.json +15 -15
@@ -1,18 +1,19 @@
1
1
  "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ExtendCurveTool = exports.BreakCurveTool = exports.OffsetCurveTool = exports.ModifyCurveTool = exports.CurveData = void 0;
4
2
  /*---------------------------------------------------------------------------------------------
5
3
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
6
4
  * See LICENSE.md in the project root for license terms and full copyright notice.
7
5
  *--------------------------------------------------------------------------------------------*/
8
- const core_frontend_1 = require("@itwin/core-frontend");
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.RegionBooleanTool = exports.RegionBooleanMode = exports.ExtendCurveTool = exports.BreakCurveTool = exports.OffsetCurveTool = exports.ModifyCurveTool = exports.CurveData = void 0;
8
+ const appui_abstract_1 = require("@itwin/appui-abstract");
9
+ const core_bentley_1 = require("@itwin/core-bentley");
9
10
  const core_common_1 = require("@itwin/core-common");
10
- const EditTool_1 = require("./EditTool");
11
+ const core_frontend_1 = require("@itwin/core-frontend");
11
12
  const core_geometry_1 = require("@itwin/core-geometry");
12
13
  const editor_common_1 = require("@itwin/editor-common");
13
- const CreateElementTool_1 = require("./CreateElementTool");
14
- const appui_abstract_1 = require("@itwin/appui-abstract");
15
- const core_bentley_1 = require("@itwin/core-bentley");
14
+ const EditTool_1 = require("./EditTool");
15
+ const EditToolIpc_1 = require("./EditToolIpc");
16
+ const ModifyElementTool_1 = require("./ModifyElementTool");
16
17
  /** @alpha */
17
18
  class CurveData {
18
19
  constructor(props, params, geom) {
@@ -22,79 +23,13 @@ class CurveData {
22
23
  }
23
24
  }
24
25
  exports.CurveData = CurveData;
25
- /** @alpha Base class for applying an offset to path and loops. */
26
- class ModifyCurveTool extends core_frontend_1.ElementSetTool {
27
- constructor() {
28
- super(...arguments);
29
- this._checkedIds = new Map();
30
- this._firstResult = true;
31
- }
32
- allowView(_vp) { return true; }
33
- isCompatibleViewport(vp, isSelectedViewChange) { return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && this.allowView(vp)); }
26
+ /** @alpha Base class for modifying all types of curve geometry. */
27
+ class ModifyCurveTool extends ModifyElementTool_1.ModifyElementWithDynamicsTool {
34
28
  async startCommand() {
35
29
  if (undefined !== this._startedCmd)
36
30
  return this._startedCmd;
37
31
  return EditTool_1.EditTools.startCommand(editor_common_1.editorBuiltInCmdIds.cmdBasicManipulation, this.iModel.key);
38
32
  }
39
- static callCommand(method, ...args) {
40
- return EditTool_1.EditTools.callCommand(method, ...args);
41
- }
42
- agendaAppearance(isDynamics) {
43
- if (isDynamics) {
44
- if (undefined === this._agendaAppearanceDynamic)
45
- this._agendaAppearanceDynamic = core_common_1.FeatureAppearance.fromTransparency(0.0);
46
- return this._agendaAppearanceDynamic;
47
- }
48
- if (undefined === this._agendaAppearanceDefault)
49
- this._agendaAppearanceDefault = core_common_1.FeatureAppearance.fromTransparency(0.9);
50
- return this._agendaAppearanceDefault;
51
- }
52
- get wantAgendaAppearanceOverride() { return false; }
53
- addFeatureOverrides(overrides, _vp) {
54
- if (this.agenda.isEmpty)
55
- return;
56
- const appearance = this.agendaAppearance(false);
57
- this.agenda.elements.forEach((elementId) => overrides.override({ elementId, appearance }));
58
- }
59
- updateAgendaAppearanceProvider(drop) {
60
- if (!this.wantAgendaAppearanceOverride)
61
- return;
62
- for (const vp of core_frontend_1.IModelApp.viewManager) {
63
- if (!this.allowView(vp))
64
- continue;
65
- if (drop || this.agenda.isEmpty)
66
- vp.dropFeatureOverrideProvider(this);
67
- else if (!vp.addFeatureOverrideProvider(this))
68
- vp.setFeatureOverrideProviderChanged();
69
- }
70
- }
71
- clearGraphics() {
72
- if (undefined === this._graphicsProvider)
73
- return;
74
- this._graphicsProvider.cleanupGraphic();
75
- this._graphicsProvider = undefined;
76
- }
77
- async createGraphics(ev) {
78
- if (!core_frontend_1.IModelApp.viewManager.inDynamicsMode)
79
- return; // Don't need to create graphic if dynamics aren't yet active...
80
- const geometry = this.getGeometryProps(ev, false);
81
- if (undefined === geometry)
82
- return;
83
- const elemProps = this.getElementProps(ev);
84
- if (undefined === (elemProps === null || elemProps === void 0 ? void 0 : elemProps.placement))
85
- return;
86
- if (undefined === this._graphicsProvider) {
87
- if (this._firstResult) {
88
- this.updateAgendaAppearanceProvider();
89
- this._firstResult = false;
90
- }
91
- this._graphicsProvider = new CreateElementTool_1.DynamicGraphicsProvider(this.iModel, this.toolId);
92
- }
93
- // Set chord tolerance for non-linear curve primitives...
94
- if (ev.viewport)
95
- this._graphicsProvider.chordTolerance = (0, CreateElementTool_1.computeChordToleranceFromPoint)(ev.viewport, ev.point);
96
- await this._graphicsProvider.createGraphic(elemProps.category, elemProps.placement, geometry);
97
- }
98
33
  static isSingleCurve(info) {
99
34
  const it = new core_common_1.ElementGeometry.Iterator(info);
100
35
  it.requestWorldCoordinates();
@@ -112,13 +47,30 @@ class ModifyCurveTool extends core_frontend_1.ElementSetTool {
112
47
  }
113
48
  return;
114
49
  }
50
+ static isInPlane(curve, plane) {
51
+ if ("curvePrimitive" === curve.geometryCategory)
52
+ return curve.isInPlane(plane);
53
+ if (!curve.children)
54
+ return false;
55
+ for (const child of curve.children) {
56
+ if (child instanceof core_geometry_1.CurvePrimitive) {
57
+ if (!child.isInPlane(plane))
58
+ return false;
59
+ }
60
+ else if (child instanceof core_geometry_1.CurveCollection) {
61
+ if (!this.isInPlane(child, plane))
62
+ return false;
63
+ }
64
+ }
65
+ return true;
66
+ }
115
67
  acceptCurve(_curve) { return true; }
116
68
  modifyCurve(_ev, _isAccept) { return undefined; }
117
69
  async getCurveData(id) {
118
70
  try {
119
71
  this._startedCmd = await this.startCommand();
120
72
  const reject = [core_common_1.ElementGeometryOpcode.Polyface, core_common_1.ElementGeometryOpcode.SolidPrimitive, core_common_1.ElementGeometryOpcode.BsplineSurface, core_common_1.ElementGeometryOpcode.BRep];
121
- const info = await ModifyCurveTool.callCommand("requestElementGeometry", id, { maxDisplayable: 1, reject, geometry: { curves: true, surfaces: true, solids: false } });
73
+ const info = await EditToolIpc_1.basicManipulationIpc.requestElementGeometry(id, { maxDisplayable: 1, reject, geometry: { curves: true, surfaces: true, solids: false } });
122
74
  if (undefined === info)
123
75
  return undefined;
124
76
  const data = ModifyCurveTool.isSingleCurve(info);
@@ -136,23 +88,8 @@ class ModifyCurveTool extends core_frontend_1.ElementSetTool {
136
88
  return undefined;
137
89
  }
138
90
  }
139
- onGeometryFilterChanged() { this._checkedIds.clear(); }
140
- async acceptElementForOperation(id) {
141
- if (core_bentley_1.Id64.isInvalid(id) || core_bentley_1.Id64.isTransient(id))
142
- return false;
143
- let accept = this._checkedIds.get(id);
144
- if (undefined === accept) {
145
- if (this.agenda.isEmpty && this._checkedIds.size > 1000)
146
- this._checkedIds.clear(); // Limit auto-locate cache size to something reasonable...
147
- accept = (undefined !== await this.getCurveData(id));
148
- this._checkedIds.set(id, accept);
149
- }
150
- return accept;
151
- }
152
- async isElementValidForOperation(hit, out) {
153
- if (!await super.isElementValidForOperation(hit, out))
154
- return false;
155
- return this.acceptElementForOperation(hit.sourceId);
91
+ async doAcceptElementForOperation(id) {
92
+ return (undefined !== await this.getCurveData(id));
156
93
  }
157
94
  async onAgendaModified() {
158
95
  this.curveData = undefined;
@@ -161,33 +98,22 @@ class ModifyCurveTool extends core_frontend_1.ElementSetTool {
161
98
  const id = this.agenda.elements[this.agenda.length - 1];
162
99
  this.curveData = await this.getCurveData(id);
163
100
  }
164
- onDynamicFrame(_ev, context) {
165
- if (undefined !== this._graphicsProvider)
166
- this._graphicsProvider.addGraphic(context);
167
- }
168
- async onMouseMotion(ev) {
169
- return this.createGraphics(ev);
170
- }
171
101
  setupAccuDraw() {
172
102
  const hints = new core_frontend_1.AccuDrawHintBuilder();
173
103
  hints.enableSmartRotation = true;
174
104
  hints.sendHints(false);
175
105
  }
176
- setupAndPromptForNextAction() {
177
- this.setupAccuDraw();
178
- super.setupAndPromptForNextAction();
179
- }
180
106
  getGeometryProps(ev, isAccept) {
181
107
  if (undefined === this.curveData)
182
108
  return;
183
- const offset = this.modifyCurve(ev, isAccept);
184
- if (undefined === offset)
109
+ const geom = this.modifyCurve(ev, isAccept);
110
+ if (undefined === geom)
185
111
  return;
186
112
  const builder = new core_common_1.ElementGeometry.Builder();
187
113
  builder.setLocalToWorldFromPlacement(this.curveData.props.placement);
188
114
  if (!builder.appendGeometryParamsChange(this.curveData.params))
189
115
  return;
190
- if (!builder.appendGeometryQuery(offset))
116
+ if (!builder.appendGeometryQuery(geom))
191
117
  return;
192
118
  return { format: "flatbuffer", data: builder.entries };
193
119
  }
@@ -202,29 +128,19 @@ class ModifyCurveTool extends core_frontend_1.ElementSetTool {
202
128
  }
203
129
  return this.curveData.props;
204
130
  }
205
- async applyAgendaOperation(ev) {
206
- const geometry = this.getGeometryProps(ev, true);
207
- if (undefined === geometry)
208
- return false;
209
- const elemProps = this.getElementProps(ev);
210
- if (undefined === elemProps)
211
- return false;
212
- if ("flatbuffer" === geometry.format)
213
- elemProps.elementGeometryBuilderParams = { entryArray: geometry.data };
214
- else
215
- elemProps.geom = geometry.data;
131
+ async doUpdateElement(elemProps) {
216
132
  try {
217
133
  this._startedCmd = await this.startCommand();
218
134
  if (undefined === elemProps.id) {
219
135
  const repeatOperation = this.wantContinueWithPreviousResult;
220
136
  if (repeatOperation)
221
137
  this.agenda.clear();
222
- const newId = await ModifyCurveTool.callCommand("insertGeometricElement", elemProps);
138
+ const newId = await EditToolIpc_1.basicManipulationIpc.insertGeometricElement(elemProps);
223
139
  if (repeatOperation && this.agenda.add(newId))
224
140
  await this.onAgendaModified();
225
141
  }
226
142
  else {
227
- await ModifyCurveTool.callCommand("updateGeometricElement", elemProps);
143
+ await EditToolIpc_1.basicManipulationIpc.updateGeometricElement(elemProps);
228
144
  }
229
145
  return true;
230
146
  }
@@ -233,10 +149,6 @@ class ModifyCurveTool extends core_frontend_1.ElementSetTool {
233
149
  return false;
234
150
  }
235
151
  }
236
- async processAgenda(ev) {
237
- if (await this.applyAgendaOperation(ev))
238
- return this.saveChanges();
239
- }
240
152
  get wantModifyOriginal() { return true; }
241
153
  get wantContinueWithPreviousResult() { return false; }
242
154
  async onProcessComplete() {
@@ -245,32 +157,10 @@ class ModifyCurveTool extends core_frontend_1.ElementSetTool {
245
157
  return;
246
158
  return super.onProcessComplete();
247
159
  }
248
- async onUnsuspend() {
249
- if (!this._firstResult)
250
- this.updateAgendaAppearanceProvider();
251
- return super.onUnsuspend();
252
- }
253
- async onSuspend() {
254
- if (!this._firstResult)
255
- this.updateAgendaAppearanceProvider(true);
256
- return super.onSuspend();
257
- }
258
- async onPostInstall() {
259
- await super.onPostInstall();
260
- if (this.wantAgendaAppearanceOverride)
261
- this.agenda.manageHiliteState = false;
262
- }
263
- async onCleanup() {
264
- this.clearGraphics();
265
- this.updateAgendaAppearanceProvider(true);
266
- return super.onCleanup();
267
- }
268
160
  }
269
161
  exports.ModifyCurveTool = ModifyCurveTool;
270
162
  /** @alpha Tool for applying an offset to paths and loops. */
271
163
  class OffsetCurveTool extends ModifyCurveTool {
272
- get wantAccuSnap() { return true; }
273
- get wantDynamics() { return true; }
274
164
  get useDistanceProperty() {
275
165
  if (!this._useDistanceProperty)
276
166
  this._useDistanceProperty = new appui_abstract_1.DialogProperty(appui_abstract_1.PropertyDescriptionHelper.buildLockPropertyDescription("useOffsetDistance"), false);
@@ -311,13 +201,7 @@ class OffsetCurveTool extends ModifyCurveTool {
311
201
  acceptCurve(curve) {
312
202
  if ("curvePrimitive" === curve.geometryCategory)
313
203
  return true;
314
- switch (curve.curveCollectionType) {
315
- case "path":
316
- case "loop":
317
- return true;
318
- default:
319
- return false;
320
- }
204
+ return (curve.isOpenPath || curve.isClosedPath);
321
205
  }
322
206
  modifyCurve(ev, isAccept) {
323
207
  var _a;
@@ -435,18 +319,12 @@ class BreakCurveTool extends ModifyCurveTool {
435
319
  super(...arguments);
436
320
  this.modifyOriginal = true;
437
321
  }
438
- get wantAccuSnap() { return true; }
322
+ get wantDynamics() { return false; }
439
323
  get wantModifyOriginal() { return this.modifyOriginal; }
440
324
  acceptCurve(curve) {
441
325
  if ("curvePrimitive" === curve.geometryCategory)
442
326
  return true;
443
- switch (curve.curveCollectionType) {
444
- case "path":
445
- case "loop":
446
- return true;
447
- default:
448
- return false;
449
- }
327
+ return (curve.isOpenPath || curve.isClosedPath);
450
328
  }
451
329
  doBreakCurve(ev) {
452
330
  var _a;
@@ -563,34 +441,16 @@ class BreakCurveTool extends ModifyCurveTool {
563
441
  exports.BreakCurveTool = BreakCurveTool;
564
442
  BreakCurveTool.toolId = "BreakCurve";
565
443
  BreakCurveTool.iconSpec = "icon-scale"; // Need better icon...
566
- /** @alpha Tool for extending/shortening curves. */
444
+ /** @alpha Tool to extend or trim a path or open curve */
567
445
  class ExtendCurveTool extends ModifyCurveTool {
568
- get wantAccuSnap() { return true; }
569
- get wantDynamics() { return true; }
570
446
  get wantAgendaAppearanceOverride() { return true; }
571
447
  acceptCurve(curve) {
572
- if ("curvePrimitive" !== curve.geometryCategory)
573
- return false;
574
- return curve.isExtensibleFractionSpace;
448
+ if ("curvePrimitive" === curve.geometryCategory)
449
+ return curve.isExtensibleFractionSpace;
450
+ return curve.isOpenPath;
575
451
  }
576
- modifyCurve(ev, _isAccept) {
577
- var _a;
578
- if (undefined === ev.viewport || undefined === this.anchorPoint)
579
- return undefined;
580
- const geom = (_a = this.curveData) === null || _a === void 0 ? void 0 : _a.geom;
581
- if (undefined === geom)
582
- return undefined;
583
- const matrix = core_frontend_1.AccuDrawHintBuilder.getCurrentRotation(ev.viewport, true, true);
584
- const localToWorld = core_geometry_1.FrameBuilder.createRightHandedFrame(matrix === null || matrix === void 0 ? void 0 : matrix.getColumn(2), geom);
585
- if (undefined === localToWorld)
586
- return undefined;
587
- const worldToLocal = localToWorld.inverse();
588
- if (undefined === worldToLocal)
589
- return undefined;
590
- const spacePoint = core_frontend_1.AccuDrawHintBuilder.projectPointToPlaneInView(ev.point, localToWorld.getOrigin(), localToWorld.matrix.getColumn(2), ev.viewport);
591
- if (undefined === spacePoint)
592
- return undefined;
593
- const pickDetail = geom.closestPoint(this.anchorPoint, false);
452
+ extendCurve(geom, pickPoint, spacePoint) {
453
+ const pickDetail = geom.closestPoint(pickPoint, false);
594
454
  if (undefined === (pickDetail === null || pickDetail === void 0 ? void 0 : pickDetail.curve))
595
455
  return undefined;
596
456
  const closeDetail = geom.closestPoint(spacePoint, true);
@@ -613,41 +473,126 @@ class ExtendCurveTool extends ModifyCurveTool {
613
473
  return fullArc;
614
474
  }
615
475
  }
616
- return closeDetail.curve.clonePartialCurve(pickDetail.fraction > 0.5 ? 0.0 : 1.0, closeDetail.fraction);
476
+ return geom.clonePartialCurve(pickDetail.fraction > 0.5 ? 0.0 : 1.0, closeDetail.fraction);
617
477
  }
618
- setupAccuDraw() {
478
+ extendPathEnd(geom, closeDetail, isStart) {
479
+ if (undefined === closeDetail.curve)
480
+ return undefined;
481
+ const curve = closeDetail.curve.clonePartialCurve(isStart ? closeDetail.fraction : 0.0, isStart ? 1.0 : closeDetail.fraction);
482
+ if (undefined === curve)
483
+ return undefined;
484
+ if (curve instanceof core_geometry_1.Arc3d && closeDetail.curve instanceof core_geometry_1.Arc3d && (curve.sweep.isCCW !== closeDetail.curve.sweep.isCCW))
485
+ curve.sweep.cloneComplement(true, curve.sweep); // Preserve current sweep direction...
486
+ const result = geom.clone();
487
+ result.children[isStart ? 0 : geom.children.length - 1] = curve;
488
+ return result;
489
+ }
490
+ extendPath(geom, pickPoint, spacePoint) {
619
491
  var _a;
492
+ if (geom.children.length < 2)
493
+ return this.extendCurve(geom.children[0], pickPoint, spacePoint);
494
+ const pathAsPrimitive = core_geometry_1.CurveChainWithDistanceIndex.createCapture(geom);
495
+ const closeDetail = pathAsPrimitive.closestPoint(spacePoint, true);
496
+ if (undefined === (closeDetail === null || closeDetail === void 0 ? void 0 : closeDetail.curve) || undefined === ((_a = closeDetail.childDetail) === null || _a === void 0 ? void 0 : _a.curve))
497
+ return undefined;
498
+ if (undefined !== this.modifyingEnd) {
499
+ if (closeDetail.childDetail.curve === this.modifyingEnd) {
500
+ this.modifyingEnd = undefined; // Ok to unlock extending first/last curve in path...
501
+ }
502
+ else {
503
+ const pathEndDetail = this.modifyingEnd.closestPoint(spacePoint, true);
504
+ if (undefined === (pathEndDetail === null || pathEndDetail === void 0 ? void 0 : pathEndDetail.curve))
505
+ return undefined;
506
+ return this.extendPathEnd(geom, pathEndDetail, (pathEndDetail.curve === geom.children[0]));
507
+ }
508
+ }
509
+ // NOTE: Special case extend instead of using CurveChainWithDistanceIndex.clonePartialCurve...
510
+ if (closeDetail.fraction < 0.0) {
511
+ this.modifyingEnd = closeDetail.childDetail.curve;
512
+ return this.extendPathEnd(geom, closeDetail.childDetail, true);
513
+ }
514
+ else if (closeDetail.fraction > 1.0) {
515
+ this.modifyingEnd = closeDetail.childDetail.curve;
516
+ return this.extendPathEnd(geom, closeDetail.childDetail, false);
517
+ }
518
+ const pickDetail = pathAsPrimitive.closestPoint(pickPoint, false);
519
+ if (undefined === (pickDetail === null || pickDetail === void 0 ? void 0 : pickDetail.curve))
520
+ return undefined;
521
+ const result = pathAsPrimitive.clonePartialCurve(pickDetail.fraction > 0.5 ? 0.0 : 1.0, closeDetail.fraction);
522
+ if (undefined === result)
523
+ return undefined;
524
+ return core_geometry_1.Path.create(...result.path.children);
525
+ }
526
+ modifyCurve(ev, _isAccept) {
527
+ var _a;
528
+ if (undefined === ev.viewport || undefined === this.anchorPoint)
529
+ return undefined;
530
+ const geom = (_a = this.curveData) === null || _a === void 0 ? void 0 : _a.geom;
531
+ if (undefined === geom)
532
+ return undefined;
533
+ const matrix = core_frontend_1.AccuDrawHintBuilder.getCurrentRotation(ev.viewport, true, true);
534
+ const localToWorld = core_geometry_1.FrameBuilder.createRightHandedFrame(matrix === null || matrix === void 0 ? void 0 : matrix.getColumn(2), geom);
535
+ if (undefined === localToWorld)
536
+ return undefined;
537
+ const worldToLocal = localToWorld.inverse();
538
+ if (undefined === worldToLocal)
539
+ return undefined;
540
+ const spacePoint = core_frontend_1.AccuDrawHintBuilder.projectPointToPlaneInView(ev.point, localToWorld.getOrigin(), localToWorld.matrix.getColumn(2), ev.viewport);
541
+ if (undefined === spacePoint)
542
+ return undefined;
543
+ if (geom instanceof core_geometry_1.CurvePrimitive)
544
+ return this.extendCurve(geom, this.anchorPoint, spacePoint);
545
+ else if (geom instanceof core_geometry_1.Path)
546
+ return this.extendPath(geom, this.anchorPoint, spacePoint);
547
+ return undefined;
548
+ }
549
+ async onAgendaModified() {
550
+ core_frontend_1.IModelApp.accuSnap.neverFlash(this.agenda.elements); // Don't flash snapped segment for better preview when trimming curve/path...
551
+ return super.onAgendaModified();
552
+ }
553
+ setupAccuDraw() {
554
+ var _a, _b, _c;
620
555
  const hints = new core_frontend_1.AccuDrawHintBuilder();
621
556
  if (this.agenda.isEmpty) {
622
557
  hints.enableSmartRotation = true;
623
558
  }
624
559
  else {
625
560
  const geom = (_a = this.curveData) === null || _a === void 0 ? void 0 : _a.geom;
626
- if (undefined === geom || "curvePrimitive" !== geom.geometryCategory)
561
+ if (undefined === geom || undefined === this.anchorPoint)
562
+ return;
563
+ let pickDetail;
564
+ if (geom instanceof core_geometry_1.CurvePrimitive)
565
+ pickDetail = geom.closestPoint(this.anchorPoint, false);
566
+ else if (geom instanceof core_geometry_1.Path)
567
+ pickDetail = core_geometry_1.CurveChainWithDistanceIndex.createCapture(geom).closestPoint(this.anchorPoint, false);
568
+ if (undefined === (pickDetail === null || pickDetail === void 0 ? void 0 : pickDetail.curve))
627
569
  return;
628
- if (geom instanceof core_geometry_1.Arc3d) {
629
- const matrix = geom.matrixClone();
570
+ const curve = (undefined !== ((_b = pickDetail.childDetail) === null || _b === void 0 ? void 0 : _b.curve) ? (_c = pickDetail.childDetail) === null || _c === void 0 ? void 0 : _c.curve : pickDetail.curve);
571
+ if (curve instanceof core_geometry_1.Arc3d) {
572
+ const matrix = curve.matrixClone();
630
573
  matrix.normalizeColumnsInPlace();
631
- hints.setOrigin(geom.center);
574
+ hints.setOrigin(curve.center);
632
575
  hints.setMatrix(matrix);
633
576
  hints.setModePolar();
634
577
  }
635
- else if (geom instanceof core_geometry_1.LineSegment3d) {
636
- const pickDetail = (undefined !== this.anchorPoint ? geom.closestPoint(this.anchorPoint, false) : undefined);
637
- if (undefined !== (pickDetail === null || pickDetail === void 0 ? void 0 : pickDetail.curve)) {
638
- hints.setOrigin(pickDetail.fraction > 0.5 ? geom.point0Ref : geom.point1Ref);
639
- hints.setXAxis(core_geometry_1.Vector3d.createStartEnd(pickDetail.fraction > 0.5 ? geom.point0Ref : geom.point1Ref, pickDetail.fraction > 0.5 ? geom.point1Ref : geom.point0Ref));
640
- }
578
+ else if (curve instanceof core_geometry_1.LineSegment3d) {
579
+ hints.setOrigin(pickDetail.fraction > 0.5 ? curve.point0Ref : curve.point1Ref);
580
+ hints.setXAxis(core_geometry_1.Vector3d.createStartEnd(pickDetail.fraction > 0.5 ? curve.point0Ref : curve.point1Ref, pickDetail.fraction > 0.5 ? curve.point1Ref : curve.point0Ref));
641
581
  hints.setModeRectangular();
642
582
  }
643
- else if (geom instanceof core_geometry_1.LineString3d) {
644
- const pickDetail = (undefined !== this.anchorPoint ? geom.closestPoint(this.anchorPoint, false) : undefined);
645
- if (undefined !== (pickDetail === null || pickDetail === void 0 ? void 0 : pickDetail.curve) && geom.numPoints() > 1) {
646
- hints.setOrigin(geom.packedPoints.getPoint3dAtUncheckedPointIndex(pickDetail.fraction > 0.5 ? geom.numPoints() - 2 : 1));
647
- hints.setXAxis(core_geometry_1.Vector3d.createStartEnd(geom.packedPoints.getPoint3dAtUncheckedPointIndex(pickDetail.fraction > 0.5 ? geom.numPoints() - 2 : 1), geom.packedPoints.getPoint3dAtUncheckedPointIndex(pickDetail.fraction > 0.5 ? geom.numPoints() - 1 : 0)));
583
+ else if (curve instanceof core_geometry_1.LineString3d) {
584
+ if (curve.numPoints() > 1) {
585
+ hints.setOrigin(curve.packedPoints.getPoint3dAtUncheckedPointIndex(pickDetail.fraction > 0.5 ? curve.numPoints() - 2 : 1));
586
+ hints.setXAxis(core_geometry_1.Vector3d.createStartEnd(curve.packedPoints.getPoint3dAtUncheckedPointIndex(pickDetail.fraction > 0.5 ? curve.numPoints() - 2 : 1), curve.packedPoints.getPoint3dAtUncheckedPointIndex(pickDetail.fraction > 0.5 ? curve.numPoints() - 1 : 0)));
648
587
  }
649
588
  hints.setModeRectangular();
650
589
  }
590
+ else {
591
+ const ray = curve.fractionToPointAndUnitTangent(pickDetail.fraction > 0.5 ? 0.0 : 1.0);
592
+ hints.setOrigin(ray.origin);
593
+ hints.setXAxis(ray.direction);
594
+ hints.setModeRectangular();
595
+ }
651
596
  }
652
597
  hints.sendHints(false);
653
598
  }
@@ -666,4 +611,175 @@ class ExtendCurveTool extends ModifyCurveTool {
666
611
  exports.ExtendCurveTool = ExtendCurveTool;
667
612
  ExtendCurveTool.toolId = "ExtendCurve";
668
613
  ExtendCurveTool.iconSpec = "icon-scale"; // Need better icon...
614
+ /** @alpha */
615
+ var RegionBooleanMode;
616
+ (function (RegionBooleanMode) {
617
+ /** Create region from union of all input regions */
618
+ RegionBooleanMode[RegionBooleanMode["Unite"] = 0] = "Unite";
619
+ /** Create region from subtraction from the first input region */
620
+ RegionBooleanMode[RegionBooleanMode["Subtract"] = 1] = "Subtract";
621
+ /** Create region from intersection of all input regions */
622
+ RegionBooleanMode[RegionBooleanMode["Intersect"] = 2] = "Intersect";
623
+ })(RegionBooleanMode = exports.RegionBooleanMode || (exports.RegionBooleanMode = {}));
624
+ /** @alpha Tool to unite, subtract, or intersect planar regions. */
625
+ class RegionBooleanTool extends ModifyCurveTool {
626
+ get makeCopyProperty() {
627
+ if (!this._makeCopyProperty)
628
+ this._makeCopyProperty = new appui_abstract_1.DialogProperty(appui_abstract_1.PropertyDescriptionHelper.buildToggleDescription("regionBooleanKeep", EditTool_1.EditTools.translate("RegionBoolean.Label.KeepOriginal")), false);
629
+ return this._makeCopyProperty;
630
+ }
631
+ get makeCopy() { return this.makeCopyProperty.value; }
632
+ set makeCopy(value) { this.makeCopyProperty.value = value; }
633
+ static modeMessage(str) { return EditTool_1.EditTools.translate(`RegionBoolean.Mode.${str}`); }
634
+ get modeProperty() {
635
+ if (!this._modeProperty)
636
+ this._modeProperty = new appui_abstract_1.DialogProperty(appui_abstract_1.PropertyDescriptionHelper.buildEnumPicklistEditorDescription("regionBooleanMode", EditTool_1.EditTools.translate("RegionBoolean.Label.Mode"), RegionBooleanTool.getModeChoices()), RegionBooleanMode.Unite);
637
+ return this._modeProperty;
638
+ }
639
+ get mode() { return this.modeProperty.value; }
640
+ set mode(mode) { this.modeProperty.value = mode; }
641
+ get clearSelectionSet() { return false; } // Don't clear for subtract so that mode can be changed...
642
+ get allowSelectionSet() { return RegionBooleanMode.Subtract !== this.mode; }
643
+ get allowDragSelect() { return RegionBooleanMode.Subtract !== this.mode; }
644
+ get controlKeyContinuesSelection() { return true; }
645
+ get requiredElementCount() { return 2; }
646
+ get wantAccuSnap() { return false; }
647
+ get wantDynamics() { return false; }
648
+ get wantModifyOriginal() { return !this.makeCopy; }
649
+ async onAgendaModified() { } // No intermediate result preview, defer to processAgenda...
650
+ acceptCurve(curve) {
651
+ if ("curvePrimitive" === curve.geometryCategory)
652
+ return false;
653
+ return curve.isAnyRegionType;
654
+ }
655
+ regionBinaryOp() {
656
+ switch (this.mode) {
657
+ case RegionBooleanMode.Subtract:
658
+ return core_geometry_1.RegionBinaryOpType.AMinusB;
659
+ case RegionBooleanMode.Intersect:
660
+ return core_geometry_1.RegionBinaryOpType.Intersection;
661
+ default:
662
+ return core_geometry_1.RegionBinaryOpType.Union;
663
+ }
664
+ }
665
+ regionFromSignedLoops(loops) {
666
+ switch (loops.negativeAreaLoops.length) {
667
+ case 0:
668
+ return undefined;
669
+ case 1:
670
+ return loops.negativeAreaLoops[0];
671
+ default:
672
+ return core_geometry_1.RegionOps.sortOuterAndHoleLoopsXY(loops.negativeAreaLoops);
673
+ }
674
+ }
675
+ regionBooleanXY(tools, op) {
676
+ if (tools.length < 2)
677
+ return undefined;
678
+ const loopsA = (core_geometry_1.RegionBinaryOpType.Union !== op ? tools[0] : tools);
679
+ const loopsB = (core_geometry_1.RegionBinaryOpType.Union !== op ? tools.slice(1) : undefined);
680
+ // TODO: Need to be able to specify group operation for loopsB to correctly support intersect w/o doing 2 at time...
681
+ const areas = core_geometry_1.RegionOps.regionBooleanXY(loopsA, loopsB, op);
682
+ if (undefined === areas)
683
+ return undefined;
684
+ // TODO: Holes are expected to be returned as negative area loops but currently are not...
685
+ const loops = core_geometry_1.RegionOps.constructAllXYRegionLoops(areas);
686
+ if (1 === loops.length)
687
+ return this.regionFromSignedLoops(loops[0]);
688
+ if (loops.length > 1) {
689
+ const unionRegion = core_geometry_1.UnionRegion.create();
690
+ for (const loop of loops) {
691
+ const child = this.regionFromSignedLoops(loop);
692
+ if (undefined === child)
693
+ continue;
694
+ unionRegion.tryAddChild(child);
695
+ }
696
+ if (unionRegion.children.length > 1)
697
+ return unionRegion;
698
+ }
699
+ return undefined;
700
+ }
701
+ async doRegionBoolean(_ev) {
702
+ this.curveData = undefined;
703
+ if (this.agenda.length < this.requiredElementCount)
704
+ return;
705
+ const targetData = await this.getCurveData(this.agenda.elements[0]);
706
+ if (undefined === (targetData === null || targetData === void 0 ? void 0 : targetData.geom))
707
+ return;
708
+ const targetLocalToWorld = core_geometry_1.FrameBuilder.createRightHandedFrame(undefined, targetData.geom);
709
+ if (undefined === targetLocalToWorld)
710
+ return;
711
+ const targetWorldToLocal = targetLocalToWorld.inverse();
712
+ if (undefined === targetWorldToLocal)
713
+ return;
714
+ const targetPlane = core_geometry_1.Plane3dByOriginAndUnitNormal.create(targetLocalToWorld.getOrigin(), targetLocalToWorld.matrix.getColumn(2));
715
+ if (undefined === targetPlane)
716
+ return;
717
+ if (!targetData.geom.tryTransformInPlace(targetWorldToLocal))
718
+ return;
719
+ const tools = [targetData.geom];
720
+ for (const id of this.agenda.elements) {
721
+ if (id === targetData.props.id)
722
+ continue;
723
+ const curveData = await this.getCurveData(id);
724
+ if (undefined === (curveData === null || curveData === void 0 ? void 0 : curveData.geom))
725
+ return;
726
+ if (!ModifyCurveTool.isInPlane(curveData.geom, targetPlane)) {
727
+ core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Info, EditTool_1.EditTools.translate("RegionBoolean.Error.NonCoplanar")));
728
+ return;
729
+ }
730
+ if (!curveData.geom.tryTransformInPlace(targetWorldToLocal))
731
+ return;
732
+ tools.push(curveData.geom);
733
+ }
734
+ const result = this.regionBooleanXY(tools, this.regionBinaryOp());
735
+ if (undefined === result || !result.tryTransformInPlace(targetLocalToWorld))
736
+ return;
737
+ this.curveData = targetData;
738
+ this.curveData.geom = result;
739
+ }
740
+ modifyCurve(_ev, _isAccept) {
741
+ var _a;
742
+ return (_a = this.curveData) === null || _a === void 0 ? void 0 : _a.geom;
743
+ }
744
+ async applyAgendaOperation(ev) {
745
+ if (!await super.applyAgendaOperation(ev))
746
+ return false;
747
+ if (this.wantModifyOriginal && this.agenda.length > 1)
748
+ await EditToolIpc_1.basicManipulationIpc.deleteElements(core_bentley_1.CompressedId64Set.sortAndCompress(this.agenda.elements.slice(1)));
749
+ return true;
750
+ }
751
+ async processAgenda(ev) {
752
+ await this.doRegionBoolean(ev);
753
+ return super.processAgenda(ev);
754
+ }
755
+ async onRestartTool() {
756
+ const tool = new RegionBooleanTool();
757
+ if (!await tool.run())
758
+ return this.exitTool();
759
+ }
760
+ async applyToolSettingPropertyChange(updatedValue) {
761
+ if (!this.changeToolSettingPropertyValue(updatedValue))
762
+ return false;
763
+ if (this.modeProperty.name === updatedValue.propertyName)
764
+ await this.onReinitialize();
765
+ return true;
766
+ }
767
+ supplyToolSettingsProperties() {
768
+ this.initializeToolSettingPropertyValues([this.makeCopyProperty, this.modeProperty]);
769
+ const toolSettings = new Array();
770
+ toolSettings.push(this.modeProperty.toDialogItem({ rowPriority: 1, columnIndex: 0 }));
771
+ toolSettings.push(this.makeCopyProperty.toDialogItem({ rowPriority: 2, columnIndex: 0 }));
772
+ return toolSettings;
773
+ }
774
+ }
775
+ exports.RegionBooleanTool = RegionBooleanTool;
776
+ RegionBooleanTool.toolId = "RegionBoolean";
777
+ RegionBooleanTool.iconSpec = "icon-scale"; // Need better icon...
778
+ RegionBooleanTool.getModeChoices = () => {
779
+ return [
780
+ { label: RegionBooleanTool.modeMessage("Unite"), value: RegionBooleanMode.Unite },
781
+ { label: RegionBooleanTool.modeMessage("Subtract"), value: RegionBooleanMode.Subtract },
782
+ { label: RegionBooleanTool.modeMessage("Intersect"), value: RegionBooleanMode.Intersect },
783
+ ];
784
+ };
669
785
  //# sourceMappingURL=ModifyCurveTools.js.map