simple-circuit-engine 0.0.9 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -139,7 +139,7 @@ export declare abstract class AbstractCircuitController extends EventEmitter<Con
139
139
  /**
140
140
  * Get the current cursor position on the ground plane (y=0) in world coordinates
141
141
  * The position is clamped within the circuit grid boundaries but not snapped to grid
142
- * @param bound - Whether to constrain position within grid boundaries
142
+ * @param bound - Whether to constrain position within grid boundaries, default false
143
143
  */
144
144
  cursorGroundPlanePosition(bound?: boolean): THREE.Vector3;
145
145
  /**
@@ -202,135 +202,147 @@ export declare abstract class AbstractCircuitController extends EventEmitter<Con
202
202
  }
203
203
 
204
204
  /**
205
- * Tool for adding new components to the circuit
206
- * Provides ghost preview, grid snapping, and placement validation
205
+ * Visual factory for AND gates components
206
+ *
207
+ * Creates:
208
+ * - Gate mesh
209
+ * - vcc, inputs and output pin groups
210
+ * - Component hitbox for raycasting
211
+ *
212
+ * Animation:
213
+ * - Emissive glow when Gate is high (based on simulation state)
207
214
  */
208
- export declare class AddComponentTool implements IEditingTool {
209
- readonly type: ToolType;
210
- private _controller;
211
- private _componentType;
212
- private _ghostPreview;
213
- private _previewPosition;
214
- private _previewRotation;
215
- private _hasOverlap;
216
- private _gridPositionMoveHandler;
217
- private _pointerDownHandler;
218
- private _wheelHandler;
219
- private _keyDownHandler;
220
- constructor(controller: CircuitController);
221
- /**
222
- * Called when tool becomes active (T010)
223
- * Attaches event listeners for hover and click interactions
224
- */
225
- onActivate(): void;
226
- /**
227
- * Called when tool is deactivated (T011)
228
- * Removes event listeners and cleans up preview objects
229
- */
230
- onDeactivate(): void;
231
- /**
232
- * Set the component type to place (T012)
233
- * Creates a new ghost preview for the selected component type
234
- *
235
- * @param type - Component type to place
236
- */
237
- setComponentType(type: ComponentType | null): void;
238
- /**
239
- * Cycle through available component types (for ctrl+scroll)
240
- * @param forward
241
- * @private
242
- */
243
- private cycleComponentTypes;
244
- /**
245
- * Create ghost preview for the current component type (T013)
246
- * Uses FactoryRegistry to create visual representation
247
- * @private
248
- */
249
- private _createGhostPreview;
215
+ export declare class And4GateVisualFactory extends AndGateVisualFactory {
216
+ /** Shared open envelope geometry */
217
+ protected readonly lowGeometry: THREE.ExtrudeGeometry;
218
+ /** Shared transient envelope geometry */
219
+ protected readonly transientGeometry: THREE.ExtrudeGeometry;
220
+ /** Shared transient envelope geometry */
221
+ protected readonly highGeometry: THREE.ExtrudeGeometry;
222
+ /** Shared geometry for negative marker **/
223
+ protected static readonly negativeMarkerGeometry: THREE.CylinderGeometry;
224
+ createVisual(component: Component): THREE.Object3D;
250
225
  /**
251
- * Apply ghost effect to preview object (T014)
252
- * Makes the preview semi-transparent to indicate it's not yet placed
226
+ * Get config form definition for Transistor (T026)
253
227
  *
254
- * @param object - Object3D to apply ghost effect to
255
- * @private
256
- */
257
- private _applyGhostEffect;
258
- /**
259
- * Dispose ghost preview and cleanup resources
260
- * @private
228
+ * @returns Form definition with activationLogic boolean field
261
229
  */
262
- private _disposeGhostPreview;
230
+ getConfigFormDefinition(): ConfigFormDefinition | null;
231
+ updateFromConfiguration(object3D: THREE.Object3D, config: Map<string, string>): void;
232
+ }
233
+
234
+ /**
235
+ * Visual factory for AND gates components
236
+ *
237
+ * Creates:
238
+ * - Gate mesh
239
+ * - vcc, inputs and output pin groups
240
+ * - Component hitbox for raycasting
241
+ *
242
+ * Animation:
243
+ * - Emissive glow when Gate is high (based on simulation state)
244
+ */
245
+ export declare class And8GateVisualFactory extends AndGateVisualFactory {
246
+ /** Shared open envelope geometry */
247
+ protected readonly lowGeometry: THREE.ExtrudeGeometry;
248
+ /** Shared transient envelope geometry */
249
+ protected readonly transientGeometry: THREE.ExtrudeGeometry;
250
+ /** Shared transient envelope geometry */
251
+ protected readonly highGeometry: THREE.ExtrudeGeometry;
252
+ /** Shared geometry for negative marker **/
253
+ protected static readonly negativeMarkerGeometry: THREE.CylinderGeometry;
254
+ createVisual(component: Component): THREE.Object3D;
263
255
  /**
264
- * Get preview objects to render in the scene (T015)
265
- * Returns the ghost preview if available
256
+ * Get config form definition for Transistor (T026)
266
257
  *
267
- * @returns Array containing ghost preview object
258
+ * @returns Form definition with activationLogic boolean field
268
259
  */
269
- getPreviewObjects(): THREE.Object3D[];
260
+ getConfigFormDefinition(): ConfigFormDefinition | null;
261
+ updateFromConfiguration(object3D: THREE.Object3D, config: Map<string, string>): void;
262
+ }
263
+
264
+ /**
265
+ * Visual factory for AND gates components
266
+ *
267
+ * Creates:
268
+ * - Gate mesh
269
+ * - vcc, inputs and output pin groups
270
+ * - Component hitbox for raycasting
271
+ *
272
+ * Animation:
273
+ * - Emissive glow when Gate is high (based on simulation state)
274
+ */
275
+ export declare class AndGateVisualFactory extends ComponentVisualFactoryBase {
276
+ /** Gate high color */
277
+ protected static readonly HIGH_COLOR = 16777215;
278
+ /** Gate high emissive intensity */
279
+ protected static readonly HIGH_INTENSITY = 0.3;
280
+ /** Shared open envelope geometry */
281
+ protected readonly lowGeometry: THREE.ExtrudeGeometry;
282
+ /** Shared transient envelope geometry */
283
+ protected readonly transientGeometry: THREE.ExtrudeGeometry;
284
+ /** Shared transient envelope geometry */
285
+ protected readonly highGeometry: THREE.ExtrudeGeometry;
286
+ /** Shared material for negative marker **/
287
+ protected static readonly negativeMarkerMaterial: THREE.MeshStandardMaterial;
288
+ /** Shared geometry for negative marker **/
289
+ protected static readonly negativeMarkerGeometry: THREE.CylinderGeometry;
290
+ defaultRotation(): number;
291
+ createVisual(component: Component): THREE.Object3D;
270
292
  /**
271
- * Check if preview overlaps with existing components (T021)
272
- * Uses THREE.Box3 bounding box collision detection
293
+ * Get config form definition for Transistor (T026)
273
294
  *
274
- * @returns true if overlap detected, false otherwise
275
- * @private
295
+ * @returns Form definition with activationLogic boolean field
276
296
  */
277
- private _checkOverlap;
297
+ getConfigFormDefinition(): ConfigFormDefinition | null;
278
298
  /**
279
- * Apply invalid placement visual effect (T022)
280
- * Sets red emissive color to indicate invalid placement
299
+ * Map core config to form data
300
+ * Converts "positive"/"negative" strings to boolean
281
301
  *
282
- * @param object - Object3D to apply effect to
283
- * @private
302
+ * @param config - Core component config
303
+ * @returns Form data with boolean activationLogic
284
304
  */
285
- private _applyInvalidEffect;
305
+ mapCoreConfigToForm(config: Map<string, string>): Map<string, any>;
286
306
  /**
287
- * Remove invalid placement visual effect (T023)
288
- * Restores normal emissive values
307
+ * Map form data to core config
308
+ * Converts boolean to "positive"/"negative" strings
289
309
  *
290
- * @param object - Object3D to restore
291
- * @private
310
+ * @param formData - Form data with boolean activationLogic
311
+ * @returns Core config with string activationLogic
292
312
  */
293
- private _removeInvalidEffect;
313
+ mapFormToCoreConfig(formData: Map<string, any>): Map<string, string>;
314
+ updateFromConfiguration(object3D: THREE.Object3D, config: Map<string, string>): void;
294
315
  /**
295
- * Handle gridPosition move events (T016, T024)
296
- * Updates preview position with grid snapping and checks for overlap
316
+ * Update animation based on simulation state
297
317
  *
298
- * @param worldPosition - Current cursor position in world coordinates (already grid-snapped)
318
+ * @param object3D - The Object3D created by createVisual()
319
+ * @param state - The component current simulation state
299
320
  */
300
- handleGridPositionMove(worldPosition: THREE.Vector3): void;
321
+ updateAnimation(object3D: THREE.Object3D, state: ComponentState | null): void;
301
322
  /**
302
- * Handle pointer down events for component placement or selection (T017, T019, T026, T027, T042)
303
- * - If clicking on existing component: select it
304
- * - If clicking empty space: place component at preview position
323
+ * Find the envelope mesh within the component group
305
324
  *
306
- * @param worldPosition - Click position in world coordinates
307
- */
308
- handlePointerDown(worldPosition: THREE.Vector3): void;
309
- /**
310
- * Handle scroll events for rotation (User Story 3 - Phase 5)
311
- * Rotates preview by 90 degrees per scroll
325
+ * @param object3D - The Object3D group created by createVisual()
326
+ * @returns The envelope mesh if found, null otherwise
312
327
  *
313
- * @param delta - Scroll delta (positive = scroll down, negative = scroll up)
314
- * @param ctrlKey
328
+ * @remarks
329
+ * Searches for a mesh with userData.part === 'envelope'
315
330
  */
316
- handleScroll(delta: number, ctrlKey: boolean): void;
331
+ protected findEnvelopeMesh(object3D: THREE.Object3D): (THREE.Mesh & {
332
+ material: THREE.MeshStandardMaterial;
333
+ }) | null;
317
334
  /**
318
- * Handle keyboard events for component deletion (T035-T039)
319
- * Deletes selected component when Delete or Backspace key is pressed
335
+ * Find the negative marker mesh within the component group
320
336
  *
321
- * @param event - Keyboard event
322
- */
323
- handleKeyDown(event: KeyboardEvent): void;
324
- /**
325
- * Get current cursor type based on tool state (T018, T043)
326
- * Returns cursor based on hover state:
327
- * - 'pointer' when hovering existing component
328
- * - 'not-allowed' when hovering over occupied space for placement
329
- * - 'crosshair' otherwise
337
+ * @param object3D - The Object3D group created by createVisual()
338
+ * @returns The negative marker mesh if found, null otherwise
330
339
  *
331
- * @returns Current cursor style
340
+ * @remarks
341
+ * Searches for a mesh with userData.part === 'negativeMarker'
332
342
  */
333
- getCursorType(): CursorType;
343
+ protected findNegativeMarkerMesh(object3D: THREE.Object3D): (THREE.Mesh & {
344
+ material: THREE.MeshStandardMaterial;
345
+ }) | null;
334
346
  }
335
347
 
336
348
  /**
@@ -438,6 +450,12 @@ declare interface BehaviorResult {
438
450
  readonly scheduledEvents: ReadonlyArray<ScheduledEvent>;
439
451
  }
440
452
 
453
+ /**
454
+ * Sentinel value representing the "Branching Point" pseudo-component entry.
455
+ * When selected, BuildTool creates a branching point instead of a component.
456
+ */
457
+ export declare const BRANCHING_POINT_SENTINEL: "__branching_point__";
458
+
441
459
  /**
442
460
  * Factory for creating branching point visuals.
443
461
  *
@@ -498,6 +516,92 @@ export declare class BranchingPointVisualFactory {
498
516
  private getColorForSourceType;
499
517
  }
500
518
 
519
+ /**
520
+ * Visual factory for Buffer/Inverter components
521
+ *
522
+ * Creates:
523
+ * - Buffer trapezoid or Inverter triangle extrude geom mesh
524
+ * - Vcc, input and output pin group
525
+ * - Component hitbox for raycasting
526
+ *
527
+ * Animation:
528
+ * - Emissive glow when component is high (based on simulation state)
529
+ */
530
+ export declare class BufferVisualFactory extends ComponentVisualFactoryBase {
531
+ /** Buffer high color (white glow) */
532
+ private static readonly HIGH_COLOR;
533
+ /** Buffer high emissive intensity */
534
+ private static readonly HIGH_INTENSITY;
535
+ /** Shared low Buffer envelope geometry */
536
+ private readonly bufferLowGeometry;
537
+ /** Shared transient Buffer envelope geometry */
538
+ private readonly bufferTransientGeometry;
539
+ /** Shared high Buffer envelope geometry */
540
+ private readonly bufferHighGeometry;
541
+ /** Shared low Inverter envelope geometry */
542
+ private readonly inverterLowGeometry;
543
+ /** Shared transient Inverter envelope geometry */
544
+ private readonly inverterTransientGeometry;
545
+ /** Shared high Inverter envelope geometry */
546
+ private readonly inverterHighGeometry;
547
+ /** Shared geometry for negative marker **/
548
+ protected readonly negativeMarkerGeometry: THREE.SphereGeometry;
549
+ createVisual(component: Component): THREE.Object3D;
550
+ private replaceEnvelope;
551
+ /**
552
+ * Get config form definition for Buffer
553
+ *
554
+ * @returns Form definition with activationLogic boolean field
555
+ */
556
+ getConfigFormDefinition(): ConfigFormDefinition | null;
557
+ /**
558
+ * Map core config to form data (T026)
559
+ * Converts "positive"/"negative" strings to boolean
560
+ *
561
+ * @param config - Core component config
562
+ * @returns Form data with boolean activationLogic
563
+ */
564
+ mapCoreConfigToForm(config: Map<string, string>): Map<string, any>;
565
+ /**
566
+ * Map form data to core config (T026)
567
+ * Converts boolean to "positive"/"negative" strings
568
+ *
569
+ * @param formData - Form data with boolean activationLogic
570
+ * @returns Core config with string activationLogic
571
+ */
572
+ mapFormToCoreConfig(formData: Map<string, any>): Map<string, string>;
573
+ updateFromConfiguration(object3D: THREE.Object3D, config: Map<string, string>): void;
574
+ /**
575
+ * Update Buffer animation based on simulation state
576
+ *
577
+ * @param object3D - The Object3D created by createVisual()
578
+ * @param state - The Buffer's current simulation state
579
+ */
580
+ updateAnimation(object3D: THREE.Object3D, state: ComponentState | null): void;
581
+ /**
582
+ * Find the envelope mesh within the component group
583
+ *
584
+ * @param object3D - The Object3D group created by createVisual()
585
+ * @returns The envelope mesh if found, null otherwise
586
+ *
587
+ * @remarks
588
+ * Searches for a mesh with userData.part === 'envelope'
589
+ */
590
+ private findEnvelopeMesh;
591
+ /**
592
+ * Find the negative marker mesh within the component group
593
+ *
594
+ * @param object3D - The Object3D group created by createVisual()
595
+ * @returns The negative marker mesh if found, null otherwise
596
+ *
597
+ * @remarks
598
+ * Searches for a mesh with userData.part === 'negativeMarker'
599
+ */
600
+ protected findNegativeMarkerMesh(object3D: THREE.Object3D): (THREE.Mesh & {
601
+ material: THREE.MeshStandardMaterial;
602
+ }) | null;
603
+ }
604
+
501
605
  /**
502
606
  * Unified tool for building circuits
503
607
  * Implements all circuit editing functionality in a single tool
@@ -507,11 +611,16 @@ export declare class BuildTool implements IEditingTool {
507
611
  private _controller;
508
612
  private mode;
509
613
  private lastCancelledOp;
614
+ private lastOperationCompletedTs;
510
615
  private wireCreationState;
511
616
  private wireDragState;
512
617
  private componentDragState;
513
618
  private bpDragState;
514
619
  private clipboard;
620
+ private pickerWidget;
621
+ private ghostPreview;
622
+ private hasOverlap;
623
+ private pickerSelection;
515
624
  /**
516
625
  * Construct a new BuildTool instance
517
626
  * @param controller - The circuit scene controllerType instance
@@ -715,6 +824,52 @@ export declare class BuildTool implements IEditingTool {
715
824
  * @param event - Mouse event for screen position
716
825
  */
717
826
  private openConfigPanel;
827
+ /**
828
+ * Enter add_component mode: open the picker widget and listen for cursor movement
829
+ * @param event - Mouse event (used for widget positioning)
830
+ */
831
+ private enterAddComponentMode;
832
+ /**
833
+ * Exit add_component mode: close widget, dispose ghost, return to idle
834
+ */
835
+ private exitAddComponentMode;
836
+ /**
837
+ * Called when user selects or deselects an item in the picker widget
838
+ */
839
+ private onPickerSelectionChange;
840
+ /**
841
+ * Place the currently selected item (component or branching point) at cursor position
842
+ */
843
+ private placeSelectedItem;
844
+ /**
845
+ * Update ghost preview position and overlap check during add_component mode
846
+ */
847
+ private updateAddComponentPreview;
848
+ /**
849
+ * Create ghost preview for the selected item
850
+ * @param selection - Component type or branching point sentinel
851
+ */
852
+ private createGhostPreview;
853
+ /**
854
+ * Dispose ghost preview and cleanup resources
855
+ */
856
+ private disposeGhostPreview;
857
+ /**
858
+ * Apply semi-transparent ghost effect to preview object
859
+ */
860
+ private applyGhostEffect;
861
+ /**
862
+ * Check if ghost preview overlaps with existing components
863
+ */
864
+ private checkGhostOverlap;
865
+ /**
866
+ * Apply red emissive to indicate invalid placement
867
+ */
868
+ private applyInvalidEffect;
869
+ /**
870
+ * Remove red emissive invalid placement effect
871
+ */
872
+ private removeInvalidEffect;
718
873
  }
