simple-circuit-engine 0.0.10 → 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.
Files changed (141) hide show
  1. package/AGENTS.md +13 -7
  2. package/CLAUDE.md +16 -103
  3. package/README.md +8 -5
  4. package/dist/core/index.d.ts +2 -23
  5. package/dist/core/index.js +75 -2000
  6. package/dist/core/setup.d.ts +17 -0
  7. package/dist/core/simulation/CircuitRunner.d.ts +176 -0
  8. package/dist/core/simulation/DirtyTracker.d.ts +87 -0
  9. package/dist/core/simulation/EventQueue.d.ts +68 -0
  10. package/dist/core/simulation/StateManager.d.ts +100 -0
  11. package/dist/core/simulation/behaviors/BehaviorRegistry.d.ts +70 -0
  12. package/dist/core/simulation/behaviors/ComponentBehavior.d.ts +53 -0
  13. package/dist/core/simulation/behaviors/basic/BatteryBehavior.d.ts +14 -0
  14. package/dist/core/simulation/behaviors/basic/ClockBehavior.d.ts +24 -0
  15. package/dist/core/simulation/behaviors/basic/DoubleThrowSwitchBehavior.d.ts +33 -0
  16. package/dist/core/simulation/behaviors/basic/LightbulbBehavior.d.ts +23 -0
  17. package/dist/core/simulation/behaviors/basic/RectangleLEDBehavior.d.ts +24 -0
  18. package/dist/core/simulation/behaviors/basic/RelayBehavior.d.ts +33 -0
  19. package/dist/core/simulation/behaviors/basic/SmallLEDBehavior.d.ts +24 -0
  20. package/dist/core/simulation/behaviors/basic/SwitchBehavior.d.ts +33 -0
  21. package/dist/core/simulation/behaviors/basic/index.d.ts +20 -0
  22. package/dist/core/simulation/behaviors/gates/InverterBehavior.d.ts +29 -0
  23. package/dist/core/simulation/behaviors/gates/Nand4GateBehavior.d.ts +18 -0
  24. package/dist/core/simulation/behaviors/gates/Nand8GateBehavior.d.ts +18 -0
  25. package/dist/core/simulation/behaviors/gates/NandGateBehavior.d.ts +28 -0
  26. package/dist/core/simulation/behaviors/gates/Nor4GateBehavior.d.ts +18 -0
  27. package/dist/core/simulation/behaviors/gates/Nor8GateBehavior.d.ts +18 -0
  28. package/dist/core/simulation/behaviors/gates/NorGateBehavior.d.ts +22 -0
  29. package/dist/core/simulation/behaviors/gates/Xor4GateBehavior.d.ts +18 -0
  30. package/dist/core/simulation/behaviors/gates/Xor8GateBehavior.d.ts +18 -0
  31. package/dist/core/simulation/behaviors/gates/XorGateBehavior.d.ts +22 -0
  32. package/dist/core/simulation/behaviors/gates/index.d.ts +34 -0
  33. package/dist/core/simulation/behaviors/index.d.ts +24 -0
  34. package/dist/core/simulation/behaviors/types.d.ts +101 -0
  35. package/dist/core/simulation/index.d.ts +18 -0
  36. package/dist/core/simulation/states/ComponentState.d.ts +57 -0
  37. package/dist/core/simulation/states/SimulationState.d.ts +46 -0
  38. package/dist/core/simulation/states/basic/BatteryState.d.ts +16 -0
  39. package/dist/core/simulation/states/basic/ClockState.d.ts +16 -0
  40. package/dist/core/simulation/states/basic/DoubleThrowSwitchState.d.ts +21 -0
  41. package/dist/core/simulation/states/basic/LightbulbState.d.ts +21 -0
  42. package/dist/core/simulation/states/basic/RectangleLEDState.d.ts +9 -0
  43. package/dist/core/simulation/states/basic/RelayState.d.ts +25 -0
  44. package/dist/core/simulation/states/basic/SmallLEDState.d.ts +21 -0
  45. package/dist/core/simulation/states/basic/SwitchState.d.ts +25 -0
  46. package/dist/core/simulation/states/gates/InverterState.d.ts +17 -0
  47. package/dist/core/simulation/states/gates/Nand4GateState.d.ts +10 -0
  48. package/dist/core/simulation/states/gates/Nand8GateState.d.ts +10 -0
  49. package/dist/core/simulation/states/gates/NandGateState.d.ts +16 -0
  50. package/dist/core/simulation/states/gates/Nor4GateState.d.ts +10 -0
  51. package/dist/core/simulation/states/gates/Nor8GateState.d.ts +10 -0
  52. package/dist/core/simulation/states/gates/NorGateState.d.ts +10 -0
  53. package/dist/core/simulation/states/gates/Xor4GateState.d.ts +10 -0
  54. package/dist/core/simulation/states/gates/Xor8GateState.d.ts +10 -0
  55. package/dist/core/simulation/states/gates/XorGateState.d.ts +10 -0
  56. package/dist/core/simulation/states/gates/index.d.ts +25 -0
  57. package/dist/core/simulation/states/index.d.ts +26 -0
  58. package/dist/core/simulation/states/types.d.ts +32 -0
  59. package/dist/core/simulation/types.d.ts +155 -0
  60. package/dist/core/topology/Circuit.d.ts +420 -0
  61. package/dist/core/topology/CircuitMetadata.d.ts +24 -0
  62. package/dist/core/topology/CircuitOptions.d.ts +14 -0
  63. package/dist/core/topology/Component.d.ts +152 -0
  64. package/dist/core/topology/ENode.d.ts +200 -0
  65. package/dist/core/topology/Wire.d.ts +130 -0
  66. package/dist/core/topology/delays.d.ts +52 -0
  67. package/dist/core/topology/index.d.ts +14 -0
  68. package/dist/core/topology/types.d.ts +175 -0
  69. package/dist/core/utils/CameraOptions.d.ts +83 -0
  70. package/dist/core/utils/MemoizeDecorator.d.ts +9 -0
  71. package/dist/core/utils/Position.d.ts +166 -0
  72. package/dist/core/utils/Position3D.d.ts +77 -0
  73. package/dist/core/utils/Rotation.d.ts +82 -0
  74. package/dist/core/utils/index.d.ts +24 -0
  75. package/dist/core/utils/types.d.ts +35 -0
  76. package/dist/core-Bjta9Y7_.js +2707 -0
  77. package/dist/core-Bjta9Y7_.js.map +1 -0
  78. package/dist/index.d.ts +13 -6286
  79. package/dist/index.js +120 -100
  80. package/dist/scene/CircuitEngine.d.ts +270 -0
  81. package/dist/scene/index.d.ts +1 -2
  82. package/dist/scene/index.js +44 -38
  83. package/dist/scene/setup.d.ts +18 -0
  84. package/dist/scene/shared/AbstractCircuitController.d.ts +211 -0
  85. package/dist/scene/shared/BranchingPointVisualFactory.d.ts +70 -0
  86. package/dist/scene/shared/EventEmitter.d.ts +92 -0
  87. package/dist/scene/shared/HoverManager.d.ts +151 -0
  88. package/dist/scene/shared/SelectionManager.d.ts +159 -0
  89. package/dist/scene/shared/WireVisualManager.d.ts +242 -0
  90. package/dist/scene/shared/components/ComponentVisualFactory.d.ts +438 -0
  91. package/dist/scene/shared/components/DefaultVisualFactory.d.ts +51 -0
  92. package/dist/scene/shared/components/FactoryRegistry.d.ts +84 -0
  93. package/dist/scene/shared/components/GroupedFactoryRegistry.d.ts +153 -0
  94. package/dist/scene/shared/components/basic/BatteryVisualFactory.d.ts +13 -0
  95. package/dist/scene/shared/components/basic/ClockVisualFactory.d.ts +79 -0
  96. package/dist/scene/shared/components/basic/DoubleThrowSwitchVisualFactory.d.ts +87 -0
  97. package/dist/scene/shared/components/basic/LabelVisualFactory.d.ts +148 -0
  98. package/dist/scene/shared/components/basic/LightbulbVisualFactory.d.ts +72 -0
  99. package/dist/scene/shared/components/basic/RectangleLEDVisualFactory.d.ts +86 -0
  100. package/dist/scene/shared/components/basic/RelayVisualFactory.d.ts +92 -0
  101. package/dist/scene/shared/components/basic/SmallLEDVisualFactory.d.ts +86 -0
  102. package/dist/scene/shared/components/basic/SwitchVisualFactory.d.ts +85 -0
  103. package/dist/scene/shared/components/gates/InverterVisualFactory.d.ts +104 -0
  104. package/dist/scene/shared/components/gates/Nand4GateVisualFactory.d.ts +27 -0
  105. package/dist/scene/shared/components/gates/Nand8GateVisualFactory.d.ts +27 -0
  106. package/dist/scene/shared/components/gates/NandGateVisualFactory.d.ts +101 -0
  107. package/dist/scene/shared/components/gates/Nor4GateVisualFactory.d.ts +27 -0
  108. package/dist/scene/shared/components/gates/Nor8GateVisualFactory.d.ts +27 -0
  109. package/dist/scene/shared/components/gates/NorGateVisualFactory.d.ts +101 -0
  110. package/dist/scene/shared/components/gates/Xor4GateVisualFactory.d.ts +29 -0
  111. package/dist/scene/shared/components/gates/Xor8GateVisualFactory.d.ts +29 -0
  112. package/dist/scene/shared/components/gates/XorGateVisualFactory.d.ts +103 -0
  113. package/dist/scene/shared/components/index.d.ts +29 -0
  114. package/dist/scene/shared/components/types.d.ts +43 -0
  115. package/dist/scene/shared/types.d.ts +476 -0
  116. package/dist/scene/shared/utils/CameraUtils.d.ts +23 -0
  117. package/dist/scene/shared/utils/ColorUtils.d.ts +26 -0
  118. package/dist/scene/shared/utils/ControlsUtils.d.ts +8 -0
  119. package/dist/scene/shared/utils/GeometryUtils.d.ts +261 -0
  120. package/dist/scene/shared/utils/LayerConstants.d.ts +40 -0
  121. package/dist/scene/shared/utils/LightingUtils.d.ts +31 -0
  122. package/dist/scene/shared/utils/MaterialUtils.d.ts +73 -0
  123. package/dist/scene/shared/utils/Options.d.ts +16 -0
  124. package/dist/scene/simulation/CircuitRunnerController.d.ts +227 -0
  125. package/dist/scene/static/CircuitController.d.ts +227 -0
  126. package/dist/scene/static/CircuitWriter.d.ts +146 -0
  127. package/dist/scene/static/PinTooltipWidget.d.ts +26 -0
  128. package/dist/scene/static/tools/BuildTool.d.ts +286 -0
  129. package/dist/scene/static/tools/ComponentPickerWidget.d.ts +82 -0
  130. package/dist/scene/static/tools/ConfigPanelWidget.d.ts +93 -0
  131. package/dist/scene/static/tools/MultiSelectTool.d.ts +265 -0
  132. package/dist/scene-CVsDdySt.js +7357 -0
  133. package/dist/scene-CVsDdySt.js.map +1 -0
  134. package/package.json +24 -25
  135. package/dist/CircuitRunner-DEb7JdNf.js +0 -1809
  136. package/dist/CircuitRunner-DEb7JdNf.js.map +0 -1
  137. package/dist/core/index.js.map +0 -1
  138. package/dist/index.js.map +0 -1
  139. package/dist/scene/index.js.map +0 -1
  140. package/dist/setup-AB1vFiis.js +0 -9918
  141. package/dist/setup-AB1vFiis.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
+ }