@itwin/editor-frontend 3.0.0-dev.154 → 3.0.0-dev.155

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.
@@ -8,9 +8,11 @@
8
8
  import { BooleanMode, BRepEntityType, ChamferMode, CutDepthMode, CutDirectionMode, EmbossDirectionMode, ProfileClosure, SubEntityType } from "@itwin/editor-common";
9
9
  import { ColorDef, ElementGeometry } from "@itwin/core-common";
10
10
  import { Angle, Geometry, LineString3d, Matrix3d, Point3d, Vector3d } from "@itwin/core-geometry";
11
- import { AccuDraw, AccuDrawHintBuilder, EventHandled, GraphicType, TentativeOrAccuSnap } from "@itwin/core-frontend";
11
+ import { AccuDraw, AccuDrawHintBuilder, AngleDescription, EventHandled, GraphicType, IModelApp, LengthDescription, TentativeOrAccuSnap } from "@itwin/core-frontend";
12
12
  import { computeChordToleranceFromPoint } from "./CreateElementTool";
13
13
  import { ElementGeometryCacheTool, isSameSubEntity, LocateSubEntityTool, SubEntityData } from "./ElementGeometryTool";
14
+ import { DialogProperty, PropertyDescriptionHelper } from "@itwin/appui-abstract";
15
+ import { EditTools } from "./EditTool";
14
16
  /** @alpha Base class for tools that perform boolean operations on a set of elements. */