719
874
 
720
875
  /**
@@ -1174,6 +1329,7 @@ declare class Circuit {
1174
1329
  * iterate through all components, enodes and wires positions to get the size that allows to enclose all elements.
1175
1330
  * @param margin - optional margin to add to the size
1176
1331
  * @returns size that allows to enclose all elements plus margin
1332
+ * @todo if calls to this method at each build operation ends causes slowness see to optimize by restricting checked elements
1177
1333
  */
1178
1334
  getEnclosingSize(margin?: number): number;
1179
1335
  /**
@@ -1297,15 +1453,6 @@ export declare class CircuitController extends AbstractCircuitController {
1297
1453
  */
1298
1454
  toggleTool(toolType: ToolType): void;
1299
1455
  deactivateTool(toolType: ToolType): void;
1300
- /**
1301
- * Get the list of available component types for the AddComponent tool
1302
- */
1303
- getAvailableComponentTypes(): ComponentType[];
1304
- /**
1305
- * Set the component type for the AddComponent tool
1306
- * @param componentType
1307
- */
1308
- setAddComponentType(componentType: ComponentType | null): void;
1309
1456
  /**
1310
1457
  * Get the currently active tool (FR-028)
1311
1458
  *
@@ -1380,12 +1527,12 @@ export declare class CircuitController extends AbstractCircuitController {
1380
1527
  *
1381
1528
  * @param type - Component type to add
1382
1529
  * @param worldPosition - Position in 3D world coordinates (x, z)
1383
- * @param rotation - 3D world rotation
1530
+ * @param rotation - 3D world rotation, if left null the default componentType rotation is applied
1384
1531
  * @param config - Optional configuration map for the component
1385
1532
  * @param pinSources - Optional array of source types for the component pins
1386
1533
  * @returns The created Component
1387
1534
  */
