@itwin/editor-frontend 3.0.0-dev.98 → 3.0.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/CHANGELOG.md +108 -1
- package/LICENSE.md +1 -1
- package/README.md +9 -9
- package/lib/cjs/EditTool.d.ts.map +1 -1
- package/lib/cjs/EditTool.js +18 -7
- package/lib/cjs/EditTool.js.map +1 -1
- package/lib/cjs/ElementGeometryTool.d.ts +64 -80
- package/lib/cjs/ElementGeometryTool.d.ts.map +1 -1
- package/lib/cjs/ElementGeometryTool.js +333 -295
- package/lib/cjs/ElementGeometryTool.js.map +1 -1
- package/lib/cjs/ProjectLocation/ProjectGeolocation.d.ts +10 -17
- package/lib/cjs/ProjectLocation/ProjectGeolocation.d.ts.map +1 -1
- package/lib/cjs/ProjectLocation/ProjectGeolocation.js +54 -94
- package/lib/cjs/ProjectLocation/ProjectGeolocation.js.map +1 -1
- package/lib/cjs/SketchTools.d.ts +21 -9
- package/lib/cjs/SketchTools.d.ts.map +1 -1
- package/lib/cjs/SketchTools.js +197 -204
- package/lib/cjs/SketchTools.js.map +1 -1
- package/lib/cjs/SolidModelingTools.d.ts +381 -0
- package/lib/cjs/SolidModelingTools.d.ts.map +1 -0
- package/lib/cjs/SolidModelingTools.js +1460 -0
- package/lib/cjs/SolidModelingTools.js.map +1 -0
- package/lib/cjs/TransformElementsTool.d.ts.map +1 -1
- package/lib/cjs/TransformElementsTool.js +8 -28
- package/lib/cjs/TransformElementsTool.js.map +1 -1
- package/lib/cjs/UndoRedoTool.js +1 -1
- package/lib/cjs/UndoRedoTool.js.map +1 -1
- package/lib/cjs/editor-frontend.d.ts +1 -0
- package/lib/cjs/editor-frontend.d.ts.map +1 -1
- package/lib/cjs/editor-frontend.js +1 -0
- package/lib/cjs/editor-frontend.js.map +1 -1
- package/lib/esm/EditTool.d.ts.map +1 -1
- package/lib/esm/EditTool.js +14 -3
- package/lib/esm/EditTool.js.map +1 -1
- package/lib/esm/ElementGeometryTool.d.ts +64 -80
- package/lib/esm/ElementGeometryTool.d.ts.map +1 -1
- package/lib/esm/ElementGeometryTool.js +334 -290
- package/lib/esm/ElementGeometryTool.js.map +1 -1
- package/lib/esm/ProjectLocation/ProjectGeolocation.d.ts +10 -17
- package/lib/esm/ProjectLocation/ProjectGeolocation.d.ts.map +1 -1
- package/lib/esm/ProjectLocation/ProjectGeolocation.js +54 -94
- package/lib/esm/ProjectLocation/ProjectGeolocation.js.map +1 -1
- package/lib/esm/SketchTools.d.ts +21 -9
- package/lib/esm/SketchTools.d.ts.map +1 -1
- package/lib/esm/SketchTools.js +198 -205
- package/lib/esm/SketchTools.js.map +1 -1
- package/lib/esm/SolidModelingTools.d.ts +381 -0
- package/lib/esm/SolidModelingTools.d.ts.map +1 -0
- package/lib/esm/SolidModelingTools.js +1435 -0
- package/lib/esm/SolidModelingTools.js.map +1 -0
- package/lib/esm/TransformElementsTool.d.ts.map +1 -1
- package/lib/esm/TransformElementsTool.js +8 -28
- package/lib/esm/TransformElementsTool.js.map +1 -1
- package/lib/esm/UndoRedoTool.js +1 -1
- package/lib/esm/UndoRedoTool.js.map +1 -1
- package/lib/esm/editor-frontend.d.ts +1 -0
- package/lib/esm/editor-frontend.d.ts.map +1 -1
- package/lib/esm/editor-frontend.js +1 -0
- package/lib/esm/editor-frontend.js.map +1 -1
- package/lib/public/locales/en/Editor.json +141 -3
- package/package.json +17 -25
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
* @module Editing
|
|
7
7
|
*/
|
|
8
8
|
import { Id64 } from "@itwin/core-bentley";
|
|
9
|
-
import {
|
|
9
|
+
import { BRepEntityType, editorBuiltInCmdIds, SubEntityType } from "@itwin/editor-common";
|
|
10
10
|
import { FeatureAppearance, FeatureAppearanceProvider, RgbColor } from "@itwin/core-common";
|
|
11
|
-
import {
|
|
12
|
-
import { AccuDrawHintBuilder, ElementSetTool, EventHandled, GraphicBranch, GraphicType, IModelApp, InputSource, readElementGraphics } from "@itwin/core-frontend";
|
|
11
|
+
import { Point3d, Range3d, Transform } from "@itwin/core-geometry";
|
|
12
|
+
import { AccuDrawHintBuilder, BeModifierKeys, CoordSource, CoreTools, ElementSetTool, EventHandled, GraphicBranch, GraphicType, IModelApp, InputSource, readElementGraphics, ToolAssistance, ToolAssistanceImage, ToolAssistanceInputMethod } from "@itwin/core-frontend";
|
|
13
13
|
import { computeChordToleranceFromPoint } from "./CreateElementTool";
|
|
14
14
|
import { EditTools } from "./EditTool";
|
|
15
15
|
/** @alpha */
|
|
@@ -62,46 +62,51 @@ export class ElementGeometryGraphicsProvider {
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
/** @alpha */
|
|
65
|
+
export function isSameSubEntity(a, b) {
|
|
66
|
+
if (a.type !== b.type)
|
|
67
|
+
return false;
|
|
68
|
+
if (a.id !== b.id)
|
|
69
|
+
return false;
|
|
70
|
+
if ((undefined !== a.index ? a.index : 0) !== (undefined !== b.index ? b.index : 0))
|
|
71
|
+
return false;
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
/** @alpha */
|
|
65
75
|
export class SubEntityData {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return false;
|
|
73
|
-
if (this.info.id !== other.id)
|
|
74
|
-
return false;
|
|
75
|
-
return true;
|
|
76
|
-
}
|
|
76
|
+
constructor(props) { this._props = props; }
|
|
77
|
+
get props() { return this._props; }
|
|
78
|
+
set props(value) { this.cleanupGraphic(); this._props = value; }
|
|
79
|
+
get geometry() { return this._geometry; }
|
|
80
|
+
set geometry(value) { this._geometry = value; }
|
|
81
|
+
isSame(other) { return isSameSubEntity(this._props, other); }
|
|
77
82
|
getAppearance(vp, accepted) {
|
|
78
|
-
var _a, _b, _c, _d
|
|
83
|
+
var _a, _b, _c, _d;
|
|
79
84
|
const color = vp.hilite.color;
|
|
80
85
|
const rgb = RgbColor.fromColorDef(accepted ? color.inverse() : color);
|
|
81
86
|
const transparency = 0.25;
|
|
82
87
|
const emphasized = true; // Necessary for obscured sub-entities w/SceneGraphic...
|
|
83
88
|
let weight;
|
|
84
|
-
switch (
|
|
89
|
+
switch (this.props.type) {
|
|
85
90
|
case SubEntityType.Face:
|
|
86
91
|
break;
|
|
87
92
|
case SubEntityType.Edge:
|
|
88
|
-
const edgeWeight = accepted ?
|
|
89
|
-
weight = ((
|
|
93
|
+
const edgeWeight = accepted ? 1 : 3;
|
|
94
|
+
weight = ((_b = (_a = this._geometry) === null || _a === void 0 ? void 0 : _a.appearance) === null || _b === void 0 ? void 0 : _b.weight) ? Math.min(this._geometry.appearance.weight + edgeWeight, 31) : edgeWeight;
|
|
90
95
|
break;
|
|
91
96
|
case SubEntityType.Vertex:
|
|
92
|
-
const vertexWeight = accepted ?
|
|
93
|
-
weight = ((
|
|
97
|
+
const vertexWeight = accepted ? 8 : 10;
|
|
98
|
+
weight = ((_d = (_c = this._geometry) === null || _c === void 0 ? void 0 : _c.appearance) === null || _d === void 0 ? void 0 : _d.weight) ? Math.min(this._geometry.appearance.weight + vertexWeight, 31) : vertexWeight;
|
|
94
99
|
break;
|
|
95
100
|
}
|
|
96
101
|
return FeatureAppearance.fromJSON({ rgb, transparency, weight, emphasized, nonLocatable: true });
|
|
97
102
|
}
|
|
98
103
|
async createGraphic(iModel) {
|
|
99
104
|
var _a;
|
|
100
|
-
if (undefined === ((_a = this.
|
|
105
|
+
if (undefined === ((_a = this._geometry) === null || _a === void 0 ? void 0 : _a.graphic))
|
|
101
106
|
return false;
|
|
102
107
|
if (undefined === this._graphicsProvider)
|
|
103
108
|
this._graphicsProvider = new ElementGeometryGraphicsProvider(iModel);
|
|
104
|
-
return this._graphicsProvider.createGraphic(this.
|
|
109
|
+
return this._graphicsProvider.createGraphic(this._geometry.graphic);
|
|
105
110
|
}
|
|
106
111
|
cleanupGraphic() {
|
|
107
112
|
if (undefined === this._graphicsProvider)
|
|
@@ -117,16 +122,15 @@ export class SubEntityData {
|
|
|
117
122
|
var _a, _b;
|
|
118
123
|
if (undefined === ((_a = this._graphicsProvider) === null || _a === void 0 ? void 0 : _a.graphic))
|
|
119
124
|
return;
|
|
120
|
-
const
|
|
121
|
-
return app.extendAppearance(this.getAppearance(context.viewport, accepted));
|
|
122
|
-
});
|
|
123
|
-
const opts = { appearanceProvider };
|
|
124
|
-
const range = (((_b = this.geom) === null || _b === void 0 ? void 0 : _b.range) ? Range3d.fromJSON(this.geom.range) : undefined);
|
|
125
|
+
const range = (((_b = this._geometry) === null || _b === void 0 ? void 0 : _b.range) ? Range3d.fromJSON(this._geometry.range) : undefined);
|
|
125
126
|
const pixelSize = context.viewport.getPixelSizeAtPoint(range ? range.center : undefined);
|
|
126
127
|
const offsetDir = context.viewport.view.getZVector();
|
|
127
128
|
offsetDir.scaleToLength(3 * pixelSize, offsetDir);
|
|
128
129
|
const offsetTrans = Transform.createTranslation(offsetDir);
|
|
129
|
-
|
|
130
|
+
const appearanceProvider = FeatureAppearanceProvider.supplement((app) => {
|
|
131
|
+
return app.extendAppearance(this.getAppearance(context.viewport, accepted));
|
|
132
|
+
});
|
|
133
|
+
this._graphicsProvider.addDecoration(context, GraphicType.Scene, offsetTrans, { appearanceProvider });
|
|
130
134
|
}
|
|
131
135
|
}
|
|
132
136
|
/** @alpha Base class for tools that want to use the backend geometry cache. */
|
|
@@ -146,14 +150,22 @@ export class ElementGeometryCacheTool extends ElementSetTool {
|
|
|
146
150
|
static callCommand(method, ...args) {
|
|
147
151
|
return EditTools.callCommand(method, ...args);
|
|
148
152
|
}
|
|
149
|
-
|
|
150
|
-
|
|
153
|
+
agendaAppearance(isDynamics) {
|
|
154
|
+
if (isDynamics) {
|
|
155
|
+
if (undefined === this._agendaAppearanceDynamic)
|
|
156
|
+
this._agendaAppearanceDynamic = FeatureAppearance.fromTransparency(0.0);
|
|
157
|
+
return this._agendaAppearanceDynamic;
|
|
158
|
+
}
|
|
159
|
+
if (undefined === this._agendaAppearanceDefault)
|
|
160
|
+
this._agendaAppearanceDefault = FeatureAppearance.fromTransparency(0.9);
|
|
161
|
+
return this._agendaAppearanceDefault;
|
|
162
|
+
}
|
|
151
163
|
get wantAgendaAppearanceOverride() { return false; }
|
|
152
164
|
addFeatureOverrides(overrides, _vp) {
|
|
153
165
|
if (this.agenda.isEmpty)
|
|
154
166
|
return;
|
|
155
|
-
const
|
|
156
|
-
this.agenda.elements.forEach((
|
|
167
|
+
const appearance = this.agendaAppearance(false);
|
|
168
|
+
this.agenda.elements.forEach((elementId) => { overrides.override({ elementId, appearance }); });
|
|
157
169
|
}
|
|
158
170
|
updateAgendaAppearanceProvider(drop) {
|
|
159
171
|
if (!this.wantAgendaAppearanceOverride)
|
|
@@ -168,18 +180,25 @@ export class ElementGeometryCacheTool extends ElementSetTool {
|
|
|
168
180
|
}
|
|
169
181
|
}
|
|
170
182
|
get geometryCacheFilter() { return undefined; }
|
|
183
|
+
onGeometryCacheFilterChanged() { this._checkedIds.clear(); }
|
|
184
|
+
async createElementGeometryCache(id) {
|
|
185
|
+
// NOTE: Creates cache if it doesn't already exist then test new or existing cache against filter...
|
|
186
|
+
try {
|
|
187
|
+
this._startedCmd = await this.startCommand();
|
|
188
|
+
return await ElementGeometryCacheTool.callCommand("createElementGeometryCache", id, this.geometryCacheFilter);
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
171
194
|
async acceptElementForOperation(id) {
|
|
172
195
|
if (Id64.isInvalid(id) || Id64.isTransient(id))
|
|
173
196
|
return false;
|
|
174
197
|
let accept = this._checkedIds.get(id);
|
|
175
198
|
if (undefined === accept) {
|
|
176
|
-
|
|
177
|
-
this.
|
|
178
|
-
|
|
179
|
-
}
|
|
180
|
-
catch (err) {
|
|
181
|
-
accept = false;
|
|
182
|
-
}
|
|
199
|
+
if (this.agenda.isEmpty && this._checkedIds.size > 1000)
|
|
200
|
+
this._checkedIds.clear(); // Limit auto-locate cache size to something reasonable...
|
|
201
|
+
accept = await this.createElementGeometryCache(id);
|
|
183
202
|
this._checkedIds.set(id, accept);
|
|
184
203
|
}
|
|
185
204
|
return accept;
|
|
@@ -207,8 +226,14 @@ export class ElementGeometryCacheTool extends ElementSetTool {
|
|
|
207
226
|
return this.postFilterIds(await super.getDragSelectCandidates(vp, origin, corner, method, overlap));
|
|
208
227
|
}
|
|
209
228
|
onDynamicFrame(_ev, context) {
|
|
210
|
-
if (undefined
|
|
211
|
-
|
|
229
|
+
if (undefined === this._graphicsProvider)
|
|
230
|
+
return;
|
|
231
|
+
if (!this.wantAgendaAppearanceOverride)
|
|
232
|
+
return this._graphicsProvider.addGraphic(context);
|
|
233
|
+
const appearanceProvider = FeatureAppearanceProvider.supplement((app) => {
|
|
234
|
+
return app.extendAppearance(this.agendaAppearance(true));
|
|
235
|
+
});
|
|
236
|
+
this._graphicsProvider.addGraphic(context, undefined, { appearanceProvider });
|
|
212
237
|
}
|
|
213
238
|
async onMouseMotion(ev) {
|
|
214
239
|
return this.updateGraphic(ev, IModelApp.viewManager.inDynamicsMode);
|
|
@@ -270,121 +295,126 @@ export class ElementGeometryCacheTool extends ElementSetTool {
|
|
|
270
295
|
this.clearGraphic();
|
|
271
296
|
}
|
|
272
297
|
}
|
|
273
|
-
/** @alpha Base class for tools that
|
|
274
|
-
export class
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
const
|
|
293
|
-
const
|
|
294
|
-
const
|
|
295
|
-
const
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
298
|
+
/** @alpha Base class for tools that need to locate faces, edges, and vertices. */
|
|
299
|
+
export class LocateSubEntityTool extends ElementGeometryCacheTool {
|
|
300
|
+
constructor() {
|
|
301
|
+
super(...arguments);
|
|
302
|
+
this._acceptedSubEntities = [];
|
|
303
|
+
this._summaryIds = new Map();
|
|
304
|
+
}
|
|
305
|
+
provideToolAssistance(mainInstrText, additionalInstr) {
|
|
306
|
+
if (this.wantAdditionalSubEntities) {
|
|
307
|
+
const faceKey = this.wantSubEntityType(SubEntityType.Face) ? "Face" : "";
|
|
308
|
+
const edgeKey = this.wantSubEntityType(SubEntityType.Edge) ? "Edge" : "";
|
|
309
|
+
const vertexKey = this.wantSubEntityType(SubEntityType.Vertex) ? "Vertex" : "";
|
|
310
|
+
const subEntityKey = `${faceKey}${edgeKey}${vertexKey}`;
|
|
311
|
+
if (0 === subEntityKey.length) {
|
|
312
|
+
super.provideToolAssistance(mainInstrText, additionalInstr);
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
if (undefined === mainInstrText)
|
|
316
|
+
mainInstrText = EditTools.translate(`LocateSubEntities.Identify.${subEntityKey}`);
|
|
317
|
+
const leftMsg = EditTools.translate(`LocateSubEntities.Accept.${subEntityKey}`);
|
|
318
|
+
const rightMsg = this.haveAcceptedSubEntities && this.allowSubEntitySelectNext ? EditTools.translate(`LocateSubEntities.AcceptNext.${subEntityKey}`) : CoreTools.translate("ElementSet.Inputs.Cancel");
|
|
319
|
+
const mouseInstructions = [];
|
|
320
|
+
const touchInstructions = [];
|
|
321
|
+
if (!ToolAssistance.createTouchCursorInstructions(touchInstructions))
|
|
322
|
+
touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchTap, leftMsg, false, ToolAssistanceInputMethod.Touch));
|
|
323
|
+
mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, leftMsg, false, ToolAssistanceInputMethod.Mouse));
|
|
324
|
+
touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.TwoTouchTap, rightMsg, false, ToolAssistanceInputMethod.Touch));
|
|
325
|
+
mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, rightMsg, false, ToolAssistanceInputMethod.Mouse));
|
|
326
|
+
if (this.allowSubEntityControlSelect)
|
|
327
|
+
mouseInstructions.push(ToolAssistance.createModifierKeyInstruction(ToolAssistance.ctrlKey, ToolAssistanceImage.LeftClickDrag, EditTools.translate(`LocateSubEntities.IdentifyAdditional.${subEntityKey}`), false, ToolAssistanceInputMethod.Mouse));
|
|
328
|
+
if (undefined !== additionalInstr) {
|
|
329
|
+
for (const instr of additionalInstr) {
|
|
330
|
+
if (ToolAssistanceInputMethod.Touch === instr.inputMethod)
|
|
331
|
+
touchInstructions.push(instr);
|
|
332
|
+
else
|
|
333
|
+
mouseInstructions.push(instr);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
const sections = [];
|
|
337
|
+
sections.push(ToolAssistance.createSection(mouseInstructions, ToolAssistance.inputsLabel));
|
|
338
|
+
sections.push(ToolAssistance.createSection(touchInstructions, ToolAssistance.inputsLabel));
|
|
339
|
+
const mainInstruction = ToolAssistance.createInstruction(this.iconSpec, mainInstrText);
|
|
340
|
+
const instructions = ToolAssistance.createInstructions(mainInstruction, sections);
|
|
341
|
+
IModelApp.notifications.setToolAssistance(instructions);
|
|
342
|
+
return;
|
|
300
343
|
}
|
|
344
|
+
super.provideToolAssistance(mainInstrText, additionalInstr);
|
|
301
345
|
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
get
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
async
|
|
323
|
-
|
|
324
|
-
if (
|
|
325
|
-
|
|
346
|
+
get wantAgendaAppearanceOverride() { return true; }
|
|
347
|
+
get wantGeometrySummary() { return false; }
|
|
348
|
+
get wantSubEntitySnap() { return false; }
|
|
349
|
+
wantSubEntityType(type) { return SubEntityType.Face === type; }
|
|
350
|
+
getMaximumSubEntityHits(type) { return this.wantSubEntityType(type) ? 25 : 0; }
|
|
351
|
+
get requiredSubEntityCount() { return 1; }
|
|
352
|
+
get haveAcceptedSubEntities() { return (0 !== this._acceptedSubEntities.length); }
|
|
353
|
+
get inhibitSubEntityDisplay() { return this.isDynamicsStarted; }
|
|
354
|
+
get allowSubEntityControlSelect() { return true; }
|
|
355
|
+
get allowSubEntityControlDeselect() { return this.allowSubEntityControlSelect; }
|
|
356
|
+
get allowSubEntitySelectNext() { return !this.isDynamicsStarted; }
|
|
357
|
+
getBRepEntityTypeForSubEntity(id, subEntity) {
|
|
358
|
+
const summary = this._summaryIds.get(id);
|
|
359
|
+
if (undefined === summary)
|
|
360
|
+
return BRepEntityType.Invalid;
|
|
361
|
+
const index = (undefined !== subEntity.index ? subEntity.index : 0);
|
|
362
|
+
if (index >= summary.length)
|
|
363
|
+
return BRepEntityType.Invalid;
|
|
364
|
+
return summary[index];
|
|
365
|
+
}
|
|
366
|
+
async createElementGeometrySummary(id) {
|
|
367
|
+
let summary = this._summaryIds.get(id);
|
|
368
|
+
if (undefined === summary) {
|
|
369
|
+
if (this.agenda.isEmpty && this._summaryIds.size > 1000)
|
|
370
|
+
this._summaryIds.clear(); // Limit auto-locate cache size to something reasonable...
|
|
371
|
+
try {
|
|
372
|
+
this._startedCmd = await this.startCommand();
|
|
373
|
+
if (undefined === (summary = await ElementGeometryCacheTool.callCommand("summarizeElementGeometryCache", id)))
|
|
374
|
+
return false;
|
|
375
|
+
}
|
|
376
|
+
catch (err) {
|
|
377
|
+
return false;
|
|
378
|
+
}
|
|
379
|
+
this._summaryIds.set(id, summary);
|
|
380
|
+
}
|
|
381
|
+
return true;
|
|
326
382
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
/** @alpha Perform boolean intersection of solid geometry. */
|
|
331
|
-
export class IntersectSolidElementsTool extends BooleanOperationTool {
|
|
332
|
-
get mode() { return BooleanMode.Intersect; }
|
|
333
|
-
async onRestartTool() {
|
|
334
|
-
const tool = new IntersectSolidElementsTool();
|
|
335
|
-
if (!await tool.run())
|
|
336
|
-
return this.exitTool();
|
|
383
|
+
async createElementGeometryCache(id) {
|
|
384
|
+
const accept = await super.createElementGeometryCache(id);
|
|
385
|
+
return (accept && this.wantGeometrySummary ? this.createElementGeometrySummary(id) : accept);
|
|
337
386
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
export class SewSheetElementsTool extends ElementGeometryCacheTool {
|
|
343
|
-
get allowSelectionSet() { return true; }
|
|
344
|
-
get allowDragSelect() { return true; }
|
|
345
|
-
get controlKeyContinuesSelection() { return true; }
|
|
346
|
-
get requiredElementCount() { return 2; }
|
|
347
|
-
get geometryCacheFilter() {
|
|
348
|
-
return { parts: true, curves: false, surfaces: true, solids: false, other: false };
|
|
349
|
-
}
|
|
350
|
-
async applyAgendaOperation() {
|
|
351
|
-
if (this.agenda.length < this.requiredElementCount)
|
|
387
|
+
getAcceptedSubEntityData(index = -1) {
|
|
388
|
+
if (-1 === index)
|
|
389
|
+
index = this._acceptedSubEntities.length - 1;
|
|
390
|
+
if (index < 0 || index > this._acceptedSubEntities.length - 1)
|
|
352
391
|
return undefined;
|
|
353
|
-
|
|
354
|
-
this._startedCmd = await this.startCommand();
|
|
355
|
-
const target = this.agenda.elements[0];
|
|
356
|
-
const tools = this.agenda.elements.slice(1);
|
|
357
|
-
const params = { tools };
|
|
358
|
-
const opts = { writeChanges: true };
|
|
359
|
-
return await ElementGeometryCacheTool.callCommand("sewSheets", target, params, opts);
|
|
360
|
-
}
|
|
361
|
-
catch (err) {
|
|
362
|
-
return undefined;
|
|
363
|
-
}
|
|
392
|
+
return this._acceptedSubEntities[index];
|
|
364
393
|
}
|
|
365
|
-
|
|
366
|
-
const
|
|
367
|
-
|
|
368
|
-
|
|
394
|
+
getAcceptedSubEntities() {
|
|
395
|
+
const accepted = [];
|
|
396
|
+
this._acceptedSubEntities.forEach((entry) => { accepted.push(entry.props); });
|
|
397
|
+
return accepted;
|
|
369
398
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
399
|
+
drawSubEntity(context, subEntity, accepted) {
|
|
400
|
+
subEntity.display(context, accepted);
|
|
401
|
+
}
|
|
402
|
+
drawAcceptedSubEntities(context) {
|
|
403
|
+
this._acceptedSubEntities.forEach((entry) => { this.drawSubEntity(context, entry, true); });
|
|
374
404
|
}
|
|
375
|
-
}
|
|
376
|
-
SewSheetElementsTool.toolId = "SewSheets";
|
|
377
|
-
SewSheetElementsTool.iconSpec = "icon-move"; // TODO: Need better icon...
|
|
378
|
-
/** @alpha Base class for tools that need to locate faces, edges, and vertices. */
|
|
379
|
-
export class LocateSubEntityTool extends ElementGeometryCacheTool {
|
|
380
|
-
wantSubEntityType(type) { return SubEntityType.Face === type; }
|
|
381
|
-
getMaximumSubEntityHits(type) { return this.wantSubEntityType(type) ? 25 : 0; }
|
|
382
|
-
get wantAgendaAppearanceOverride() { return true; }
|
|
383
405
|
decorate(context) {
|
|
384
|
-
if (!this.allowView(context.viewport))
|
|
406
|
+
if (this.inhibitSubEntityDisplay || !this.allowView(context.viewport))
|
|
385
407
|
return;
|
|
408
|
+
if (this.haveAcceptedSubEntities)
|
|
409
|
+
this.drawAcceptedSubEntities(context);
|
|
386
410
|
if (undefined !== this._currentSubEntity)
|
|
387
|
-
this.
|
|
411
|
+
this.drawSubEntity(context, this._currentSubEntity, false);
|
|
412
|
+
}
|
|
413
|
+
decorateSuspended(context) {
|
|
414
|
+
if (this.inhibitSubEntityDisplay || !this.allowView(context.viewport))
|
|
415
|
+
return;
|
|
416
|
+
if (this.haveAcceptedSubEntities)
|
|
417
|
+
this.drawAcceptedSubEntities(context);
|
|
388
418
|
}
|
|
389
419
|
getLocateAperture(ev) {
|
|
390
420
|
if (undefined === ev.viewport)
|
|
@@ -404,6 +434,19 @@ export class LocateSubEntityTool extends ElementGeometryCacheTool {
|
|
|
404
434
|
// The edge and vertex hits get post-filtered on xy distance, so this is fine for perspective views...
|
|
405
435
|
return (aperture * vec[0].distance(vec[1]));
|
|
406
436
|
}
|
|
437
|
+
getRayOrigin(ev) {
|
|
438
|
+
const spacePoint = ev.point.clone();
|
|
439
|
+
const vp = ev.viewport;
|
|
440
|
+
if (undefined === vp)
|
|
441
|
+
return spacePoint;
|
|
442
|
+
vp.worldToNpc(spacePoint, spacePoint);
|
|
443
|
+
spacePoint.z = 1.0;
|
|
444
|
+
vp.npcToWorld(spacePoint, spacePoint);
|
|
445
|
+
return spacePoint;
|
|
446
|
+
}
|
|
447
|
+
wantHiddenEdges(vp) {
|
|
448
|
+
return vp.viewFlags.hiddenEdgesVisible();
|
|
449
|
+
}
|
|
407
450
|
getSubEntityFilter() { return undefined; }
|
|
408
451
|
async pickSubEntities(id, boresite, maxFace, maxEdge, maxVertex, maxDistance, hiddenEdgesVisible, filter) {
|
|
409
452
|
try {
|
|
@@ -433,8 +476,9 @@ export class LocateSubEntityTool extends ElementGeometryCacheTool {
|
|
|
433
476
|
return undefined;
|
|
434
477
|
const aperture = this.getLocateAperture(ev);
|
|
435
478
|
const maxDistance = this.getMaxRayDistance(ev, aperture);
|
|
436
|
-
const
|
|
437
|
-
const
|
|
479
|
+
const spacePoint = this.getRayOrigin(ev);
|
|
480
|
+
const boresite = AccuDrawHintBuilder.getBoresite(spacePoint, vp);
|
|
481
|
+
const hiddenEdgesVisible = this.wantHiddenEdges(vp);
|
|
438
482
|
const filter = this.getSubEntityFilter();
|
|
439
483
|
let hits = await this.pickSubEntities(id, boresite, maxFace, maxEdge, maxVertex, maxDistance, hiddenEdgesVisible, filter);
|
|
440
484
|
// NOTE: Remove erroneous edge/vertex hits in perspective views by checking real xy distance to hit point...
|
|
@@ -458,39 +502,103 @@ export class LocateSubEntityTool extends ElementGeometryCacheTool {
|
|
|
458
502
|
}
|
|
459
503
|
return hits;
|
|
460
504
|
}
|
|
505
|
+
async createSubEntityData(id, hit) {
|
|
506
|
+
const data = new SubEntityData(hit.subEntity);
|
|
507
|
+
const chordTolerance = (this.targetView ? computeChordToleranceFromPoint(this.targetView, Point3d.fromJSON(hit.point)) : undefined);
|
|
508
|
+
await this.createSubEntityGraphic(id, data, chordTolerance);
|
|
509
|
+
return data;
|
|
510
|
+
}
|
|
511
|
+
/** Append specified sub-entity to accepted array. */
|
|
512
|
+
async addSubEntity(id, props) {
|
|
513
|
+
this._acceptedSubEntities.push(await this.createSubEntityData(id, props));
|
|
514
|
+
}
|
|
515
|
+
/** Remove specified sub-entity from accepted array, or pop last sub-entity if undefined. */
|
|
516
|
+
async removeSubEntity(_id, props) {
|
|
517
|
+
if (undefined !== props)
|
|
518
|
+
this._acceptedSubEntities = this._acceptedSubEntities.filter((entry) => !isSameSubEntity(entry.props, props.subEntity));
|
|
519
|
+
else
|
|
520
|
+
this._acceptedSubEntities.pop();
|
|
521
|
+
}
|
|
522
|
+
/** Locate sub-entities for the most recently added (last) agenda entry. Tool sub-classes that wish to identity
|
|
523
|
+
* sub-entities from multiple elements are responsible for maintaining the sub-entities per-element.
|
|
524
|
+
*/
|
|
461
525
|
async doLocateSubEntity(ev, newSearch) {
|
|
526
|
+
var _a;
|
|
462
527
|
if (this.agenda.isEmpty || undefined === ev.viewport)
|
|
463
528
|
return false;
|
|
529
|
+
const id = this.agenda.elements[this.agenda.length - 1];
|
|
464
530
|
if (newSearch) {
|
|
465
|
-
|
|
466
|
-
if (undefined ===
|
|
531
|
+
this._locatedSubEntities = await this.doPickSubEntities(id, ev);
|
|
532
|
+
if (undefined === this._locatedSubEntities || 0 === this._locatedSubEntities.length)
|
|
467
533
|
return false;
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
534
|
+
/** NOTE: Set last button location to point on sub-entity when not snapping.
|
|
535
|
+
* If dynamics are enabled on this event, onDynamicFrame is called with this location.
|
|
536
|
+
*/
|
|
537
|
+
if (CoordSource.ElemSnap !== ev.coordsFrom) {
|
|
538
|
+
ev.point.setFrom(Point3d.fromJSON(this._locatedSubEntities[0].point));
|
|
539
|
+
IModelApp.toolAdmin.setAdjustedDataPoint(ev);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
else {
|
|
543
|
+
await this.removeSubEntity(id);
|
|
471
544
|
}
|
|
472
|
-
this.
|
|
545
|
+
const hit = (_a = this._locatedSubEntities) === null || _a === void 0 ? void 0 : _a.shift();
|
|
546
|
+
if (undefined !== hit) {
|
|
547
|
+
if (undefined === this._acceptedSubEntities.find((entry) => isSameSubEntity(entry.props, hit.subEntity)))
|
|
548
|
+
await this.addSubEntity(id, hit);
|
|
549
|
+
else if (this.allowSubEntityControlDeselect)
|
|
550
|
+
await this.removeSubEntity(id, hit);
|
|
551
|
+
}
|
|
552
|
+
IModelApp.viewManager.invalidateDecorationsAllViews();
|
|
473
553
|
return true;
|
|
474
554
|
}
|
|
475
555
|
async chooseNextHit(ev) {
|
|
476
|
-
if (
|
|
556
|
+
if (!this.haveAcceptedSubEntities)
|
|
477
557
|
return super.chooseNextHit(ev);
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
558
|
+
if (!this.allowSubEntitySelectNext) {
|
|
559
|
+
await this.onReinitialize(); // Don't cycle through hits after starting dynamics...
|
|
560
|
+
}
|
|
561
|
+
else {
|
|
562
|
+
await this.doLocateSubEntity(ev, false);
|
|
563
|
+
if (!this.haveAcceptedSubEntities)
|
|
564
|
+
await this.onReinitialize();
|
|
565
|
+
}
|
|
481
566
|
return EventHandled.No;
|
|
482
567
|
}
|
|
568
|
+
get wantAdditionalSubEntities() {
|
|
569
|
+
return (this._acceptedSubEntities.length < this.requiredSubEntityCount || (this.allowSubEntityControlSelect && this.isControlDown));
|
|
570
|
+
}
|
|
483
571
|
async gatherInput(ev) {
|
|
484
|
-
if (
|
|
572
|
+
if (this.wantAdditionalSubEntities) {
|
|
485
573
|
await this.doLocateSubEntity(ev, true);
|
|
574
|
+
if (this.wantAdditionalSubEntities) {
|
|
575
|
+
this.setupAndPromptForNextAction();
|
|
576
|
+
return EventHandled.No;
|
|
577
|
+
}
|
|
578
|
+
this.clearCurrentSubEntity();
|
|
579
|
+
}
|
|
486
580
|
return super.gatherInput(ev);
|
|
487
581
|
}
|
|
488
|
-
|
|
489
|
-
if (
|
|
490
|
-
return
|
|
491
|
-
|
|
582
|
+
getCurrentElement() {
|
|
583
|
+
if (!this.agenda.isEmpty)
|
|
584
|
+
return this.agenda.elements[this.agenda.length - 1];
|
|
585
|
+
const hit = IModelApp.accuSnap.currHit;
|
|
586
|
+
return (undefined !== hit && hit.isElementHit ? hit.sourceId : undefined);
|
|
587
|
+
}
|
|
588
|
+
clearCurrentSubEntity() {
|
|
589
|
+
if (undefined === this._currentSubEntity)
|
|
590
|
+
return;
|
|
591
|
+
this._currentSubEntity.cleanupGraphic();
|
|
592
|
+
this._currentSubEntity = undefined;
|
|
492
593
|
}
|
|
493
|
-
async setCurrentSubEntity(id,
|
|
594
|
+
async setCurrentSubEntity(id, hit, chordTolerance) {
|
|
595
|
+
if (undefined === this._currentSubEntity)
|
|
596
|
+
this._currentSubEntity = new SubEntityData(hit.subEntity);
|
|
597
|
+
else
|
|
598
|
+
this._currentSubEntity.props = hit.subEntity;
|
|
599
|
+
return this.createSubEntityGraphic(id, this._currentSubEntity, chordTolerance);
|
|
600
|
+
}
|
|
601
|
+
async changeCurrentSubEntity(id, current, chordTolerance) {
|
|
494
602
|
if (undefined === id || undefined === current) {
|
|
495
603
|
if (undefined === this._currentSubEntity || !this._currentSubEntity.hasGraphic)
|
|
496
604
|
return false;
|
|
@@ -499,159 +607,95 @@ export class LocateSubEntityTool extends ElementGeometryCacheTool {
|
|
|
499
607
|
}
|
|
500
608
|
if (undefined !== this._currentSubEntity && this._currentSubEntity.hasGraphic && this._currentSubEntity.isSame(current.subEntity))
|
|
501
609
|
return false;
|
|
502
|
-
|
|
503
|
-
this._currentSubEntity = new SubEntityData();
|
|
504
|
-
else
|
|
505
|
-
this._currentSubEntity.cleanupGraphic();
|
|
506
|
-
const opts = {
|
|
507
|
-
wantGraphic: true,
|
|
508
|
-
wantRange: true,
|
|
509
|
-
wantAppearance: true,
|
|
510
|
-
chordTolerance,
|
|
511
|
-
};
|
|
512
|
-
this._currentSubEntity.info = current.subEntity;
|
|
513
|
-
this._currentSubEntity.geom = await ElementGeometryCacheTool.callCommand("getSubEntityGeometry", id, current.subEntity, opts);
|
|
514
|
-
return this._currentSubEntity.createGraphic(this.iModel);
|
|
515
|
-
}
|
|
516
|
-
clearSubEntityGraphic() {
|
|
517
|
-
if (undefined === this._currentSubEntity)
|
|
518
|
-
return;
|
|
519
|
-
this._currentSubEntity.cleanupGraphic();
|
|
520
|
-
this._currentSubEntity = undefined;
|
|
610
|
+
return this.setCurrentSubEntity(id, current, chordTolerance);
|
|
521
611
|
}
|
|
522
|
-
async
|
|
612
|
+
async updateCurrentSubEntity(ev) {
|
|
523
613
|
if (undefined === ev.viewport)
|
|
524
614
|
return false;
|
|
525
|
-
const
|
|
526
|
-
if (undefined ===
|
|
527
|
-
return this.
|
|
528
|
-
|
|
615
|
+
const id = this.wantAdditionalSubEntities ? this.getCurrentElement() : undefined;
|
|
616
|
+
if (undefined === id)
|
|
617
|
+
return this.changeCurrentSubEntity();
|
|
618
|
+
if (this._subEntityGraphicPending)
|
|
619
|
+
return false;
|
|
620
|
+
this._subEntityGraphicPending = true;
|
|
621
|
+
const current = await this.doPickSubEntities(id, ev);
|
|
529
622
|
const chordTolerance = current ? computeChordToleranceFromPoint(ev.viewport, Point3d.fromJSON(current[0].point)) : 0.0;
|
|
530
|
-
|
|
623
|
+
const status = await this.changeCurrentSubEntity(id, current ? current[0] : undefined, chordTolerance);
|
|
624
|
+
this._subEntityGraphicPending = undefined;
|
|
625
|
+
if (status)
|
|
626
|
+
IModelApp.viewManager.invalidateDecorationsAllViews();
|
|
627
|
+
return status;
|
|
628
|
+
}
|
|
629
|
+
async createSubEntityGraphic(id, data, chordTolerance) {
|
|
630
|
+
try {
|
|
631
|
+
const opts = {
|
|
632
|
+
wantGraphic: true,
|
|
633
|
+
wantRange: true,
|
|
634
|
+
wantAppearance: true,
|
|
635
|
+
chordTolerance,
|
|
636
|
+
};
|
|
637
|
+
data.chordTolerance = chordTolerance;
|
|
638
|
+
data.geometry = await ElementGeometryCacheTool.callCommand("getSubEntityGeometry", id, data.props, opts);
|
|
639
|
+
return await data.createGraphic(this.iModel);
|
|
640
|
+
}
|
|
641
|
+
catch (err) {
|
|
531
642
|
return false;
|
|
532
|
-
|
|
533
|
-
return true;
|
|
643
|
+
}
|
|
534
644
|
}
|
|
535
645
|
async updateGraphic(ev, isDynamics) {
|
|
536
646
|
if (isDynamics)
|
|
537
647
|
return super.updateGraphic(ev, isDynamics);
|
|
538
|
-
await this.
|
|
648
|
+
await this.updateCurrentSubEntity(ev);
|
|
539
649
|
}
|
|
540
|
-
async applyAgendaOperation(_ev, _isAccept) { return undefined; }
|
|
541
650
|
async getGraphicData(ev) {
|
|
542
651
|
const result = await this.applyAgendaOperation(ev, false);
|
|
543
652
|
return result === null || result === void 0 ? void 0 : result.graphic;
|
|
544
653
|
}
|
|
654
|
+
async applyAgendaOperation(_ev, _isAccept) { return undefined; }
|
|
545
655
|
async processAgenda(ev) {
|
|
546
|
-
if (undefined === this._acceptedSubEntity)
|
|
547
|
-
return;
|
|
548
656
|
const result = await this.applyAgendaOperation(ev, true);
|
|
549
657
|
if (result === null || result === void 0 ? void 0 : result.elementId)
|
|
550
658
|
await this.saveChanges();
|
|
551
659
|
}
|
|
660
|
+
async onModifierKeyTransition(wentDown, modifier, event) {
|
|
661
|
+
if (EventHandled.Yes === await super.onModifierKeyTransition(wentDown, modifier, event))
|
|
662
|
+
return EventHandled.Yes;
|
|
663
|
+
if (BeModifierKeys.Control !== modifier)
|
|
664
|
+
return EventHandled.No;
|
|
665
|
+
if (IModelApp.toolAdmin.isLocateCircleOn === this.wantAdditionalSubEntities)
|
|
666
|
+
return EventHandled.No;
|
|
667
|
+
this.setupAndPromptForNextAction();
|
|
668
|
+
return EventHandled.Yes;
|
|
669
|
+
}
|
|
670
|
+
changeLocateState(enableLocate, enableSnap, cursor, coordLockOvr) {
|
|
671
|
+
super.changeLocateState(enableLocate, enableSnap, cursor, coordLockOvr);
|
|
672
|
+
// Keep showing locate circle when identifing sub-entities even if done locating elements...
|
|
673
|
+
if (!IModelApp.toolAdmin.isLocateCircleOn && this.wantAdditionalSubEntities)
|
|
674
|
+
IModelApp.toolAdmin.setLocateCircleOn(true);
|
|
675
|
+
}
|
|
676
|
+
get shouldEnableSnap() {
|
|
677
|
+
if (this.isSelectByPoints || !this.wantAccuSnap)
|
|
678
|
+
return false;
|
|
679
|
+
if (this.isDynamicsStarted)
|
|
680
|
+
return true;
|
|
681
|
+
const isCtrlSelect = (this.isControlDown && (this.controlKeyContinuesSelection || this.allowSubEntityControlSelect));
|
|
682
|
+
if (isCtrlSelect || this.wantAdditionalElements || this.wantAdditionalSubEntities)
|
|
683
|
+
return this.wantSubEntitySnap;
|
|
684
|
+
return !this.wantSubEntitySnap;
|
|
685
|
+
}
|
|
552
686
|
setupAccuDraw() { }
|
|
553
687
|
setupAndPromptForNextAction() {
|
|
554
688
|
this.setupAccuDraw();
|
|
555
689
|
super.setupAndPromptForNextAction();
|
|
556
690
|
}
|
|
691
|
+
clearSubEntityGraphics() {
|
|
692
|
+
if (undefined !== this._currentSubEntity)
|
|
693
|
+
this._currentSubEntity.cleanupGraphic();
|
|
694
|
+
this._acceptedSubEntities.forEach((entry) => { entry.cleanupGraphic(); });
|
|
695
|
+
}
|
|
557
696
|
async onCleanup() {
|
|
558
|
-
this.
|
|
697
|
+
this.clearSubEntityGraphics();
|
|
559
698
|
return super.onCleanup();
|
|
560
699
|
}
|
|
561
700
|
}
|
|
562
|
-
/** @alpha Identify faces of solids and surfaces to offset. */
|
|
563
|
-
export class OffsetFacesTool extends LocateSubEntityTool {
|
|
564
|
-
requireWriteableTarget() { return false; } // TODO: Testing...
|
|
565
|
-
get wantDynamics() { return true; }
|
|
566
|
-
get wantAccuSnap() { return undefined !== this._acceptedSubEntity; }
|
|
567
|
-
get geometryCacheFilter() {
|
|
568
|
-
return { minGeom: 1, maxGeom: 1, parts: true, curves: false, surfaces: true, solids: true, other: false };
|
|
569
|
-
}
|
|
570
|
-
async applyAgendaOperation(ev, isAccept) {
|
|
571
|
-
var _a, _b;
|
|
572
|
-
if (undefined === ev.viewport || this.agenda.isEmpty || undefined === ((_a = this._acceptedSubEntity) === null || _a === void 0 ? void 0 : _a.point) || undefined === ((_b = this._acceptedSubEntity) === null || _b === void 0 ? void 0 : _b.normal))
|
|
573
|
-
return undefined;
|
|
574
|
-
const facePt = Point3d.fromJSON(this._acceptedSubEntity.point);
|
|
575
|
-
const faceNormal = Vector3d.fromJSON(this._acceptedSubEntity.normal);
|
|
576
|
-
const projPt = AccuDrawHintBuilder.projectPointToLineInView(ev.point, facePt, faceNormal, ev.viewport);
|
|
577
|
-
if (undefined === projPt)
|
|
578
|
-
return undefined;
|
|
579
|
-
const offsetDir = Vector3d.createStartEnd(facePt, projPt);
|
|
580
|
-
let offset = offsetDir.magnitude();
|
|
581
|
-
if (offset < Geometry.smallMetricDistance)
|
|
582
|
-
return undefined;
|
|
583
|
-
if (offsetDir.dotProduct(faceNormal) < 0.0)
|
|
584
|
-
offset = -offset;
|
|
585
|
-
try {
|
|
586
|
-
this._startedCmd = await this.startCommand();
|
|
587
|
-
const params = { faces: this._acceptedSubEntity.subEntity, distances: offset };
|
|
588
|
-
const opts = {
|
|
589
|
-
wantGraphic: isAccept ? undefined : true,
|
|
590
|
-
chordTolerance: computeChordToleranceFromPoint(ev.viewport, ev.point),
|
|
591
|
-
requestId: `${this.toolId}:${this.agenda.elements[0]}`,
|
|
592
|
-
writeChanges: isAccept ? true : undefined,
|
|
593
|
-
};
|
|
594
|
-
return await ElementGeometryCacheTool.callCommand("offsetFaces", this.agenda.elements[0], params, opts);
|
|
595
|
-
}
|
|
596
|
-
catch (err) {
|
|
597
|
-
return undefined;
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
setupAccuDraw() {
|
|
601
|
-
var _a, _b;
|
|
602
|
-
if (undefined === ((_a = this._acceptedSubEntity) === null || _a === void 0 ? void 0 : _a.point) || undefined === ((_b = this._acceptedSubEntity) === null || _b === void 0 ? void 0 : _b.normal))
|
|
603
|
-
return;
|
|
604
|
-
const facePt = Point3d.fromJSON(this._acceptedSubEntity.point);
|
|
605
|
-
const faceNormal = Vector3d.fromJSON(this._acceptedSubEntity.normal);
|
|
606
|
-
const hints = new AccuDrawHintBuilder();
|
|
607
|
-
hints.setOriginFixed = true;
|
|
608
|
-
hints.setLockY = true;
|
|
609
|
-
hints.setLockZ = true;
|
|
610
|
-
hints.setModeRectangular();
|
|
611
|
-
hints.setOrigin(facePt);
|
|
612
|
-
hints.setXAxis2(faceNormal);
|
|
613
|
-
hints.sendHints();
|
|
614
|
-
}
|
|
615
|
-
async onRestartTool() {
|
|
616
|
-
const tool = new OffsetFacesTool();
|
|
617
|
-
if (!await tool.run())
|
|
618
|
-
return this.exitTool();
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
OffsetFacesTool.toolId = "OffsetFaces";
|
|
622
|
-
OffsetFacesTool.iconSpec = "icon-move"; // TODO: Need better icon...
|
|
623
|
-
/** @alpha Identify faces to offset to hollow solids. */
|
|
624
|
-
export class HollowFacesTool extends LocateSubEntityTool {
|
|
625
|
-
get geometryCacheFilter() {
|
|
626
|
-
return { minGeom: 1, maxGeom: 1, parts: true, curves: false, surfaces: false, solids: true, other: false };
|
|
627
|
-
}
|
|
628
|
-
async applyAgendaOperation(ev, isAccept) {
|
|
629
|
-
if (undefined === ev.viewport || this.agenda.isEmpty || undefined === this._acceptedSubEntity)
|
|
630
|
-
return undefined;
|
|
631
|
-
// TODO: Tool settings for shell thickness and face thickness...
|
|
632
|
-
const shellThickness = 0.1;
|
|
633
|
-
const faceThickness = 0.0;
|
|
634
|
-
try {
|
|
635
|
-
this._startedCmd = await this.startCommand();
|
|
636
|
-
const params = { faces: this._acceptedSubEntity.subEntity, distances: faceThickness, defaultDistance: shellThickness };
|
|
637
|
-
const opts = {
|
|
638
|
-
wantGraphic: isAccept ? undefined : true,
|
|
639
|
-
chordTolerance: computeChordToleranceFromPoint(ev.viewport, ev.point),
|
|
640
|
-
requestId: `${this.toolId}:${this.agenda.elements[0]}`,
|
|
641
|
-
writeChanges: isAccept ? true : undefined,
|
|
642
|
-
};
|
|
643
|
-
return await ElementGeometryCacheTool.callCommand("hollowFaces", this.agenda.elements[0], params, opts);
|
|
644
|
-
}
|
|
645
|
-
catch (err) {
|
|
646
|
-
return undefined;
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
async onRestartTool() {
|
|
650
|
-
const tool = new HollowFacesTool();
|
|
651
|
-
if (!await tool.run())
|
|
652
|
-
return this.exitTool();
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
HollowFacesTool.toolId = "HollowFaces";
|
|
656
|
-
HollowFacesTool.iconSpec = "icon-move"; // TODO: Need better icon...
|
|
657
701
|
//# sourceMappingURL=ElementGeometryTool.js.map
|