pcb-scene3d-viewer 1.1.19 → 1.1.21
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/package.json +3 -2
- package/src/PcbAssemblyBoardSubstrateBuilder.mjs +467 -0
- package/src/PcbAssemblyExportCoordinateFrame.mjs +19 -0
- package/src/PcbAssemblyGeometryBuildProgress.mjs +201 -0
- package/src/PcbAssemblyGeometryBuilder.mjs +994 -0
- package/src/PcbAssemblyMeshUtils.mjs +541 -0
- package/src/PcbAssemblyModelMeshLoader.mjs +447 -0
- package/src/PcbAssemblyPolygonTriangulator.mjs +301 -0
- package/src/PcbAssemblyStepWriter.mjs +952 -0
- package/src/PcbAssemblyWrlWriter.mjs +144 -0
- package/src/PcbScene3dCameraRig.mjs +11 -5
- package/src/PcbScene3dComponentVisibility.mjs +161 -0
- package/src/PcbScene3dController.mjs +29 -4
- package/src/PcbScene3dExternalModelPlacementRepair.mjs +1 -1
- package/src/PcbScene3dInteractionHints.mjs +14 -6
- package/src/PcbScene3dRenderScheduler.mjs +55 -0
- package/src/PcbScene3dRuntime.mjs +56 -4
- package/src/PcbScene3dSelectionInspectorRenderer.mjs +64 -3
- package/src/PcbScene3dSelectionVisibilityBinder.mjs +119 -0
- package/src/PcbScene3dText.mjs +4 -2
- package/src/scene3d.mjs +12 -0
- package/src/styles/scene3d.css +48 -0
|
@@ -2,6 +2,7 @@ import { PcbScene3dBoardSolderMaskFactory } from './PcbScene3dBoardSolderMaskFac
|
|
|
2
2
|
import { PcbScene3dBodyColor } from './PcbScene3dBodyColor.mjs'
|
|
3
3
|
import { PcbScene3dCameraRig } from './PcbScene3dCameraRig.mjs'
|
|
4
4
|
import { PcbScene3dCircuitJsonAdapter } from './PcbScene3dCircuitJsonAdapter.mjs'
|
|
5
|
+
import { PcbScene3dComponentVisibility } from './PcbScene3dComponentVisibility.mjs'
|
|
5
6
|
import { PcbScene3dComponentAdjustment } from './PcbScene3dComponentAdjustment.mjs'
|
|
6
7
|
import { PcbScene3dComponentAdjustmentRegistry } from './PcbScene3dComponentAdjustmentRegistry.mjs'
|
|
7
8
|
import { PcbScene3dCopperDetailGroupBuilder } from './PcbScene3dCopperDetailGroupBuilder.mjs'
|
|
@@ -15,6 +16,7 @@ import { PcbScene3dMountRig } from './PcbScene3dMountRig.mjs'
|
|
|
15
16
|
import { PcbScene3dModelSearchPlacement } from './PcbScene3dModelSearchPlacement.mjs'
|
|
16
17
|
import { PcbScene3dPresetState } from './PcbScene3dPresetState.mjs'
|
|
17
18
|
import { PcbScene3dRenderGroupVisibility } from './PcbScene3dRenderGroupVisibility.mjs'
|
|
19
|
+
import { PcbScene3dRenderScheduler } from './PcbScene3dRenderScheduler.mjs'
|
|
18
20
|
import { PcbScene3dRuntimeBoardMeshes } from './PcbScene3dRuntimeBoardMeshes.mjs'
|
|
19
21
|
import { PcbScene3dSilkscreenChunkedFactory } from './PcbScene3dSilkscreenChunkedFactory.mjs'
|
|
20
22
|
import { PcbScene3dTrueTypeTextFactory } from './PcbScene3dTrueTypeTextFactory.mjs'
|
|
@@ -52,6 +54,7 @@ export class PcbScene3dRuntime {
|
|
|
52
54
|
#pointer
|
|
53
55
|
#pointerDownPosition
|
|
54
56
|
#selectionRoots
|
|
57
|
+
#hiddenComponentDesignators
|
|
55
58
|
#componentAdjustmentRegistry
|
|
56
59
|
#fallbackBodyRoots
|
|
57
60
|
#loadedExternalModelDesignators
|
|
@@ -64,6 +67,7 @@ export class PcbScene3dRuntime {
|
|
|
64
67
|
#readyPromise
|
|
65
68
|
#resolveReadyPromise
|
|
66
69
|
#hasSettledReady
|
|
70
|
+
#renderScheduler
|
|
67
71
|
/**
|
|
68
72
|
* @param {HTMLElement} viewportNode
|
|
69
73
|
* @param {any} sceneDescription Scene description or CircuitJSON model.
|
|
@@ -96,6 +100,7 @@ export class PcbScene3dRuntime {
|
|
|
96
100
|
this.#pointer = null
|
|
97
101
|
this.#pointerDownPosition = null
|
|
98
102
|
this.#selectionRoots = new Map()
|
|
103
|
+
this.#hiddenComponentDesignators = new Set()
|
|
99
104
|
this.#componentAdjustmentRegistry =
|
|
100
105
|
new PcbScene3dComponentAdjustmentRegistry(() => this.#three)
|
|
101
106
|
this.#fallbackBodyRoots = new Map()
|
|
@@ -108,6 +113,11 @@ export class PcbScene3dRuntime {
|
|
|
108
113
|
this.#presetState = new PcbScene3dPresetState()
|
|
109
114
|
this.#isDisposed = false
|
|
110
115
|
this.#hasSettledReady = false
|
|
116
|
+
this.#renderScheduler = new PcbScene3dRenderScheduler(() => {
|
|
117
|
+
if (!this.#isDisposed) {
|
|
118
|
+
this.#render()
|
|
119
|
+
}
|
|
120
|
+
})
|
|
111
121
|
this.#resolveReadyPromise = null
|
|
112
122
|
this.#readyPromise = new Promise((resolve) => {
|
|
113
123
|
this.#resolveReadyPromise = resolve
|
|
@@ -124,10 +134,14 @@ export class PcbScene3dRuntime {
|
|
|
124
134
|
setPreset(preset) {
|
|
125
135
|
const normalizedPreset = this.#presetState.set(preset)
|
|
126
136
|
this.#applyViewScale(normalizedPreset)
|
|
137
|
+
PcbScene3dInteractionHints.configureControls(
|
|
138
|
+
this.#controls,
|
|
139
|
+
this.#three,
|
|
140
|
+
normalizedPreset
|
|
141
|
+
)
|
|
127
142
|
if (!this.#camera) {
|
|
128
143
|
return
|
|
129
144
|
}
|
|
130
|
-
|
|
131
145
|
PcbScene3dCameraRig.applyPreset(
|
|
132
146
|
this.#camera,
|
|
133
147
|
this.#controls,
|
|
@@ -141,7 +155,6 @@ export class PcbScene3dRuntime {
|
|
|
141
155
|
if (!(toggleName in this.#toggles)) {
|
|
142
156
|
return
|
|
143
157
|
}
|
|
144
|
-
|
|
145
158
|
this.#toggles[toggleName] = enabled
|
|
146
159
|
this.#applyToggleVisibility()
|
|
147
160
|
this.#render()
|
|
@@ -150,6 +163,27 @@ export class PcbScene3dRuntime {
|
|
|
150
163
|
setSelectedDesignator(designator) {
|
|
151
164
|
this.#setSelectedDesignator(designator)
|
|
152
165
|
}
|
|
166
|
+
/** @param {string} designator @param {boolean} hidden */
|
|
167
|
+
setComponentHidden(designator, hidden) {
|
|
168
|
+
if (
|
|
169
|
+
!PcbScene3dComponentVisibility.setHidden(
|
|
170
|
+
this.#hiddenComponentDesignators,
|
|
171
|
+
designator,
|
|
172
|
+
hidden
|
|
173
|
+
)
|
|
174
|
+
) {
|
|
175
|
+
return
|
|
176
|
+
}
|
|
177
|
+
this.#applyToggleVisibility()
|
|
178
|
+
this.#render()
|
|
179
|
+
}
|
|
180
|
+
/** @param {string} designator @returns {boolean} */
|
|
181
|
+
isComponentHidden(designator) {
|
|
182
|
+
return PcbScene3dComponentVisibility.isHidden(
|
|
183
|
+
this.#hiddenComponentDesignators,
|
|
184
|
+
designator
|
|
185
|
+
)
|
|
186
|
+
}
|
|
153
187
|
/**
|
|
154
188
|
* Applies a live model-local adjustment to one component.
|
|
155
189
|
* @param {string} designator Component designator.
|
|
@@ -172,6 +206,7 @@ export class PcbScene3dRuntime {
|
|
|
172
206
|
/** @returns {void} */
|
|
173
207
|
dispose() {
|
|
174
208
|
this.#isDisposed = true
|
|
209
|
+
this.#renderScheduler.cancel()
|
|
175
210
|
this.#listeners.forEach(({ node, type, listener }) => {
|
|
176
211
|
node.removeEventListener?.(type, listener)
|
|
177
212
|
})
|
|
@@ -196,6 +231,7 @@ export class PcbScene3dRuntime {
|
|
|
196
231
|
this.#pointer = null
|
|
197
232
|
this.#pointerDownPosition = null
|
|
198
233
|
this.#selectionRoots.clear()
|
|
234
|
+
this.#hiddenComponentDesignators.clear()
|
|
199
235
|
this.#componentAdjustmentRegistry.clear()
|
|
200
236
|
this.#fallbackBodyRoots.clear()
|
|
201
237
|
this.#loadedExternalModelDesignators.clear()
|
|
@@ -636,7 +672,11 @@ export class PcbScene3dRuntime {
|
|
|
636
672
|
this.#controls.minDistance = 140
|
|
637
673
|
this.#controls.maxDistance = this.#initialRadius * 8
|
|
638
674
|
this.#controls.target.set(0, 0, 0)
|
|
639
|
-
PcbScene3dInteractionHints.configureControls(
|
|
675
|
+
PcbScene3dInteractionHints.configureControls(
|
|
676
|
+
this.#controls,
|
|
677
|
+
THREE,
|
|
678
|
+
this.#presetState.get()
|
|
679
|
+
)
|
|
640
680
|
|
|
641
681
|
PcbScene3dCameraRig.applyPreset(
|
|
642
682
|
this.#camera,
|
|
@@ -645,7 +685,9 @@ export class PcbScene3dRuntime {
|
|
|
645
685
|
this.#sceneDescription
|
|
646
686
|
)
|
|
647
687
|
|
|
648
|
-
this.#bindListener(this.#controls, 'change', () =>
|
|
688
|
+
this.#bindListener(this.#controls, 'change', () => {
|
|
689
|
+
this.#renderScheduler.schedule()
|
|
690
|
+
})
|
|
649
691
|
this.#bindListener(domElement, 'contextmenu', (event) => {
|
|
650
692
|
event.preventDefault?.()
|
|
651
693
|
})
|
|
@@ -726,6 +768,16 @@ export class PcbScene3dRuntime {
|
|
|
726
768
|
modelSearchExternalModelRoots: this.#modelSearchExternalModelRoots,
|
|
727
769
|
hasLoadedBoardAssemblyModel: this.#hasLoadedBoardAssemblyModel
|
|
728
770
|
})
|
|
771
|
+
PcbScene3dComponentVisibility.apply({
|
|
772
|
+
selectionRoots: this.#selectionRoots,
|
|
773
|
+
hiddenDesignators: this.#hiddenComponentDesignators,
|
|
774
|
+
fallbackBodyRoots: this.#fallbackBodyRoots,
|
|
775
|
+
loadedExternalModelDesignators:
|
|
776
|
+
this.#loadedExternalModelDesignators,
|
|
777
|
+
modelSearchExternalModelRoots: this.#modelSearchExternalModelRoots,
|
|
778
|
+
toggles: this.#toggles,
|
|
779
|
+
hasLoadedBoardAssemblyModel: this.#hasLoadedBoardAssemblyModel
|
|
780
|
+
})
|
|
729
781
|
}
|
|
730
782
|
|
|
731
783
|
/** @returns {void} */
|
|
@@ -46,12 +46,13 @@ export class PcbScene3dSelectionInspectorRenderer {
|
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
48
|
* Renders selected component details and optional editable transform controls.
|
|
49
|
-
* @param {{ designator: string, selection?: { sourceType?: string } | null, selectionEntry: { component: any | null, externalPlacement: any | null }, adjustment: { scale: { x: number, y: number, z: number }, rotationDeg: { x: number, y: number, z: number }, offsetMil: { x: number, y: number, z: number } }, includeControls?: boolean, translate: (key: string) => string }} options Render options.
|
|
49
|
+
* @param {{ designator: string, hidden?: boolean, selection?: { sourceType?: string } | null, selectionEntry: { component: any | null, externalPlacement: any | null }, adjustment: { scale: { x: number, y: number, z: number }, rotationDeg: { x: number, y: number, z: number }, offsetMil: { x: number, y: number, z: number } }, includeControls?: boolean, translate: (key: string) => string }} options Render options.
|
|
50
50
|
* @returns {string}
|
|
51
51
|
*/
|
|
52
52
|
static renderSelected(options) {
|
|
53
53
|
const component = options.selectionEntry.component
|
|
54
54
|
const externalPlacement = options.selectionEntry.externalPlacement
|
|
55
|
+
const hidden = options.hidden === true
|
|
55
56
|
const fields = [
|
|
56
57
|
[options.translate('scene3d.designator'), options.designator],
|
|
57
58
|
[
|
|
@@ -127,11 +128,18 @@ export class PcbScene3dSelectionInspectorRenderer {
|
|
|
127
128
|
].filter(([, value]) => String(value || '').trim())
|
|
128
129
|
|
|
129
130
|
return (
|
|
130
|
-
'<h4 class="scene-3d__selection-title">' +
|
|
131
|
+
'<div class="scene-3d__selection-header"><h4 class="scene-3d__selection-title">' +
|
|
131
132
|
PcbScene3dSelectionInspectorRenderer.#escapeHtml(
|
|
132
133
|
options.translate('scene3d.componentInspector')
|
|
133
134
|
) +
|
|
134
|
-
'</h4
|
|
135
|
+
'</h4>' +
|
|
136
|
+
PcbScene3dSelectionInspectorRenderer.#renderVisibilityToggle(
|
|
137
|
+
options.designator,
|
|
138
|
+
options.selection?.sourceType || '',
|
|
139
|
+
hidden,
|
|
140
|
+
options.translate
|
|
141
|
+
) +
|
|
142
|
+
'</div><dl class="scene-3d__selection-list">' +
|
|
135
143
|
fields
|
|
136
144
|
.map(
|
|
137
145
|
([label, value]) =>
|
|
@@ -461,6 +469,59 @@ export class PcbScene3dSelectionInspectorRenderer {
|
|
|
461
469
|
)
|
|
462
470
|
}
|
|
463
471
|
|
|
472
|
+
/**
|
|
473
|
+
* Renders the selected-component visibility toggle.
|
|
474
|
+
* @param {string} designator Selected component designator.
|
|
475
|
+
* @param {string} sourceType Selection source type.
|
|
476
|
+
* @param {boolean} hidden Whether the component is hidden.
|
|
477
|
+
* @param {(key: string) => string} translate Translation lookup.
|
|
478
|
+
* @returns {string}
|
|
479
|
+
*/
|
|
480
|
+
static #renderVisibilityToggle(designator, sourceType, hidden, translate) {
|
|
481
|
+
const label = hidden
|
|
482
|
+
? translate('scene3d.showSelectedComponent')
|
|
483
|
+
: translate('scene3d.hideSelectedComponent')
|
|
484
|
+
const iconClass = hidden
|
|
485
|
+
? 'scene-3d__selection-eye-icon scene-3d__selection-eye-off-icon'
|
|
486
|
+
: 'scene-3d__selection-eye-icon'
|
|
487
|
+
|
|
488
|
+
return (
|
|
489
|
+
'<button class="scene-3d__selection-visibility" type="button" data-scene-3d-component-visibility="' +
|
|
490
|
+
PcbScene3dSelectionInspectorRenderer.#escapeHtml(designator) +
|
|
491
|
+
'" data-scene-3d-component-source="' +
|
|
492
|
+
PcbScene3dSelectionInspectorRenderer.#escapeHtml(sourceType) +
|
|
493
|
+
'" aria-label="' +
|
|
494
|
+
PcbScene3dSelectionInspectorRenderer.#escapeHtml(label) +
|
|
495
|
+
'" title="' +
|
|
496
|
+
PcbScene3dSelectionInspectorRenderer.#escapeHtml(label) +
|
|
497
|
+
'" aria-pressed="' +
|
|
498
|
+
(hidden ? 'true' : 'false') +
|
|
499
|
+
'"><span class="' +
|
|
500
|
+
iconClass +
|
|
501
|
+
'" aria-hidden="true">' +
|
|
502
|
+
PcbScene3dSelectionInspectorRenderer.#renderVisibilityIcon(
|
|
503
|
+
!hidden
|
|
504
|
+
) +
|
|
505
|
+
'</span></button>'
|
|
506
|
+
)
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Renders an eye icon for component visibility state.
|
|
511
|
+
* @param {boolean} visible Whether the component is visible.
|
|
512
|
+
* @returns {string}
|
|
513
|
+
*/
|
|
514
|
+
static #renderVisibilityIcon(visible) {
|
|
515
|
+
const slash = visible ? '' : '<path d="M4 4l16 16" />'
|
|
516
|
+
return (
|
|
517
|
+
'<svg class="icon" viewBox="0 0 24 24" aria-hidden="true">' +
|
|
518
|
+
'<path d="M2 12s3.5-6 10-6 10 6 10 6-3.5 6-10 6-10-6-10-6z" />' +
|
|
519
|
+
'<circle cx="12" cy="12" r="2.5" />' +
|
|
520
|
+
slash +
|
|
521
|
+
'</svg>'
|
|
522
|
+
)
|
|
523
|
+
}
|
|
524
|
+
|
|
464
525
|
/**
|
|
465
526
|
* Formats a model file label.
|
|
466
527
|
* @param {any} externalPlacement External placement.
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Binds the selected-component visibility toggle in the inspector.
|
|
3
|
+
*/
|
|
4
|
+
export class PcbScene3dSelectionVisibilityBinder {
|
|
5
|
+
/** @type {HTMLElement | null} */
|
|
6
|
+
#selectionNode
|
|
7
|
+
|
|
8
|
+
/** @type {{ node: EventTarget, type: string, listener: (event: any) => void } | null} */
|
|
9
|
+
#listenerRecord
|
|
10
|
+
|
|
11
|
+
/** @type {() => string} */
|
|
12
|
+
#resolveDesignator
|
|
13
|
+
|
|
14
|
+
/** @type {(designator: string) => boolean} */
|
|
15
|
+
#resolveHidden
|
|
16
|
+
|
|
17
|
+
/** @type {(designator: string, hidden: boolean) => void} */
|
|
18
|
+
#setHidden
|
|
19
|
+
|
|
20
|
+
/** @type {(designator: string, sourceType: string) => void} */
|
|
21
|
+
#refreshSelection
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @param {{ resolveDesignator: () => string, resolveHidden: (designator: string) => boolean, setHidden: (designator: string, hidden: boolean) => void, refreshSelection: (designator: string, sourceType: string) => void }} options Binder callbacks.
|
|
25
|
+
*/
|
|
26
|
+
constructor(options) {
|
|
27
|
+
this.#selectionNode = null
|
|
28
|
+
this.#listenerRecord = null
|
|
29
|
+
this.#resolveDesignator = options.resolveDesignator
|
|
30
|
+
this.#resolveHidden = options.resolveHidden
|
|
31
|
+
this.#setHidden = options.setHidden
|
|
32
|
+
this.#refreshSelection = options.refreshSelection
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Binds delegated visibility toggles in the selection inspector.
|
|
37
|
+
* @param {HTMLElement | null} selectionNode Inspector node.
|
|
38
|
+
* @returns {void}
|
|
39
|
+
*/
|
|
40
|
+
bindSelectionNode(selectionNode) {
|
|
41
|
+
this.dispose()
|
|
42
|
+
this.#selectionNode =
|
|
43
|
+
selectionNode && typeof selectionNode === 'object'
|
|
44
|
+
? selectionNode
|
|
45
|
+
: null
|
|
46
|
+
if (!this.#selectionNode) {
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const listener = (event) => this.#handleClick(event)
|
|
51
|
+
this.#selectionNode.addEventListener?.('click', listener)
|
|
52
|
+
this.#listenerRecord = {
|
|
53
|
+
node: this.#selectionNode,
|
|
54
|
+
type: 'click',
|
|
55
|
+
listener
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Removes the active delegated click listener.
|
|
61
|
+
* @returns {void}
|
|
62
|
+
*/
|
|
63
|
+
dispose() {
|
|
64
|
+
if (this.#listenerRecord) {
|
|
65
|
+
const { node, type, listener } = this.#listenerRecord
|
|
66
|
+
node.removeEventListener?.(type, listener)
|
|
67
|
+
}
|
|
68
|
+
this.#listenerRecord = null
|
|
69
|
+
this.#selectionNode = null
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Handles one delegated visibility-button click.
|
|
74
|
+
* @param {any} event DOM event.
|
|
75
|
+
* @returns {void}
|
|
76
|
+
*/
|
|
77
|
+
#handleClick(event) {
|
|
78
|
+
const button =
|
|
79
|
+
PcbScene3dSelectionVisibilityBinder.#closestVisibilityButton(
|
|
80
|
+
event?.target
|
|
81
|
+
)
|
|
82
|
+
if (!button) {
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
event?.preventDefault?.()
|
|
87
|
+
const designator = String(
|
|
88
|
+
button?.getAttribute?.('data-scene-3d-component-visibility') ||
|
|
89
|
+
this.#resolveDesignator() ||
|
|
90
|
+
''
|
|
91
|
+
).trim()
|
|
92
|
+
if (!designator) {
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
this.#setHidden(designator, !this.#resolveHidden(designator))
|
|
97
|
+
this.#refreshSelection(
|
|
98
|
+
designator,
|
|
99
|
+
String(
|
|
100
|
+
button?.getAttribute?.('data-scene-3d-component-source') || ''
|
|
101
|
+
)
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Finds a visibility button from an event target.
|
|
107
|
+
* @param {any} target Event target.
|
|
108
|
+
* @returns {any | null}
|
|
109
|
+
*/
|
|
110
|
+
static #closestVisibilityButton(target) {
|
|
111
|
+
const closest = target?.closest?.(
|
|
112
|
+
'[data-scene-3d-component-visibility]'
|
|
113
|
+
)
|
|
114
|
+
return closest ||
|
|
115
|
+
target?.getAttribute?.('data-scene-3d-component-visibility')
|
|
116
|
+
? closest || target
|
|
117
|
+
: null
|
|
118
|
+
}
|
|
119
|
+
}
|
package/src/PcbScene3dText.mjs
CHANGED
|
@@ -22,6 +22,7 @@ const FALLBACK_MESSAGES = {
|
|
|
22
22
|
'scene3d.fallbackBody': 'Fallback body',
|
|
23
23
|
'scene3d.fallbackBodies': 'Fallback bodies',
|
|
24
24
|
'scene3d.footprint': 'Footprint',
|
|
25
|
+
'scene3d.hideSelectedComponent': 'Hide selected component',
|
|
25
26
|
'scene3d.inspectPrompt': 'Click a component to inspect it.',
|
|
26
27
|
'scene3d.interactiveViewAria': 'Interactive 3D PCB view',
|
|
27
28
|
'scene3d.isometric': 'Isometric',
|
|
@@ -39,11 +40,12 @@ const FALLBACK_MESSAGES = {
|
|
|
39
40
|
'scene3d.picked': 'Picked',
|
|
40
41
|
'scene3d.placements': 'Placements',
|
|
41
42
|
'scene3d.pointerHint':
|
|
42
|
-
'Drag
|
|
43
|
+
'Drag pans in Top/Bottom and orbits in Isometric; right-drag uses the alternate action. Use the wheel to zoom.',
|
|
43
44
|
'scene3d.offset': 'Offset',
|
|
44
45
|
'scene3d.resetTransform': 'Reset',
|
|
45
46
|
'scene3d.rotation': 'Rotation',
|
|
46
47
|
'scene3d.scale': 'Scale',
|
|
48
|
+
'scene3d.showSelectedComponent': 'Show selected component',
|
|
47
49
|
'scene3d.skipped': 'Skipped',
|
|
48
50
|
'scene3d.source': 'Source',
|
|
49
51
|
'scene3d.startFailed': '3D preview could not start:',
|
|
@@ -53,7 +55,7 @@ const FALLBACK_MESSAGES = {
|
|
|
53
55
|
'scene3d.toolbarAria': '3D camera presets',
|
|
54
56
|
'scene3d.top': 'Top',
|
|
55
57
|
'scene3d.touchHint':
|
|
56
|
-
'
|
|
58
|
+
'One-finger drag pans in Top/Bottom and orbits in Isometric. Pinch to zoom.',
|
|
57
59
|
'scene3d.unresolved': 'unresolved'
|
|
58
60
|
}
|
|
59
61
|
|
package/src/scene3d.mjs
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
export { PcbModelArchiveExporter } from './PcbModelArchiveExporter.mjs'
|
|
2
|
+
export { PcbAssemblyBoardSubstrateBuilder } from './PcbAssemblyBoardSubstrateBuilder.mjs'
|
|
3
|
+
export { PcbAssemblyExportCoordinateFrame } from './PcbAssemblyExportCoordinateFrame.mjs'
|
|
4
|
+
export { PcbAssemblyGeometryBuildProgress } from './PcbAssemblyGeometryBuildProgress.mjs'
|
|
5
|
+
export { PcbAssemblyGeometryBuilder } from './PcbAssemblyGeometryBuilder.mjs'
|
|
6
|
+
export { PcbAssemblyMeshUtils } from './PcbAssemblyMeshUtils.mjs'
|
|
7
|
+
export { PcbAssemblyModelMeshLoader } from './PcbAssemblyModelMeshLoader.mjs'
|
|
8
|
+
export { PcbAssemblyPolygonTriangulator } from './PcbAssemblyPolygonTriangulator.mjs'
|
|
9
|
+
export { PcbAssemblyStepWriter } from './PcbAssemblyStepWriter.mjs'
|
|
10
|
+
export { PcbAssemblyWrlWriter } from './PcbAssemblyWrlWriter.mjs'
|
|
2
11
|
export { PcbScene3dBoardAssemblyPlacement } from './PcbScene3dBoardAssemblyPlacement.mjs'
|
|
3
12
|
export { PcbScene3dBoardAssemblyPresentation } from './PcbScene3dBoardAssemblyPresentation.mjs'
|
|
4
13
|
export { PcbScene3dBoardEdgeCutoutBuilder } from './PcbScene3dBoardEdgeCutoutBuilder.mjs'
|
|
@@ -8,6 +17,7 @@ export { PcbScene3dBoardSolderMaskFactory } from './PcbScene3dBoardSolderMaskFac
|
|
|
8
17
|
export { PcbScene3dCameraRig } from './PcbScene3dCameraRig.mjs'
|
|
9
18
|
export { PcbScene3dController } from './PcbScene3dController.mjs'
|
|
10
19
|
export { PcbScene3dCircuitJsonAdapter } from './PcbScene3dCircuitJsonAdapter.mjs'
|
|
20
|
+
export { PcbScene3dComponentVisibility } from './PcbScene3dComponentVisibility.mjs'
|
|
11
21
|
export { PcbScene3dCopperDetailFilter } from './PcbScene3dCopperDetailFilter.mjs'
|
|
12
22
|
export { PcbScene3dCopperFactory } from './PcbScene3dCopperFactory.mjs'
|
|
13
23
|
export { PcbScene3dCopperTextFactory } from './PcbScene3dCopperTextFactory.mjs'
|
|
@@ -25,9 +35,11 @@ export { PcbScene3dOutlineBuilder } from './PcbScene3dOutlineBuilder.mjs'
|
|
|
25
35
|
export { PcbScene3dPadFactory } from './PcbScene3dPadFactory.mjs'
|
|
26
36
|
export { PcbScene3dPresetState } from './PcbScene3dPresetState.mjs'
|
|
27
37
|
export { PcbScene3dRenderGroupVisibility } from './PcbScene3dRenderGroupVisibility.mjs'
|
|
38
|
+
export { PcbScene3dRenderScheduler } from './PcbScene3dRenderScheduler.mjs'
|
|
28
39
|
export { PcbScene3dRuntime } from './PcbScene3dRuntime.mjs'
|
|
29
40
|
export { PcbScene3dRuntimeBoardMeshes } from './PcbScene3dRuntimeBoardMeshes.mjs'
|
|
30
41
|
export { PcbScene3dSelectionStyler } from './PcbScene3dSelectionStyler.mjs'
|
|
42
|
+
export { PcbScene3dSelectionVisibilityBinder } from './PcbScene3dSelectionVisibilityBinder.mjs'
|
|
31
43
|
export { PcbScene3dShapePathFactory } from './PcbScene3dShapePathFactory.mjs'
|
|
32
44
|
export { PcbScene3dShellRenderer } from './PcbScene3dShellRenderer.mjs'
|
|
33
45
|
export { PcbScene3dSilkscreenFactory } from './PcbScene3dSilkscreenFactory.mjs'
|
package/src/styles/scene3d.css
CHANGED
|
@@ -173,11 +173,59 @@ body.is-viewer-mode.is-viewer-3d .scene-3d {
|
|
|
173
173
|
border: 1px solid rgba(95, 112, 124, 0.12);
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
+
.scene-3d__selection-header {
|
|
177
|
+
display: grid;
|
|
178
|
+
grid-template-columns: minmax(0, 1fr) 2.1rem;
|
|
179
|
+
align-items: center;
|
|
180
|
+
gap: 0.5rem;
|
|
181
|
+
}
|
|
182
|
+
|
|
176
183
|
.scene-3d__selection-title {
|
|
177
184
|
margin: 0;
|
|
178
185
|
font-size: 0.9rem;
|
|
179
186
|
}
|
|
180
187
|
|
|
188
|
+
.scene-3d__selection-visibility {
|
|
189
|
+
display: inline-flex;
|
|
190
|
+
align-items: center;
|
|
191
|
+
justify-content: center;
|
|
192
|
+
width: 2.1rem;
|
|
193
|
+
height: 2.1rem;
|
|
194
|
+
border: 1px solid rgba(95, 112, 124, 0.16);
|
|
195
|
+
border-radius: 8px;
|
|
196
|
+
background: rgba(255, 255, 255, 0.78);
|
|
197
|
+
color: #425d70;
|
|
198
|
+
cursor: pointer;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.scene-3d__selection-visibility:hover,
|
|
202
|
+
.scene-3d__selection-visibility[aria-pressed='true'] {
|
|
203
|
+
border-color: rgba(184, 90, 37, 0.34);
|
|
204
|
+
color: var(--accent);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.scene-3d__selection-eye-icon {
|
|
208
|
+
width: 1.1rem;
|
|
209
|
+
height: 1.1rem;
|
|
210
|
+
display: inline-flex;
|
|
211
|
+
align-items: center;
|
|
212
|
+
justify-content: center;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.scene-3d__selection-eye-icon .icon {
|
|
216
|
+
width: 1.05rem;
|
|
217
|
+
height: 1.05rem;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.scene-3d__selection-eye-icon .icon path,
|
|
221
|
+
.scene-3d__selection-eye-icon .icon circle {
|
|
222
|
+
fill: none;
|
|
223
|
+
stroke: currentColor;
|
|
224
|
+
stroke-width: 1.8;
|
|
225
|
+
stroke-linecap: round;
|
|
226
|
+
stroke-linejoin: round;
|
|
227
|
+
}
|
|
228
|
+
|
|
181
229
|
.scene-3d__selection-empty {
|
|
182
230
|
margin: 0;
|
|
183
231
|
color: var(--muted);
|