1388
- addComponent(type: ComponentType, worldPosition: THREE.Vector3, rotation: Euler, config?: Map<string, string> | undefined, pinSources?: Array<ENodeSourceType | undefined | null> | undefined): Component;
1535
+ addComponent(type: ComponentType, worldPosition: THREE.Vector3, rotation: Euler | null, config?: Map<string, string> | undefined, pinSources?: Array<ENodeSourceType | undefined | null> | undefined): Component;
1389
1536
  /**
1390
1537
  * edit component config and update visuals if necessary
1391
1538
  *
@@ -2331,6 +2478,14 @@ declare interface ComponentBehavior {
2331
2478
  onEventFiring(component: Component, state: ComponentState, event: ScheduledEvent): BehaviorResult;
2332
2479
  }
2333
2480
 
2481
+ /**
2482
+ * Describes a named group of component types
2483
+ */
2484
+ export declare interface ComponentGroup {
2485
+ readonly id: string;
2486
+ readonly label: string;
2487
+ }
2488
+
2334
2489
  /**
2335
2490
  * UserData structure for component hitbox meshes
2336
2491
  */
@@ -2340,6 +2495,79 @@ export declare interface ComponentHitboxUserData {
2340
2495
  componentType: ComponentType;
2341
2496
  }
2342
2497
 
