simple-circuit-engine 0.0.11 → 0.0.12
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/AGENTS.md +10 -7
- package/CLAUDE.md +4 -6
- package/README.md +5 -2
- package/dist/core/index.d.ts +0 -1
- package/dist/core/index.js +74 -2114
- package/dist/core/setup.d.ts +17 -0
- package/dist/core/simulation/CircuitRunner.d.ts +176 -0
- package/dist/core/simulation/DirtyTracker.d.ts +87 -0
- package/dist/core/simulation/EventQueue.d.ts +68 -0
- package/dist/core/simulation/StateManager.d.ts +100 -0
- package/dist/core/simulation/behaviors/BehaviorRegistry.d.ts +70 -0
- package/dist/core/simulation/behaviors/ComponentBehavior.d.ts +53 -0
- package/dist/core/simulation/behaviors/basic/BatteryBehavior.d.ts +14 -0
- package/dist/core/simulation/behaviors/basic/ClockBehavior.d.ts +24 -0
- package/dist/core/simulation/behaviors/basic/DoubleThrowSwitchBehavior.d.ts +33 -0
- package/dist/core/simulation/behaviors/basic/LightbulbBehavior.d.ts +23 -0
- package/dist/core/simulation/behaviors/basic/RectangleLEDBehavior.d.ts +24 -0
- package/dist/core/simulation/behaviors/basic/RelayBehavior.d.ts +33 -0
- package/dist/core/simulation/behaviors/basic/SmallLEDBehavior.d.ts +24 -0
- package/dist/core/simulation/behaviors/basic/SwitchBehavior.d.ts +33 -0
- package/dist/core/simulation/behaviors/basic/index.d.ts +20 -0
- package/dist/core/simulation/behaviors/gates/InverterBehavior.d.ts +29 -0
- package/dist/core/simulation/behaviors/gates/Nand4GateBehavior.d.ts +18 -0
- package/dist/core/simulation/behaviors/gates/Nand8GateBehavior.d.ts +18 -0
- package/dist/core/simulation/behaviors/gates/NandGateBehavior.d.ts +28 -0
- package/dist/core/simulation/behaviors/gates/Nor4GateBehavior.d.ts +18 -0
- package/dist/core/simulation/behaviors/gates/Nor8GateBehavior.d.ts +18 -0
- package/dist/core/simulation/behaviors/gates/NorGateBehavior.d.ts +22 -0
- package/dist/core/simulation/behaviors/gates/Xor4GateBehavior.d.ts +18 -0
- package/dist/core/simulation/behaviors/gates/Xor8GateBehavior.d.ts +18 -0
- package/dist/core/simulation/behaviors/gates/XorGateBehavior.d.ts +22 -0
- package/dist/core/simulation/behaviors/gates/index.d.ts +34 -0
- package/dist/core/simulation/behaviors/index.d.ts +24 -0
- package/dist/core/simulation/behaviors/types.d.ts +101 -0
- package/dist/core/simulation/index.d.ts +18 -0
- package/dist/core/simulation/states/ComponentState.d.ts +57 -0
- package/dist/core/simulation/states/SimulationState.d.ts +46 -0
- package/dist/core/simulation/states/basic/BatteryState.d.ts +16 -0
- package/dist/core/simulation/states/basic/ClockState.d.ts +16 -0
- package/dist/core/simulation/states/basic/DoubleThrowSwitchState.d.ts +21 -0
- package/dist/core/simulation/states/basic/LightbulbState.d.ts +21 -0
- package/dist/core/simulation/states/basic/RectangleLEDState.d.ts +9 -0
- package/dist/core/simulation/states/basic/RelayState.d.ts +25 -0
- package/dist/core/simulation/states/basic/SmallLEDState.d.ts +21 -0
- package/dist/core/simulation/states/basic/SwitchState.d.ts +25 -0
- package/dist/core/simulation/states/gates/InverterState.d.ts +17 -0
- package/dist/core/simulation/states/gates/Nand4GateState.d.ts +10 -0
- package/dist/core/simulation/states/gates/Nand8GateState.d.ts +10 -0
- package/dist/core/simulation/states/gates/NandGateState.d.ts +16 -0
- package/dist/core/simulation/states/gates/Nor4GateState.d.ts +10 -0
- package/dist/core/simulation/states/gates/Nor8GateState.d.ts +10 -0
- package/dist/core/simulation/states/gates/NorGateState.d.ts +10 -0
- package/dist/core/simulation/states/gates/Xor4GateState.d.ts +10 -0
- package/dist/core/simulation/states/gates/Xor8GateState.d.ts +10 -0
- package/dist/core/simulation/states/gates/XorGateState.d.ts +10 -0
- package/dist/core/simulation/states/gates/index.d.ts +25 -0
- package/dist/core/simulation/states/index.d.ts +26 -0
- package/dist/core/simulation/states/types.d.ts +32 -0
- package/dist/core/simulation/types.d.ts +155 -0
- package/dist/core/topology/Circuit.d.ts +420 -0
- package/dist/core/topology/CircuitMetadata.d.ts +24 -0
- package/dist/core/topology/CircuitOptions.d.ts +14 -0
- package/dist/core/topology/Component.d.ts +152 -0
- package/dist/core/topology/ENode.d.ts +200 -0
- package/dist/core/topology/Wire.d.ts +130 -0
- package/dist/core/topology/delays.d.ts +52 -0
- package/dist/core/topology/index.d.ts +14 -0
- package/dist/core/topology/types.d.ts +175 -0
- package/dist/core/utils/CameraOptions.d.ts +83 -0
- package/dist/core/utils/MemoizeDecorator.d.ts +9 -0
- package/dist/core/utils/Position.d.ts +166 -0
- package/dist/core/utils/Position3D.d.ts +77 -0
- package/dist/core/utils/Rotation.d.ts +82 -0
- package/dist/core/utils/index.d.ts +24 -0
- package/dist/core/utils/types.d.ts +35 -0
- package/dist/core-Bjta9Y7_.js +2707 -0
- package/dist/core-Bjta9Y7_.js.map +1 -0
- package/dist/index.d.ts +13 -6306
- package/dist/index.js +117 -110
- package/dist/scene/CircuitEngine.d.ts +270 -0
- package/dist/scene/index.d.ts +0 -1
- package/dist/scene/index.js +43 -39
- package/dist/scene/setup.d.ts +18 -0
- package/dist/scene/shared/AbstractCircuitController.d.ts +211 -0
- package/dist/scene/shared/BranchingPointVisualFactory.d.ts +70 -0
- package/dist/scene/shared/EventEmitter.d.ts +92 -0
- package/dist/scene/shared/HoverManager.d.ts +151 -0
- package/dist/scene/shared/SelectionManager.d.ts +159 -0
- package/dist/scene/shared/WireVisualManager.d.ts +242 -0
- package/dist/scene/shared/components/ComponentVisualFactory.d.ts +438 -0
- package/dist/scene/shared/components/DefaultVisualFactory.d.ts +51 -0
- package/dist/scene/shared/components/FactoryRegistry.d.ts +84 -0
- package/dist/scene/shared/components/GroupedFactoryRegistry.d.ts +153 -0
- package/dist/scene/shared/components/basic/BatteryVisualFactory.d.ts +13 -0
- package/dist/scene/shared/components/basic/ClockVisualFactory.d.ts +79 -0
- package/dist/scene/shared/components/basic/DoubleThrowSwitchVisualFactory.d.ts +87 -0
- package/dist/scene/shared/components/basic/LabelVisualFactory.d.ts +148 -0
- package/dist/scene/shared/components/basic/LightbulbVisualFactory.d.ts +72 -0
- package/dist/scene/shared/components/basic/RectangleLEDVisualFactory.d.ts +86 -0
- package/dist/scene/shared/components/basic/RelayVisualFactory.d.ts +92 -0
- package/dist/scene/shared/components/basic/SmallLEDVisualFactory.d.ts +86 -0
- package/dist/scene/shared/components/basic/SwitchVisualFactory.d.ts +85 -0
- package/dist/scene/shared/components/gates/InverterVisualFactory.d.ts +104 -0
- package/dist/scene/shared/components/gates/Nand4GateVisualFactory.d.ts +27 -0
- package/dist/scene/shared/components/gates/Nand8GateVisualFactory.d.ts +27 -0
- package/dist/scene/shared/components/gates/NandGateVisualFactory.d.ts +101 -0
- package/dist/scene/shared/components/gates/Nor4GateVisualFactory.d.ts +27 -0
- package/dist/scene/shared/components/gates/Nor8GateVisualFactory.d.ts +27 -0
- package/dist/scene/shared/components/gates/NorGateVisualFactory.d.ts +101 -0
- package/dist/scene/shared/components/gates/Xor4GateVisualFactory.d.ts +29 -0
- package/dist/scene/shared/components/gates/Xor8GateVisualFactory.d.ts +29 -0
- package/dist/scene/shared/components/gates/XorGateVisualFactory.d.ts +103 -0
- package/dist/scene/shared/components/index.d.ts +29 -0
- package/dist/scene/shared/components/types.d.ts +43 -0
- package/dist/scene/shared/types.d.ts +476 -0
- package/dist/scene/shared/utils/CameraUtils.d.ts +23 -0
- package/dist/scene/shared/utils/ColorUtils.d.ts +26 -0
- package/dist/scene/shared/utils/ControlsUtils.d.ts +8 -0
- package/dist/scene/shared/utils/GeometryUtils.d.ts +261 -0
- package/dist/scene/shared/utils/LayerConstants.d.ts +40 -0
- package/dist/scene/shared/utils/LightingUtils.d.ts +31 -0
- package/dist/scene/shared/utils/MaterialUtils.d.ts +73 -0
- package/dist/scene/shared/utils/Options.d.ts +16 -0
- package/dist/scene/simulation/CircuitRunnerController.d.ts +227 -0
- package/dist/scene/static/CircuitController.d.ts +227 -0
- package/dist/scene/static/CircuitWriter.d.ts +146 -0
- package/dist/scene/static/PinTooltipWidget.d.ts +26 -0
- package/dist/scene/static/tools/BuildTool.d.ts +286 -0
- package/dist/scene/static/tools/ComponentPickerWidget.d.ts +82 -0
- package/dist/scene/static/tools/ConfigPanelWidget.d.ts +93 -0
- package/dist/scene/static/tools/MultiSelectTool.d.ts +265 -0
- package/dist/scene-CVsDdySt.js +7357 -0
- package/dist/scene-CVsDdySt.js.map +1 -0
- package/package.json +24 -25
- package/dist/CircuitRunner-BQQlhwjD.js +0 -1981
- package/dist/CircuitRunner-BQQlhwjD.js.map +0 -1
- package/dist/core/index.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/scene/index.js.map +0 -1
- package/dist/setup-CIq_kgaw.js +0 -10230
- package/dist/setup-CIq_kgaw.js.map +0 -1
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { Line2 } from 'three/examples/jsm/lines/Line2.js';
|
|
2
|
+
import { UUID, Wire, Circuit } from '../../core/index.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Wire Visual Manager
|
|
5
|
+
* @module scene/shared/WireVisualManager
|
|
6
|
+
*
|
|
7
|
+
* Manages wire visual rendering with:
|
|
8
|
+
* - Pin-accurate endpoints (derived from component visuals)
|
|
9
|
+
* - Multi-segment rendering via intermediate positions
|
|
10
|
+
* - Dynamic updates during component movement
|
|
11
|
+
*/
|
|
12
|
+
import * as THREE from 'three';
|
|
13
|
+
/**
|
|
14
|
+
* Wire path representation for rendering
|
|
15
|
+
*/
|
|
16
|
+
export interface WirePath {
|
|
17
|
+
/** Wire ID */
|
|
18
|
+
wireId: UUID;
|
|
19
|
+
/** Ordered points in world space (Three.js coordinates) */
|
|
20
|
+
points: THREE.Vector3[];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Delegation of CircuitController which handles wire visual rendering with proper pin targeting and dynamic updates.
|
|
24
|
+
*
|
|
25
|
+
* Key responsibilities:
|
|
26
|
+
* - Create wire visuals with endpoints at actual pin positions
|
|
27
|
+
* - Support multi-segment wires via intermediatePositions
|
|
28
|
+
* - Update wires dynamically when components move/rotate
|
|
29
|
+
* - Update wire materials for hover/selection states
|
|
30
|
+
* - may add and remove wire and branching point object3Ds in the scene directly
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* const wireManager = new WireVisualManager();
|
|
35
|
+
*
|
|
36
|
+
* // Create wire visual
|
|
37
|
+
* const line = wireManager.createOrUpdateWire(wire, circuit, scene, componentGroups);
|
|
38
|
+
*
|
|
39
|
+
* // Update wires when component moves
|
|
40
|
+
* wireManager.updateWiresForComponent(componentId, circuit, componentGroups);
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export declare class WireVisualManager {
|
|
44
|
+
private containerWidth;
|
|
45
|
+
private containerHeight;
|
|
46
|
+
private _scene;
|
|
47
|
+
private _camera;
|
|
48
|
+
private _componentObject3Ds;
|
|
49
|
+
private _wireObject3Ds;
|
|
50
|
+
private _container;
|
|
51
|
+
private _circuit;
|
|
52
|
+
/** Shared LineMaterials for all wires (memory efficient, consistent styling) */
|
|
53
|
+
private wireMaterials;
|
|
54
|
+
/** Preview wire for wire creation mode */
|
|
55
|
+
private previewWire;
|
|
56
|
+
constructor(componentObject3Ds: Map<UUID, THREE.Object3D>, wireObject3Ds: Map<UUID, Line2>);
|
|
57
|
+
setContainer(container: HTMLElement | null): void;
|
|
58
|
+
setSceneAndCamera(scene: THREE.Scene, camera: THREE.Camera): void;
|
|
59
|
+
setCircuit(circuit: Circuit | null): void;
|
|
60
|
+
/**
|
|
61
|
+
* Set the resolution for LineMaterial rendering
|
|
62
|
+
*
|
|
63
|
+
* MUST be called after initialization and on window/container resize
|
|
64
|
+
* for Line2 to render correctly.
|
|
65
|
+
*
|
|
66
|
+
* @param width - Viewport width in pixels
|
|
67
|
+
* @param height - Viewport height in pixels
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* wireManager.setResolution(window.innerWidth, window.innerHeight);
|
|
72
|
+
*
|
|
73
|
+
* window.addEventListener('resize', () => {
|
|
74
|
+
* wireManager.setResolution(window.innerWidth, window.innerHeight);
|
|
75
|
+
* });
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
setResolution(width: number, height: number): void;
|
|
79
|
+
/**
|
|
80
|
+
* Get the Line2 object for a wire
|
|
81
|
+
*
|
|
82
|
+
* @param wireId - Wire ID
|
|
83
|
+
* @returns Line2 or undefined if not found or disposed
|
|
84
|
+
*/
|
|
85
|
+
getWireLine(wireId: UUID): Line2 | undefined;
|
|
86
|
+
/**
|
|
87
|
+
* Check if a wire visual exists
|
|
88
|
+
*
|
|
89
|
+
* @param wireId - Wire ID
|
|
90
|
+
* @returns true if wire visual exists, false if not found or disposed
|
|
91
|
+
*/
|
|
92
|
+
hasWire(wireId: UUID): boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Get all wire IDs managed by this controllerType
|
|
95
|
+
*
|
|
96
|
+
* @returns Array of wire UUIDs, empty if disposed
|
|
97
|
+
*/
|
|
98
|
+
getWireIds(): UUID[];
|
|
99
|
+
/**
|
|
100
|
+
* Create or update the visual for a wire using model wire positions
|
|
101
|
+
*
|
|
102
|
+
* @param wire - Wire to render
|
|
103
|
+
* @returns The created/updated Line2 object
|
|
104
|
+
*/
|
|
105
|
+
createOrUpdateWire(wire: Wire): Line2;
|
|
106
|
+
/**
|
|
107
|
+
* Update a specific wire's geometry
|
|
108
|
+
*
|
|
109
|
+
* @param wireId - Wire ID to update
|
|
110
|
+
*/
|
|
111
|
+
updateWireById(wireId: UUID): void;
|
|
112
|
+
/**
|
|
113
|
+
* Update all wires connected to a component
|
|
114
|
+
*
|
|
115
|
+
* Called when a component is moved or rotated to update wire endpoints.
|
|
116
|
+
*
|
|
117
|
+
* @param componentId - Component that moved
|
|
118
|
+
*/
|
|
119
|
+
updateWiresForComponent(componentId: UUID): void;
|
|
120
|
+
/**
|
|
121
|
+
* visual hover and selection effects
|
|
122
|
+
*/
|
|
123
|
+
/**
|
|
124
|
+
* Apply hovered visual effect to a wire
|
|
125
|
+
* @param wireId
|
|
126
|
+
*/
|
|
127
|
+
applyHoveredVisual(wireId: UUID): void;
|
|
128
|
+
removeHoveredVisual(wireId: UUID): void;
|
|
129
|
+
applySelectedVisual(wireId: UUID): void;
|
|
130
|
+
removeSelectedVisual(wireId: UUID): void;
|
|
131
|
+
/**
|
|
132
|
+
* Apply electrical state material to a wire
|
|
133
|
+
* Used during simulation to visualize voltage/current flow
|
|
134
|
+
*
|
|
135
|
+
* @param wireId - Wire ID to update
|
|
136
|
+
* @param state - Material state: 'current', 'voltage', 'vc' (voltage and current) or 'idle'
|
|
137
|
+
*/
|
|
138
|
+
applyElectricalState(wireId: UUID, state: 'current' | 'voltage' | 'vc' | 'idle'): void;
|
|
139
|
+
/**
|
|
140
|
+
* removal and dispose
|
|
141
|
+
*/
|
|
142
|
+
/**
|
|
143
|
+
* Remove a wire visual from the scene
|
|
144
|
+
*
|
|
145
|
+
* @param wireId - Wire ID to remove
|
|
146
|
+
*/
|
|
147
|
+
removeWire(wireId: UUID): void;
|
|
148
|
+
/**
|
|
149
|
+
* Clean up all managed wire visuals
|
|
150
|
+
*/
|
|
151
|
+
dispose(): void;
|
|
152
|
+
/**
|
|
153
|
+
* Preview wire helpers
|
|
154
|
+
*/
|
|
155
|
+
/**
|
|
156
|
+
* Create a preview wire for wire creation mode.
|
|
157
|
+
* @param startPosition - World position of wire start
|
|
158
|
+
* @returns Line2 object for preview
|
|
159
|
+
*/
|
|
160
|
+
createPreviewWire(startPosition: THREE.Vector3): Line2;
|
|
161
|
+
/**
|
|
162
|
+
* Update preview wire endpoint.
|
|
163
|
+
* @param endPosition - World position of wire end
|
|
164
|
+
*/
|
|
165
|
+
updatePreviewWire(endPosition: THREE.Vector3): void;
|
|
166
|
+
/**
|
|
167
|
+
* Remove preview wire from scene.
|
|
168
|
+
*/
|
|
169
|
+
removePreviewWire(): void;
|
|
170
|
+
/**
|
|
171
|
+
* Intermediate points and position helpers
|
|
172
|
+
*/
|
|
173
|
+
/**
|
|
174
|
+
* Get pin world position by traversing component group
|
|
175
|
+
*
|
|
176
|
+
* @param enodeId - The pin's ENode ID
|
|
177
|
+
* @param componentGroup - The component's Three.js group
|
|
178
|
+
* @returns World position of the pin, or null if not found
|
|
179
|
+
*/
|
|
180
|
+
getPinWorldPositionFromGroup(enodeId: UUID, componentGroup: THREE.Object3D): THREE.Vector3 | null;
|
|
181
|
+
/**
|
|
182
|
+
* Get insertion index for a new intermediate point on a wire (T058)
|
|
183
|
+
* @param wireId - Wire ID
|
|
184
|
+
* @param worldPosition - Position where user clicked
|
|
185
|
+
* @returns Index where new point should be inserted
|
|
186
|
+
*/
|
|
187
|
+
getInsertIndexForPosition(wireId: UUID, worldPosition: THREE.Vector3): number;
|
|
188
|
+
/**
|
|
189
|
+
* Find nearest intermediate point on a wire within proximity threshold (T057)
|
|
190
|
+
* @param wireId - Wire ID to search
|
|
191
|
+
* @param clientPos - Client position (event.clientX/Y) to test - will be converted to container-relative
|
|
192
|
+
* @param thresholdPx - Proximity threshold in pixels (default: 10)
|
|
193
|
+
* @returns Object with pointIndex and distance, or null if none found
|
|
194
|
+
*/
|
|
195
|
+
findNearestIntermediatePoint(wireId: UUID, clientPos: THREE.Vector2, thresholdPx?: number): {
|
|
196
|
+
pointIndex: number;
|
|
197
|
+
distance: number;
|
|
198
|
+
} | null;
|
|
199
|
+
/**
|
|
200
|
+
* Compute the full path for a wire including intermediate positions
|
|
201
|
+
*
|
|
202
|
+
* @param wire - Wire to compute path for
|
|
203
|
+
* @returns WirePath with array of Vector3 points from start to end
|
|
204
|
+
*/
|
|
205
|
+
computeWirePath(wire: Wire): WirePath;
|
|
206
|
+
/**
|
|
207
|
+
* private helpers
|
|
208
|
+
*/
|
|
209
|
+
/**
|
|
210
|
+
* Get the world position of an ENode (pin or branching point)
|
|
211
|
+
*
|
|
212
|
+
* For pins: Traverses component group to find pin visual and gets world position
|
|
213
|
+
* For branching points: Converts grid position to world coordinates
|
|
214
|
+
*
|
|
215
|
+
* @param enodeId - The ENode ID
|
|
216
|
+
* @param enodeType - Type of the ENode (Pin or BranchingPoint)
|
|
217
|
+
* @param componentId - Parent component ID (for pins)
|
|
218
|
+
* @param circuit - Circuit for position lookup
|
|
219
|
+
* @param componentGroups - Map of component ID to Three.js objects
|
|
220
|
+
* @returns World position as Vector3
|
|
221
|
+
*/
|
|
222
|
+
private _getENodeWorldPosition;
|
|
223
|
+
/**
|
|
224
|
+
* Convert 3D world position to 2D screen position (T056)
|
|
225
|
+
* @param worldPosition - World position as Vector3
|
|
226
|
+
* @returns Screen position as Vector2
|
|
227
|
+
*/
|
|
228
|
+
private worldToScreen;
|
|
229
|
+
/**
|
|
230
|
+
* Calculate distance between two 2D screen positions (T056)
|
|
231
|
+
* @param screenPos1 - First screen position
|
|
232
|
+
* @param screenPos2 - Second screen position
|
|
233
|
+
* @returns Distance in pixels
|
|
234
|
+
*/
|
|
235
|
+
private screenDistance;
|
|
236
|
+
/**
|
|
237
|
+
* Convert client coordinates (event.clientX/Y) to container-relative coordinates
|
|
238
|
+
* @param clientPos - Position in client/viewport coordinates
|
|
239
|
+
* @returns Position relative to the container's top-left corner
|
|
240
|
+
*/
|
|
241
|
+
private clientToContainerCoords;
|
|
242
|
+
}
|
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
import { Component, ComponentType, ComponentState, ENode, ENodeSourceType } from '../../../core/index.ts';
|
|
2
|
+
import { AnimationContext, ConfigFormDefinition, VisualContext } from '../types';
|
|
3
|
+
import { Direction2D } from '../utils/GeometryUtils';
|
|
4
|
+
import { MeshLambertMaterial } from 'three';
|
|
5
|
+
import { CmpMatCategory, CmpMatVariant } from './types';
|
|
6
|
+
import * as THREE from 'three';
|
|
7
|
+
/**
|
|
8
|
+
* Interface for component visual factories
|
|
9
|
+
*
|
|
10
|
+
* Implementations provide methods for:
|
|
11
|
+
* - Creating the 3D visual representation
|
|
12
|
+
* - Applying/removing hover effects
|
|
13
|
+
* - Applying/removing selection effects
|
|
14
|
+
* - Updating animation based on simulation state
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* class MyComponentFactory extends ComponentVisualFactoryBase {
|
|
19
|
+
* createVisual(component: Component, context?: VisualContext): THREE.Object3D {
|
|
20
|
+
* const group = new THREE.Group();
|
|
21
|
+
* // ... create visual elements
|
|
22
|
+
* group.userData.componentId = component.id;
|
|
23
|
+
* group.userData.componentType = component.type;
|
|
24
|
+
* return group;
|
|
25
|
+
* }
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export interface IComponentVisualFactory {
|
|
30
|
+
/**
|
|
31
|
+
* @returns nominal rotation along the Y axis when component added (angle in radian)
|
|
32
|
+
*/
|
|
33
|
+
defaultRotation(): number;
|
|
34
|
+
/**
|
|
35
|
+
* Create the Three.js visual representation for a component
|
|
36
|
+
*
|
|
37
|
+
* @param component - The circuit component to visualize
|
|
38
|
+
* @param context - Optional visual context providing access to ENode data
|
|
39
|
+
* @returns THREE.Object3D (typically a Group) containing the visual
|
|
40
|
+
*
|
|
41
|
+
* @remarks
|
|
42
|
+
* Implementations MUST:
|
|
43
|
+
* - Set `object.userData.componentId = component.id`
|
|
44
|
+
* - Set `object.userData.componentType = component.type`
|
|
45
|
+
* - Create component hitbox on HitboxLayers.COMPONENT layer
|
|
46
|
+
* - Create pin groups with enodes on HitboxLayers.ENODE layer
|
|
47
|
+
* - Return objects positioned at origin (scene controllerType handles placement)
|
|
48
|
+
*/
|
|
49
|
+
createVisual(component: Component, context: VisualContext): THREE.Object3D;
|
|
50
|
+
/**
|
|
51
|
+
* Update visual based on component configuration
|
|
52
|
+
*
|
|
53
|
+
* @param object3D - The Object3D created by createVisual()
|
|
54
|
+
* @param config - The core component configuration Map
|
|
55
|
+
*
|
|
56
|
+
*/
|
|
57
|
+
updateFromConfiguration(object3D: THREE.Object3D, config: Map<string, string>): void;
|
|
58
|
+
/**
|
|
59
|
+
* Apply hover visual effect to a component's Object3D
|
|
60
|
+
*
|
|
61
|
+
* @param object3D - The Object3D created by createVisual()
|
|
62
|
+
*
|
|
63
|
+
* @remarks
|
|
64
|
+
* - Should store original material state in userData for restoration
|
|
65
|
+
* - Default implementation: emissive glow effect (light blue, 0.5 intensity)
|
|
66
|
+
* - Called by scene controllerType when component is hovered
|
|
67
|
+
* - Should be idempotent (safe to call multiple times)
|
|
68
|
+
*/
|
|
69
|
+
applyHover(object3D: THREE.Object3D): void;
|
|
70
|
+
/**
|
|
71
|
+
* Remove hover visual effect from a component's Object3D
|
|
72
|
+
*
|
|
73
|
+
* @param object3D - The Object3D created by createVisual()
|
|
74
|
+
*
|
|
75
|
+
* @remarks
|
|
76
|
+
* - Should restore original material state from userData
|
|
77
|
+
* - Called by scene controllerType when hover ends
|
|
78
|
+
* - Should be safe to call even if not currently hovered
|
|
79
|
+
*/
|
|
80
|
+
removeHover(object3D: THREE.Object3D): void;
|
|
81
|
+
/**
|
|
82
|
+
* Apply selection visual effect to a component's Object3D
|
|
83
|
+
*
|
|
84
|
+
* @param object3D - The Object3D created by createVisual()
|
|
85
|
+
*
|
|
86
|
+
* @remarks
|
|
87
|
+
* - Currently a placeholder (no-op) for future implementation
|
|
88
|
+
*/
|
|
89
|
+
applySelection(object3D: THREE.Object3D): void;
|
|
90
|
+
/**
|
|
91
|
+
* Remove selection visual effect from a component's Object3D
|
|
92
|
+
*
|
|
93
|
+
* @param object3D - The Object3D created by createVisual()
|
|
94
|
+
*
|
|
95
|
+
* @remarks
|
|
96
|
+
* - Currently a placeholder (no-op) for future implementation
|
|
97
|
+
*/
|
|
98
|
+
removeSelection(object3D: THREE.Object3D): void;
|
|
99
|
+
/**
|
|
100
|
+
* Update pin source type visual (optional method)
|
|
101
|
+
*
|
|
102
|
+
* @param pinGroup - The THREE.Group containing the pin visual
|
|
103
|
+
* @param sourceType - The new source type (null for no source)
|
|
104
|
+
*
|
|
105
|
+
* @remarks
|
|
106
|
+
* - Optional method for component factories that support pin source type visualization
|
|
107
|
+
* - Changes pin color based on source type (bronze/red/blue)
|
|
108
|
+
* - Default implementation in ComponentVisualFactoryBase
|
|
109
|
+
*/
|
|
110
|
+
updatePinSourceType(pinGroup: THREE.Object3D, sourceType: ENodeSourceType | null): void;
|
|
111
|
+
/**
|
|
112
|
+
* Apply hover effect on a pin
|
|
113
|
+
* @param pinGroup
|
|
114
|
+
*/
|
|
115
|
+
applyPinHover(pinGroup: THREE.Object3D): void;
|
|
116
|
+
/**
|
|
117
|
+
* Remove hover effect on a pin
|
|
118
|
+
*/
|
|
119
|
+
removePinHover(pinGroup: THREE.Object3D): void;
|
|
120
|
+
/**
|
|
121
|
+
* Update animation state based on simulation data
|
|
122
|
+
*
|
|
123
|
+
* @param object3D - The Object3D created by createVisual()
|
|
124
|
+
* @param state - The component's current simulation state or null to reset to edition mode
|
|
125
|
+
*
|
|
126
|
+
* @remarks
|
|
127
|
+
* - Called by CircuitRunnerController during simulation
|
|
128
|
+
* - Animation visual updates have priority over hover effects
|
|
129
|
+
* - Default implementation: no-op (static components)
|
|
130
|
+
* - Subclasses override for component-specific animation
|
|
131
|
+
* (e.g., LED glow, switch contactor rotation)
|
|
132
|
+
*/
|
|
133
|
+
updateAnimation(object3D: THREE.Object3D, state: ComponentState | null): void;
|
|
134
|
+
/**
|
|
135
|
+
* Get the config form definition for this component type
|
|
136
|
+
*
|
|
137
|
+
* @param config - Optional current component config to compute field states (e.g., disabled)
|
|
138
|
+
* @returns Form definition with field specifications, or null if no config
|
|
139
|
+
*
|
|
140
|
+
* @remarks
|
|
141
|
+
* Defines the UI controls for editing component configuration.
|
|
142
|
+
* Return null for components with no configurable options.
|
|
143
|
+
* When config is provided, implementations may use it to set field.disabled
|
|
144
|
+
* based on interdependencies (e.g., transitionSpan disabled when defaultLogicFamily != Sandbox).
|
|
145
|
+
*/
|
|
146
|
+
getConfigFormDefinition(config?: Map<string, string>): ConfigFormDefinition | null;
|
|
147
|
+
/**
|
|
148
|
+
* Map core component config (string values) to form data (typed values)
|
|
149
|
+
*
|
|
150
|
+
* @param config - Core config from Component.config
|
|
151
|
+
* @returns Form data with appropriate types for UI controls
|
|
152
|
+
*
|
|
153
|
+
* @remarks
|
|
154
|
+
* Called when config panel opens to initialize form controls.
|
|
155
|
+
* Converts core string values to UI-appropriate types (e.g., "open" → true).
|
|
156
|
+
*/
|
|
157
|
+
mapCoreConfigToForm(config: Map<string, string>): Map<string, any>;
|
|
158
|
+
/**
|
|
159
|
+
* Map form data (typed values) back to core config (string values)
|
|
160
|
+
*
|
|
161
|
+
* @param formData - Current form values from UI
|
|
162
|
+
* @returns Core config ready for Component.setAllParameters()
|
|
163
|
+
*
|
|
164
|
+
* @remarks
|
|
165
|
+
* Called on each value change to update Component.config.
|
|
166
|
+
* Converts UI values back to core string format (e.g., true → "open").
|
|
167
|
+
*/
|
|
168
|
+
mapFormToCoreConfig(formData: Map<string, any>): Map<string, string>;
|
|
169
|
+
/**
|
|
170
|
+
* Set the shared animation context for simulation-aware factories.
|
|
171
|
+
* Called by the registry fan-out when entering/leaving simulation.
|
|
172
|
+
*
|
|
173
|
+
* @param ctx - Animation context, or null when leaving simulation
|
|
174
|
+
*/
|
|
175
|
+
setAnimationContext(ctx: AnimationContext | null): void;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Abstract base class for component visual factories
|
|
179
|
+
*
|
|
180
|
+
* Provides default implementations for:
|
|
181
|
+
* - Hover effect (emissive glow)
|
|
182
|
+
* - Selection effect (placeholder/no-op)
|
|
183
|
+
* - Animation update (placeholder/no-op)
|
|
184
|
+
* - Pin group creation (shared helper)
|
|
185
|
+
* - Component hitbox creation (shared helper)
|
|
186
|
+
*
|
|
187
|
+
* Subclasses must implement:
|
|
188
|
+
* - createVisual() - component-specific visual creation
|
|
189
|
+
*
|
|
190
|
+
* Subclasses may override:
|
|
191
|
+
* - applyHover() / removeHover() - custom hover effect
|
|
192
|
+
* - applySelection() / removeSelection() - custom selection effect (future)
|
|
193
|
+
* - updateAnimation() - component-specific animation
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```typescript
|
|
197
|
+
* export class BatteryVisualFactory extends ComponentVisualFactoryBase {
|
|
198
|
+
* createVisual(component: Component, context?: VisualContext): THREE.Object3D {
|
|
199
|
+
* const group = new THREE.Group();
|
|
200
|
+
* // ... create battery-specific visual
|
|
201
|
+
* return group;
|
|
202
|
+
* }
|
|
203
|
+
* // Inherits default hover, selection, and animation
|
|
204
|
+
* }
|
|
205
|
+
* ```
|
|
206
|
+
*/
|
|
207
|
+
export declare abstract class ComponentVisualFactoryBase implements IComponentVisualFactory {
|
|
208
|
+
/** Shared animation context injected by the registry during simulation */
|
|
209
|
+
protected _animationContext: AnimationContext | null;
|
|
210
|
+
/** ComponentType handled by this factory, set in each subclass constructor */
|
|
211
|
+
protected _componentType: ComponentType | null;
|
|
212
|
+
/** Default hover glow color (light blue) */
|
|
213
|
+
protected static readonly DEFAULT_HOVER_COLOR = 4491519;
|
|
214
|
+
/** Default hover emissive intensity */
|
|
215
|
+
protected static readonly DEFAULT_HOVER_INTENSITY = 0.6;
|
|
216
|
+
protected getMat(category: CmpMatCategory, variant?: CmpMatVariant): MeshLambertMaterial;
|
|
217
|
+
defaultRotation(): number;
|
|
218
|
+
/**
|
|
219
|
+
* Create the Three.js visual representation for a component
|
|
220
|
+
* Must be implemented by subclasses
|
|
221
|
+
*/
|
|
222
|
+
abstract createVisual(component: Component, context: VisualContext): THREE.Object3D;
|
|
223
|
+
/**
|
|
224
|
+
* By default no visual configuration-based updates is needed
|
|
225
|
+
*/
|
|
226
|
+
updateFromConfiguration(_object3D: THREE.Object3D, _config: Map<string, string>): void;
|
|
227
|
+
/**
|
|
228
|
+
* Apply hover visual effect using emissive glow
|
|
229
|
+
*
|
|
230
|
+
* Default implementation traverses all meshes and applies
|
|
231
|
+
* an emissive blue glow effect, storing original values in userData.
|
|
232
|
+
*
|
|
233
|
+
* Note: If component is selected, selection visual takes precedence
|
|
234
|
+
* and hover visual is not applied (but isHovered flag is still set).
|
|
235
|
+
*/
|
|
236
|
+
applyHover(object3D: THREE.Object3D): void;
|
|
237
|
+
/**
|
|
238
|
+
* Remove hover visual effect, restoring original materials
|
|
239
|
+
*/
|
|
240
|
+
removeHover(object3D: THREE.Object3D): void;
|
|
241
|
+
/**
|
|
242
|
+
* Apply selection visual effect using emissive orange glow
|
|
243
|
+
*
|
|
244
|
+
* Selection takes precedence over hover effect.
|
|
245
|
+
* Stores original material state in userData for restoration.
|
|
246
|
+
*
|
|
247
|
+
* @param object3D - The component's root Three.js object
|
|
248
|
+
*/
|
|
249
|
+
applySelection(object3D: THREE.Object3D): void;
|
|
250
|
+
/**
|
|
251
|
+
* Remove selection visual effect, restoring original or hover state
|
|
252
|
+
*
|
|
253
|
+
* If component was hovered before selection, restores hover visual.
|
|
254
|
+
* Otherwise, restores original material state.
|
|
255
|
+
*
|
|
256
|
+
* @param object3D - The component's root Three.js object
|
|
257
|
+
*/
|
|
258
|
+
removeSelection(object3D: THREE.Object3D): void;
|
|
259
|
+
/**
|
|
260
|
+
* @private
|
|
261
|
+
*/
|
|
262
|
+
private pointPinGroupToward;
|
|
263
|
+
/**
|
|
264
|
+
* Create a pin group with hitbox and visual sphere
|
|
265
|
+
*
|
|
266
|
+
* Creates a THREE.Group containing:
|
|
267
|
+
* - Hemisphere hitbox (on ENODE layer for raycasting)
|
|
268
|
+
* - Hemisphere visual (blue sphere)
|
|
269
|
+
* - Hover callback in userData
|
|
270
|
+
*
|
|
271
|
+
* @param node - ENode to create as visual pin
|
|
272
|
+
* @param pointsTo - rotate pin to make it point the wanted direction
|
|
273
|
+
* @param visualRotation - if set rotate the visual of the pin to adjust display without affecting hitbox
|
|
274
|
+
* @returns THREE.Group configured as pin group
|
|
275
|
+
*/
|
|
276
|
+
protected createPinGroup(node: ENode, pointsTo?: Direction2D, visualRotation?: THREE.Euler | null): THREE.Group;
|
|
277
|
+
/**
|
|
278
|
+
* Utility to create semi spheres visually closing pins
|
|
279
|
+
* @param pinGroup
|
|
280
|
+
* @param material
|
|
281
|
+
* @protected
|
|
282
|
+
*/
|
|
283
|
+
protected createPinCounterpart(pinGroup: THREE.Group, material: THREE.MeshLambertMaterial): THREE.Mesh | null;
|
|
284
|
+
/**
|
|
285
|
+
* Find pin group by label within a component Object3D
|
|
286
|
+
* @param object3D
|
|
287
|
+
* @param label
|
|
288
|
+
*/
|
|
289
|
+
findPinGroup(object3D: THREE.Object3D, label: string): THREE.Group | null;
|
|
290
|
+
/**
|
|
291
|
+
* fin pin inner visual from within its pin group
|
|
292
|
+
* @param pinGroup
|
|
293
|
+
*/
|
|
294
|
+
findPinVisualFromGroup(pinGroup: THREE.Group): THREE.Mesh | null;
|
|
295
|
+
/**
|
|
296
|
+
* Find pin group visual by label within a component Object3D
|
|
297
|
+
* @param object3D
|
|
298
|
+
* @param label
|
|
299
|
+
*/
|
|
300
|
+
findPinVisual(object3D: THREE.Object3D, label: string): THREE.Mesh | null;
|
|
301
|
+
/**
|
|
302
|
+
* Create component hitbox mesh
|
|
303
|
+
*
|
|
304
|
+
* Helper to create standard component hitbox with proper userData and layer.
|
|
305
|
+
*
|
|
306
|
+
* @param componentId - UUID of the component
|
|
307
|
+
* @param groupId - ID of the parent THREE.Group
|
|
308
|
+
* @param width - Hitbox width
|
|
309
|
+
* @param height - Hitbox height
|
|
310
|
+
* @param depth - Hitbox depth
|
|
311
|
+
* @returns THREE.Mesh configured as component hitbox
|
|
312
|
+
*/
|
|
313
|
+
protected createComponentHitbox(componentId: string, groupId: number, width: number, height: number, depth: number): THREE.Mesh;
|
|
314
|
+
protected findHitbox(object3D: THREE.Object3D): THREE.Mesh | null;
|
|
315
|
+
protected pinColorForSourceType(sourceType: ENodeSourceType | null): number;
|
|
316
|
+
protected pinColorForElectricalState(state: 'current' | 'voltage' | 'vc' | 'idle'): number;
|
|
317
|
+
/**
|
|
318
|
+
* Updates the visual color of a component pin based on its sourceType type.
|
|
319
|
+
*
|
|
320
|
+
* This method changes the pin's material color to reflect the sourceType type:
|
|
321
|
+
* - null/undefined: copper (default pin color)
|
|
322
|
+
* - Voltage: red
|
|
323
|
+
* - Current: blue
|
|
324
|
+
*
|
|
325
|
+
* @param pinGroup - The THREE.Group containing the pin visual (created by createPinGroup)
|
|
326
|
+
* @param sourceType - The new sourceType (null for no sourceType)
|
|
327
|
+
*
|
|
328
|
+
* @remarks
|
|
329
|
+
* - Searches for the child mesh with userData.type === 'enode'
|
|
330
|
+
* - Updates both color and emissive properties for visual consistency
|
|
331
|
+
* - If sourceType is null/undefined, restores default copper pin color
|
|
332
|
+
* - Color scheme matches BranchingPointVisualFactory for consistency
|
|
333
|
+
*/
|
|
334
|
+
updatePinSourceType(pinGroup: THREE.Object3D, sourceType: ENodeSourceType | null): void;
|
|
335
|
+
/**
|
|
336
|
+
* Apply hover visual effect on this pin
|
|
337
|
+
*/
|
|
338
|
+
applyPinHover(pinGroup: THREE.Object3D): void;
|
|
339
|
+
/**
|
|
340
|
+
* remove hover visual effect on this pin
|
|
341
|
+
*/
|
|
342
|
+
removePinHover(pinGroup: THREE.Object3D): void;
|
|
343
|
+
/**
|
|
344
|
+
* Update animation state based on simulation data (placeholder)
|
|
345
|
+
*
|
|
346
|
+
* Default implementation is a no-op for static components.
|
|
347
|
+
* Override in subclasses that have animation (LED, Switch).
|
|
348
|
+
*/
|
|
349
|
+
updateAnimation(_object3D: THREE.Object3D, _state: ComponentState | null): void;
|
|
350
|
+
/**
|
|
351
|
+
* Get config form definition (default: null - no config)
|
|
352
|
+
*
|
|
353
|
+
* Override in subclasses that have configurable options.
|
|
354
|
+
*/
|
|
355
|
+
getConfigFormDefinition(_config?: Map<string, string>): ConfigFormDefinition | null;
|
|
356
|
+
/**
|
|
357
|
+
* Map core config to form data (default: identity mapping)
|
|
358
|
+
*
|
|
359
|
+
* Override in subclasses that need type conversions.
|
|
360
|
+
*/
|
|
361
|
+
mapCoreConfigToForm(config: Map<string, string>): Map<string, any>;
|
|
362
|
+
/**
|
|
363
|
+
* Map form data to core config (default: convert all to strings)
|
|
364
|
+
*
|
|
365
|
+
* Override in subclasses that need type conversions.
|
|
366
|
+
*/
|
|
367
|
+
mapFormToCoreConfig(formData: Map<string, any>): Map<string, string>;
|
|
368
|
+
/**
|
|
369
|
+
* Set the shared animation context for simulation-aware factories.
|
|
370
|
+
*/
|
|
371
|
+
setAnimationContext(ctx: AnimationContext | null): void;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Registry interface for managing component visual factories
|
|
375
|
+
*
|
|
376
|
+
* Provides type-safe registration and retrieval of component factories.
|
|
377
|
+
* Falls back to a default factory for unregistered component types.
|
|
378
|
+
*
|
|
379
|
+
* @remarks
|
|
380
|
+
* Updated to support both function-based and class-based factories.
|
|
381
|
+
* Prefer using IComponentVisualFactory class instances.
|
|
382
|
+
*
|
|
383
|
+
* @example
|
|
384
|
+
* ```typescript
|
|
385
|
+
* const registry = new FactoryRegistry(new DefaultVisualFactory());
|
|
386
|
+
* registry.register(ComponentType.Battery, new BatteryVisualFactory());
|
|
387
|
+
* registry.register(ComponentType.LED, new SmallLEDVisualFactory());
|
|
388
|
+
*
|
|
389
|
+
* const factory = registry.get(ComponentType.Battery);
|
|
390
|
+
* const mesh = factory.createVisual(batteryComponent);
|
|
391
|
+
* ```
|
|
392
|
+
*/
|
|
393
|
+
export interface IFactoryRegistry {
|
|
394
|
+
/**
|
|
395
|
+
* Retrieve the factory for a component type
|
|
396
|
+
*
|
|
397
|
+
* @param type - Component type identifier
|
|
398
|
+
* @returns Factory (fallback factory if type not registered)
|
|
399
|
+
*
|
|
400
|
+
* @remarks
|
|
401
|
+
* This method NEVER returns null/undefined. If the type is not registered,
|
|
402
|
+
* the fallback factory provided in the constructor is returned.
|
|
403
|
+
*/
|
|
404
|
+
get(type: ComponentType): IComponentVisualFactory;
|
|
405
|
+
/**
|
|
406
|
+
* Check if a factory is registered for a component type
|
|
407
|
+
*
|
|
408
|
+
* @param type - Component type identifier
|
|
409
|
+
* @returns true if explicitly registered, false if would use fallback
|
|
410
|
+
*/
|
|
411
|
+
has(type: ComponentType): boolean;
|
|
412
|
+
/**
|
|
413
|
+
* Get the fallback factory used for unregistered component types
|
|
414
|
+
*/
|
|
415
|
+
getFallbackFactory(): IComponentVisualFactory;
|
|
416
|
+
/**
|
|
417
|
+
* Unregister a factory for a component type
|
|
418
|
+
*
|
|
419
|
+
* @param type - Component type identifier
|
|
420
|
+
* @returns true if factory was registered and removed, false otherwise
|
|
421
|
+
*
|
|
422
|
+
* @remarks
|
|
423
|
+
* After unregistering, get() will return the fallback factory for this type.
|
|
424
|
+
*/
|
|
425
|
+
unregister(type: ComponentType): boolean;
|
|
426
|
+
/**
|
|
427
|
+
* Get all registered component types
|
|
428
|
+
*
|
|
429
|
+
* @returns Array of ComponentType values that have registered factories
|
|
430
|
+
*/
|
|
431
|
+
getRegisteredTypes(): ComponentType[];
|
|
432
|
+
/**
|
|
433
|
+
* Fan out animation context to all registered factories and the fallback.
|
|
434
|
+
*
|
|
435
|
+
* @param ctx - Animation context, or null when leaving simulation
|
|
436
|
+
*/
|
|
437
|
+
setAnimationContext(ctx: AnimationContext | null): void;
|
|
438
|
+
}
|