15
17
  export class BooleanOperationTool extends ElementGeometryCacheTool {
16
18
  get allowSelectionSet() { return BooleanMode.Subtract !== this.mode; }
@@ -118,12 +120,20 @@ SewSheetElementsTool.toolId = "SewSheets";
118
120
  SewSheetElementsTool.iconSpec = "icon-move"; // TODO: Need better icon...
119
121
  /** @alpha Perform thicken operation on surface geometry. */
120
122
  export class ThickenSheetElementsTool extends ElementGeometryCacheTool {
121
- constructor() {
122
- super(...arguments);
123
- // TODO: Tool settings for front and back distances...
124
- this.frontDistance = 0.5;
125
- this.backDistance = 0.0;
126
- }
123
+ get frontDistanceProperty() {
124
+ if (!this._frontDistanceProperty)
125
+ this._frontDistanceProperty = new DialogProperty(new LengthDescription("thickenFront", EditTools.translate("ThickenSheets.Label.FrontDistance")), 0.1, undefined);
126
+ return this._frontDistanceProperty;
127
+ }
128
+ get frontDistance() { return this.frontDistanceProperty.value; }
129
+ set frontDistance(value) { this.frontDistanceProperty.value = value; }
130
+ get backDistanceProperty() {
131
+ if (!this._backDistanceProperty)
132
+ this._backDistanceProperty = new DialogProperty(new LengthDescription("thickenBack", EditTools.translate("ThickenSheets.Label.BackDistance")), 0.0, undefined);
133
+ return this._backDistanceProperty;
134
+ }
135
+ get backDistance() { return this.backDistanceProperty.value; }
136
+ set backDistance(value) { this.backDistanceProperty.value = value; }
127
137
  get geometryCacheFilter() {
128
138
  return { parts: true, curves: false, surfaces: true, solids: false, other: false };
129
139
  }
@@ -146,6 +156,32 @@ export class ThickenSheetElementsTool extends ElementGeometryCacheTool {
146
156
  if (result === null || result === void 0 ? void 0 : result.elementId)
147
157
  await this.saveChanges();
148
158
  }
159
+ async applyToolSettingPropertyChange(updatedValue) {
160
+ if (updatedValue.propertyName === this.frontDistanceProperty.name) {
161
+ this.frontDistance = updatedValue.value.value;
162
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.frontDistanceProperty.item);
163
+ return true;
164
+ }
165
+ else if (updatedValue.propertyName === this.backDistanceProperty.name) {
166
+ this.backDistance = updatedValue.value.value;
167
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.backDistanceProperty.item);
168
+ return true;
169
+ }
170
+ return false;
171
+ }
172
+ supplyToolSettingsProperties() {
173
+ var _a;
174
+ (_a = IModelApp.toolAdmin.toolSettingsState.getInitialToolSettingValues(this.toolId, [this.frontDistanceProperty.name, this.backDistanceProperty.name])) === null || _a === void 0 ? void 0 : _a.forEach((value) => {
175
+ if (value.propertyName === this.frontDistanceProperty.name)
176
+ this.frontDistanceProperty.dialogItemValue = value.value;
177
+ else if (value.propertyName === this.backDistanceProperty.name)
178
+ this.backDistanceProperty.dialogItemValue = value.value;
179
+ });
180
+ const toolSettings = new Array();
181
+ toolSettings.push(this.frontDistanceProperty.toDialogItem({ rowPriority: 1, columnIndex: 0 }));
182
+ toolSettings.push(this.backDistanceProperty.toDialogItem({ rowPriority: 2, columnIndex: 0 }));
183
+ return toolSettings;
184
+ }
149
185
  async onRestartTool() {
150
186
  const tool = new ThickenSheetElementsTool();
151
187
  if (!await tool.run())
@@ -156,13 +192,34 @@ ThickenSheetElementsTool.toolId = "ThickenSheets";
156
192
  ThickenSheetElementsTool.iconSpec = "icon-move"; // TODO: Need better icon...
157
193
  /** @alpha Perform cut operation on solid using region or path profile. */
158
194
  export class CutSolidElementsTool extends ElementGeometryCacheTool {
159
- constructor() {
160
- super(...arguments);
161
- // TODO: Tool settings for both directions, blind cut depth, and outside...
162
- this.bothDirections = false;
163
- this.distance = 0.0;
164
- this.outside = undefined;
165
- }
195
+ get bothDirectionsProperty() {
196
+ if (!this._bothDirectionsProperty)
197
+ this._bothDirectionsProperty = new DialogProperty(PropertyDescriptionHelper.buildToggleDescription("cutBothDirections", EditTools.translate("CutSolids.Label.BothDirections")), false);
198
+ return this._bothDirectionsProperty;
199
+ }
200
+ get bothDirections() { return this.bothDirectionsProperty.value; }
201
+ set bothDirections(value) { this.bothDirectionsProperty.value = value; }
202
+ get outsideProperty() {
203
+ if (!this._outsideProperty)
204
+ this._outsideProperty = new DialogProperty(PropertyDescriptionHelper.buildToggleDescription("cutOutside", EditTools.translate("CutSolids.Label.Outside")), false);
205
+ return this._outsideProperty;
206
+ }
207
+ get outside() { return this.outsideProperty.value; }
208
+ set outside(value) { this.outsideProperty.value = value; }
209
+ get useDepthProperty() {
210
+ if (!this._useDepthProperty)
211
+ this._useDepthProperty = new DialogProperty(PropertyDescriptionHelper.buildLockPropertyDescription("useCutDepth"), false);
212
+ return this._useDepthProperty;
213
+ }
214
+ get useDepth() { return this.useDepthProperty.value; }
215
+ set useDepth(value) { this.useDepthProperty.value = value; }
216
+ get depthProperty() {
217
+ if (!this._depthProperty)
218
+ this._depthProperty = new DialogProperty(new LengthDescription("cutDepth", EditTools.translate("CutSolids.Label.Depth")), 0.1, undefined, !this.useDepth);
219
+ return this._depthProperty;
220
+ }
221
+ get depth() { return this.depthProperty.value; }
222
+ set depth(value) { this.depthProperty.value = value; }
166
223
  get requiredElementCount() { return 2; }
167
224
  get isProfilePhase() { return !this.agenda.isEmpty; }
168
225
  get geometryCacheFilter() {
@@ -191,12 +248,12 @@ export class CutSolidElementsTool extends ElementGeometryCacheTool {
191
248
  if (this.agenda.length < this.requiredElementCount)
192
249
  return undefined;
193
250
  const direction = (this.bothDirections ? CutDirectionMode.Both : CutDirectionMode.Auto);
194
- const depth = (0.0 === this.distance ? CutDepthMode.All : CutDepthMode.Blind);
251
+ const depth = (this.useDepth ? CutDepthMode.Blind : CutDepthMode.All);
195
252
  try {
196
253
  this._startedCmd = await this.startCommand();
197
254
  const target = this.agenda.elements[0];
198
255
  const profile = this.agenda.elements[1];
199
- const params = { profile, direction, depth, distance: this.distance, outside: this.outside, closeOpen: ProfileClosure.Auto, targetPoint: this.targetPoint, toolPoint: this.toolPoint };
256
+ const params = { profile, direction, depth, distance: this.depth, outside: this.outside ? true : undefined, closeOpen: ProfileClosure.Auto, targetPoint: this.targetPoint, toolPoint: this.toolPoint };
200
257
  const opts = { writeChanges: true };
201
258
  return await ElementGeometryCacheTool.callCommand("cutSolid", target, params, opts);
202
259
  }
@@ -216,6 +273,60 @@ export class CutSolidElementsTool extends ElementGeometryCacheTool {
216
273
  this.targetPoint = hit.hitPoint;
217
274
  return super.buildLocateAgenda(hit);
218
275
  }
276
+ syncDepthState() {
277
+ this.depthProperty.displayValue = this.depthProperty.description.format(this.depth);
278
+ this.depthProperty.isDisabled = !this.useDepth;
279
+ this.syncToolSettingsProperties([this.depthProperty.syncItem]);
280
+ }
281
+ async applyToolSettingPropertyChange(updatedValue) {
282
+ if (updatedValue.propertyName === this.bothDirectionsProperty.name) {
283
+ this.bothDirections = updatedValue.value.value;
284
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.bothDirectionsProperty.item);
285
+ return true;
286
+ }
287
+ else if (updatedValue.propertyName === this.outsideProperty.name) {
288
+ this.outside = updatedValue.value.value;
289
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.outsideProperty.item);
290
+ return true;
291
+ }
292
+ else if (updatedValue.propertyName === this.useDepthProperty.name) {
293
+ this.useDepth = updatedValue.value.value;
294
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.useDepthProperty.item);
295
+ this.syncDepthState();
296
+ return true;
297
+ }
298
+ else if (updatedValue.propertyName === this.depthProperty.name) {
299
+ if (!updatedValue.value.value) {
300
+ this.syncDepthState(); // force UI to redisplay last valid value
301
+ return false;
302
+ }
303
+ this.depth = updatedValue.value.value;
304
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.depthProperty.item);
305
+ return true;
306
+ }
307
+ return false;
308
+ }
309
+ supplyToolSettingsProperties() {
310
+ var _a;
311
+ (_a = IModelApp.toolAdmin.toolSettingsState.getInitialToolSettingValues(this.toolId, [this.bothDirectionsProperty.name, this.outsideProperty.name, this.useDepthProperty.name, this.depthProperty.name])) === null || _a === void 0 ? void 0 : _a.forEach((value) => {
312
+ if (value.propertyName === this.bothDirectionsProperty.name)
313
+ this.bothDirectionsProperty.dialogItemValue = value.value;
314
+ else if (value.propertyName === this.outsideProperty.name)
315
+ this.outsideProperty.dialogItemValue = value.value;
316
+ else if (value.propertyName === this.useDepthProperty.name)
317
+ this.useDepthProperty.dialogItemValue = value.value;
318
+ else if (value.propertyName === this.depthProperty.name)
319
+ this.depthProperty.dialogItemValue = value.value;
320
+ });
321
+ const toolSettings = new Array();
322
+ toolSettings.push(this.bothDirectionsProperty.toDialogItem({ rowPriority: 1, columnIndex: 0 }));
323
+ toolSettings.push(this.outsideProperty.toDialogItem({ rowPriority: 2, columnIndex: 0 }));
324
+ // ensure controls are enabled/disabled based on current lock property state
325
+ this.depthProperty.isDisabled = !this.useDepth;
326
+ const useDepthLock = this.useDepthProperty.toDialogItem({ rowPriority: 3, columnIndex: 0 });
327
+ toolSettings.push(this.depthProperty.toDialogItem({ rowPriority: 3, columnIndex: 1 }, useDepthLock));
328
+ return toolSettings;
329
+ }
219
330
  async onRestartTool() {
220
331
  const tool = new CutSolidElementsTool();
221
332
  if (!await tool.run())
@@ -353,13 +464,27 @@ export class FaceLocationData {
353
464
  }
354
465
  /** @alpha Identify faces of solids and surfaces to offset. */
355
466
  export class OffsetFacesTool extends LocateSubEntityTool {
356
- constructor() {
357
- super(...arguments);
358
- // TODO: Tool settings for offset distance...
359
- this.useOffset = false;
360
- this.offset = 0.1;
361
- this.addSmoothFaces = false;
362
- }
467
+ get addSmoothProperty() {
468
+ if (!this._addSmoothProperty)
469
+ this._addSmoothProperty = new DialogProperty(PropertyDescriptionHelper.buildToggleDescription("offsetSmooth", EditTools.translate("OffsetFaces.Label.AddSmooth")), false);
470
+ return this._addSmoothProperty;
471
+ }
472
+ get addSmooth() { return this.addSmoothProperty.value; }
473
+ set addSmooth(value) { this.addSmoothProperty.value = value; }
474
+ get useDistanceProperty() {
475
+ if (!this._useDistanceProperty)
476
+ this._useDistanceProperty = new DialogProperty(PropertyDescriptionHelper.buildLockPropertyDescription("useOffsetDistance"), false);
477
+ return this._useDistanceProperty;
478
+ }
479
+ get useDistance() { return this.useDistanceProperty.value; }
480
+ set useDistance(value) { this.useDistanceProperty.value = value; }
481
+ get distanceProperty() {
482
+ if (!this._distanceProperty)
483
+ this._distanceProperty = new DialogProperty(new LengthDescription("offsetDistance", EditTools.translate("OffsetFaces.Label.Distance")), 0.1, undefined, !this.useDistance);
484
+ return this._distanceProperty;
485
+ }
486
+ get distance() { return this.distanceProperty.value; }
487
+ set distance(value) { this.distanceProperty.value = value; }
363
488
  get wantDynamics() { return true; }
364
489
  get wantAccuSnap() { return this.isDynamicsStarted; }
365
490
  get geometryCacheFilter() {
@@ -403,7 +528,7 @@ export class OffsetFacesTool extends LocateSubEntityTool {
403
528
  if (undefined === projPt)
404
529
  return undefined;
405
530
  const offsetDir = Vector3d.createStartEnd(faceData.point, projPt);
406
- if (this.useOffset && undefined === offsetDir.scaleToLength(this.offset, offsetDir))
531
+ if (this.useDistance && undefined === offsetDir.scaleToLength(this.distance, offsetDir))
407
532
  return undefined;
408
533
  let offset = offsetDir.magnitude();
409
534
  if (offset < Geometry.smallMetricDistance)
@@ -414,7 +539,7 @@ export class OffsetFacesTool extends LocateSubEntityTool {
414
539
  this._startedCmd = await this.startCommand();
415
540
  const id = this.agenda.elements[0];
416
541
  const faces = this.getAcceptedSubEntities();
417
- if (this.addSmoothFaces) {
542
+ if (this.addSmooth) {
418
543
  const allSmoothFaces = [];
419
544
  for (const face of faces) {
420
545
  const smoothFaces = await this.getSmoothFaces(id, face);
@@ -455,6 +580,52 @@ export class OffsetFacesTool extends LocateSubEntityTool {
455
580
  hints.setXAxis2(faceData.normal);
456
581
  hints.sendHints(false);
457
582
  }
583
+ syncDistanceState() {
584
+ this.distanceProperty.displayValue = this.distanceProperty.description.format(this.distance);
585
+ this.distanceProperty.isDisabled = !this.useDistance;
586
+ this.syncToolSettingsProperties([this.distanceProperty.syncItem]);
587
+ }
588
+ async applyToolSettingPropertyChange(updatedValue) {
589
+ if (updatedValue.propertyName === this.addSmoothProperty.name) {
590
+ this.addSmooth = updatedValue.value.value;
591
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.addSmoothProperty.item);
592
+ return true;
593
+ }
594
+ else if (updatedValue.propertyName === this.useDistanceProperty.name) {
595
+ this.useDistance = updatedValue.value.value;
596
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.useDistanceProperty.item);
597
+ this.syncDistanceState();
598
+ return true;
599
+ }
600
+ else if (updatedValue.propertyName === this.distanceProperty.name) {
601
+ if (!updatedValue.value.value) {
602
+ this.syncDistanceState(); // force UI to redisplay last valid value
603
+ return false;
604
+ }
605
+ this.distance = updatedValue.value.value;
606
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.distanceProperty.item);
607
+ return true;
608
+ }
609
+ return false;
610
+ }
611
+ supplyToolSettingsProperties() {
612
+ var _a;
613
+ (_a = IModelApp.toolAdmin.toolSettingsState.getInitialToolSettingValues(this.toolId, [this.addSmoothProperty.name, this.useDistanceProperty.name, this.distanceProperty.name])) === null || _a === void 0 ? void 0 : _a.forEach((value) => {
614
+ if (value.propertyName === this.addSmoothProperty.name)
615
+ this.addSmoothProperty.dialogItemValue = value.value;
616
+ else if (value.propertyName === this.useDistanceProperty.name)
617
+ this.useDistanceProperty.dialogItemValue = value.value;
618
+ else if (value.propertyName === this.distanceProperty.name)
619
+ this.distanceProperty.dialogItemValue = value.value;
620
+ });
621
+ const toolSettings = new Array();
622
+ // ensure controls are enabled/disabled based on current lock property state
623
+ this.distanceProperty.isDisabled = !this.useDistance;
624
+ const useDistanceLock = this.useDistanceProperty.toDialogItem({ rowPriority: 1, columnIndex: 0 });
625
+ toolSettings.push(this.distanceProperty.toDialogItem({ rowPriority: 1, columnIndex: 1 }, useDistanceLock));
626
+ toolSettings.push(this.addSmoothProperty.toDialogItem({ rowPriority: 2, columnIndex: 0 }));
627
+ return toolSettings;
628
+ }
458
629
  async onRestartTool() {
459
630
  const tool = new OffsetFacesTool();
460
631
  if (!await tool.run())
@@ -465,12 +636,20 @@ OffsetFacesTool.toolId = "OffsetFaces";
465
636
  OffsetFacesTool.iconSpec = "icon-move"; // TODO: Need better icon...
466
637
  /** @alpha Identify faces to offset to hollow solids. */
467
638
  export class HollowFacesTool extends LocateSubEntityTool {
468
- constructor() {
469
- super(...arguments);
470
- // TODO: Tool settings for shell thickness and face thickness...
471
- this.shellThickness = 0.1;
472
- this.faceThickness = 0.0;
473
- }
639
+ get shellThicknessProperty() {
640
+ if (!this._shellThicknessProperty)
641
+ this._shellThicknessProperty = new DialogProperty(new LengthDescription("hollowShellThickness", EditTools.translate("HollowFaces.Label.ShellThickness")), 0.1, undefined);
642
+ return this._shellThicknessProperty;
643
+ }
644
+ get shellThickness() { return this.shellThicknessProperty.value; }
645
+ set shellThickness(value) { this.shellThicknessProperty.value = value; }
646
+ get faceThicknessProperty() {
647
+ if (!this._faceThicknessProperty)
648
+ this._faceThicknessProperty = new DialogProperty(new LengthDescription("hollowFaceThickness", EditTools.translate("HollowFaces.Label.FaceThickness")), 0.0, undefined);
649
+ return this._faceThicknessProperty;
650
+ }
651
+ get faceThickness() { return this.faceThicknessProperty.value; }
652
+ set faceThickness(value) { this.faceThicknessProperty.value = value; }
474
653
  get geometryCacheFilter() {
475
654
  return { parts: true, curves: false, surfaces: false, solids: true, other: false };
476
655
  }
@@ -492,6 +671,32 @@ export class HollowFacesTool extends LocateSubEntityTool {
492
671
  return undefined;
493
672
  }
494
673
  }
674
+ async applyToolSettingPropertyChange(updatedValue) {
675
+ if (updatedValue.propertyName === this.shellThicknessProperty.name) {
676
+ this.shellThickness = updatedValue.value.value;
677
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.shellThicknessProperty.item);
678
+ return true;
679
+ }
680
+ else if (updatedValue.propertyName === this.faceThicknessProperty.name) {
681
+ this.faceThickness = updatedValue.value.value;
682
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.faceThicknessProperty.item);
683
+ return true;
684
+ }
685
+ return false;
686
+ }
687
+ supplyToolSettingsProperties() {
688
+ var _a;
689
+ (_a = IModelApp.toolAdmin.toolSettingsState.getInitialToolSettingValues(this.toolId, [this.shellThicknessProperty.name, this.faceThicknessProperty.name])) === null || _a === void 0 ? void 0 : _a.forEach((value) => {
690
+ if (value.propertyName === this.shellThicknessProperty.name)
691
+ this.shellThicknessProperty.dialogItemValue = value.value;
692
+ else if (value.propertyName === this.faceThicknessProperty.name)
693
+ this.faceThicknessProperty.dialogItemValue = value.value;
694
+ });
695
+ const toolSettings = new Array();
696
+ toolSettings.push(this.shellThicknessProperty.toDialogItem({ rowPriority: 1, columnIndex: 0 }));
697
+ toolSettings.push(this.faceThicknessProperty.toDialogItem({ rowPriority: 2, columnIndex: 0 }));
698
+ return toolSettings;
699
+ }
495
700
  async onRestartTool() {
496
701
  const tool = new HollowFacesTool();
497
702
  if (!await tool.run())
@@ -580,12 +785,31 @@ export var ImprintSolidMethod;
580
785
  export class ImprintSolidElementsTool extends LocateSubEntityTool {
581
786
  constructor() {
582
787
  super(...arguments);
583
- // TODO: Tool settings for method, propagate for edges, offset distance...
584
- this.method = ImprintSolidMethod.Points;
585
788
  this.points = [];
586
- this.extend = true;
587
- this.distance = 0.1;
588
789
  }
790
+ static methodMessage(str) { return EditTools.translate(`ImprintSolids.Method.${str}`); }
791
+ get methodProperty() {
792
+ if (!this._methodProperty)
793
+ this._methodProperty = new DialogProperty(PropertyDescriptionHelper.buildEnumPicklistEditorDescription("imprintMethod", EditTools.translate("ImprintSolids.Label.Method"), ImprintSolidElementsTool.getMethodChoices()), ImprintSolidMethod.Element);
794
+ return this._methodProperty;
795
+ }
796
+ get method() { return this.methodProperty.value; }
797
+ set method(method) { this.methodProperty.value = method; }
798
+ get distanceProperty() {
799
+ if (!this._distanceProperty)
800
+ this._distanceProperty = new DialogProperty(new LengthDescription("imprintDistance", EditTools.translate("ImprintSolids.Label.Distance")), 0.1, undefined);
801
+ return this._distanceProperty;
802
+ }
803
+ get distance() { return this.distanceProperty.value; }
804
+ set distance(value) { this.distanceProperty.value = value; }
805
+ get extendProperty() {
806
+ if (!this._extendProperty)
807
+ this._extendProperty = new DialogProperty(PropertyDescriptionHelper.buildToggleDescription("imprintExtend", EditTools.translate("ImprintSolids.Label.Extend")), false);
808
+ return this._extendProperty;
809
+ }
810
+ get extend() { return this.extendProperty.value; }
811
+ set extend(value) { this.extendProperty.value = value; }
812
+ get requiredSubEntityCount() { return ImprintSolidMethod.Element === this.method ? 0 : 1; }
589
813
  get requiredElementCount() { return ImprintSolidMethod.Element === this.method ? 2 : 1; }
590
814
  get allowSubEntityControlSelect() { return ImprintSolidMethod.Edges === this.method; }
591
815
  get inhibitSubEntityDisplay() { return ImprintSolidMethod.Points === this.method ? false : super.inhibitSubEntityDisplay; }
@@ -708,6 +932,50 @@ export class ImprintSolidElementsTool extends LocateSubEntityTool {
708
932
  hints.setNormal(faceData.normal);
709
933
  hints.sendHints(false);
710
934
  }
935
+ async applyToolSettingPropertyChange(updatedValue) {
936
+ if (updatedValue.propertyName === this.methodProperty.name) {
937
+ this.method = updatedValue.value.value;
938
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.methodProperty.item);
939
+ await this.onReinitialize();
940
+ return true;
941
+ }
942
+ else if (updatedValue.propertyName === this.extendProperty.name) {
943
+ this.extend = updatedValue.value.value;
944
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.extendProperty.item);
945
+ return true;
946
+ }
947
+ else if (updatedValue.propertyName === this.distanceProperty.name) {
948
+ this.distance = updatedValue.value.value;
949
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.distanceProperty.item);
950
+ return true;
951
+ }
952
+ return false;
953
+ }
954
+ supplyToolSettingsProperties() {
955
+ var _a;
956
+ (_a = IModelApp.toolAdmin.toolSettingsState.getInitialToolSettingValues(this.toolId, [this.methodProperty.name, this.extendProperty.name, this.distanceProperty.name])) === null || _a === void 0 ? void 0 : _a.forEach((value) => {
957
+ if (value.propertyName === this.methodProperty.name)
958
+ this.methodProperty.dialogItemValue = value.value;
959
+ else if (value.propertyName === this.extendProperty.name)
960
+ this.extendProperty.dialogItemValue = value.value;
961
+ else if (value.propertyName === this.distanceProperty.name)
962
+ this.distanceProperty.dialogItemValue = value.value;
963
+ });
964
+ const toolSettings = new Array();
965
+ toolSettings.push(this.methodProperty.toDialogItem({ rowPriority: 1, columnIndex: 0 }));
966
+ switch (this.method) {
967
+ case ImprintSolidMethod.Element:
968
+ toolSettings.push(this.extendProperty.toDialogItem({ rowPriority: 2, columnIndex: 0 }));
969
+ break;
970
+ case ImprintSolidMethod.Edges:
971
+ toolSettings.push(this.distanceProperty.toDialogItem({ rowPriority: 2, columnIndex: 0 }));
972
+ break;
973
+ case ImprintSolidMethod.Points:
974
+ toolSettings.push(this.extendProperty.toDialogItem({ rowPriority: 2, columnIndex: 0 }));
975
+ break;
976
+ }
977
+ return toolSettings;
978
+ }
711
979
  async onRestartTool() {
712
980
  const tool = new ImprintSolidElementsTool();
713
981
  if (!await tool.run())
@@ -716,13 +984,22 @@ export class ImprintSolidElementsTool extends LocateSubEntityTool {
716
984
  }
717
985
  ImprintSolidElementsTool.toolId = "ImprintSolids";
718
986
  ImprintSolidElementsTool.iconSpec = "icon-move"; // TODO: Need better icon...
987
+ ImprintSolidElementsTool.getMethodChoices = () => {
988
+ return [
989
+ { label: ImprintSolidElementsTool.methodMessage("Element"), value: ImprintSolidMethod.Element },
990
+ { label: ImprintSolidElementsTool.methodMessage("Edges"), value: ImprintSolidMethod.Edges },
991
+ { label: ImprintSolidElementsTool.methodMessage("Points"), value: ImprintSolidMethod.Points },
992
+ ];
993
+ };
719
994
  /** @alpha Base class for tools to identify edges of solids and surfaces and apply blends. */
720
995
  export class BlendEdgesTool extends LocateSubEntityTool {
721
- constructor() {
722
- super(...arguments);
723
- // TODO: Tool settings for tangent edge propagation...
724
- this.propagateSmooth = true;
996
+ get addSmoothProperty() {
997
+ if (!this._addSmoothProperty)
998
+ this._addSmoothProperty = new DialogProperty(PropertyDescriptionHelper.buildToggleDescription("blendSmooth", EditTools.translate("RoundEdges.Label.AddSmooth")), false);
999
+ return this._addSmoothProperty;
725
1000
  }
1001
+ get addSmooth() { return this.addSmoothProperty.value; }
1002
+ set addSmooth(value) { this.addSmoothProperty.value = value; }
726
1003
  wantSubEntityType(type) { return SubEntityType.Edge === type; }
727
1004
  getSubEntityFilter() {
728
1005
  return { laminarEdges: true, smoothEdges: true };
@@ -773,16 +1050,26 @@ export class BlendEdgesTool extends LocateSubEntityTool {
773
1050
  const primaryEdge = (undefined !== edgeData.toolData ? edgeData.toolData : edgeData.props);
774
1051
  this._acceptedSubEntities = this._acceptedSubEntities.filter((entry) => !isTangentEdge(entry));
775
1052
  }
1053
+ async syncTangentEdges() {
1054
+ const id = this.getCurrentElement();
1055
+ if (undefined === id)
1056
+ return;
1057
+ if (this.addSmooth)
1058
+ await this.addTangentEdges(id);
1059
+ else
1060
+ await this.removeTangentEdges(id);
1061
+ IModelApp.viewManager.invalidateDecorationsAllViews();
1062
+ }
776
1063
  async addSubEntity(id, props) {
777
1064
  await super.addSubEntity(id, props);
778
- if (!this.propagateSmooth)
1065
+ if (!this.addSmooth)
779
1066
  return;
780
1067
  const chordTolerance = (this.targetView ? computeChordToleranceFromPoint(this.targetView, Point3d.fromJSON(props.point)) : undefined);
781
1068
  return this.addTangentEdges(id, props.subEntity, chordTolerance);
782
1069
  }
783
1070
  async removeSubEntity(id, props) {
784
1071
  var _a;
785
- if (!this.propagateSmooth)
1072
+ if (!this.addSmooth)
786
1073
  return super.removeSubEntity(id, props);
787
1074
  const edge = (undefined !== props) ? props.subEntity : (_a = this.getAcceptedSubEntityData()) === null || _a === void 0 ? void 0 : _a.props;
788
1075
  if (undefined === edge)
@@ -798,17 +1085,19 @@ export class BlendEdgesTool extends LocateSubEntityTool {
798
1085
  }
799
1086
  /** @alpha Identify edges of solids and surfaces to apply a rolling ball blend to. */
800
1087
  export class RoundEdgesTool extends BlendEdgesTool {
801
- constructor() {
802
- super(...arguments);
803
- // TODO: Tool settings for blend radius...
804
- this.radius = 0.5;
1088
+ get radiusProperty() {
1089
+ if (!this._radiusProperty)
1090
+ this._radiusProperty = new DialogProperty(new LengthDescription("roundRadius", EditTools.translate("RoundEdges.Label.Radius")), 0.1, undefined);
1091
+ return this._radiusProperty;
805
1092
  }
1093
+ get radius() { return this.radiusProperty.value; }
1094
+ set radius(value) { this.radiusProperty.value = value; }
806
1095
  async applyAgendaOperation(ev, isAccept) {
807
1096
  if (undefined === ev.viewport || this.agenda.isEmpty || !this.haveAcceptedSubEntities)
808
1097
  return undefined;
809
1098
  try {
810
1099
  this._startedCmd = await this.startCommand();
811
- const params = { edges: this.getAcceptedSubEntities(), radii: this.radius, propagateSmooth: this.propagateSmooth };
1100
+ const params = { edges: this.getAcceptedSubEntities(), radii: this.radius, propagateSmooth: this.addSmooth };
812
1101
  const opts = {
813
1102
  wantGraphic: isAccept ? undefined : true,
814
1103
  chordTolerance: computeChordToleranceFromPoint(ev.viewport, ev.point),
@@ -821,6 +1110,33 @@ export class RoundEdgesTool extends BlendEdgesTool {
821
1110
  return undefined;
822
1111
  }
823
1112
  }
1113
+ async applyToolSettingPropertyChange(updatedValue) {
1114
+ if (updatedValue.propertyName === this.radiusProperty.name) {
1115
+ this.radius = updatedValue.value.value;
1116
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.radiusProperty.item);
1117
+ return true;
1118
+ }
1119
+ else if (updatedValue.propertyName === this.addSmoothProperty.name) {
1120
+ this.addSmooth = updatedValue.value.value;
1121
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.addSmoothProperty.item);
1122
+ await this.syncTangentEdges();
1123
+ return true;
1124
+ }
1125
+ return false;
1126
+ }
1127
+ supplyToolSettingsProperties() {
1128
+ var _a;
1129
+ (_a = IModelApp.toolAdmin.toolSettingsState.getInitialToolSettingValues(this.toolId, [this.radiusProperty.name, this.addSmoothProperty.name])) === null || _a === void 0 ? void 0 : _a.forEach((value) => {
1130
+ if (value.propertyName === this.radiusProperty.name)
1131
+ this.radiusProperty.dialogItemValue = value.value;
1132
+ else if (value.propertyName === this.addSmoothProperty.name)
1133
+ this.addSmoothProperty.dialogItemValue = value.value;
1134
+ });
1135
+ const toolSettings = new Array();
1136
+ toolSettings.push(this.radiusProperty.toDialogItem({ rowPriority: 1, columnIndex: 0 }));
1137
+ toolSettings.push(this.addSmoothProperty.toDialogItem({ rowPriority: 2, columnIndex: 0 }));
1138
+ return toolSettings;
1139
+ }
824
1140
  async onRestartTool() {
825
1141
  const tool = new RoundEdgesTool();
826
1142
  if (!await tool.run())
@@ -831,18 +1147,69 @@ RoundEdgesTool.toolId = "RoundEdges";
831
1147
  RoundEdgesTool.iconSpec = "icon-move"; // TODO: Need better icon...
832
1148
  /** @alpha Identify edges of solids and surfaces to apply a rolling ball blend to. */
833
1149
  export class ChamferEdgesTool extends BlendEdgesTool {
834
- constructor() {
835
- super(...arguments);
836
- // TODO: Tool settings for chamfer length, distances, distance + angle...
837
- this.mode = ChamferMode.Length;
838
- this.length = 0.5;
839
- }
1150
+ static methodMessage(str) { return EditTools.translate(`ChamferEdges.Method.${str}`); }
1151
+ get methodProperty() {
1152
+ if (!this._methodProperty)
1153
+ this._methodProperty = new DialogProperty(PropertyDescriptionHelper.buildEnumPicklistEditorDescription("chamferMethod", EditTools.translate("ChamferEdges.Label.Method"), ChamferEdgesTool.getMethodChoices()), ChamferMode.Length);
1154
+ return this._methodProperty;
1155
+ }
1156
+ get method() { return this.methodProperty.value; }
1157
+ set method(method) { this.methodProperty.value = method; }
1158
+ get lengthProperty() {
1159
+ if (!this._lengthProperty)
1160
+ this._lengthProperty = new DialogProperty(new LengthDescription("chamferLength", EditTools.translate("ChamferEdges.Label.Length")), 0.1, undefined);
1161
+ return this._lengthProperty;
1162
+ }
1163
+ get length() { return this.lengthProperty.value; }
1164
+ set length(value) { this.lengthProperty.value = value; }
1165
+ get distanceLeftProperty() {
1166
+ if (!this._distanceLeftProperty)
1167
+ this._distanceLeftProperty = new DialogProperty(new LengthDescription("chamferLeftDist", EditTools.translate("ChamferEdges.Label.LeftDistance")), 0.1, undefined);
1168
+ return this._distanceLeftProperty;
1169
+ }
1170
+ get distanceLeft() { return this.distanceLeftProperty.value; }
1171
+ set distanceLeft(value) { this.distanceLeftProperty.value = value; }
1172
+ get distanceRightProperty() {
1173
+ if (!this._distanceRightProperty)
1174
+ this._distanceRightProperty = new DialogProperty(new LengthDescription("chamferRightDist", EditTools.translate("ChamferEdges.Label.RightDistance")), 0.1, undefined);
1175
+ return this._distanceRightProperty;
1176
+ }
1177
+ get distanceRight() { return this.distanceRightProperty.value; }
1178
+ set distanceRight(value) { this.distanceRightProperty.value = value; }
1179
+ get angleProperty() {
1180
+ if (!this._angleProperty)
1181
+ this._angleProperty = new DialogProperty(new AngleDescription("chamferAngle", EditTools.translate("ChamferEdges.Label.Angle")), Angle.piOver4Radians, undefined, false);
1182
+ return this._angleProperty;
1183
+ }
1184
+ get angle() { return this.angleProperty.value; }
1185
+ set angle(value) { this.angleProperty.value = value; }
840
1186
  async applyAgendaOperation(ev, isAccept) {
841
1187
  if (undefined === ev.viewport || this.agenda.isEmpty || !this.haveAcceptedSubEntities)
842
1188
  return undefined;
843
1189
  try {
844
1190
  this._startedCmd = await this.startCommand();
845
- const params = { edges: this.getAcceptedSubEntities(), mode: this.mode, values1: this.length, propagateSmooth: this.propagateSmooth };
1191
+ let values1;
1192
+ let values2;
1193
+ switch (this.method) {
1194
+ case ChamferMode.Length:
1195
+ values1 = this.length;
1196
+ break;
1197
+ case ChamferMode.Distances:
1198
+ values1 = this.distanceLeft;
1199
+ values2 = this.distanceRight;
1200
+ break;
1201
+ case ChamferMode.DistanceAngle:
1202
+ values1 = this.distanceLeft;
1203
+ values2 = this.angle;
1204
+ break;
1205
+ case ChamferMode.AngleDistance:
1206
+ values1 = this.angle;
1207
+ values2 = this.distanceRight;
1208
+ break;
1209
+ default:
1210
+ return undefined;
1211
+ }
1212
+ const params = { edges: this.getAcceptedSubEntities(), mode: this.method, values1, values2, propagateSmooth: this.addSmooth };
846
1213
  const opts = {
847
1214
  wantGraphic: isAccept ? undefined : true,
848
1215
  chordTolerance: computeChordToleranceFromPoint(ev.viewport, ev.point),
@@ -855,6 +1222,78 @@ export class ChamferEdgesTool extends BlendEdgesTool {
855
1222
  return undefined;
856
1223
  }
857
1224
  }
1225
+ async applyToolSettingPropertyChange(updatedValue) {
1226
+ if (updatedValue.propertyName === this.methodProperty.name) {
1227
+ this.method = updatedValue.value.value;
1228
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.methodProperty.item);
1229
+ await this.onReinitialize();
1230
+ return true;
1231
+ }
1232
+ else if (updatedValue.propertyName === this.addSmoothProperty.name) {
1233
+ this.addSmooth = updatedValue.value.value;
1234
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.addSmoothProperty.item);
1235
+ return true;
1236
+ }
1237
+ else if (updatedValue.propertyName === this.lengthProperty.name) {
1238
+ this.length = updatedValue.value.value;
1239
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.lengthProperty.item);
1240
+ return true;
1241
+ }
1242
+ else if (updatedValue.propertyName === this.distanceLeftProperty.name) {
1243
+ this.distanceLeft = updatedValue.value.value;
1244
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.distanceLeftProperty.item);
1245
+ return true;
1246
+ }
1247
+ else if (updatedValue.propertyName === this.distanceRightProperty.name) {
1248
+ this.distanceRight = updatedValue.value.value;
1249
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.distanceRightProperty.item);
1250
+ return true;
1251
+ }
1252
+ else if (updatedValue.propertyName === this.angleProperty.name) {
1253
+ this.angle = updatedValue.value.value;
1254
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.angleProperty.item);
1255
+ return true;
1256
+ }
1257
+ return false;
1258
+ }
1259
+ supplyToolSettingsProperties() {
1260
+ var _a;
1261
+ (_a = IModelApp.toolAdmin.toolSettingsState.getInitialToolSettingValues(this.toolId, [this.methodProperty.name, this.addSmoothProperty.name, this.lengthProperty.name, this.distanceLeftProperty.name, this.distanceRightProperty.name, this.angleProperty.name])) === null || _a === void 0 ? void 0 : _a.forEach((value) => {
1262
+ if (value.propertyName === this.methodProperty.name)
1263
+ this.methodProperty.dialogItemValue = value.value;
1264
+ else if (value.propertyName === this.addSmoothProperty.name)
1265
+ this.addSmoothProperty.dialogItemValue = value.value;
1266
+ else if (value.propertyName === this.lengthProperty.name)
1267
+ this.lengthProperty.dialogItemValue = value.value;
1268
+ else if (value.propertyName === this.distanceLeftProperty.name)
1269
+ this.distanceLeftProperty.dialogItemValue = value.value;
1270
+ else if (value.propertyName === this.distanceRightProperty.name)
1271
+ this.distanceRightProperty.dialogItemValue = value.value;
1272
+ else if (value.propertyName === this.angleProperty.name)
1273
+ this.angleProperty.dialogItemValue = value.value;
1274
+ });
1275
+ const toolSettings = new Array();
1276
+ toolSettings.push(this.methodProperty.toDialogItem({ rowPriority: 1, columnIndex: 0 }));
1277
+ toolSettings.push(this.addSmoothProperty.toDialogItem({ rowPriority: ChamferMode.Length === this.method ? 3 : 4, columnIndex: 0 }));
1278
+ switch (this.method) {
1279
+ case ChamferMode.Length:
1280
+ toolSettings.push(this.lengthProperty.toDialogItem({ rowPriority: 2, columnIndex: 0 }));
1281
+ break;
1282
+ case ChamferMode.Distances:
1283
+ toolSettings.push(this.distanceLeftProperty.toDialogItem({ rowPriority: 2, columnIndex: 0 }));
1284
+ toolSettings.push(this.distanceRightProperty.toDialogItem({ rowPriority: 3, columnIndex: 0 }));
1285
+ break;
1286
+ case ChamferMode.DistanceAngle:
1287
+ toolSettings.push(this.distanceLeftProperty.toDialogItem({ rowPriority: 2, columnIndex: 0 }));
1288
+ toolSettings.push(this.angleProperty.toDialogItem({ rowPriority: 3, columnIndex: 0 }));
1289
+ break;
1290
+ case ChamferMode.AngleDistance:
1291
+ toolSettings.push(this.distanceRightProperty.toDialogItem({ rowPriority: 2, columnIndex: 0 }));
1292
+ toolSettings.push(this.angleProperty.toDialogItem({ rowPriority: 3, columnIndex: 0 }));
1293
+ break;
1294
+ }
1295
+ return toolSettings;
1296
+ }
858
1297
  async onRestartTool() {
859
1298
  const tool = new ChamferEdgesTool();
860
1299
  if (!await tool.run())
@@ -863,6 +1302,14 @@ export class ChamferEdgesTool extends BlendEdgesTool {
863
1302
  }
864
1303
  ChamferEdgesTool.toolId = "ChamferEdges";
865
1304
  ChamferEdgesTool.iconSpec = "icon-move"; // TODO: Need better icon...
1305
+ ChamferEdgesTool.getMethodChoices = () => {
1306
+ return [
1307
+ { label: ChamferEdgesTool.methodMessage("Length"), value: ChamferMode.Length },
1308
+ { label: ChamferEdgesTool.methodMessage("Distances"), value: ChamferMode.Distances },
1309
+ { label: ChamferEdgesTool.methodMessage("DistanceAngle"), value: ChamferMode.DistanceAngle },
1310
+ { label: ChamferEdgesTool.methodMessage("AngleDistance"), value: ChamferMode.AngleDistance },
1311
+ ];
1312
+ };
866
1313
  /** @alpha */
867
1314
  export class ProfileLocationData {
868
1315
  constructor(point, orientation) {
@@ -928,16 +1375,30 @@ export class LocateFaceOrProfileTool extends LocateSubEntityTool {
928
1375
  }
929
1376
  /** @alpha Identify faces of solids and surfaces to translate. */
930
1377
  export class SweepFacesTool extends LocateFaceOrProfileTool {
931
- constructor() {
932
- super(...arguments);
933
- // TODO: Tool settings for sweep distance...
934
- this.useDistance = false;
935
- this.distance = 0.1;
936
- this.addSmoothFaces = false;
937
- }
938
1378
  get wantDynamics() { return true; }
939
1379
  get wantAccuSnap() { return true; }
940
1380
  get wantSubEntitySnap() { return true; }
1381
+ get addSmoothProperty() {
1382
+ if (!this._addSmoothProperty)
1383
+ this._addSmoothProperty = new DialogProperty(PropertyDescriptionHelper.buildToggleDescription("sweepSmooth", EditTools.translate("SweepFaces.Label.AddSmooth")), false);
1384
+ return this._addSmoothProperty;
1385
+ }
1386
+ get addSmooth() { return this.addSmoothProperty.value; }
1387
+ set addSmooth(value) { this.addSmoothProperty.value = value; }
1388
+ get useDistanceProperty() {
1389
+ if (!this._useDistanceProperty)
1390
+ this._useDistanceProperty = new DialogProperty(PropertyDescriptionHelper.buildLockPropertyDescription("useOffsetDistance"), false);
1391
+ return this._useDistanceProperty;
1392
+ }
1393
+ get useDistance() { return this.useDistanceProperty.value; }
1394
+ set useDistance(value) { this.useDistanceProperty.value = value; }
1395
+ get distanceProperty() {
1396
+ if (!this._distanceProperty)
1397
+ this._distanceProperty = new DialogProperty(new LengthDescription("sweepDistance", EditTools.translate("SweepFaces.Label.Distance")), 0.1, undefined, !this.useDistance);
1398
+ return this._distanceProperty;
1399
+ }
1400
+ get distance() { return this.distanceProperty.value; }
1401
+ set distance(value) { this.distanceProperty.value = value; }
941
1402
  async getSmoothFaces(id, face) {
942
1403
  try {
943
1404
  // NOTE: For sweep/translation, it makes sense to limit smooth to immediately adjacent...
@@ -973,7 +1434,7 @@ export class SweepFacesTool extends LocateFaceOrProfileTool {
973
1434
  if (SubEntityType.Edge === subEntities[0].type || BRepEntityType.Solid !== this.getBRepEntityTypeForSubEntity(id, subEntities[0])) {
974
1435
  return await ElementGeometryCacheTool.callCommand("sweepFaces", id, params, opts);
975
1436
  }
976
- if (this.addSmoothFaces) {
1437
+ if (this.addSmooth) {
977
1438
  const allSmoothFaces = [];
978
1439
  for (const face of subEntities) {
979
1440
  const smoothFaces = await this.getSmoothFaces(id, face);
@@ -1008,6 +1469,52 @@ export class SweepFacesTool extends LocateFaceOrProfileTool {
1008
1469
  hints.setXAxis2(profileData.orientation instanceof Matrix3d ? profileData.orientation.getColumn(2) : profileData.orientation);
1009
1470
  hints.sendHints(false);
1010
1471
  }
1472
+ syncDistanceState() {
1473
+ this.distanceProperty.displayValue = this.distanceProperty.description.format(this.distance);
1474
+ this.distanceProperty.isDisabled = !this.useDistance;
1475
+ this.syncToolSettingsProperties([this.distanceProperty.syncItem]);
1476
+ }
1477
+ async applyToolSettingPropertyChange(updatedValue) {
1478
+ if (updatedValue.propertyName === this.addSmoothProperty.name) {
1479
+ this.addSmooth = updatedValue.value.value;
1480
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.addSmoothProperty.item);
1481
+ return true;
1482
+ }
1483
+ else if (updatedValue.propertyName === this.useDistanceProperty.name) {
1484
+ this.useDistance = updatedValue.value.value;
1485
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.useDistanceProperty.item);
1486
+ this.syncDistanceState();
1487
+ return true;
1488
+ }
1489
+ else if (updatedValue.propertyName === this.distanceProperty.name) {
1490
+ if (!updatedValue.value.value) {
1491
+ this.syncDistanceState(); // force UI to redisplay last valid value
1492
+ return false;
1493
+ }
1494
+ this.distance = updatedValue.value.value;
1495
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.distanceProperty.item);
1496
+ return true;
1497
+ }
1498
+ return false;
1499
+ }
1500
+ supplyToolSettingsProperties() {
1501
+ var _a;
1502
+ (_a = IModelApp.toolAdmin.toolSettingsState.getInitialToolSettingValues(this.toolId, [this.addSmoothProperty.name, this.useDistanceProperty.name, this.distanceProperty.name])) === null || _a === void 0 ? void 0 : _a.forEach((value) => {
1503
+ if (value.propertyName === this.addSmoothProperty.name)
1504
+ this.addSmoothProperty.dialogItemValue = value.value;
1505
+ else if (value.propertyName === this.useDistanceProperty.name)
1506
+ this.useDistanceProperty.dialogItemValue = value.value;
1507
+ else if (value.propertyName === this.distanceProperty.name)
1508
+ this.distanceProperty.dialogItemValue = value.value;
1509
+ });
1510
+ const toolSettings = new Array();
1511
+ // ensure controls are enabled/disabled based on current lock property state
1512
+ this.distanceProperty.isDisabled = !this.useDistance;
1513
+ const useDistanceLock = this.useDistanceProperty.toDialogItem({ rowPriority: 1, columnIndex: 0 });
1514
+ toolSettings.push(this.distanceProperty.toDialogItem({ rowPriority: 1, columnIndex: 1 }, useDistanceLock));
1515
+ toolSettings.push(this.addSmoothProperty.toDialogItem({ rowPriority: 2, columnIndex: 0 }));
1516
+ return toolSettings;
1517
+ }
1011
1518
  async onRestartTool() {
1012
1519
  const tool = new SweepFacesTool();
1013
1520
  if (!await tool.run())
@@ -1020,10 +1527,15 @@ SweepFacesTool.iconSpec = "icon-move"; // TODO: Need better icon...
1020
1527
  export class SpinFacesTool extends LocateFaceOrProfileTool {
1021
1528
  constructor() {
1022
1529
  super(...arguments);
1023
- // TODO: Tool settings for sweep angle...
1024
- this.sweep = Angle.piOver2Radians;
1025
1530
  this.points = [];
1026
1531
  }
1532
+ get angleProperty() {
1533
+ if (!this._angleProperty)
1534
+ this._angleProperty = new DialogProperty(new AngleDescription("spinAngle", EditTools.translate("SpinFaces.Label.Angle")), Angle.piOver2Radians, undefined, false);
1535
+ return this._angleProperty;
1536
+ }
1537
+ get angle() { return this.angleProperty.value; }
1538
+ set angle(value) { this.angleProperty.value = value; }
1027
1539
  get wantDynamics() { return true; }
1028
1540
  get wantAccuSnap() { return true; }
1029
1541
  get wantSubEntitySnap() { return true; }
@@ -1034,7 +1546,7 @@ export class SpinFacesTool extends LocateFaceOrProfileTool {
1034
1546
  if (direction.magnitude() < Geometry.smallMetricDistance)
1035
1547
  return undefined;
1036
1548
  const origin = this.points[0];
1037
- const angle = Angle.createRadians(this.sweep);
1549
+ const angle = Angle.createRadians(this.angle);
1038
1550
  try {
1039
1551
  this._startedCmd = await this.startCommand();
1040
1552
  const id = this.agenda.elements[0];
@@ -1097,6 +1609,24 @@ export class SpinFacesTool extends LocateFaceOrProfileTool {
1097
1609
  hints.setNormal(profileData.orientation);
1098
1610
  hints.sendHints(false);
1099
1611
  }
1612
+ async applyToolSettingPropertyChange(updatedValue) {
1613
+ if (updatedValue.propertyName === this.angleProperty.name) {
1614
+ this.angle = updatedValue.value.value;
1615
+ IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, this.angleProperty.item);
1616
+ return true;
1617
+ }
1618
+ return false;
1619
+ }
1620
+ supplyToolSettingsProperties() {
1621
+ var _a;
1622
+ (_a = IModelApp.toolAdmin.toolSettingsState.getInitialToolSettingValues(this.toolId, [this.angleProperty.name])) === null || _a === void 0 ? void 0 : _a.forEach((value) => {
1623
+ if (value.propertyName === this.angleProperty.name)
1624
+ this.angleProperty.dialogItemValue = value.value;
1625
+ });
1626
+ const toolSettings = new Array();
1627
+ toolSettings.push(this.angleProperty.toDialogItem({ rowPriority: 1, columnIndex: 0 }));
1628
+ return toolSettings;
1629
+ }
1100
1630
  async onRestartTool() {
1101
1631
  const tool = new SpinFacesTool();
1102
1632
  if (!await tool.run())