2498
+ /**
2499
+ * Persisted widget state (survives open/close cycles within a session).
2500
+ */
2501
+ export declare interface ComponentPickerState {
2502
+ selectedGroupId: string;
2503
+ selectedItem: PickerSelection | null;
2504
+ widgetWidth: number;
2505
+ widgetHeight: number;
2506
+ }
2507
+
2508
+ /**
2509
+ * DOM overlay widget for selecting components from grouped registry.
2510
+ *
2511
+ * Features:
2512
+ * - Group dropdown for filtering component types
2513
+ * - Scrollable item list with selection highlight
2514
+ * - Draggable header bar
2515
+ * - Resizable via CSS resize
2516
+ * - State persistence across open/close (group, selection, size)
2517
+ */
2518
+ export declare class ComponentPickerWidget {
2519
+ private readonly registry;
2520
+ private container;
2521
+ private groupDropdown;
2522
+ private itemList;
2523
+ private state;
2524
+ private readonly onSelectionChange;
2525
+ private readonly onClose;
2526
+ private escapeHandler;
2527
+ private dragOffset;
2528
+ private dragMoveHandler;
2529
+ private dragEndHandler;
2530
+ /**
2531
+ * @param registry - Grouped factory registry providing groups and component types
2532
+ * @param onSelectionChange - Called when user selects or deselects an item
2533
+ * @param onClose - Called when user closes the widget (close button or Escape)
2534
+ */
2535
+ constructor(registry: IGroupedFactoryRegistry, onSelectionChange: (selection: PickerSelection | null) => void, onClose: () => void);
2536
+ /** Whether the widget is currently open and visible */
2537
+ get isOpen(): boolean;
2538
+ /** The currently selected item (persists across open/close) */
2539
+ get currentSelection(): PickerSelection | null;
2540
+ /**
2541
+ * Open the widget at the given screen position.
2542
+ * If already open, repositions to the new location.
2543
+ *
2544
+ * @param screenPosition - Screen coordinates (typically from mouse event)
2545
+ */
2546
+ open(screenPosition: {
2547
+ x: number;
2548
+ y: number;
2549
+ }): void;
2550
+ /**
2551
+ * Close the widget and remove DOM.
2552
+ * Preserves state (group, selection, size) for next open.
2553
+ */
2554
+ close(): void;
2555
+ /**
2556
+ * Full cleanup including state reset.
2557
+ */
2558
+ dispose(): void;
2559
+ private createDOM;
2560
+ private renderItemList;
2561
+ private createItemElement;
2562
+ private selectItem;
2563
+ private positionContainer;
2564
+ private startDrag;
2565
+ private onDragMove;
2566
+ private endDrag;
2567
+ private registerEventListeners;
2568
+ private removeEventListeners;
2569
+ }
2570
+
2343
2571
  /**
2344
2572
  * Base class for component simulation state.
2345
2573
  * Extended by specific component types (BatteryState, LEDState, etc.)
@@ -2388,15 +2616,23 @@ declare abstract class ComponentState {
2388
2616
  * ```
2389
2617
  */
2390
2618
  declare enum ComponentType {
2619
+ Cube = "cube",// no pins component for testing purposes mainly
2620
+ Label = "label",// decorative text label with no pins
2391
2621
  Battery = "battery",
2392
2622
  Switch = "switch",
2393
2623
  Lightbulb = "lightbulb",
2394
2624
  Relay = "relay",
2395
2625
  Transistor = "transistor",
2626
+ Buffer = "buffer",
2396
2627
  SmallLED = "smallLED",
2397
2628
  RectangleLED = "rectangleLED",
2398
- Cube = "cube",// no pins component for testing purposes mainly
2399
- Label = "label"
2629
+ AndGate = "andGate",
2630
+ And4Gate = "and4Gate",
2631
+ And8Gate = "and8Gate",
2632
+ OrGate = "orGate",
2633
+ Or4Gate = "or4Gate",
2634
+ Or8Gate = "or8Gate",
2635
+ XorGate = "xorGate"
2400
2636
  }
2401
2637
 
2402
2638
  /**
@@ -2438,6 +2674,7 @@ declare abstract class ComponentVisualFactoryBase implements IComponentVisualFac
2438
2674
  protected static readonly DEFAULT_SELECTION_COLOR = 16746496;
2439
2675
  /** Default selection emissive intensity (higher than hover) */
2440
2676
  protected static readonly DEFAULT_SELECTION_INTENSITY = 0.8;
2677
+ defaultRotation(): number;
2441
2678
  /**
2442
2679
  * Create the Three.js visual representation for a component
2443
2680
  * Must be implemented by subclasses
@@ -2491,15 +2728,22 @@ declare abstract class ComponentVisualFactoryBase implements IComponentVisualFac
2491
2728
  * @param pinId - UUID of this pin/enode
2492
2729
  * @param label - Human-readable label (e.g., 'input', 'output', 'cathode')
2493
2730
  * @param sourceType - Optional source type (voltage/current) : if provided this pin will be locked to that type
2731
+ * @param visualRotation - if set rotate the visual of the pin to adjust display without affecting hitbox
2494
2732
  * @returns THREE.Group configured as pin group
2495
2733
  */
2496
- protected createPinGroup(componentId: string, pinId: string, label: string, sourceType?: ENodeSourceType | null): THREE.Group;
2734
+ protected createPinGroup(componentId: string, pinId: string, label: string, sourceType?: ENodeSourceType | null, visualRotation?: THREE.Euler | null): THREE.Group;
2497
2735
  /**
2498
2736
  * Find pin group by label within a component Object3D
2499
2737
  * @param object3D
2500
2738
  * @param label
2501
2739
  */
2502
2740
  findPinGroup(object3D: THREE.Object3D, label: string): THREE.Group | null;
