brep-io-kernel 1.0.17 → 1.0.18
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 +12652 -11749
- package/package.json +1 -1
- package/src/PartHistory.js +106 -0
- package/src/UI/CADmaterials.js +2 -2
- package/src/UI/MainToolbar.js +39 -2
- package/src/UI/SelectionFilter.js +194 -0
- package/src/UI/featureDialogWidgets/booleanOperationField.js +33 -52
- package/src/UI/featureDialogWidgets/referenceSelectionField.js +10 -0
- package/src/UI/featureDialogs.js +593 -7
- 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/UI/featureDialogs.js
CHANGED
|
@@ -2,11 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
import { SelectionFilter } from './SelectionFilter.js';
|
|
4
4
|
import * as THREE from 'three';
|
|
5
|
+
import { Line2, LineGeometry, LineMaterial } from 'three/examples/jsm/Addons.js';
|
|
5
6
|
// Use hybrid translate+rotate gizmo used by the Viewer
|
|
6
7
|
import { CombinedTransformControls } from './controls/CombinedTransformControls.js';
|
|
7
8
|
import { getWidgetRenderer } from './featureDialogWidgets/index.js';
|
|
8
9
|
import { normalizeReferenceList, normalizeReferenceName } from './featureDialogWidgets/utils.js';
|
|
9
|
-
|
|
10
|
+
const REF_PREVIEW_COLORS = {
|
|
11
|
+
EDGE: '#ff00ff',
|
|
12
|
+
FACE: '#ffc400',
|
|
13
|
+
PLANE: '#2eff2e',
|
|
14
|
+
VERTEX: '#00ffff',
|
|
15
|
+
};
|
|
10
16
|
|
|
11
17
|
|
|
12
18
|
|
|
@@ -29,6 +35,7 @@ export class SchemaForm {
|
|
|
29
35
|
if (prev && prev !== el) {
|
|
30
36
|
try { prev.style.filter = 'none'; } catch (_) { }
|
|
31
37
|
try { prev.removeAttribute('active-reference-selection'); } catch (_) { }
|
|
38
|
+
try { if (typeof prev.__refPreviewCleanup === 'function') prev.__refPreviewCleanup(); } catch (_) { }
|
|
32
39
|
}
|
|
33
40
|
} catch (_) { }
|
|
34
41
|
SchemaForm.__activeRefInput = el || null;
|
|
@@ -494,6 +501,502 @@ export class SchemaForm {
|
|
|
494
501
|
|| null;
|
|
495
502
|
}
|
|
496
503
|
|
|
504
|
+
_getReferencePreviewCacheRoot() {
|
|
505
|
+
const holder = this.options?.featureRef || this;
|
|
506
|
+
if (!holder) return null;
|
|
507
|
+
if (!holder.__refPreviewCache) {
|
|
508
|
+
try {
|
|
509
|
+
Object.defineProperty(holder, '__refPreviewCache', {
|
|
510
|
+
value: new Map(),
|
|
511
|
+
configurable: true,
|
|
512
|
+
enumerable: false,
|
|
513
|
+
writable: true,
|
|
514
|
+
});
|
|
515
|
+
} catch (_) {
|
|
516
|
+
holder.__refPreviewCache = new Map();
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
return holder.__refPreviewCache;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
_getReferencePreviewCache(inputEl) {
|
|
523
|
+
const root = this._getReferencePreviewCacheRoot();
|
|
524
|
+
if (!root) return null;
|
|
525
|
+
const key = (inputEl?.dataset?.key || inputEl?.dataset?.refKey || inputEl?.__refPreviewKey || '__default');
|
|
526
|
+
let bucket = root.get(key);
|
|
527
|
+
if (!bucket) {
|
|
528
|
+
bucket = new Map();
|
|
529
|
+
root.set(key, bucket);
|
|
530
|
+
}
|
|
531
|
+
return bucket;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
_getReferencePreviewPersistentBucket(inputEl) {
|
|
535
|
+
const entry = this.options?.featureRef || null;
|
|
536
|
+
if (!entry) return null;
|
|
537
|
+
if (!entry.persistentData || typeof entry.persistentData !== 'object') {
|
|
538
|
+
entry.persistentData = {};
|
|
539
|
+
}
|
|
540
|
+
if (!entry.persistentData.__refPreviewSnapshots || typeof entry.persistentData.__refPreviewSnapshots !== 'object') {
|
|
541
|
+
entry.persistentData.__refPreviewSnapshots = {};
|
|
542
|
+
}
|
|
543
|
+
const key = (inputEl?.dataset?.key || inputEl?.dataset?.refKey || inputEl?.__refPreviewKey || '__default');
|
|
544
|
+
if (!entry.persistentData.__refPreviewSnapshots[key] || typeof entry.persistentData.__refPreviewSnapshots[key] !== 'object') {
|
|
545
|
+
entry.persistentData.__refPreviewSnapshots[key] = {};
|
|
546
|
+
}
|
|
547
|
+
return entry.persistentData.__refPreviewSnapshots[key];
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
_resolveReferencePreviewName(obj) {
|
|
551
|
+
if (!obj) return null;
|
|
552
|
+
const raw = obj.name != null ? String(obj.name).trim() : '';
|
|
553
|
+
if (raw) return raw;
|
|
554
|
+
const type = obj.type || 'OBJECT';
|
|
555
|
+
const pos = obj.position || {};
|
|
556
|
+
const x = Number.isFinite(pos.x) ? pos.x : 0;
|
|
557
|
+
const y = Number.isFinite(pos.y) ? pos.y : 0;
|
|
558
|
+
const z = Number.isFinite(pos.z) ? pos.z : 0;
|
|
559
|
+
return `${type}(${x},${y},${z})`;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
_extractEdgeWorldPositions(obj) {
|
|
563
|
+
if (!obj) return [];
|
|
564
|
+
try {
|
|
565
|
+
if (typeof obj.points === 'function') {
|
|
566
|
+
const pts = obj.points(true);
|
|
567
|
+
if (Array.isArray(pts) && pts.length) {
|
|
568
|
+
const flat = [];
|
|
569
|
+
for (const p of pts) {
|
|
570
|
+
if (!p) continue;
|
|
571
|
+
const x = Number(p.x);
|
|
572
|
+
const y = Number(p.y);
|
|
573
|
+
const z = Number(p.z);
|
|
574
|
+
if (!Number.isFinite(x) || !Number.isFinite(y) || !Number.isFinite(z)) continue;
|
|
575
|
+
flat.push(x, y, z);
|
|
576
|
+
}
|
|
577
|
+
if (flat.length >= 6) return flat;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
} catch (_) { /* ignore */ }
|
|
581
|
+
|
|
582
|
+
try {
|
|
583
|
+
const geom = obj.geometry;
|
|
584
|
+
const pos = geom && typeof geom.getAttribute === 'function' ? geom.getAttribute('position') : null;
|
|
585
|
+
if (!pos || pos.itemSize !== 3 || pos.count < 2) return [];
|
|
586
|
+
const tmp = new THREE.Vector3();
|
|
587
|
+
const flat = [];
|
|
588
|
+
for (let i = 0; i < pos.count; i++) {
|
|
589
|
+
tmp.set(pos.getX(i), pos.getY(i), pos.getZ(i));
|
|
590
|
+
tmp.applyMatrix4(obj.matrixWorld);
|
|
591
|
+
flat.push(tmp.x, tmp.y, tmp.z);
|
|
592
|
+
}
|
|
593
|
+
return flat.length >= 6 ? flat : [];
|
|
594
|
+
} catch (_) { /* ignore */ }
|
|
595
|
+
return [];
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
_syncPreviewLineResolution(mat) {
|
|
599
|
+
if (!mat || !mat.resolution || typeof mat.resolution.set !== 'function') return;
|
|
600
|
+
let width = 0;
|
|
601
|
+
let height = 0;
|
|
602
|
+
try {
|
|
603
|
+
const viewer = this.options?.viewer || null;
|
|
604
|
+
const el = viewer?.renderer?.domElement || null;
|
|
605
|
+
if (el && typeof el.getBoundingClientRect === 'function') {
|
|
606
|
+
const rect = el.getBoundingClientRect();
|
|
607
|
+
width = rect.width || rect.right - rect.left;
|
|
608
|
+
height = rect.height || rect.bottom - rect.top;
|
|
609
|
+
}
|
|
610
|
+
if ((!width || !height) && viewer?.container) {
|
|
611
|
+
width = viewer.container.clientWidth || width;
|
|
612
|
+
height = viewer.container.clientHeight || height;
|
|
613
|
+
}
|
|
614
|
+
} catch (_) { /* ignore */ }
|
|
615
|
+
if (!width || !height) {
|
|
616
|
+
try {
|
|
617
|
+
if (typeof window !== 'undefined') {
|
|
618
|
+
width = window.innerWidth || width;
|
|
619
|
+
height = window.innerHeight || height;
|
|
620
|
+
}
|
|
621
|
+
} catch (_) { /* ignore */ }
|
|
622
|
+
}
|
|
623
|
+
if (Number.isFinite(width) && Number.isFinite(height) && width > 0 && height > 0) {
|
|
624
|
+
try { mat.resolution.set(width, height); } catch (_) { }
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
_createPreviewLineMaterial(sourceMat, colorHex = REF_PREVIEW_COLORS.EDGE) {
|
|
629
|
+
let mat = null;
|
|
630
|
+
if (sourceMat && typeof sourceMat.clone === 'function') {
|
|
631
|
+
try { mat = sourceMat.clone(); } catch (_) { mat = null; }
|
|
632
|
+
}
|
|
633
|
+
if (!mat) {
|
|
634
|
+
try {
|
|
635
|
+
mat = new LineMaterial({ color: colorHex, linewidth: 3, transparent: true, opacity: 0.95, worldUnits: false });
|
|
636
|
+
} catch (_) { mat = null; }
|
|
637
|
+
}
|
|
638
|
+
if (mat && mat.color && typeof mat.color.set === 'function') {
|
|
639
|
+
try { mat.color.set(colorHex); } catch (_) { }
|
|
640
|
+
}
|
|
641
|
+
if (mat) {
|
|
642
|
+
try { mat.transparent = true; } catch (_) { }
|
|
643
|
+
try { mat.opacity = Number.isFinite(mat.opacity) ? Math.min(0.95, mat.opacity) : 0.95; } catch (_) { }
|
|
644
|
+
try { mat.depthTest = false; } catch (_) { }
|
|
645
|
+
try { mat.depthWrite = false; } catch (_) { }
|
|
646
|
+
try { this._syncPreviewLineResolution(mat); } catch (_) { }
|
|
647
|
+
}
|
|
648
|
+
return mat;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
_createPreviewMeshMaterial(sourceMat, colorHex = REF_PREVIEW_COLORS.FACE) {
|
|
652
|
+
let mat = null;
|
|
653
|
+
if (sourceMat && typeof sourceMat.clone === 'function') {
|
|
654
|
+
try { mat = sourceMat.clone(); } catch (_) { mat = null; }
|
|
655
|
+
}
|
|
656
|
+
if (!mat) {
|
|
657
|
+
try {
|
|
658
|
+
mat = new THREE.MeshStandardMaterial({
|
|
659
|
+
color: colorHex,
|
|
660
|
+
transparent: true,
|
|
661
|
+
opacity: 0.25,
|
|
662
|
+
depthWrite: false,
|
|
663
|
+
side: THREE.DoubleSide,
|
|
664
|
+
});
|
|
665
|
+
} catch (_) { mat = null; }
|
|
666
|
+
}
|
|
667
|
+
if (mat && mat.color && typeof mat.color.set === 'function') {
|
|
668
|
+
try { mat.color.set(colorHex); } catch (_) { }
|
|
669
|
+
}
|
|
670
|
+
if (mat) {
|
|
671
|
+
try { mat.transparent = true; } catch (_) { }
|
|
672
|
+
try { mat.opacity = 0.25; } catch (_) { }
|
|
673
|
+
try { mat.depthWrite = false; } catch (_) { }
|
|
674
|
+
try { mat.depthTest = true; } catch (_) { }
|
|
675
|
+
try { mat.side = THREE.DoubleSide; } catch (_) { }
|
|
676
|
+
try { mat.polygonOffset = true; mat.polygonOffsetFactor = -1; mat.polygonOffsetUnits = -1; } catch (_) { }
|
|
677
|
+
}
|
|
678
|
+
return mat;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
_createPreviewPointMaterial(sourceMat, colorHex = REF_PREVIEW_COLORS.VERTEX) {
|
|
682
|
+
let mat = null;
|
|
683
|
+
if (sourceMat && typeof sourceMat.clone === 'function') {
|
|
684
|
+
try { mat = sourceMat.clone(); } catch (_) { mat = null; }
|
|
685
|
+
}
|
|
686
|
+
if (!mat || !mat.isPointsMaterial) {
|
|
687
|
+
try {
|
|
688
|
+
mat = new THREE.PointsMaterial({
|
|
689
|
+
color: colorHex,
|
|
690
|
+
size: 7,
|
|
691
|
+
sizeAttenuation: false,
|
|
692
|
+
transparent: true,
|
|
693
|
+
opacity: 0.9,
|
|
694
|
+
});
|
|
695
|
+
} catch (_) { mat = null; }
|
|
696
|
+
}
|
|
697
|
+
if (mat && mat.color && typeof mat.color.set === 'function') {
|
|
698
|
+
try { mat.color.set(colorHex); } catch (_) { }
|
|
699
|
+
}
|
|
700
|
+
if (mat) {
|
|
701
|
+
try { mat.transparent = true; } catch (_) { }
|
|
702
|
+
try { mat.opacity = 0.9; } catch (_) { }
|
|
703
|
+
}
|
|
704
|
+
return mat;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
_configurePreviewObject(obj, refName, previewType) {
|
|
708
|
+
if (!obj) return obj;
|
|
709
|
+
try { obj.name = `__refPreview__${refName}`; } catch (_) { }
|
|
710
|
+
try {
|
|
711
|
+
obj.userData = obj.userData || {};
|
|
712
|
+
obj.userData.refPreview = true;
|
|
713
|
+
obj.userData.refName = refName;
|
|
714
|
+
obj.userData.previewType = previewType;
|
|
715
|
+
obj.userData.excludeFromFit = true;
|
|
716
|
+
} catch (_) { }
|
|
717
|
+
try { obj.renderOrder = Math.max(10050, obj.renderOrder || 0); } catch (_) { }
|
|
718
|
+
try { obj.raycast = () => { }; } catch (_) { }
|
|
719
|
+
try {
|
|
720
|
+
obj.traverse?.((child) => {
|
|
721
|
+
if (!child || child === obj) return;
|
|
722
|
+
try { child.raycast = () => { }; } catch (_) { }
|
|
723
|
+
try {
|
|
724
|
+
child.userData = child.userData || {};
|
|
725
|
+
child.userData.refPreview = true;
|
|
726
|
+
child.userData.refName = refName;
|
|
727
|
+
} catch (_) { }
|
|
728
|
+
});
|
|
729
|
+
} catch (_) { }
|
|
730
|
+
return obj;
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
_getOwningFeatureIdForObject(obj) {
|
|
734
|
+
let cur = obj;
|
|
735
|
+
let guard = 0;
|
|
736
|
+
while (cur && guard < 8) {
|
|
737
|
+
if (cur.owningFeatureID != null) return cur.owningFeatureID;
|
|
738
|
+
cur = cur.parent || null;
|
|
739
|
+
guard += 1;
|
|
740
|
+
}
|
|
741
|
+
return null;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
_buildReferencePreviewObject(obj, refName) {
|
|
745
|
+
if (!obj) return null;
|
|
746
|
+
const type = String(obj.type || '').toUpperCase();
|
|
747
|
+
if (type === SelectionFilter.EDGE || type === 'EDGE') {
|
|
748
|
+
const positions = this._extractEdgeWorldPositions(obj);
|
|
749
|
+
if (!positions || positions.length < 6) return null;
|
|
750
|
+
const geom = new LineGeometry();
|
|
751
|
+
geom.setPositions(positions);
|
|
752
|
+
try { geom.computeBoundingSphere(); } catch (_) { }
|
|
753
|
+
const mat = this._createPreviewLineMaterial(obj.material, REF_PREVIEW_COLORS.EDGE);
|
|
754
|
+
const line = new Line2(geom, mat || undefined);
|
|
755
|
+
try { line.computeLineDistances?.(); } catch (_) { }
|
|
756
|
+
line.type = 'REF_PREVIEW_EDGE';
|
|
757
|
+
return this._configurePreviewObject(line, refName, 'EDGE');
|
|
758
|
+
}
|
|
759
|
+
if (type === SelectionFilter.FACE || type === SelectionFilter.PLANE || type === 'FACE' || type === 'PLANE') {
|
|
760
|
+
const geom = obj.geometry && typeof obj.geometry.clone === 'function' ? obj.geometry.clone() : null;
|
|
761
|
+
if (!geom) return null;
|
|
762
|
+
try { geom.applyMatrix4(obj.matrixWorld); } catch (_) { }
|
|
763
|
+
const color = (type === SelectionFilter.PLANE || type === 'PLANE') ? REF_PREVIEW_COLORS.PLANE : REF_PREVIEW_COLORS.FACE;
|
|
764
|
+
const mat = this._createPreviewMeshMaterial(obj.material, color);
|
|
765
|
+
const mesh = new THREE.Mesh(geom, mat || undefined);
|
|
766
|
+
mesh.type = (type === SelectionFilter.PLANE || type === 'PLANE') ? 'REF_PREVIEW_PLANE' : 'REF_PREVIEW_FACE';
|
|
767
|
+
try { mesh.matrixAutoUpdate = false; } catch (_) { }
|
|
768
|
+
return this._configurePreviewObject(mesh, refName, mesh.type);
|
|
769
|
+
}
|
|
770
|
+
if (type === SelectionFilter.VERTEX || type === 'VERTEX') {
|
|
771
|
+
const pos = new THREE.Vector3();
|
|
772
|
+
try {
|
|
773
|
+
if (typeof obj.getWorldPosition === 'function') obj.getWorldPosition(pos);
|
|
774
|
+
else pos.set(obj.position?.x || 0, obj.position?.y || 0, obj.position?.z || 0);
|
|
775
|
+
} catch (_) { }
|
|
776
|
+
const geom = new THREE.BufferGeometry();
|
|
777
|
+
geom.setAttribute('position', new THREE.Float32BufferAttribute([0, 0, 0], 3));
|
|
778
|
+
const mat = this._createPreviewPointMaterial(obj.material, REF_PREVIEW_COLORS.VERTEX);
|
|
779
|
+
const pts = new THREE.Points(geom, mat || undefined);
|
|
780
|
+
pts.position.copy(pos);
|
|
781
|
+
pts.type = 'REF_PREVIEW_VERTEX';
|
|
782
|
+
return this._configurePreviewObject(pts, refName, 'VERTEX');
|
|
783
|
+
}
|
|
784
|
+
return null;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
_buildReferencePreviewFromSnapshot(refName, snapshot) {
|
|
788
|
+
if (!snapshot || !refName) return null;
|
|
789
|
+
const type = String(snapshot.type || '').toUpperCase();
|
|
790
|
+
if (type === 'EDGE') {
|
|
791
|
+
const positions = Array.isArray(snapshot.positions) ? snapshot.positions : null;
|
|
792
|
+
if (!positions || positions.length < 6) return null;
|
|
793
|
+
const geom = new LineGeometry();
|
|
794
|
+
geom.setPositions(positions);
|
|
795
|
+
try { geom.computeBoundingSphere(); } catch (_) { }
|
|
796
|
+
const mat = this._createPreviewLineMaterial(null, REF_PREVIEW_COLORS.EDGE);
|
|
797
|
+
const line = new Line2(geom, mat || undefined);
|
|
798
|
+
try { line.computeLineDistances?.(); } catch (_) { }
|
|
799
|
+
line.type = 'REF_PREVIEW_EDGE';
|
|
800
|
+
return this._configurePreviewObject(line, refName, 'EDGE');
|
|
801
|
+
}
|
|
802
|
+
if (type === 'VERTEX') {
|
|
803
|
+
const pos = snapshot.position;
|
|
804
|
+
if (!Array.isArray(pos) || pos.length < 3) return null;
|
|
805
|
+
const geom = new THREE.BufferGeometry();
|
|
806
|
+
geom.setAttribute('position', new THREE.Float32BufferAttribute([0, 0, 0], 3));
|
|
807
|
+
const mat = this._createPreviewPointMaterial(null, REF_PREVIEW_COLORS.VERTEX);
|
|
808
|
+
const pts = new THREE.Points(geom, mat || undefined);
|
|
809
|
+
pts.position.set(Number(pos[0]) || 0, Number(pos[1]) || 0, Number(pos[2]) || 0);
|
|
810
|
+
pts.type = 'REF_PREVIEW_VERTEX';
|
|
811
|
+
return this._configurePreviewObject(pts, refName, 'VERTEX');
|
|
812
|
+
}
|
|
813
|
+
return null;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
_ensureReferencePreviewGroup(inputEl) {
|
|
817
|
+
const scene = this._getReferenceSelectionScene();
|
|
818
|
+
if (!scene || !inputEl) return null;
|
|
819
|
+
const existing = inputEl.__refPreviewGroup;
|
|
820
|
+
if (existing && existing.isObject3D) {
|
|
821
|
+
if (existing.parent !== scene) {
|
|
822
|
+
try { scene.add(existing); } catch (_) { }
|
|
823
|
+
}
|
|
824
|
+
return existing;
|
|
825
|
+
}
|
|
826
|
+
const group = new THREE.Group();
|
|
827
|
+
try { group.name = `__REF_PREVIEW_GROUP__${inputEl?.dataset?.key || ''}`; } catch (_) { }
|
|
828
|
+
try {
|
|
829
|
+
group.userData = group.userData || {};
|
|
830
|
+
group.userData.preventRemove = true;
|
|
831
|
+
group.userData.excludeFromFit = true;
|
|
832
|
+
group.userData.refPreview = true;
|
|
833
|
+
} catch (_) { }
|
|
834
|
+
try { group.renderOrder = 10040; } catch (_) { }
|
|
835
|
+
try { group.raycast = () => { }; } catch (_) { }
|
|
836
|
+
inputEl.__refPreviewGroup = group;
|
|
837
|
+
try { scene.add(group); } catch (_) { }
|
|
838
|
+
return group;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
_removeReferencePreviewGroup(inputEl) {
|
|
842
|
+
const group = inputEl?.__refPreviewGroup;
|
|
843
|
+
if (!group || !group.isObject3D) return;
|
|
844
|
+
try { if (group.userData) group.userData.preventRemove = false; } catch (_) { }
|
|
845
|
+
try { if (group.parent) group.parent.remove(group); } catch (_) { }
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
_syncActiveReferenceSelectionPreview(inputEl, def = null) {
|
|
849
|
+
try {
|
|
850
|
+
const active = SchemaForm.__activeRefInput;
|
|
851
|
+
if (!active || active !== inputEl) return;
|
|
852
|
+
const scene = this._getReferenceSelectionScene();
|
|
853
|
+
if (!scene) return;
|
|
854
|
+
const names = this._collectReferenceSelectionNames(inputEl, def);
|
|
855
|
+
if (!names.length) {
|
|
856
|
+
this._removeReferencePreviewGroup(inputEl);
|
|
857
|
+
return;
|
|
858
|
+
}
|
|
859
|
+
const cache = this._getReferencePreviewCache(inputEl);
|
|
860
|
+
if (!cache || cache.size === 0) return;
|
|
861
|
+
const group = this._ensureReferencePreviewGroup(inputEl);
|
|
862
|
+
const wanted = new Set(names);
|
|
863
|
+
if (group && Array.isArray(group.children)) {
|
|
864
|
+
for (const child of group.children.slice()) {
|
|
865
|
+
const refName = child?.userData?.refName;
|
|
866
|
+
if (!refName || !wanted.has(refName)) {
|
|
867
|
+
try { group.remove(child); } catch (_) { }
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
for (const name of names) {
|
|
872
|
+
const entry = cache.get(name);
|
|
873
|
+
let ghost = entry && entry.object ? entry.object : entry;
|
|
874
|
+
if (!ghost) continue;
|
|
875
|
+
const sourceUuid = entry?.sourceUuid || null;
|
|
876
|
+
let originalPresent = false;
|
|
877
|
+
if (sourceUuid && typeof scene.getObjectByProperty === 'function') {
|
|
878
|
+
try { originalPresent = !!scene.getObjectByProperty('uuid', sourceUuid); } catch (_) { originalPresent = false; }
|
|
879
|
+
} else {
|
|
880
|
+
const real = scene.getObjectByName(name);
|
|
881
|
+
originalPresent = !!real;
|
|
882
|
+
}
|
|
883
|
+
if (originalPresent) {
|
|
884
|
+
if (ghost.parent === group) {
|
|
885
|
+
try { group.remove(ghost); } catch (_) { }
|
|
886
|
+
}
|
|
887
|
+
continue;
|
|
888
|
+
}
|
|
889
|
+
if (ghost.parent !== group) {
|
|
890
|
+
try { group.add(ghost); } catch (_) { }
|
|
891
|
+
}
|
|
892
|
+
try { ghost.visible = true; } catch (_) { }
|
|
893
|
+
}
|
|
894
|
+
} catch (_) { }
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
_seedReferencePreviewCacheFromScene(inputEl, def = null, names = null, sceneOverride = null) {
|
|
898
|
+
if (!inputEl) return;
|
|
899
|
+
const scene = sceneOverride || this._getReferenceSelectionScene();
|
|
900
|
+
if (!scene) return;
|
|
901
|
+
const list = Array.isArray(names) ? names : this._collectReferenceSelectionNames(inputEl, def);
|
|
902
|
+
if (!list.length) return;
|
|
903
|
+
const cache = this._getReferencePreviewCache(inputEl);
|
|
904
|
+
if (!cache) return;
|
|
905
|
+
const store = this._getReferencePreviewPersistentBucket(inputEl);
|
|
906
|
+
for (const name of list) {
|
|
907
|
+
if (!name || cache.has(name)) continue;
|
|
908
|
+
const obj = scene.getObjectByName(name);
|
|
909
|
+
if (obj && !obj?.userData?.refPreview) {
|
|
910
|
+
this._storeReferencePreviewSnapshot(inputEl, def, obj);
|
|
911
|
+
continue;
|
|
912
|
+
}
|
|
913
|
+
if (store && store[name]) {
|
|
914
|
+
const snapshot = store[name];
|
|
915
|
+
const ghost = this._buildReferencePreviewFromSnapshot(name, snapshot);
|
|
916
|
+
if (ghost) {
|
|
917
|
+
cache.set(name, {
|
|
918
|
+
object: ghost,
|
|
919
|
+
type: snapshot.type || null,
|
|
920
|
+
sourceUuid: snapshot.sourceUuid || null,
|
|
921
|
+
sourceFeatureId: snapshot.sourceFeatureId || null,
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
_storeReferencePreviewSnapshot(inputEl, def, obj) {
|
|
929
|
+
try {
|
|
930
|
+
if (!inputEl || !obj) return;
|
|
931
|
+
const refName = this._resolveReferencePreviewName(obj);
|
|
932
|
+
if (!refName) return;
|
|
933
|
+
const cache = this._getReferencePreviewCache(inputEl);
|
|
934
|
+
if (!cache) return;
|
|
935
|
+
const ghost = this._buildReferencePreviewObject(obj, refName);
|
|
936
|
+
if (!ghost) return;
|
|
937
|
+
const sourceUuid = obj.uuid || null;
|
|
938
|
+
const sourceFeatureId = this._getOwningFeatureIdForObject(obj);
|
|
939
|
+
cache.set(refName, {
|
|
940
|
+
object: ghost,
|
|
941
|
+
type: obj.type || null,
|
|
942
|
+
sourceUuid,
|
|
943
|
+
sourceFeatureId,
|
|
944
|
+
});
|
|
945
|
+
try {
|
|
946
|
+
const store = this._getReferencePreviewPersistentBucket(inputEl);
|
|
947
|
+
if (store) {
|
|
948
|
+
const objType = String(obj.type || '').toUpperCase();
|
|
949
|
+
if (objType === SelectionFilter.EDGE || objType === 'EDGE') {
|
|
950
|
+
const positions = this._extractEdgeWorldPositions(obj);
|
|
951
|
+
if (positions && positions.length >= 6) {
|
|
952
|
+
store[refName] = { type: 'EDGE', positions, sourceUuid, sourceFeatureId };
|
|
953
|
+
}
|
|
954
|
+
} else if (objType === SelectionFilter.VERTEX || objType === 'VERTEX') {
|
|
955
|
+
const pos = new THREE.Vector3();
|
|
956
|
+
try {
|
|
957
|
+
if (typeof obj.getWorldPosition === 'function') obj.getWorldPosition(pos);
|
|
958
|
+
else pos.set(obj.position?.x || 0, obj.position?.y || 0, obj.position?.z || 0);
|
|
959
|
+
} catch (_) { }
|
|
960
|
+
store[refName] = { type: 'VERTEX', position: [pos.x, pos.y, pos.z], sourceUuid, sourceFeatureId };
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
} catch (_) { }
|
|
964
|
+
if (SchemaForm.__activeRefInput === inputEl) {
|
|
965
|
+
try { this._syncActiveReferenceSelectionPreview(inputEl, def); } catch (_) { }
|
|
966
|
+
}
|
|
967
|
+
} catch (_) { }
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
_startReferencePreviewWatcher(inputEl, def) {
|
|
971
|
+
if (!inputEl) return;
|
|
972
|
+
if (this._refPreviewWatcher && this._refPreviewWatcher.inputEl === inputEl) return;
|
|
973
|
+
this._stopReferencePreviewWatcher();
|
|
974
|
+
const tick = () => {
|
|
975
|
+
if (!this._refPreviewWatcher || this._refPreviewWatcher.inputEl !== inputEl) return;
|
|
976
|
+
if (SchemaForm.__activeRefInput !== inputEl) {
|
|
977
|
+
this._stopReferencePreviewWatcher();
|
|
978
|
+
return;
|
|
979
|
+
}
|
|
980
|
+
try { this._syncActiveReferenceSelectionPreview(inputEl, def); } catch (_) { }
|
|
981
|
+
this._refPreviewWatcher.timer = setTimeout(tick, 300);
|
|
982
|
+
};
|
|
983
|
+
this._refPreviewWatcher = { inputEl, timer: null };
|
|
984
|
+
inputEl.__refPreviewCleanup = () => {
|
|
985
|
+
try { this._stopReferencePreviewWatcher(); } catch (_) { }
|
|
986
|
+
try { this._removeReferencePreviewGroup(inputEl); } catch (_) { }
|
|
987
|
+
};
|
|
988
|
+
tick();
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
_stopReferencePreviewWatcher() {
|
|
992
|
+
if (!this._refPreviewWatcher) return;
|
|
993
|
+
const timer = this._refPreviewWatcher.timer;
|
|
994
|
+
if (timer) {
|
|
995
|
+
clearTimeout(timer);
|
|
996
|
+
}
|
|
997
|
+
this._refPreviewWatcher = null;
|
|
998
|
+
}
|
|
999
|
+
|
|
497
1000
|
_collectReferenceSelectionNames(inputEl, def = null) {
|
|
498
1001
|
if (!inputEl) return [];
|
|
499
1002
|
const isMulti = Boolean(def && def.multiple) || (inputEl.dataset && inputEl.dataset.multiple === 'true');
|
|
@@ -530,11 +1033,48 @@ export class SchemaForm {
|
|
|
530
1033
|
const scene = this._getReferenceSelectionScene();
|
|
531
1034
|
if (!scene) return;
|
|
532
1035
|
const names = this._collectReferenceSelectionNames(inputEl, def);
|
|
1036
|
+
try { this._seedReferencePreviewCacheFromScene(inputEl, def, names, scene); } catch (_) { }
|
|
533
1037
|
SelectionFilter.unselectAll(scene);
|
|
534
1038
|
for (const name of names) {
|
|
535
1039
|
if (!name) continue;
|
|
536
1040
|
try { SelectionFilter.selectItem(scene, name); } catch (_) { }
|
|
537
1041
|
}
|
|
1042
|
+
try { this._syncActiveReferenceSelectionPreview(inputEl, def); } catch (_) { }
|
|
1043
|
+
} catch (_) { }
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
_hoverReferenceSelectionItem(inputEl, def, name) {
|
|
1047
|
+
try {
|
|
1048
|
+
if (!inputEl || SchemaForm.__activeRefInput !== inputEl) return;
|
|
1049
|
+
const normalized = normalizeReferenceName(name);
|
|
1050
|
+
if (!normalized) return;
|
|
1051
|
+
const scene = this._getReferenceSelectionScene();
|
|
1052
|
+
if (!scene) return;
|
|
1053
|
+
try { this._seedReferencePreviewCacheFromScene(inputEl, def, [normalized], scene); } catch (_) { }
|
|
1054
|
+
try { this._syncActiveReferenceSelectionPreview(inputEl, def); } catch (_) { }
|
|
1055
|
+
|
|
1056
|
+
let target = null;
|
|
1057
|
+
try { target = scene.getObjectByName(normalized); } catch (_) { target = null; }
|
|
1058
|
+
if (!target) {
|
|
1059
|
+
const cache = this._getReferencePreviewCache(inputEl);
|
|
1060
|
+
const entry = cache ? cache.get(normalized) : null;
|
|
1061
|
+
target = entry?.object || entry || null;
|
|
1062
|
+
}
|
|
1063
|
+
if (!target) {
|
|
1064
|
+
try { target = scene.getObjectByName(`__refPreview__${normalized}`); } catch (_) { target = null; }
|
|
1065
|
+
}
|
|
1066
|
+
if (!target) return;
|
|
1067
|
+
inputEl.__refChipHoverActive = true;
|
|
1068
|
+
try { SelectionFilter.setHoverObject(target, { ignoreFilter: true }); } catch (_) { }
|
|
1069
|
+
} catch (_) { }
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
_clearReferenceSelectionHover(inputEl) {
|
|
1073
|
+
try {
|
|
1074
|
+
if (!inputEl || SchemaForm.__activeRefInput !== inputEl) return;
|
|
1075
|
+
if (!inputEl.__refChipHoverActive) return;
|
|
1076
|
+
inputEl.__refChipHoverActive = false;
|
|
1077
|
+
SelectionFilter.clearHover();
|
|
538
1078
|
} catch (_) { }
|
|
539
1079
|
}
|
|
540
1080
|
|
|
@@ -581,8 +1121,37 @@ export class SchemaForm {
|
|
|
581
1121
|
SelectionFilter.SetSelectionTypes(def.selectionFilter);
|
|
582
1122
|
try { window.__BREP_activeRefInput = inputEl; } catch (_) { }
|
|
583
1123
|
|
|
1124
|
+
// Log current selected objects for this reference field on activation
|
|
1125
|
+
try {
|
|
1126
|
+
const scene = this._getReferenceSelectionScene();
|
|
1127
|
+
const names = this._collectReferenceSelectionNames(inputEl, def);
|
|
1128
|
+
const keyLabel = inputEl?.dataset?.key ? ` (${inputEl.dataset.key})` : '';
|
|
1129
|
+
if (!names.length) {
|
|
1130
|
+
console.log(`[ReferenceSelection] Activated${keyLabel}: no selections`);
|
|
1131
|
+
} else {
|
|
1132
|
+
const cache = this._getReferencePreviewCache(inputEl);
|
|
1133
|
+
for (const name of names) {
|
|
1134
|
+
if (!name) continue;
|
|
1135
|
+
const obj = scene ? scene.getObjectByName(name) : null;
|
|
1136
|
+
const cached = cache ? cache.get(name) : null;
|
|
1137
|
+
const cachedObj = cached && cached.object ? cached.object : null;
|
|
1138
|
+
console.log(`[ReferenceSelection] Selected${keyLabel}: ${name}`, {
|
|
1139
|
+
object: obj || cachedObj || null,
|
|
1140
|
+
inScene: !!obj,
|
|
1141
|
+
cached: !!cachedObj,
|
|
1142
|
+
});
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
} catch (_) { }
|
|
1146
|
+
|
|
584
1147
|
// Highlight existing selections while this reference field is active
|
|
585
1148
|
try { this._syncActiveReferenceSelectionHighlight(inputEl, def); } catch (_) { }
|
|
1149
|
+
try {
|
|
1150
|
+
if (typeof inputEl.__captureReferencePreview !== 'function') {
|
|
1151
|
+
inputEl.__captureReferencePreview = (obj) => this._storeReferencePreviewSnapshot(inputEl, def, obj);
|
|
1152
|
+
}
|
|
1153
|
+
} catch (_) { }
|
|
1154
|
+
try { this._startReferencePreviewWatcher(inputEl, def); } catch (_) { }
|
|
586
1155
|
}
|
|
587
1156
|
|
|
588
1157
|
// Activate a TransformControls session for a transform widget
|
|
@@ -1044,17 +1613,25 @@ export class SchemaForm {
|
|
|
1044
1613
|
|
|
1045
1614
|
_stopActiveReferenceSelection() {
|
|
1046
1615
|
// Clear global active if it belongs to this instance
|
|
1616
|
+
const activeInput = SchemaForm.__activeRefInput || null;
|
|
1047
1617
|
try {
|
|
1048
|
-
if (
|
|
1049
|
-
try {
|
|
1050
|
-
try {
|
|
1618
|
+
if (activeInput) {
|
|
1619
|
+
try { activeInput.style.filter = 'none'; } catch (_) { }
|
|
1620
|
+
try { activeInput.removeAttribute('active-reference-selection'); } catch (_) { }
|
|
1051
1621
|
try {
|
|
1052
|
-
const wrap =
|
|
1622
|
+
const wrap = activeInput.closest('.ref-single-wrap, .ref-multi-wrap');
|
|
1053
1623
|
if (wrap) wrap.classList.remove('ref-active');
|
|
1054
1624
|
} catch (_) { }
|
|
1055
1625
|
}
|
|
1056
1626
|
} catch (_) { }
|
|
1057
|
-
const hadActive = !!
|
|
1627
|
+
const hadActive = !!activeInput;
|
|
1628
|
+
try {
|
|
1629
|
+
if (activeInput && typeof activeInput.__refPreviewCleanup === 'function') {
|
|
1630
|
+
activeInput.__refPreviewCleanup();
|
|
1631
|
+
} else if (activeInput) {
|
|
1632
|
+
this._removeReferencePreviewGroup(activeInput);
|
|
1633
|
+
}
|
|
1634
|
+
} catch (_) { }
|
|
1058
1635
|
SchemaForm.__activeRefInput = null;
|
|
1059
1636
|
try { if (window.__BREP_activeRefInput === undefined || window.__BREP_activeRefInput === SchemaForm.__activeRefInput) window.__BREP_activeRefInput = null; } catch (_) { }
|
|
1060
1637
|
if (hadActive) {
|
|
@@ -1071,6 +1648,7 @@ export class SchemaForm {
|
|
|
1071
1648
|
const arr = Array.isArray(values) ? values : [];
|
|
1072
1649
|
const normalizedValues = normalizeReferenceList(arr);
|
|
1073
1650
|
const inputEl = (this._inputs && typeof this._inputs.get === 'function') ? this._inputs.get(key) : null;
|
|
1651
|
+
const def = (inputEl && inputEl.__refSelectionDef) || (this.schema ? (this.schema[key] || null) : null);
|
|
1074
1652
|
if (inputEl) {
|
|
1075
1653
|
if (typeof inputEl.__updateSelectionMetadata === 'function') {
|
|
1076
1654
|
try { inputEl.__updateSelectionMetadata(normalizedValues); } catch (_) { }
|
|
@@ -1095,9 +1673,17 @@ export class SchemaForm {
|
|
|
1095
1673
|
|
|
1096
1674
|
// Hover highlight on chip hover
|
|
1097
1675
|
chip.addEventListener('mouseenter', () => {
|
|
1676
|
+
if (def && def.type === 'reference_selection') {
|
|
1677
|
+
this._hoverReferenceSelectionItem(inputEl, def, name);
|
|
1678
|
+
return;
|
|
1679
|
+
}
|
|
1098
1680
|
try { SelectionFilter.setHoverByName(this.options?.scene || null, name); } catch (_) { }
|
|
1099
1681
|
});
|
|
1100
1682
|
chip.addEventListener('mouseleave', () => {
|
|
1683
|
+
if (def && def.type === 'reference_selection') {
|
|
1684
|
+
this._clearReferenceSelectionHover(inputEl);
|
|
1685
|
+
return;
|
|
1686
|
+
}
|
|
1101
1687
|
try { SelectionFilter.clearHover(); } catch (_) { }
|
|
1102
1688
|
});
|
|
1103
1689
|
|
|
@@ -1158,7 +1744,7 @@ export class SchemaForm {
|
|
|
1158
1744
|
|
|
1159
1745
|
try {
|
|
1160
1746
|
if (inputEl && inputEl === SchemaForm.__activeRefInput) {
|
|
1161
|
-
const def = this.schema ? (this.schema[key] || {}) : null;
|
|
1747
|
+
const def = (inputEl && inputEl.__refSelectionDef) || (this.schema ? (this.schema[key] || {}) : null);
|
|
1162
1748
|
this._syncActiveReferenceSelectionHighlight(inputEl, def);
|
|
1163
1749
|
}
|
|
1164
1750
|
} catch (_) { }
|
|
@@ -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;
|