brep-io-kernel 1.0.17 → 1.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-kernel/brep-kernel.js +13547 -12034
- package/package.json +1 -1
- package/src/FeatureRegistry.js +3 -0
- package/src/PartHistory.js +141 -0
- package/src/UI/CADmaterials.js +2 -2
- package/src/UI/MainToolbar.js +39 -2
- package/src/UI/SelectionFilter.js +438 -0
- package/src/UI/featureDialogWidgets/booleanOperationField.js +33 -52
- package/src/UI/featureDialogWidgets/referenceSelectionField.js +10 -0
- package/src/UI/featureDialogs.js +841 -8
- package/src/UI/history/HistoryCollectionWidget.js +20 -1
- package/src/UI/pmi/AnnotationRegistry.js +3 -0
- package/src/UI/toolbarButtons/orientToFaceButton.js +3 -0
- package/src/UI/toolbarButtons/registerDefaultButtons.js +0 -6
- package/src/UI/toolbarButtons/registerSelectionButtons.js +68 -0
- package/src/UI/viewer.js +22 -4
- package/src/assemblyConstraints/AssemblyConstraintRegistry.js +3 -0
- package/src/features/boolean/BooleanFeature.js +15 -0
- package/src/features/chamfer/ChamferFeature.js +12 -0
- package/src/features/extrude/ExtrudeFeature.js +11 -0
- package/src/features/fillet/FilletFeature.js +12 -0
- package/src/features/hole/HoleFeature.js +15 -0
- package/src/features/loft/LoftFeature.js +17 -0
- package/src/features/mirror/MirrorFeature.js +14 -0
- package/src/features/patternLinear/PatternLinearFeature.js +9 -0
- package/src/features/patternRadial/PatternRadialFeature.js +13 -0
- package/src/features/plane/PlaneFeature.js +10 -0
- package/src/features/revolve/RevolveFeature.js +15 -0
- package/src/features/sketch/SketchFeature.js +11 -0
- package/src/features/sweep/SweepFeature.js +17 -0
- package/src/features/transform/TransformFeature.js +12 -0
- package/src/features/tube/TubeFeature.js +12 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { SchemaForm } from '../featureDialogs.js';
|
|
2
|
+
import { SelectionFilter } from '../SelectionFilter.js';
|
|
2
3
|
import { resolveEntryId, resolveHistoryDisplayInfo } from './historyDisplayInfo.js';
|
|
3
4
|
import { HISTORY_COLLECTION_WIDGET_CSS } from './historyCollectionWidget.css.js';
|
|
4
5
|
|
|
@@ -43,6 +44,8 @@ export class HistoryCollectionWidget {
|
|
|
43
44
|
this._addMenu = null;
|
|
44
45
|
this._onGlobalClick = null;
|
|
45
46
|
this._globalRefreshHandler = null;
|
|
47
|
+
this._contextSuppressKey = `hc-${Math.random().toString(36).slice(2, 9)}`;
|
|
48
|
+
this._contextSuppressActive = false;
|
|
46
49
|
|
|
47
50
|
this.uiElement = document.createElement('div');
|
|
48
51
|
this.uiElement.className = 'history-collection-widget-host';
|
|
@@ -100,6 +103,7 @@ export class HistoryCollectionWidget {
|
|
|
100
103
|
}
|
|
101
104
|
|
|
102
105
|
dispose() {
|
|
106
|
+
this._setContextSuppression(false);
|
|
103
107
|
if (typeof this._listenerUnsub === 'function') {
|
|
104
108
|
try { this._listenerUnsub(); } catch (_) {}
|
|
105
109
|
}
|
|
@@ -152,6 +156,7 @@ export class HistoryCollectionWidget {
|
|
|
152
156
|
this._listEl.textContent = '';
|
|
153
157
|
|
|
154
158
|
if (!entries.length) {
|
|
159
|
+
this._setContextSuppression(false);
|
|
155
160
|
const empty = document.createElement('div');
|
|
156
161
|
empty.className = 'hc-empty';
|
|
157
162
|
empty.textContent = 'No entries yet.';
|
|
@@ -185,6 +190,7 @@ export class HistoryCollectionWidget {
|
|
|
185
190
|
targetId = null;
|
|
186
191
|
}
|
|
187
192
|
this._expandedId = targetId;
|
|
193
|
+
this._setContextSuppression(!!this._expandedId);
|
|
188
194
|
|
|
189
195
|
for (let i = 0; i < entries.length; i++) {
|
|
190
196
|
const entry = entries[i];
|
|
@@ -589,12 +595,24 @@ export class HistoryCollectionWidget {
|
|
|
589
595
|
}
|
|
590
596
|
|
|
591
597
|
_notifyEntryToggle(entry, isOpen) {
|
|
598
|
+
this._setContextSuppression(!!isOpen);
|
|
592
599
|
if (!this._onEntryToggle) return;
|
|
593
600
|
try {
|
|
594
601
|
this._onEntryToggle(entry || null, isOpen);
|
|
595
602
|
} catch (_) { /* ignore toggle hook errors */ }
|
|
596
603
|
}
|
|
597
604
|
|
|
605
|
+
_setContextSuppression(isOpen) {
|
|
606
|
+
const next = !!isOpen;
|
|
607
|
+
if (this._contextSuppressActive === next) return;
|
|
608
|
+
this._contextSuppressActive = next;
|
|
609
|
+
if (SelectionFilter && typeof SelectionFilter.setContextBarSuppressed === 'function') {
|
|
610
|
+
try {
|
|
611
|
+
SelectionFilter.setContextBarSuppressed(this._contextSuppressKey, next);
|
|
612
|
+
} catch (_) { /* ignore */ }
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
|
|
598
616
|
async _moveEntry(id, delta) {
|
|
599
617
|
if (!id) return;
|
|
600
618
|
const entries = this._getEntries();
|
|
@@ -659,7 +677,7 @@ export class HistoryCollectionWidget {
|
|
|
659
677
|
this.render();
|
|
660
678
|
this._emitCollectionChange('add', entry);
|
|
661
679
|
this._deferScrollToEntry(createdEntryId);
|
|
662
|
-
return;
|
|
680
|
+
return entry;
|
|
663
681
|
}
|
|
664
682
|
const entry = await this._instantiateEntryForType(typeStr);
|
|
665
683
|
if (!entry) return;
|
|
@@ -680,6 +698,7 @@ export class HistoryCollectionWidget {
|
|
|
680
698
|
this.render();
|
|
681
699
|
this._emitCollectionChange('add', entry);
|
|
682
700
|
this._deferScrollToEntry(createdEntryId);
|
|
701
|
+
return entry;
|
|
683
702
|
}
|
|
684
703
|
|
|
685
704
|
_handleSchemaChange(id, entry, details) {
|
|
@@ -29,6 +29,9 @@ class AnnotationRegistry {
|
|
|
29
29
|
if (!ctor.longName) {
|
|
30
30
|
ctor.longName = ctor.featureName || ctor.name || ctor.shortName || ctor.type || 'Annotation';
|
|
31
31
|
}
|
|
32
|
+
if (typeof ctor.showContexButton !== 'function') {
|
|
33
|
+
ctor.showContexButton = () => false;
|
|
34
|
+
}
|
|
32
35
|
}
|
|
33
36
|
const typeKey = normalizeKey(
|
|
34
37
|
handler.type
|
|
@@ -92,7 +92,10 @@ function _orientCameraToFace(viewer, face) {
|
|
|
92
92
|
try { if (controls?.target) controls.target.copy(target); } catch {}
|
|
93
93
|
try { if (controls?._gizmos?.position) controls._gizmos.position.copy(target); } catch {}
|
|
94
94
|
try { controls?.update?.(); } catch {}
|
|
95
|
+
try { controls?._gizmos?.updateMatrix?.(); } catch {}
|
|
96
|
+
try { controls?._gizmos?.updateMatrixWorld?.(true); } catch {}
|
|
95
97
|
try { controls?.updateMatrixState?.(); } catch {}
|
|
98
|
+
try { controls?.saveState?.(); } catch {}
|
|
96
99
|
try { viewer.render?.(); } catch {}
|
|
97
100
|
|
|
98
101
|
return true;
|
|
@@ -4,10 +4,7 @@
|
|
|
4
4
|
import { createSaveButton } from './saveButton.js';
|
|
5
5
|
import { createUndoButton, createRedoButton } from './undoRedoButtons.js';
|
|
6
6
|
import { createZoomToFitButton } from './zoomToFitButton.js';
|
|
7
|
-
import { createOrientToFaceButton } from './orientToFaceButton.js';
|
|
8
7
|
import { createWireframeToggleButton } from './wireframeToggleButton.js';
|
|
9
|
-
import { createInspectorToggleButton } from './inspectorToggleButton.js';
|
|
10
|
-
import { createMetadataButton } from './metadataButton.js';
|
|
11
8
|
import { createImportButton } from './importButton.js';
|
|
12
9
|
import { createExportButton } from './exportButton.js';
|
|
13
10
|
import { createFlatPatternButton } from './flatPatternButton.js';
|
|
@@ -21,10 +18,7 @@ export function registerDefaultToolbarButtons(viewer) {
|
|
|
21
18
|
const creators = [
|
|
22
19
|
createSaveButton,
|
|
23
20
|
createZoomToFitButton,
|
|
24
|
-
createOrientToFaceButton,
|
|
25
21
|
createWireframeToggleButton,
|
|
26
|
-
createInspectorToggleButton,
|
|
27
|
-
createMetadataButton,
|
|
28
22
|
createImportButton,
|
|
29
23
|
createExportButton,
|
|
30
24
|
createFlatPatternButton,
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { SelectionFilter } from '../SelectionFilter.js';
|
|
2
|
+
import { createOrientToFaceButton } from './orientToFaceButton.js';
|
|
3
|
+
import { createInspectorToggleButton } from './inspectorToggleButton.js';
|
|
4
|
+
import { createMetadataButton } from './metadataButton.js';
|
|
5
|
+
|
|
6
|
+
const hasSelection = (items) => Array.isArray(items) && items.length > 0;
|
|
7
|
+
const hasType = (items, types) => {
|
|
8
|
+
if (!Array.isArray(items) || items.length === 0) return false;
|
|
9
|
+
const typeSet = new Set((types || []).map((t) => String(t || '').toUpperCase()));
|
|
10
|
+
if (typeSet.size === 0) return false;
|
|
11
|
+
return items.some((obj) => typeSet.has(String(obj?.type || '').toUpperCase()));
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export function registerSelectionToolbarButtons(viewer) {
|
|
15
|
+
if (!viewer || typeof SelectionFilter?.registerSelectionAction !== 'function') return;
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
SelectionFilter.registerSelectionAction({
|
|
20
|
+
id: 'selection-action-clear',
|
|
21
|
+
label: '␛',
|
|
22
|
+
title: 'Clear selection',
|
|
23
|
+
onClick: () => {
|
|
24
|
+
const scene = viewer?.partHistory?.scene || viewer?.scene || null;
|
|
25
|
+
if (scene) SelectionFilter.unselectAll(scene);
|
|
26
|
+
try { viewer?._hideSelectionOverlay?.(); } catch { }
|
|
27
|
+
},
|
|
28
|
+
shouldShow: (selection) => hasSelection(selection),
|
|
29
|
+
});
|
|
30
|
+
} catch { }
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
const perpSpec = createOrientToFaceButton(viewer);
|
|
36
|
+
if (perpSpec) {
|
|
37
|
+
SelectionFilter.registerSelectionAction({
|
|
38
|
+
id: 'selection-action-perp',
|
|
39
|
+
...perpSpec,
|
|
40
|
+
shouldShow: (selection) => hasType(selection, ['FACE', 'PLANE']),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
} catch { }
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
const inspectorSpec = createInspectorToggleButton(viewer);
|
|
47
|
+
if (inspectorSpec) {
|
|
48
|
+
SelectionFilter.registerSelectionAction({
|
|
49
|
+
id: 'selection-action-inspector',
|
|
50
|
+
...inspectorSpec,
|
|
51
|
+
shouldShow: (selection) => hasSelection(selection),
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
} catch { }
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const metadataSpec = createMetadataButton(viewer);
|
|
60
|
+
if (metadataSpec) {
|
|
61
|
+
SelectionFilter.registerSelectionAction({
|
|
62
|
+
id: 'selection-action-metadata',
|
|
63
|
+
...metadataSpec,
|
|
64
|
+
shouldShow: (selection) => hasSelection(selection),
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
} catch { }
|
|
68
|
+
}
|
package/src/UI/viewer.js
CHANGED
|
@@ -20,6 +20,7 @@ import './expressionsManager.js'
|
|
|
20
20
|
import { expressionsManager } from './expressionsManager.js';
|
|
21
21
|
import { MainToolbar } from './MainToolbar.js';
|
|
22
22
|
import { registerDefaultToolbarButtons } from './toolbarButtons/registerDefaultButtons.js';
|
|
23
|
+
import { registerSelectionToolbarButtons } from './toolbarButtons/registerSelectionButtons.js';
|
|
23
24
|
import { FileManagerWidget } from './fileManagerWidget.js';
|
|
24
25
|
import './mobile.js';
|
|
25
26
|
import { SketchMode3D } from './sketcher/SketchMode3D.js';
|
|
@@ -1239,6 +1240,9 @@ export class Viewer {
|
|
|
1239
1240
|
this.mainToolbar = new MainToolbar(this);
|
|
1240
1241
|
// Register core/default toolbar buttons via the public API
|
|
1241
1242
|
try { registerDefaultToolbarButtons(this); } catch { }
|
|
1243
|
+
// Register selection-context toolbar buttons (shown based on selection)
|
|
1244
|
+
try { registerSelectionToolbarButtons(this); } catch { }
|
|
1245
|
+
try { SelectionFilter.refreshSelectionActions?.(); } catch { }
|
|
1242
1246
|
// Drain any queued custom toolbar buttons from early plugin registration
|
|
1243
1247
|
try {
|
|
1244
1248
|
const q = Array.isArray(this._pendingToolbarButtons) ? this._pendingToolbarButtons : [];
|
|
@@ -3471,15 +3475,29 @@ export class Viewer {
|
|
|
3471
3475
|
// Inspector panel (toggle + update-on-click)
|
|
3472
3476
|
// ----------------------------------------
|
|
3473
3477
|
toggleInspectorPanel() { this._inspectorOpen ? this._closeInspectorPanel() : this._openInspectorPanel(); }
|
|
3478
|
+
_getInspectorSelectionTarget() {
|
|
3479
|
+
const last = this._lastInspectorTarget;
|
|
3480
|
+
if (last && last.selected) return last;
|
|
3481
|
+
const scene = this.partHistory?.scene || this.scene || null;
|
|
3482
|
+
if (!scene || typeof scene.traverse !== 'function') return null;
|
|
3483
|
+
let found = null;
|
|
3484
|
+
scene.traverse((obj) => {
|
|
3485
|
+
if (found || !obj || !obj.selected) return;
|
|
3486
|
+
found = obj;
|
|
3487
|
+
});
|
|
3488
|
+
return found;
|
|
3489
|
+
}
|
|
3474
3490
|
_openInspectorPanel() {
|
|
3475
3491
|
if (this._inspectorOpen) return;
|
|
3476
3492
|
this._ensureInspectorPanel();
|
|
3477
3493
|
this._inspectorEl.style.display = 'flex';
|
|
3478
3494
|
this._inspectorOpen = true;
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
this.
|
|
3482
|
-
|
|
3495
|
+
const target = this._getInspectorSelectionTarget();
|
|
3496
|
+
if (target) {
|
|
3497
|
+
try { this._updateInspectorFor(target); } catch { }
|
|
3498
|
+
return;
|
|
3499
|
+
}
|
|
3500
|
+
try { this._setInspectorPlaceholder('Click an object in the scene to inspect.'); } catch { }
|
|
3483
3501
|
}
|
|
3484
3502
|
_closeInspectorPanel() {
|
|
3485
3503
|
if (!this._inspectorOpen) return;
|
|
@@ -54,6 +54,9 @@ export class AssemblyConstraintRegistry {
|
|
|
54
54
|
if (!ConstraintClass.longName) {
|
|
55
55
|
ConstraintClass.longName = ConstraintClass.constraintName || ConstraintClass.name || ConstraintClass.shortName || 'Constraint';
|
|
56
56
|
}
|
|
57
|
+
if (typeof ConstraintClass.showContexButton !== 'function') {
|
|
58
|
+
ConstraintClass.showContexButton = () => false;
|
|
59
|
+
}
|
|
57
60
|
const keys = this.#collectKeys(ConstraintClass);
|
|
58
61
|
if (!keys.typeKey) return;
|
|
59
62
|
|
|
@@ -25,6 +25,21 @@ export class BooleanFeature {
|
|
|
25
25
|
static shortName = "B";
|
|
26
26
|
static longName = "Boolean";
|
|
27
27
|
static inputParamsSchema = inputParamsSchema;
|
|
28
|
+
static showContexButton(selectedItems) {
|
|
29
|
+
const items = Array.isArray(selectedItems) ? selectedItems : [];
|
|
30
|
+
const solids = items
|
|
31
|
+
.filter((it) => String(it?.type || '').toUpperCase() === 'SOLID')
|
|
32
|
+
.map((it) => it?.name)
|
|
33
|
+
.filter((name) => !!name);
|
|
34
|
+
if (solids.length < 2) return false;
|
|
35
|
+
const [targetSolid, ...tools] = solids;
|
|
36
|
+
return {
|
|
37
|
+
params: {
|
|
38
|
+
targetSolid,
|
|
39
|
+
boolean: { operation: 'UNION', targets: tools },
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
28
43
|
|
|
29
44
|
constructor() {
|
|
30
45
|
this.inputParams = {};
|
|
@@ -46,6 +46,18 @@ export class ChamferFeature {
|
|
|
46
46
|
static shortName = "CH";
|
|
47
47
|
static longName = "Chamfer";
|
|
48
48
|
static inputParamsSchema = inputParamsSchema;
|
|
49
|
+
static showContexButton(selectedItems) {
|
|
50
|
+
const items = Array.isArray(selectedItems) ? selectedItems : [];
|
|
51
|
+
const edges = items
|
|
52
|
+
.filter((it) => {
|
|
53
|
+
const type = String(it?.type || '').toUpperCase();
|
|
54
|
+
return type === 'EDGE' || type === 'FACE';
|
|
55
|
+
})
|
|
56
|
+
.map((it) => it?.name || it?.userData?.edgeName || it?.userData?.faceName)
|
|
57
|
+
.filter((name) => !!name);
|
|
58
|
+
if (!edges.length) return false;
|
|
59
|
+
return { params: { edges } };
|
|
60
|
+
}
|
|
49
61
|
|
|
50
62
|
constructor() {
|
|
51
63
|
this.inputParams = {};
|
|
@@ -41,6 +41,17 @@ export class ExtrudeFeature {
|
|
|
41
41
|
static shortName = "E";
|
|
42
42
|
static longName = "Extrude";
|
|
43
43
|
static inputParamsSchema = inputParamsSchema;
|
|
44
|
+
static showContexButton(selectedItems) {
|
|
45
|
+
const items = Array.isArray(selectedItems) ? selectedItems : [];
|
|
46
|
+
const pick = items.find((it) => {
|
|
47
|
+
const type = String(it?.type || '').toUpperCase();
|
|
48
|
+
return type === 'FACE' || type === 'SKETCH';
|
|
49
|
+
});
|
|
50
|
+
if (!pick) return false;
|
|
51
|
+
const name = pick?.name || pick?.userData?.faceName || pick?.userData?.edgeName || null;
|
|
52
|
+
if (!name) return false;
|
|
53
|
+
return { field: 'profile', value: name };
|
|
54
|
+
}
|
|
44
55
|
|
|
45
56
|
constructor() {
|
|
46
57
|
this.inputParams = {};
|
|
@@ -63,6 +63,18 @@ export class FilletFeature {
|
|
|
63
63
|
static shortName = "F";
|
|
64
64
|
static longName = "Fillet";
|
|
65
65
|
static inputParamsSchema = inputParamsSchema;
|
|
66
|
+
static showContexButton(selectedItems) {
|
|
67
|
+
const items = Array.isArray(selectedItems) ? selectedItems : [];
|
|
68
|
+
const edges = items
|
|
69
|
+
.filter((it) => {
|
|
70
|
+
const type = String(it?.type || '').toUpperCase();
|
|
71
|
+
return type === 'EDGE' || type === 'FACE';
|
|
72
|
+
})
|
|
73
|
+
.map((it) => it?.name || it?.userData?.edgeName || it?.userData?.faceName)
|
|
74
|
+
.filter((name) => !!name);
|
|
75
|
+
if (!edges.length) return false;
|
|
76
|
+
return { params: { edges } };
|
|
77
|
+
}
|
|
66
78
|
|
|
67
79
|
constructor() {
|
|
68
80
|
this.inputParams = {};
|
|
@@ -569,6 +569,21 @@ export class HoleFeature {
|
|
|
569
569
|
static shortName = 'H';
|
|
570
570
|
static longName = 'Hole';
|
|
571
571
|
static inputParamsSchema = inputParamsSchema;
|
|
572
|
+
static showContexButton(selectedItems) {
|
|
573
|
+
const items = Array.isArray(selectedItems) ? selectedItems : [];
|
|
574
|
+
const sketch = items.find((it) => {
|
|
575
|
+
const type = String(it?.type || '').toUpperCase();
|
|
576
|
+
if (type === 'SKETCH') return true;
|
|
577
|
+
if (it?.parent && String(it.parent.type || '').toUpperCase() === 'SKETCH') return true;
|
|
578
|
+
return false;
|
|
579
|
+
});
|
|
580
|
+
if (!sketch) return false;
|
|
581
|
+
const name = (String(sketch?.type || '').toUpperCase() === 'SKETCH')
|
|
582
|
+
? sketch.name
|
|
583
|
+
: sketch.parent?.name;
|
|
584
|
+
if (!name) return false;
|
|
585
|
+
return { field: 'face', value: name };
|
|
586
|
+
}
|
|
572
587
|
|
|
573
588
|
constructor() {
|
|
574
589
|
this.inputParams = {};
|
|
@@ -58,6 +58,23 @@ export class LoftFeature {
|
|
|
58
58
|
static shortName = "LOFT";
|
|
59
59
|
static longName = "Loft";
|
|
60
60
|
static inputParamsSchema = inputParamsSchema;
|
|
61
|
+
static showContexButton(selectedItems) {
|
|
62
|
+
const items = Array.isArray(selectedItems) ? selectedItems : [];
|
|
63
|
+
const profiles = items
|
|
64
|
+
.filter((it) => {
|
|
65
|
+
const type = String(it?.type || '').toUpperCase();
|
|
66
|
+
return type === 'FACE' || type === 'SKETCH';
|
|
67
|
+
})
|
|
68
|
+
.map((it) => {
|
|
69
|
+
if (!it) return null;
|
|
70
|
+
if (String(it.type || '').toUpperCase() === 'SKETCH') return it.name || null;
|
|
71
|
+
if (it.parent && String(it.parent.type || '').toUpperCase() === 'SKETCH') return it.parent.name || null;
|
|
72
|
+
return it.name || it.userData?.faceName || null;
|
|
73
|
+
})
|
|
74
|
+
.filter((name) => !!name);
|
|
75
|
+
if (profiles.length < 2) return false;
|
|
76
|
+
return { params: { profiles } };
|
|
77
|
+
}
|
|
61
78
|
|
|
62
79
|
constructor() {
|
|
63
80
|
this.inputParams = {};
|
|
@@ -35,6 +35,20 @@ export class MirrorFeature {
|
|
|
35
35
|
static longName = "Mirror";
|
|
36
36
|
|
|
37
37
|
static inputParamsSchema = inputParamsSchema;
|
|
38
|
+
static showContexButton(selectedItems) {
|
|
39
|
+
const items = Array.isArray(selectedItems) ? selectedItems : [];
|
|
40
|
+
const solids = items
|
|
41
|
+
.filter((it) => String(it?.type || '').toUpperCase() === 'SOLID')
|
|
42
|
+
.map((it) => it?.name)
|
|
43
|
+
.filter((name) => !!name);
|
|
44
|
+
const plane = items.find((it) => {
|
|
45
|
+
const type = String(it?.type || '').toUpperCase();
|
|
46
|
+
return type === 'FACE' || type === 'PLANE';
|
|
47
|
+
});
|
|
48
|
+
const planeName = plane?.name || plane?.userData?.faceName || null;
|
|
49
|
+
if (!solids.length || !planeName) return false;
|
|
50
|
+
return { params: { solids, mirrorPlane: planeName } };
|
|
51
|
+
}
|
|
38
52
|
|
|
39
53
|
constructor() {
|
|
40
54
|
this.inputParams = {};
|
|
@@ -34,6 +34,15 @@ export class PatternLinearFeature {
|
|
|
34
34
|
static shortName = "PATLIN";
|
|
35
35
|
static longName = "Pattern Linear";
|
|
36
36
|
static inputParamsSchema = inputParamsSchema;
|
|
37
|
+
static showContexButton(selectedItems) {
|
|
38
|
+
const items = Array.isArray(selectedItems) ? selectedItems : [];
|
|
39
|
+
const solids = items
|
|
40
|
+
.filter((it) => String(it?.type || '').toUpperCase() === 'SOLID')
|
|
41
|
+
.map((it) => it?.name)
|
|
42
|
+
.filter((name) => !!name);
|
|
43
|
+
if (!solids.length) return false;
|
|
44
|
+
return { params: { solids } };
|
|
45
|
+
}
|
|
37
46
|
|
|
38
47
|
constructor() {
|
|
39
48
|
this.inputParams = {};
|
|
@@ -49,6 +49,19 @@ export class PatternRadialFeature {
|
|
|
49
49
|
static shortName = "PATRAD";
|
|
50
50
|
static longName = "Pattern Radial";
|
|
51
51
|
static inputParamsSchema = inputParamsSchema;
|
|
52
|
+
static showContexButton(selectedItems) {
|
|
53
|
+
const items = Array.isArray(selectedItems) ? selectedItems : [];
|
|
54
|
+
const solids = items
|
|
55
|
+
.filter((it) => String(it?.type || '').toUpperCase() === 'SOLID')
|
|
56
|
+
.map((it) => it?.name)
|
|
57
|
+
.filter((name) => !!name);
|
|
58
|
+
if (!solids.length) return false;
|
|
59
|
+
const axis = items.find((it) => String(it?.type || '').toUpperCase() === 'EDGE');
|
|
60
|
+
const axisName = axis?.name || axis?.userData?.edgeName || null;
|
|
61
|
+
const params = { solids };
|
|
62
|
+
if (axisName) params.axisRef = axisName;
|
|
63
|
+
return { params };
|
|
64
|
+
}
|
|
52
65
|
|
|
53
66
|
constructor() {
|
|
54
67
|
this.inputParams = {};
|
|
@@ -46,6 +46,16 @@ export class PlaneFeature {
|
|
|
46
46
|
static shortName = "P";
|
|
47
47
|
static longName = "Plane";
|
|
48
48
|
static inputParamsSchema = inputParamsSchema;
|
|
49
|
+
static showContexButton(selectedItems) {
|
|
50
|
+
const items = Array.isArray(selectedItems) ? selectedItems : [];
|
|
51
|
+
const ref = items.find((it) => {
|
|
52
|
+
const type = String(it?.type || '').toUpperCase();
|
|
53
|
+
return type === 'FACE' || type === 'PLANE';
|
|
54
|
+
});
|
|
55
|
+
const name = ref?.name || ref?.userData?.faceName || null;
|
|
56
|
+
if (!name) return false;
|
|
57
|
+
return { field: 'datum', value: name };
|
|
58
|
+
}
|
|
49
59
|
|
|
50
60
|
constructor() {
|
|
51
61
|
this.inputParams = {};
|
|
@@ -47,6 +47,21 @@ export class RevolveFeature {
|
|
|
47
47
|
static shortName = "R";
|
|
48
48
|
static longName = "Revolve";
|
|
49
49
|
static inputParamsSchema = inputParamsSchema;
|
|
50
|
+
static showContexButton(selectedItems) {
|
|
51
|
+
const items = Array.isArray(selectedItems) ? selectedItems : [];
|
|
52
|
+
const profileObj = items.find((it) => {
|
|
53
|
+
const type = String(it?.type || '').toUpperCase();
|
|
54
|
+
return type === 'FACE' || type === 'SKETCH';
|
|
55
|
+
});
|
|
56
|
+
if (!profileObj) return false;
|
|
57
|
+
const profileName = profileObj?.name || profileObj?.userData?.faceName || null;
|
|
58
|
+
if (!profileName) return false;
|
|
59
|
+
const axisObj = items.find((it) => String(it?.type || '').toUpperCase() === 'EDGE');
|
|
60
|
+
const axisName = axisObj?.name || axisObj?.userData?.edgeName || null;
|
|
61
|
+
const params = { profile: profileName };
|
|
62
|
+
if (axisName) params.axis = axisName;
|
|
63
|
+
return { params };
|
|
64
|
+
}
|
|
50
65
|
|
|
51
66
|
constructor() {
|
|
52
67
|
this.inputParams = {};
|
|
@@ -82,6 +82,17 @@ export class SketchFeature {
|
|
|
82
82
|
static shortName = "S";
|
|
83
83
|
static longName = "Sketch";
|
|
84
84
|
static inputParamsSchema = inputParamsSchema;
|
|
85
|
+
static showContexButton(selectedItems) {
|
|
86
|
+
const items = Array.isArray(selectedItems) ? selectedItems : [];
|
|
87
|
+
const target = items.find((it) => {
|
|
88
|
+
const type = String(it?.type || '').toUpperCase();
|
|
89
|
+
return type === 'FACE' || type === 'PLANE';
|
|
90
|
+
});
|
|
91
|
+
if (!target) return false;
|
|
92
|
+
const name = target?.name || target?.userData?.faceName || null;
|
|
93
|
+
if (!name) return false;
|
|
94
|
+
return { field: 'sketchPlane', value: name };
|
|
95
|
+
}
|
|
85
96
|
|
|
86
97
|
constructor() {
|
|
87
98
|
this.inputParams = {};
|
|
@@ -48,6 +48,23 @@ export class SweepFeature {
|
|
|
48
48
|
static shortName = "SW";
|
|
49
49
|
static longName = "Sweep";
|
|
50
50
|
static inputParamsSchema = inputParamsSchema;
|
|
51
|
+
static showContexButton(selectedItems) {
|
|
52
|
+
const items = Array.isArray(selectedItems) ? selectedItems : [];
|
|
53
|
+
const profileObj = items.find((it) => {
|
|
54
|
+
const type = String(it?.type || '').toUpperCase();
|
|
55
|
+
return type === 'FACE' || type === 'SKETCH';
|
|
56
|
+
});
|
|
57
|
+
if (!profileObj) return false;
|
|
58
|
+
const profileName = profileObj?.name || profileObj?.userData?.faceName || null;
|
|
59
|
+
if (!profileName) return false;
|
|
60
|
+
const edges = items
|
|
61
|
+
.filter((it) => String(it?.type || '').toUpperCase() === 'EDGE')
|
|
62
|
+
.map((it) => it?.name || it?.userData?.edgeName)
|
|
63
|
+
.filter((name) => !!name);
|
|
64
|
+
const params = { profile: profileName };
|
|
65
|
+
if (edges.length) params.path = edges;
|
|
66
|
+
return { params };
|
|
67
|
+
}
|
|
51
68
|
|
|
52
69
|
constructor() {
|
|
53
70
|
this.inputParams = {};
|
|
@@ -57,6 +57,18 @@ export class TransformFeature {
|
|
|
57
57
|
static shortName = "XFORM";
|
|
58
58
|
static longName = "Transform";
|
|
59
59
|
static inputParamsSchema = inputParamsSchema;
|
|
60
|
+
static showContexButton(selectedItems) {
|
|
61
|
+
const items = Array.isArray(selectedItems) ? selectedItems : [];
|
|
62
|
+
const solids = items
|
|
63
|
+
.filter((it) => {
|
|
64
|
+
const type = String(it?.type || '').toUpperCase();
|
|
65
|
+
return type === 'SOLID';
|
|
66
|
+
})
|
|
67
|
+
.map((it) => it?.name)
|
|
68
|
+
.filter((name) => !!name);
|
|
69
|
+
if (!solids.length) return false;
|
|
70
|
+
return { params: { solids } };
|
|
71
|
+
}
|
|
60
72
|
|
|
61
73
|
constructor() {
|
|
62
74
|
this.inputParams = {};
|
|
@@ -332,6 +332,18 @@ export class TubeFeature {
|
|
|
332
332
|
static shortName = 'TU';
|
|
333
333
|
static longName = 'Tube';
|
|
334
334
|
static inputParamsSchema = inputParamsSchema;
|
|
335
|
+
static showContexButton(selectedItems) {
|
|
336
|
+
const items = Array.isArray(selectedItems) ? selectedItems : [];
|
|
337
|
+
if (items.some((it) => String(it?.type || '').toUpperCase() !== 'EDGE')) {
|
|
338
|
+
return false;
|
|
339
|
+
}
|
|
340
|
+
const edges = items
|
|
341
|
+
.filter((it) => String(it?.type || '').toUpperCase() === 'EDGE')
|
|
342
|
+
.map((it) => it?.name || it?.userData?.edgeName)
|
|
343
|
+
.filter((name) => !!name);
|
|
344
|
+
if (!edges.length) return false;
|
|
345
|
+
return { params: { path: edges } };
|
|
346
|
+
}
|
|
335
347
|
|
|
336
348
|
constructor() {
|
|
337
349
|
this.inputParams = {};
|