2741
+ /**
2742
+ * Find pin group visual by label within a component Object3D
2743
+ * @param object3D
2744
+ * @param label
2745
+ */
2746
+ findPinVisual(object3D: THREE.Object3D, label: string): THREE.Mesh | null;
2503
2747
  /**
2504
2748
  * Create component hitbox mesh
2505
2749
  *
@@ -2610,7 +2854,7 @@ export declare type ControllerCallback<T = any> = (payload: T) => void;
2610
2854
  /**
2611
2855
  * Supported scene controllerType event types (includes tool system events)
2612
2856
  */
2613
- export declare type ControllerEvent = 'ready' | 'error' | 'circuitLoaded' | 'circuitCleared' | 'gridPositionMove' | 'hover' | 'unhover' | 'select' | 'deselect' | 'toolActivated' | 'toolDeactivated' | 'toolOperationStarted' | 'toolOperationCompleted' | 'toolOperationCancelled' | 'toolValidationError' | 'addComponentTypeChanged' | 'cursorChangeRequested' | 'circuitElementAction' | 'circuitMetadataEdition' | 'selectionChange' | 'simulationPlayed' | 'simulationPaused' | 'simulationStepped' | 'simulationTick' | 'simulationUserCommand' | 'simulationStopped' | 'simulationSpeedChanged';
2857
+ export declare type ControllerEvent = 'ready' | 'error' | 'circuitLoaded' | 'circuitCleared' | 'gridPositionMove' | 'hover' | 'unhover' | 'select' | 'deselect' | 'toolActivated' | 'toolDeactivated' | 'toolOperationStarted' | 'toolOperationCompleted' | 'toolOperationCancelled' | 'toolValidationError' | 'cursorChangeRequested' | 'circuitElementAction' | 'circuitMetadataEdition' | 'selectionChange' | 'simulationPlayed' | 'simulationPaused' | 'simulationStepped' | 'simulationTick' | 'simulationUserCommand' | 'simulationStopped' | 'simulationSpeedChanged';
2614
2858
 
2615
2859
  /**
2616
2860
  * Event payload map for type-safe event emission
@@ -2688,9 +2932,6 @@ export declare interface ControllerEventMap {
2688
2932
  mode: unknown;
2689
2933
  errorMessage: string;
2690
2934
  };
2691
- addComponentTypeChanged: {
2692
- componentType: ComponentType | null;
2693
- };
2694
2935
  cursorChangeRequested: {
2695
2936
  cursorType: CursorType;
2696
2937
  };
@@ -3321,6 +3562,114 @@ export declare class FactoryRegistry implements IFactoryRegistry {
3321
3562
  getRegisteredTypes(): ComponentType[];
3322
3563
  }
3323
3564
 
3565
+ /**
3566
+ * Factory registry with named group support.
3567
+ *
3568
+ * Implements both IFactoryRegistry (backward compat) and IGroupedFactoryRegistry.
3569
+ * Components may only be registered inside a group context via addGroup().
3570
+ *
3571
+ * Group insertion order is preserved (Map maintains insertion order).
3572
+ * Duplicate group ids merge their components; the label from the first
3573
+ * registration is preserved.
3574
+ *
3575
+ * @example
3576
+ * ```typescript
3577
+ * const registry = new GroupedFactoryRegistry(new DefaultVisualFactory())
3578
+ * .addGroup('basic', 'Basic Components', group => group
3579
+ * .add(ComponentType.Battery, new BatteryVisualFactory())
3580
+ * .add(ComponentType.Switch, new SwitchVisualFactory())
3581
+ * )
3582
+ * .addGroup('outputs', 'Output Components', group => group
3583
+ * .add(ComponentType.Lightbulb, new LightbulbVisualFactory())
3584
+ * );
3585
+ *
3586
+ * registry.getGroups(); // [{ id: 'basic', ... }, { id: 'outputs', ... }]
3587
+ * registry.getGroupOf(ComponentType.Battery); // { id: 'basic', label: 'Basic Components' }
3588
+ * registry.getRegisteredTypes('basic'); // [ComponentType.Battery, ComponentType.Switch]
3589
+ * registry.get(ComponentType.Battery); // BatteryVisualFactory instance
3590
+ * ```
3591
+ */
3592
+ export declare class GroupedFactoryRegistry implements IFactoryRegistry, IGroupedFactoryRegistry {
3593
+ private readonly _factories;
3594
+ private readonly _fallbackFactory;
3595
+ private readonly _groups;
3596
+ private readonly _typeToGroupId;
3597
+ /**
3598
+ * Create a new grouped factory registry.
3599
+ *
3600
+ * @param fallbackFactory - Factory to use for unregistered component types
3601
+ * @throws {TypeError} If fallbackFactory is null or undefined
3602
+ */
3603
+ constructor(fallbackFactory: IComponentVisualFactory);
3604
+ /**
3605
+ * Add a named group and register component factories within it.
3606
+ *
3607
+ * If a group with the same id already exists, the new components are merged
3608
+ * into it and the original label is preserved.
3609
+ *
3610
+ * @param id - Unique group identifier
3611
+ * @param label - Human-readable group display name
3612
+ * @param builderCallback - Callback receiving a builder for adding components
3613
+ * @throws {TypeError} If id or label is empty/whitespace
3614
+ * @returns this (for chaining)
3615
+ */
3616
+ addGroup(id: string, label: string, builderCallback: (group: IComponentGroupBuilder) => void): this;
3617
+ /**
3618
+ * Retrieve the factory for a component type.
3619
+ *
3620
+ * @returns Factory, or the fallback factory if type not registered.
3621
+ * Never returns null or undefined.
3622
+ */
3623
+ get(type: ComponentType): IComponentVisualFactory;
3624
+ /**
3625
+ * Check if a factory is registered for a component type.
3626
+ *
3627
+ * @returns true if explicitly registered, false if would use fallback
3628
+ */
3629
+ has(type: ComponentType): boolean;
3630
+ /**
3631
+ * Get the fallback factory used for unregistered types.
3632
+ */
3633
+ getFallbackFactory(): IComponentVisualFactory;
3634
+ /**
3635
+ * Get all defined groups in insertion order.
3636
+ *
3637
+ * @returns New array of ComponentGroup objects (safe to mutate)
3638
+ */
3639
+ getGroups(): ComponentGroup[];
3640
+ /**
3641
+ * Get the group a component type belongs to.
3642
+ *
3643
+ * @param type - Component type to look up
3644
+ * @returns ComponentGroup, or undefined if type is not registered
3645
+ */
3646
+ getGroupOf(type: ComponentType): ComponentGroup | undefined;
3647
+ /**
3648
+ * Get registered component types, optionally filtered by group.
3649
+ *
3650
+ * @param groupId - If provided, returns only types in that group
3651
+ * @returns New array of ComponentType values (safe to mutate).
3652
+ * Returns empty array if groupId is unknown.
3653
+ */
3654
+ getRegisteredTypes(groupId?: string): ComponentType[];
3655
+ /**
3656
+ * Unregister a factory for a component type.
3657
+ *
3658
+ * The type is removed from its group's list and from the reverse lookup.
3659
+ * The group record itself is preserved even if it becomes empty.
3660
+ *
3661
+ * @param type - Component type to remove
3662
+ * @returns true if factory was registered and removed, false otherwise
3663
+ */
3664
+ unregister(type: ComponentType): boolean;
3665
+ /**
3666
+ * Not supported. Use addGroup() to register components within a named group.
3667
+ *
3668
+ * @throws {Error} Always throws
3669
+ */
3670
+ register(_type: ComponentType, _factory: IComponentVisualFactory): IFactoryRegistry;
3671
+ }
3672
+
3324
3673
  /**
3325
3674
  * Three.js layer assignments for hitbox meshes and rendering
3326
3675
  *
@@ -3548,6 +3897,23 @@ declare type ICircuitMetadata = {
3548
3897
  cameraOptions: ICameraOptions;
3549
3898
  };
3550
3899
 
3900
+ /**
3901
+ * Builder interface for adding components to a group.
3902
+ * Used as the callback parameter type in addGroup().
3903
+ *
3904
+ * @example
3905
+ * ```typescript
3906
+ * registry.addGroup('basic', 'Basic Components', (group: IComponentGroupBuilder) => {
3907
+ * group
3908
+ * .add(ComponentType.Battery, new BatteryVisualFactory())
3909
+ * .add(ComponentType.Switch, new SwitchVisualFactory());
3910
+ * });
3911
+ * ```
3912
+ */
3913
+ export declare interface IComponentGroupBuilder {
3914
+ add(type: ComponentType, factory: IComponentVisualFactory): IComponentGroupBuilder;
3915
+ }
3916
+
3551
3917
  /**
3552
3918
  * Interface for component visual factories
3553
3919
  *
@@ -3571,6 +3937,10 @@ declare type ICircuitMetadata = {
3571
3937
  * ```
3572
3938
  */
3573
3939
  export declare interface IComponentVisualFactory {
3940
+ /**
3941
+ * @returns nominal rotation along the Y axis when component added (angle in radian)
3942
+ */
3943
+ defaultRotation(): number;
3574
3944
  /**
3575
3945
  * Create the Three.js visual representation for a component
3576
3946
  *
@@ -3785,15 +4155,6 @@ export declare interface IEditingTool {
3785
4155
  * ```
3786
4156
  */
3787
4157
  export declare interface IFactoryRegistry {
3788
- /**
3789
- * Register a visual factory for a specific component type
3790
- *
3791
- * @param type - Component type identifier
3792
- * @param factory - Factory (class instance or function) to create visuals for this type
3793
- * @throws {TypeError} If factory is null or undefined
3794
- * @returns This IFactoryRegistry instance (for chaining)
3795
- */
3796
- register(type: ComponentType, factory: IComponentVisualFactory): IFactoryRegistry;
3797
4158
  /**
3798
4159
  * Retrieve the factory for a component type
3799
4160
  *
@@ -3834,6 +4195,23 @@ export declare interface IFactoryRegistry {
3834
4195
  getRegisteredTypes(): ComponentType[];
3835
4196
  }
3836
4197
 
4198
+ /**
4199
+ * Extended registry interface with grouping support.
4200
+ *
4201
+ * Adds group management on top of the basic factory retrieval,
4202
+ * allowing client UIs to build organized component palettes.
4203
+ */
4204
+ export declare interface IGroupedFactoryRegistry {
4205
+ addGroup(id: string, label: string, builderCallback: (group: IComponentGroupBuilder) => void): IGroupedFactoryRegistry;
4206
+ get(type: ComponentType): IComponentVisualFactory;
4207
+ has(type: ComponentType): boolean;
4208
+ getFallbackFactory(): IComponentVisualFactory;
4209
+ getGroups(): ComponentGroup[];
4210
+ getGroupOf(type: ComponentType): ComponentGroup | undefined;
4211
+ getRegisteredTypes(groupId?: string): ComponentType[];
4212
+ unregister(type: ComponentType): boolean;
4213
+ }
4214
+
3837
4215
  /**
3838
4216
  * 3D Position Type
3839
4217
  *
@@ -4320,6 +4698,155 @@ declare interface NodeElectricalState {
4320
4698
  locked: boolean;
4321
4699
  }
4322
4700
 
4701
+ /**
4702
+ * Visual factory for OR gates components
4703
+ *
4704
+ * Creates:
4705
+ * - Gate mesh
4706
+ * - vcc, inputs and output pin groups
4707
+ * - Component hitbox for raycasting
4708
+ *
4709
+ * Animation:
4710
+ * - Emissive glow when Gate is high (based on simulation state)
4711
+ */
4712
+ export declare class Or4GateVisualFactory extends OrGateVisualFactory {
4713
+ /** Shared open envelope geometry */
4714
+ protected readonly lowGeometry: THREE.ExtrudeGeometry;
4715
+ /** Shared transient envelope geometry */
4716
+ protected readonly transientGeometry: THREE.ExtrudeGeometry;
4717
+ /** Shared transient envelope geometry */
4718
+ protected readonly highGeometry: THREE.ExtrudeGeometry;
4719
+ /** Shared geometry for negative marker **/
4720
+ protected static readonly negativeMarkerGeometry: THREE.CylinderGeometry;
4721
+ createVisual(component: Component): THREE.Object3D;
4722
+ /**
4723
+ * Get config form definition for Transistor (T026)
4724
+ *
4725
+ * @returns Form definition with activationLogic boolean field
4726
+ */
4727
+ getConfigFormDefinition(): ConfigFormDefinition | null;
4728
+ updateFromConfiguration(object3D: THREE.Object3D, config: Map<string, string>): void;
4729
+ }
4730
+
4731
+ /**
4732
+ * Visual factory for OR gates components
4733
+ *
4734
+ * Creates:
4735
+ * - Gate mesh
4736
+ * - vcc, inputs and output pin groups
4737
+ * - Component hitbox for raycasting
4738
+ *
4739
+ * Animation:
4740
+ * - Emissive glow when Gate is high (based on simulation state)
4741
+ */
4742
+ export declare class Or8GateVisualFactory extends OrGateVisualFactory {
4743
+ /** Shared open envelope geometry */
4744
+ protected readonly lowGeometry: THREE.ExtrudeGeometry;
4745
+ /** Shared transient envelope geometry */
4746
+ protected readonly transientGeometry: THREE.ExtrudeGeometry;
4747
+ /** Shared transient envelope geometry */
4748
+ protected readonly highGeometry: THREE.ExtrudeGeometry;
4749
+ /** Shared geometry for negative marker **/
4750
+ protected static readonly negativeMarkerGeometry: THREE.CylinderGeometry;
4751
+ createVisual(component: Component): THREE.Object3D;
4752
+ /**
4753
+ * Get config form definition for Transistor (T026)
4754
+ *
4755
+ * @returns Form definition with activationLogic boolean field
4756
+ */
4757
+ getConfigFormDefinition(): ConfigFormDefinition | null;
4758
+ updateFromConfiguration(object3D: THREE.Object3D, config: Map<string, string>): void;
4759
+ }
4760
+
4761
+ /**
4762
+ * Visual factory for OR gates components
4763
+ *
4764
+ * Creates:
4765
+ * - Gate mesh
4766
+ * - vcc, inputs and output pin groups
4767
+ * - Component hitbox for raycasting
4768
+ *
4769
+ * Animation:
4770
+ * - Emissive glow when Gate is high (based on simulation state)
4771
+ */
4772
+ export declare class OrGateVisualFactory extends ComponentVisualFactoryBase {
4773
+ /** Gate high color */
4774
+ protected static readonly HIGH_COLOR = 16777215;
4775
+ /** Gate high emissive intensity */
4776
+ protected static readonly HIGH_INTENSITY = 0.3;
4777
+ /** Shared open envelope geometry */
4778
+ protected readonly lowGeometry: THREE.ExtrudeGeometry;
4779
+ /** Shared transient envelope geometry */
4780
+ protected readonly transientGeometry: THREE.ExtrudeGeometry;
4781
+ /** Shared transient envelope geometry */
4782
+ protected readonly highGeometry: THREE.ExtrudeGeometry;
4783
+ /** Shared material for negative marker **/
4784
+ protected static readonly negativeMarkerMaterial: THREE.MeshStandardMaterial;
4785
+ /** Shared geometry for negative marker **/
4786
+ protected static readonly negativeMarkerGeometry: THREE.CylinderGeometry;
4787
+ defaultRotation(): number;
4788
+ createVisual(component: Component): THREE.Object3D;
4789
+ /**
4790
+ * Get config form definition for OR Gate
4791
+ *
4792
+ * @returns Form definition with activationLogic boolean field
4793
+ */
4794
+ getConfigFormDefinition(): ConfigFormDefinition | null;
4795
+ /**
4796
+ * Map core config to form data
4797
+ * Converts "positive"/"negative" strings to boolean
4798
+ *
4799
+ * @param config - Core component config
4800
+ * @returns Form data with boolean activationLogic
4801
+ */
4802
+ mapCoreConfigToForm(config: Map<string, string>): Map<string, any>;
4803
+ /**
4804
+ * Map form data to core config
4805
+ * Converts boolean to "positive"/"negative" strings
4806
+ *
4807
+ * @param formData - Form data with boolean activationLogic
4808
+ * @returns Core config with string activationLogic
4809
+ */
4810
+ mapFormToCoreConfig(formData: Map<string, any>): Map<string, string>;
4811
+ updateFromConfiguration(object3D: THREE.Object3D, config: Map<string, string>): void;
4812
+ /**
4813
+ * Update animation based on simulation state
4814
+ *
4815
+ * @param object3D - The Object3D created by createVisual()
4816
+ * @param state - The component current simulation state
4817
+ */
4818
+ updateAnimation(object3D: THREE.Object3D, state: ComponentState | null): void;
4819
+ /**
4820
+ * Find the envelope mesh within the component group
4821
+ *
4822
+ * @param object3D - The Object3D group created by createVisual()
4823
+ * @returns The envelope mesh if found, null otherwise
4824
+ *
4825
+ * @remarks
4826
+ * Searches for a mesh with userData.part === 'envelope'
4827
+ */
4828
+ protected findEnvelopeMesh(object3D: THREE.Object3D): (THREE.Mesh & {
4829
+ material: THREE.MeshStandardMaterial;
4830
+ }) | null;
4831
+ /**
4832
+ * Find the negative marker mesh within the component group
4833
+ *
4834
+ * @param object3D - The Object3D group created by createVisual()
4835
+ * @returns The negative marker mesh if found, null otherwise
4836
+ *
4837
+ * @remarks
4838
+ * Searches for a mesh with userData.part === 'negativeMarker'
4839
+ */
4840
+ protected findNegativeMarkerMesh(object3D: THREE.Object3D): (THREE.Mesh & {
4841
+ material: THREE.MeshStandardMaterial;
4842
+ }) | null;
4843
+ }
4844
+
4845
+ /**
4846
+ * Union of actual component types and the branching point sentinel.
4847
+ */
4848
+ export declare type PickerSelection = ComponentType | typeof BRANCHING_POINT_SENTINEL;
4849
+
4323
4850
  /**
4324
4851
  * Position Type for 2D Discrete Grid
4325
4852
  *
@@ -4568,13 +5095,23 @@ export declare class RectangleLEDVisualFactory extends ComponentVisualFactoryBas
4568
5095
  }
4569
5096
 
4570
5097
  /**
4571
- * Register all basic component visual factories in the given registry
4572
- * Basic components are : Battery, Lightbulb, RectangleLED, Relay, SmallLED, Switch, Transistor
5098
+ * Register all basic components visual factories in the basic group
5099
+ * Basic components are : Battery, Label, Switch, Lightbulb, RectangleLED, Relay, SmallLED, Transistor
4573
5100
  * @public
4574
- * @param registry
4575
- * @return the input factory registry for chaining
5101
+ * @param registry - A grouped factory registry to populate
5102
+ * @returns The input registry for chaining
4576
5103
  */
4577
- export declare function registerBasicComponentsFactories(registry: IFactoryRegistry): IFactoryRegistry;
5104
+ export declare function registerBasicComponentsFactories(registry: IGroupedFactoryRegistry): IGroupedFactoryRegistry;
5105
+
5106
+ /**
5107
+ * Register all logic gates components visual factories in the gates group
5108
+ * gates are : AND (2,4,8,16 inputs), OR (2,4,8,16 inputs) and XOR
5109
+ * NAND and NOR are gotten by changing the activationLogic of AND and OR
5110
+ * @public
5111
+ * @param registry - A grouped factory registry to populate
5112
+ * @returns The input registry for chaining
5113
+ */
5114
+ export declare function registerGatesComponentsFactories(registry: IGroupedFactoryRegistry): IGroupedFactoryRegistry;
4578
5115
 
4579
5116
  /**
4580
5117
  * Visual factory for Relay components
@@ -5131,7 +5668,7 @@ export declare class SwitchVisualFactory extends ComponentVisualFactoryBase {
5131
5668
  *
5132
5669
  * Note: 'build' replaces the previous tools: 'position', 'wire', 'delete', 'branchingPoint'
5133
5670
  */
5134
- export declare type ToolType = 'build' | 'addComponent' | 'multiSelect';
5671
+ export declare type ToolType = 'build' | 'multiSelect';
5135
5672
 
5136
5673
  /**
5137
5674
  * Visual factory for Transistor components
@@ -5142,12 +5679,12 @@ export declare type ToolType = 'build' | 'addComponent' | 'multiSelect';
5142
5679
  * - Component hitbox for raycasting
5143
5680
  *
5144
5681
  * Animation:
5145
- * - Emissive glow when Transistor is lit (based on simulation state)
5682
+ * - Emissive glow when Transistor is closed (based on simulation state)
5146
5683
  */
5147
5684
  export declare class TransistorVisualFactory extends ComponentVisualFactoryBase {
5148
- /** Transistor lit color (yellow glow) */
5685
+ /** Transistor closed color (white glow) */
5149
5686
  private static readonly TRANSISTOR_CLOSED_COLOR;
5150
- /** Transistor lit emissive intensity */
5687
+ /** Transistor closed emissive intensity */
5151
5688
  private static readonly TRANSISTOR_CLOSED_INTENSITY;
5152
5689
  /** Shared open Transistor envelope geometry */
5153
5690
  private readonly openGeometry;
@@ -5155,6 +5692,10 @@ export declare class TransistorVisualFactory extends ComponentVisualFactoryBase
5155
5692
  private readonly transientGeometry;
5156
5693
  /** Shared transient Transistor envelope geometry */
5157
5694
  private readonly closedGeometry;
5695
+ /** Shared material for negative marker **/
5696
+ protected static readonly negativeMarkerMaterial: THREE.MeshStandardMaterial;
5697
+ /** Shared geometry for negative marker **/
5698
+ protected static readonly negativeMarkerGeometry: THREE.CylinderGeometry;
5158
5699
  createVisual(component: Component): THREE.Object3D;
5159
5700
  /**
5160
5701
  * Get config form definition for Transistor (T026)
@@ -5196,6 +5737,18 @@ export declare class TransistorVisualFactory extends ComponentVisualFactoryBase
5196
5737
  * Searches for a mesh with userData.part === 'envelope'
5197
5738
  */
5198
5739
  private findEnvelopeMesh;
5740
+ /**
5741
+ * Find the negative marker mesh within the component group
5742
+ *
5743
+ * @param object3D - The Object3D group created by createVisual()
5744
+ * @returns The negative marker mesh if found, null otherwise
5745
+ *
5746
+ * @remarks
5747
+ * Searches for a mesh with userData.part === 'negativeMarker'
5748
+ */
5749
+ protected findNegativeMarkerMesh(object3D: THREE.Object3D): (THREE.Mesh & {
5750
+ material: THREE.MeshStandardMaterial;
5751
+ }) | null;
5199
5752
  }
5200
5753
 
5201
5754
  /**
@@ -5644,4 +6197,90 @@ export declare class WireVisualManager {
5644
6197
  private clientToContainerCoords;
5645
6198
  }
5646
6199
 
6200
+ /**
6201
+ * Visual factory for XOR gates components
6202
+ *
6203
+ * Creates:
6204
+ * - Gate mesh
6205
+ * - vcc, inputs and output pin groups
6206
+ * - Component hitbox for raycasting
6207
+ *
6208
+ * Animation:
6209
+ * - Emissive glow when Gate is high (based on simulation state)
6210
+ */
6211
+ export declare class XorGateVisualFactory extends ComponentVisualFactoryBase {
6212
+ /** Gate high color */
6213
+ protected static readonly HIGH_COLOR = 16777215;
6214
+ /** Gate high emissive intensity */
6215
+ protected static readonly HIGH_INTENSITY = 0.3;
6216
+ /** XOR tail geometry */
6217
+ protected static readonly tailGeometry: THREE.ExtrudeGeometry;
6218
+ /** Shared open envelope geometry */
6219
+ protected readonly lowGeometry: THREE.ExtrudeGeometry;
6220
+ /** Shared transient envelope geometry */
6221
+ protected readonly transientGeometry: THREE.ExtrudeGeometry;
6222
+ /** Shared transient envelope geometry */
6223
+ protected readonly highGeometry: THREE.ExtrudeGeometry;
6224
+ /** Shared material for negative marker **/
6225
+ protected static readonly negativeMarkerMaterial: THREE.MeshStandardMaterial;
6226
+ /** Shared geometry for negative marker **/
6227
+ protected static readonly negativeMarkerGeometry: THREE.CylinderGeometry;
6228
+ defaultRotation(): number;
6229
+ createVisual(component: Component): THREE.Object3D;
6230
+ /**
6231
+ * Get config form definition for OR Gate
6232
+ *
6233
+ * @returns Form definition with activationLogic boolean field
6234
+ */
6235
+ getConfigFormDefinition(): ConfigFormDefinition | null;
6236
+ /**
6237
+ * Map core config to form data
6238
+ * Converts "positive"/"negative" strings to boolean
6239
+ *
6240
+ * @param config - Core component config
6241
+ * @returns Form data with boolean activationLogic
6242
+ */
6243
+ mapCoreConfigToForm(config: Map<string, string>): Map<string, any>;
6244
+ /**
6245
+ * Map form data to core config
6246
+ * Converts boolean to "positive"/"negative" strings
6247
+ *
6248
+ * @param formData - Form data with boolean activationLogic
6249
+ * @returns Core config with string activationLogic
6250
+ */
6251
+ mapFormToCoreConfig(formData: Map<string, any>): Map<string, string>;
6252
+ updateFromConfiguration(object3D: THREE.Object3D, config: Map<string, string>): void;
6253
+ /**
6254
+ * Update animation based on simulation state
6255
+ *
6256
+ * @param object3D - The Object3D created by createVisual()
6257
+ * @param state - The component current simulation state
6258
+ */
6259
+ updateAnimation(object3D: THREE.Object3D, state: ComponentState | null): void;
6260
+ /**
6261
+ * Find the envelope mesh within the component group
6262
+ *
6263
+ * @param object3D - The Object3D group created by createVisual()
6264
+ * @returns The envelope mesh if found, null otherwise
6265
+ *
6266
+ * @remarks
6267
+ * Searches for a mesh with userData.part === 'envelope'
6268
+ */
6269
+ protected findEnvelopeMesh(object3D: THREE.Object3D): (THREE.Mesh & {
6270
+ material: THREE.MeshStandardMaterial;
6271
+ }) | null;
6272
+ /**
6273
+ * Find the negative marker mesh within the component group
6274
+ *
6275
+ * @param object3D - The Object3D group created by createVisual()
6276
+ * @returns The negative marker mesh if found, null otherwise
6277
+ *
6278
+ * @remarks
6279
+ * Searches for a mesh with userData.part === 'negativeMarker'
6280
+ */
6281
+ protected findNegativeMarkerMesh(object3D: THREE.Object3D): (THREE.Mesh & {
6282
+ material: THREE.MeshStandardMaterial;
6283
+ }) | null;
6284
+ }
6285
+
5647
6286
  export { }