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,211 @@
|
|
|
1
|
+
import { MapControls } from 'three/addons/controls/MapControls.js';
|
|
2
|
+
import { UUID, Circuit } from '../../core/index.ts';
|
|
3
|
+
import { EventEmitter } from './EventEmitter';
|
|
4
|
+
import { IFactoryRegistry } from './components/ComponentVisualFactory';
|
|
5
|
+
import { ControllerEventMap, ControllerOptions, HoveredElement, HoverableType, SharedResources, VisualContext } from './types';
|
|
6
|
+
import { HoverManager } from './HoverManager';
|
|
7
|
+
import { Line2 } from 'three/examples/jsm/lines/Line2.js';
|
|
8
|
+
import { BranchingPointVisualFactory } from './BranchingPointVisualFactory';
|
|
9
|
+
import { WireVisualManager } from './WireVisualManager';
|
|
10
|
+
/**
|
|
11
|
+
* Abstract Circuit Controller
|
|
12
|
+
* @module scene/shared/AbstractCircuitController
|
|
13
|
+
*
|
|
14
|
+
* Base class for circuit visualization controllers.
|
|
15
|
+
* Provides common Three.js scene management, camera controls, and hover detection.
|
|
16
|
+
*/
|
|
17
|
+
import * as THREE from 'three';
|
|
18
|
+
/**
|
|
19
|
+
* Abstract base class for circuit controllers.
|
|
20
|
+
*
|
|
21
|
+
* Provides common functionality for both static editing (CircuitController)
|
|
22
|
+
* and live simulation (CircuitRunnerController) modes:
|
|
23
|
+
* - Three.js scene, camera, and MapControls management
|
|
24
|
+
* - Container lifecycle (initialize/dispose)
|
|
25
|
+
* - Hover detection via HoverManager
|
|
26
|
+
* - Visual object tracking maps
|
|
27
|
+
*
|
|
28
|
+
* Subclasses must implement:
|
|
29
|
+
* - Circuit/CircuitRunner specific logic
|
|
30
|
+
* - Visual creation and update methods
|
|
31
|
+
* - Mode-specific features (editing tools or simulation interpolation)
|
|
32
|
+
*/
|
|
33
|
+
export declare abstract class AbstractCircuitController extends EventEmitter<ControllerEventMap> {
|
|
34
|
+
protected _container: HTMLElement | null;
|
|
35
|
+
protected _scene: THREE.Scene | null;
|
|
36
|
+
protected _grid: THREE.GridHelper | null;
|
|
37
|
+
protected _camera: THREE.PerspectiveCamera | null;
|
|
38
|
+
protected _mapControls: MapControls | null;
|
|
39
|
+
protected _circuit: Circuit | null;
|
|
40
|
+
readonly wireVisualManager: WireVisualManager;
|
|
41
|
+
protected _initialized: boolean;
|
|
42
|
+
protected _options: ControllerOptions | null;
|
|
43
|
+
protected _active: boolean;
|
|
44
|
+
protected _disposed: boolean;
|
|
45
|
+
protected _gridHalfSize: number;
|
|
46
|
+
readonly factoryRegistry: IFactoryRegistry;
|
|
47
|
+
readonly branchingPointVisualFactory: BranchingPointVisualFactory;
|
|
48
|
+
protected _componentObject3Ds: Map<UUID, THREE.Object3D>;
|
|
49
|
+
protected _enodeObject3Ds: Map<UUID, THREE.Object3D>;
|
|
50
|
+
protected _wireObject3Ds: Map<UUID, Line2>;
|
|
51
|
+
protected _hoverManager: HoverManager | null;
|
|
52
|
+
protected _mouseMoveHandler: ((event: MouseEvent) => void) | null;
|
|
53
|
+
protected _mouseLeaveHandler: ((event: MouseEvent) => void) | null;
|
|
54
|
+
protected _mapControlsChangeHandler: (() => void) | null;
|
|
55
|
+
protected _sharedResources: SharedResources | null;
|
|
56
|
+
protected _useSharedResources: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Create a new circuit controller
|
|
59
|
+
*
|
|
60
|
+
* @param factoryRegistry - Component visual factory registry
|
|
61
|
+
* @param sharedResources - Optional shared resources for facade pattern (CircuitEngine)
|
|
62
|
+
* @throws {TypeError} If factoryRegistry is null/undefined
|
|
63
|
+
*/
|
|
64
|
+
constructor(factoryRegistry: IFactoryRegistry, sharedResources?: SharedResources);
|
|
65
|
+
get componentObject3Ds(): Map<UUID, THREE.Object3D>;
|
|
66
|
+
get enodeObject3Ds(): Map<UUID, THREE.Object3D>;
|
|
67
|
+
get wireObject3Ds(): Map<UUID, Line2>;
|
|
68
|
+
get visualContext(): VisualContext;
|
|
69
|
+
protected get grid(): THREE.GridHelper | null;
|
|
70
|
+
protected set grid(grid: THREE.GridHelper);
|
|
71
|
+
/**
|
|
72
|
+
* Initialize the controller with a DOM container.
|
|
73
|
+
* Creates scene, camera, lights, MapControls, and HoverManager.
|
|
74
|
+
*
|
|
75
|
+
* When sharedResources were provided in constructor, uses those instead
|
|
76
|
+
* of creating new resources. This enables the CircuitEngine facade pattern.
|
|
77
|
+
*
|
|
78
|
+
* @param container - HTMLElement to attach scene to
|
|
79
|
+
* @param options - Optional configuration
|
|
80
|
+
* @throws {TypeError} If container is not a valid HTMLElement
|
|
81
|
+
* @throws {Error} If already initialized
|
|
82
|
+
*/
|
|
83
|
+
initialize(container: HTMLElement, options?: ControllerOptions): void;
|
|
84
|
+
/**
|
|
85
|
+
* Hook for subclasses to perform additional initialization.
|
|
86
|
+
* Called after base initialization but before emitting 'ready'.
|
|
87
|
+
*
|
|
88
|
+
* @param options - Controller options passed to initialize()
|
|
89
|
+
*/
|
|
90
|
+
protected abstract onInitialize(options?: ControllerOptions): void;
|
|
91
|
+
/**
|
|
92
|
+
* Emit the ready event with controller-specific data.
|
|
93
|
+
*/
|
|
94
|
+
protected abstract emitReady(): void;
|
|
95
|
+
/**
|
|
96
|
+
* Emit an error event.
|
|
97
|
+
*/
|
|
98
|
+
protected emitError(error: Error): void;
|
|
99
|
+
/**
|
|
100
|
+
* Check that controller is initialized and not disposed.
|
|
101
|
+
* @throws {Error} If not initialized or already disposed
|
|
102
|
+
*/
|
|
103
|
+
protected _checkInitialized(): void;
|
|
104
|
+
/**
|
|
105
|
+
* Clean up all WebGL resources.
|
|
106
|
+
* Disposes geometries, materials, controls, and clears event listeners.
|
|
107
|
+
*
|
|
108
|
+
* When using shared resources, does not dispose scene, camera, controls, or hover manager
|
|
109
|
+
* as those are owned by the CircuitEngine facade.
|
|
110
|
+
*/
|
|
111
|
+
dispose(): void;
|
|
112
|
+
/**
|
|
113
|
+
* Hook for subclasses to perform cleanup before base dispose.
|
|
114
|
+
*/
|
|
115
|
+
protected abstract onDispose(): void;
|
|
116
|
+
/**
|
|
117
|
+
* Remove all visual objects from scene.
|
|
118
|
+
* Subclasses must implement to handle their specific wire types.
|
|
119
|
+
*/
|
|
120
|
+
protected abstract _removeAllVisuals(): void;
|
|
121
|
+
setActive(active: boolean): void;
|
|
122
|
+
protected abstract onSetActive(active: boolean): void;
|
|
123
|
+
/**
|
|
124
|
+
* Set the current circuit to visualize or null to clear the scene
|
|
125
|
+
* @param circuit
|
|
126
|
+
*/
|
|
127
|
+
abstract setCircuit(circuit: Circuit | null): void;
|
|
128
|
+
/**
|
|
129
|
+
* Get the current circuit being visualized
|
|
130
|
+
*/
|
|
131
|
+
getCircuit(): Circuit | null;
|
|
132
|
+
protected abstract onSetCircuit(): void;
|
|
133
|
+
/**
|
|
134
|
+
* Loads a new circuit to visualize or null for clearing the scene
|
|
135
|
+
* @param circuit
|
|
136
|
+
*/
|
|
137
|
+
protected _setCircuit(circuit: Circuit | null): void;
|
|
138
|
+
/**
|
|
139
|
+
* get the object3D (Group for components and enodes, Line2 for wires) by hoverable type and id
|
|
140
|
+
* @param type
|
|
141
|
+
* @param id
|
|
142
|
+
*/
|
|
143
|
+
getObject3D(type: HoverableType, id: UUID): THREE.Object3D | undefined;
|
|
144
|
+
/**
|
|
145
|
+
* Get the MapControls instance for direct manipulation.
|
|
146
|
+
*/
|
|
147
|
+
getControls(): MapControls | null;
|
|
148
|
+
/**
|
|
149
|
+
* Get the current cursor position on the ground plane (y=0) in world coordinates
|
|
150
|
+
* The position is clamped within the circuit grid boundaries but not snapped to grid
|
|
151
|
+
* @param bound - Whether to constrain position within grid boundaries, default false
|
|
152
|
+
*/
|
|
153
|
+
cursorGroundPlanePosition(bound?: boolean): THREE.Vector3;
|
|
154
|
+
/**
|
|
155
|
+
* Initialize HoverManager for hover detection
|
|
156
|
+
*
|
|
157
|
+
* @private
|
|
158
|
+
*/
|
|
159
|
+
private _initializeHoverManager;
|
|
160
|
+
protected _setupMouseCallbacks(): void;
|
|
161
|
+
/**
|
|
162
|
+
* Get the currently hovered element.
|
|
163
|
+
*/
|
|
164
|
+
getHoveredElement(): HoveredElement | null;
|
|
165
|
+
/**
|
|
166
|
+
* Enable or disable hover detection.
|
|
167
|
+
*/
|
|
168
|
+
setHoverEnabled(enabled: boolean): void;
|
|
169
|
+
/**
|
|
170
|
+
* Check if hover detection is enabled.
|
|
171
|
+
*/
|
|
172
|
+
isHoverEnabled(): boolean;
|
|
173
|
+
/**
|
|
174
|
+
* Get the Three.js scene for rendering.
|
|
175
|
+
* @throws {Error} If not initialized
|
|
176
|
+
*/
|
|
177
|
+
getScene(): THREE.Scene;
|
|
178
|
+
/**
|
|
179
|
+
* Get the Three.js camera for rendering.
|
|
180
|
+
* @throws {Error} If not initialized
|
|
181
|
+
*/
|
|
182
|
+
getCamera(): THREE.PerspectiveCamera;
|
|
183
|
+
/**
|
|
184
|
+
* Get the HTML container element.
|
|
185
|
+
* @throws {Error} If not initialized
|
|
186
|
+
*/
|
|
187
|
+
getContainer(): HTMLElement;
|
|
188
|
+
/**
|
|
189
|
+
* Check if controller is initialized.
|
|
190
|
+
*/
|
|
191
|
+
get isInitialized(): boolean;
|
|
192
|
+
/**
|
|
193
|
+
* Check if controller is disposed.
|
|
194
|
+
*/
|
|
195
|
+
get isDisposed(): boolean;
|
|
196
|
+
/**
|
|
197
|
+
* event handler when the container size changes
|
|
198
|
+
* Can override the container boundingClientRect size by providing width and height
|
|
199
|
+
* - Update camera projection matrix
|
|
200
|
+
* - Update viewport size for Line2 material resolution
|
|
201
|
+
* Should be called when the container size changes (e.g., window resize)
|
|
202
|
+
*
|
|
203
|
+
* @param width - New width (optional, uses container size if not provided)
|
|
204
|
+
* @param height - New height (optional, uses container size if not provided)
|
|
205
|
+
*/
|
|
206
|
+
onContainerResize(width?: number, height?: number): void;
|
|
207
|
+
/**
|
|
208
|
+
* Hook for subclasses to handle container resize.
|
|
209
|
+
*/
|
|
210
|
+
protected onResize(_width: number, _height: number): void;
|
|
211
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { ENodeSourceType, ENode } from '../../core/index.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Branching Point Visual Factory
|
|
4
|
+
* @module scene/shared/components/BranchingPointVisualFactory
|
|
5
|
+
*
|
|
6
|
+
* Creates cone-shaped visuals for branching point enodes with:
|
|
7
|
+
* - SourceType-based color coding (white/red/blue)
|
|
8
|
+
* - Hover/selection feedback via brightness shift
|
|
9
|
+
* - Hitbox for raycasting on ENODE layer
|
|
10
|
+
*/
|
|
11
|
+
import * as THREE from 'three';
|
|
12
|
+
/**
|
|
13
|
+
* Factory for creating branching point visuals.
|
|
14
|
+
*
|
|
15
|
+
* Branching points are rendered as cones with colors indicating their sourceType:
|
|
16
|
+
* - White (0xffffff): No source (null)
|
|
17
|
+
* - Red (0xff0000): Voltage source
|
|
18
|
+
* - Blue (0x0000ff): Current source
|
|
19
|
+
*
|
|
20
|
+
* Hover and selection states use brightness shift of the base color.
|
|
21
|
+
*/
|
|
22
|
+
export declare class BranchingPointVisualFactory {
|
|
23
|
+
private static readonly COLORS;
|
|
24
|
+
private static readonly DEFAULT_HOVER_COLOR;
|
|
25
|
+
private static readonly HOVER_EMISSIVE;
|
|
26
|
+
private static readonly SELECTED_EMISSIVE;
|
|
27
|
+
private static readonly CONE_RADIUS;
|
|
28
|
+
private static readonly CONE_HEIGHT;
|
|
29
|
+
private static readonly CONE_SEGMENTS;
|
|
30
|
+
private static readonly HITBOX_SQUARE;
|
|
31
|
+
/**
|
|
32
|
+
* Create visual representation for a branching point.
|
|
33
|
+
* @param enode - The branching point ENode
|
|
34
|
+
* @returns THREE.Group containing cone mesh and hitbox
|
|
35
|
+
*/
|
|
36
|
+
createVisual(enode: ENode): THREE.Group;
|
|
37
|
+
/**
|
|
38
|
+
* Update branching point object3D's visual to reflect sourceType change.
|
|
39
|
+
* @param object3D - The branching point basis object3D (group)
|
|
40
|
+
* @param sourceType - New source type
|
|
41
|
+
*/
|
|
42
|
+
updateSourceType(object3D: THREE.Object3D, sourceType: ENodeSourceType | null): void;
|
|
43
|
+
protected colorForElectricalState(state: 'current' | 'voltage' | 'vc' | 'idle'): number;
|
|
44
|
+
/**
|
|
45
|
+
* Apply hover object3D feedback.
|
|
46
|
+
* @param object3D - The branching point basis object3D (group)
|
|
47
|
+
*/
|
|
48
|
+
applyHover(object3D: THREE.Object3D): void;
|
|
49
|
+
/**
|
|
50
|
+
* Remove hover object3D feedback.
|
|
51
|
+
* @param object3D - The branching point basis object3D (group)
|
|
52
|
+
*/
|
|
53
|
+
removeHover(object3D: THREE.Object3D): void;
|
|
54
|
+
/**
|
|
55
|
+
* Apply selection object3D feedback.
|
|
56
|
+
* @param object3D - The branching point basis object3D (group)
|
|
57
|
+
*/
|
|
58
|
+
applySelection(object3D: THREE.Object3D): void;
|
|
59
|
+
/**
|
|
60
|
+
* Remove selection object3D feedback.
|
|
61
|
+
* @param object3D - The branching point basis object3D (group)
|
|
62
|
+
*/
|
|
63
|
+
removeSelection(object3D: THREE.Object3D): void;
|
|
64
|
+
/**
|
|
65
|
+
* Get the base color for a sourceType.
|
|
66
|
+
* @param sourceType - Source type (null, 'Voltage', or 'Current')
|
|
67
|
+
* @returns Color hex value
|
|
68
|
+
*/
|
|
69
|
+
private getColorForSourceType;
|
|
70
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type-safe Event Emitter
|
|
3
|
+
* @module scene/shared/EventEmitter
|
|
4
|
+
*
|
|
5
|
+
* Provides type-safe event handling without external dependencies.
|
|
6
|
+
* Generic EventMap type ensures compile-time type safety for event payloads.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Generic event emitter with type-safe event emission and subscription
|
|
10
|
+
*
|
|
11
|
+
* @template EventMap - Map of event names to their payload types
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* interface MyEvents {
|
|
16
|
+
* click: { x: number; y: number };
|
|
17
|
+
* error: { message: string };
|
|
18
|
+
* }
|
|
19
|
+
*
|
|
20
|
+
* const emitter = new EventEmitter<MyEvents>();
|
|
21
|
+
* emitter.on('click', ({ x, y }) => console.log(x, y)); // Type-safe!
|
|
22
|
+
* emitter.emit('click', { x: 10, y: 20 });
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare class EventEmitter<EventMap extends Record<string, any>> {
|
|
26
|
+
private listeners;
|
|
27
|
+
/**
|
|
28
|
+
* Register an event listener
|
|
29
|
+
*
|
|
30
|
+
* @param event - Event name to listen for
|
|
31
|
+
* @param callback - Function to call when event occurs
|
|
32
|
+
*
|
|
33
|
+
* @remarks
|
|
34
|
+
* Same callback can be registered multiple times (will be called multiple times).
|
|
35
|
+
* Callbacks are wrapped in try-catch to prevent errors from breaking emission.
|
|
36
|
+
*/
|
|
37
|
+
on<K extends keyof EventMap>(event: K, callback: (payload: EventMap[K]) => void): void;
|
|
38
|
+
/**
|
|
39
|
+
* Unregister an event listener
|
|
40
|
+
*
|
|
41
|
+
* @param event - Event name
|
|
42
|
+
* @param callback - Function to remove (must be same reference used in on())
|
|
43
|
+
*
|
|
44
|
+
* @remarks
|
|
45
|
+
* If callback was registered multiple times, only removes one registration.
|
|
46
|
+
*/
|
|
47
|
+
off<K extends keyof EventMap>(event: K, callback: (payload: EventMap[K]) => void): void;
|
|
48
|
+
/**
|
|
49
|
+
* Emit an event to all registered listeners
|
|
50
|
+
* This method is public so that tools may emit events directly on behalf of the EventEmitter owner (controller).
|
|
51
|
+
*
|
|
52
|
+
* @param event - Event name to emit
|
|
53
|
+
* @param payload - Event-specific payload
|
|
54
|
+
*
|
|
55
|
+
* @remarks
|
|
56
|
+
* Listeners are called in registration order.
|
|
57
|
+
* Errors in callbacks are caught and logged but do not stop other callbacks.
|
|
58
|
+
*/
|
|
59
|
+
emit<K extends keyof EventMap>(event: K, payload: EventMap[K]): void;
|
|
60
|
+
/**
|
|
61
|
+
* Remove all listeners for a specific event or all events
|
|
62
|
+
*
|
|
63
|
+
* @param event - Optional event name. If omitted, removes all listeners for all events.
|
|
64
|
+
*/
|
|
65
|
+
removeAllListeners<K extends keyof EventMap>(event?: K): void;
|
|
66
|
+
/**
|
|
67
|
+
* Get count of listeners for a specific event
|
|
68
|
+
*
|
|
69
|
+
* @param event - Event name
|
|
70
|
+
* @returns Number of registered listeners
|
|
71
|
+
*/
|
|
72
|
+
listenerCount<K extends keyof EventMap>(event: K): number;
|
|
73
|
+
/**
|
|
74
|
+
* Register a listener that receives all events
|
|
75
|
+
*
|
|
76
|
+
* @param callback - Function called with event name and payload for every event
|
|
77
|
+
* @returns Cleanup function to remove the listener
|
|
78
|
+
*
|
|
79
|
+
* @remarks
|
|
80
|
+
* Useful for event forwarding/delegation patterns where you want to
|
|
81
|
+
* re-emit all events from one emitter to another.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```typescript
|
|
85
|
+
* const cleanup = source.onAny((event, payload) => {
|
|
86
|
+
* target.emit(event, payload);
|
|
87
|
+
* });
|
|
88
|
+
* // Later: cleanup();
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
onAny(callback: <K extends keyof EventMap>(event: K, payload: EventMap[K]) => void): () => void;
|
|
92
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { HoveredElement } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* HoverManager Implementation
|
|
4
|
+
* @module scene/shared/HoverManager
|
|
5
|
+
*
|
|
6
|
+
* Handles priority-based hover detection using Three.js Raycaster and Layers.
|
|
7
|
+
* Implements priority: enode > component > wire
|
|
8
|
+
*/
|
|
9
|
+
import * as THREE from 'three';
|
|
10
|
+
/**
|
|
11
|
+
* Callback type for hover state changes
|
|
12
|
+
*/
|
|
13
|
+
export type HoverCallback = (element: HoveredElement | null, previousElement: HoveredElement | null) => void;
|
|
14
|
+
/**
|
|
15
|
+
* HoverManager Class
|
|
16
|
+
*
|
|
17
|
+
* Manages hover detection using Three.js Raycaster against hitbox layers.
|
|
18
|
+
* Implements priority-based detection: enode > component > wire.
|
|
19
|
+
*/
|
|
20
|
+
export declare class HoverManager {
|
|
21
|
+
private scene;
|
|
22
|
+
private camera;
|
|
23
|
+
private raycaster;
|
|
24
|
+
private readonly groundPlane;
|
|
25
|
+
private readonly groundPlanePosition;
|
|
26
|
+
private currentlyHovered;
|
|
27
|
+
private callbacks;
|
|
28
|
+
private enabled;
|
|
29
|
+
private initialized;
|
|
30
|
+
private lastMouseX;
|
|
31
|
+
private lastMouseY;
|
|
32
|
+
private lastUpdateTime;
|
|
33
|
+
private throttleMs;
|
|
34
|
+
/**
|
|
35
|
+
* Create a new HoverManager
|
|
36
|
+
*
|
|
37
|
+
* @param scene - Three.js scene containing hitbox meshes
|
|
38
|
+
* @param camera - Three.js camera for raycasting
|
|
39
|
+
*/
|
|
40
|
+
constructor(scene: THREE.Scene, camera: THREE.Camera);
|
|
41
|
+
/**
|
|
42
|
+
* Get the last computed ground plane position under the mouse
|
|
43
|
+
*
|
|
44
|
+
* @returns THREE.Vector3 position on ground plane
|
|
45
|
+
*/
|
|
46
|
+
getGroundPlanePosition(): THREE.Vector3;
|
|
47
|
+
/**
|
|
48
|
+
* Update hover state based on normalized mouse coordinates
|
|
49
|
+
* Also update the VERY IMPORTANT ground plane position used for CircuitManager cursorGroundPlanePosition
|
|
50
|
+
*
|
|
51
|
+
* Performs priority-based raycasting against hitbox layers.
|
|
52
|
+
* If hover state changes, triggers onHoverChange callback.
|
|
53
|
+
*
|
|
54
|
+
* @param normalizedX - Mouse X in normalized HTML container coordinates [-1, 1]
|
|
55
|
+
* @param normalizedY - Mouse Y in normalized HTML container coordinates [-1, 1]
|
|
56
|
+
*/
|
|
57
|
+
updateFromMouse(normalizedX: number, normalizedY: number): void;
|
|
58
|
+
/**
|
|
59
|
+
* Force update hover state at current mouse position
|
|
60
|
+
*
|
|
61
|
+
* Useful after camera changes or scene updates to refresh hover state
|
|
62
|
+
* without requiring a new mouse event.
|
|
63
|
+
*/
|
|
64
|
+
refresh(): void;
|
|
65
|
+
/**
|
|
66
|
+
* Clear current hover state
|
|
67
|
+
*
|
|
68
|
+
* Triggers unhover callback if an element was hovered.
|
|
69
|
+
* Call this when mouse leaves the container.
|
|
70
|
+
*/
|
|
71
|
+
clear(): void;
|
|
72
|
+
/**
|
|
73
|
+
* Get the currently hovered element
|
|
74
|
+
*
|
|
75
|
+
* @returns HoveredElement if something is hovered, null otherwise
|
|
76
|
+
*/
|
|
77
|
+
getHoveredElement(): HoveredElement | null;
|
|
78
|
+
/**
|
|
79
|
+
* Register callback for hover state changes
|
|
80
|
+
*
|
|
81
|
+
* Callback is invoked when:
|
|
82
|
+
* - Hover starts (element becomes non-null)
|
|
83
|
+
* - Hover changes to different element
|
|
84
|
+
* - Hover ends (element becomes null)
|
|
85
|
+
*
|
|
86
|
+
* @param callback - Function to call on hover state change
|
|
87
|
+
*/
|
|
88
|
+
onHoverChange(callback: HoverCallback): void;
|
|
89
|
+
/**
|
|
90
|
+
* Remove previously registered hover change callback
|
|
91
|
+
*
|
|
92
|
+
* @param callback - Same function reference passed to onHoverChange
|
|
93
|
+
*/
|
|
94
|
+
offHoverChange(callback: HoverCallback): void;
|
|
95
|
+
/**
|
|
96
|
+
* Enable or disable hover detection
|
|
97
|
+
*
|
|
98
|
+
* When disabled, updateFromMouse() becomes a no-op.
|
|
99
|
+
* Useful for temporarily disabling hover during drag operations.
|
|
100
|
+
*
|
|
101
|
+
* @param enabled - Whether to enable hover detection
|
|
102
|
+
*/
|
|
103
|
+
setEnabled(enabled: boolean): void;
|
|
104
|
+
/**
|
|
105
|
+
* Check if hover detection is enabled
|
|
106
|
+
*
|
|
107
|
+
* @returns true if enabled
|
|
108
|
+
*/
|
|
109
|
+
isEnabled(): boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Set initialization state (to prevent double init)
|
|
112
|
+
* @param initialized
|
|
113
|
+
*/
|
|
114
|
+
setInitialized(initialized: boolean): void;
|
|
115
|
+
/**
|
|
116
|
+
* Check if HoverManager is initialized (to prevent double init)
|
|
117
|
+
*/
|
|
118
|
+
isInitialized(): boolean;
|
|
119
|
+
/**
|
|
120
|
+
* Clean up resources
|
|
121
|
+
*
|
|
122
|
+
* Removes all callbacks and clears state.
|
|
123
|
+
* Call when disposing the scene controllerType.
|
|
124
|
+
*/
|
|
125
|
+
dispose(): void;
|
|
126
|
+
/**
|
|
127
|
+
* Perform raycasting on a specific layer and extract hit information
|
|
128
|
+
*
|
|
129
|
+
* @param layer - Hitbox layer number to raycast against
|
|
130
|
+
* @param hoverableType - Type for HoveredElement
|
|
131
|
+
* @param objectType - CircuitSceneObjectType for event payload
|
|
132
|
+
* @returns HoveredElement if hit found, null otherwise
|
|
133
|
+
*/
|
|
134
|
+
private _raycastLayer;
|
|
135
|
+
/**
|
|
136
|
+
* Update hover state and trigger callbacks if changed
|
|
137
|
+
*
|
|
138
|
+
* Compares new hit with currentlyHovered and only triggers callbacks on change.
|
|
139
|
+
*
|
|
140
|
+
* @param newHit - New hover element or null
|
|
141
|
+
*/
|
|
142
|
+
private _updateHoverState;
|
|
143
|
+
/**
|
|
144
|
+
* Compare two hover elements for equality
|
|
145
|
+
*
|
|
146
|
+
* @param a - First element
|
|
147
|
+
* @param b - Second element
|
|
148
|
+
* @returns true if both represent the same hover state
|
|
149
|
+
*/
|
|
150
|
+
private _isSameHover;
|
|
151
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { UUID } from '../../core/index.ts';
|
|
2
|
+
import { HoverableType, SelectionData } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Callback invoked when selection changes
|
|
5
|
+
*
|
|
6
|
+
* @param newSelection - The new selection, or null if deselected
|
|
7
|
+
* @param previousSelection - The previous selection, or null if none was selected
|
|
8
|
+
*/
|
|
9
|
+
export type SelectionCallback = (newSelection: SelectionData | null, previousSelection: SelectionData | null) => void;
|
|
10
|
+
/**
|
|
11
|
+
* Manages selected components, enodes or wires for the circuit scene.
|
|
12
|
+
* Multi-selection is planned (notably with the use of a flexible SelectionData) but still to implement.
|
|
13
|
+
*
|
|
14
|
+
* Key current responsibilities:
|
|
15
|
+
* - Track -currently single object- selection state
|
|
16
|
+
* - Notify listeners of selection changes (observer pattern)
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const selectionManager = new SelectionManager();
|
|
21
|
+
*
|
|
22
|
+
*
|
|
23
|
+
* // Select a single object
|
|
24
|
+
* selectionManager.selectOne('component', 'component-uuid-1234');
|
|
25
|
+
* selectionManager.selectOne('enode', 'enode-uuid-1234');
|
|
26
|
+
* selectionManager.selectOne('wire', 'wire-uuid-1234');
|
|
27
|
+
*
|
|
28
|
+
* // Deselect
|
|
29
|
+
* selectionManager.deselect();
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare class SelectionManager {
|
|
33
|
+
/** Current selection */
|
|
34
|
+
private selection;
|
|
35
|
+
/** Timestamp when selection occurred (for double-click detection) */
|
|
36
|
+
private selectedAt;
|
|
37
|
+
/** Registered selection change callbacks */
|
|
38
|
+
private callbacks;
|
|
39
|
+
/**
|
|
40
|
+
* Create a new SelectionManager
|
|
41
|
+
*/
|
|
42
|
+
constructor();
|
|
43
|
+
/**
|
|
44
|
+
* Get the current selection
|
|
45
|
+
*
|
|
46
|
+
* @returns The SelectionData, or null if nothing is selected
|
|
47
|
+
*/
|
|
48
|
+
getSelection(): SelectionData | null;
|
|
49
|
+
/**
|
|
50
|
+
* Get the timestamp when selection occurred
|
|
51
|
+
*
|
|
52
|
+
* @returns Timestamp in milliseconds, or null if nothing is selected
|
|
53
|
+
*/
|
|
54
|
+
getSelectedAt(): number | null;
|
|
55
|
+
/**
|
|
56
|
+
* Check if a specific object is selected
|
|
57
|
+
*
|
|
58
|
+
* @param type - The type of hoverable object
|
|
59
|
+
* @param objectId - The object ID to check
|
|
60
|
+
* @returns true if the object is currently selected
|
|
61
|
+
*/
|
|
62
|
+
isSelected(type: HoverableType, objectId: UUID): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Check if anything is selected
|
|
65
|
+
*
|
|
66
|
+
* @returns true if one object is currently selected or several objects are currently selected
|
|
67
|
+
*/
|
|
68
|
+
hasSelection(): boolean;
|
|
69
|
+
private _selectionsEqual;
|
|
70
|
+
/**
|
|
71
|
+
* Select one object
|
|
72
|
+
*
|
|
73
|
+
* If another object was previously selected or a multi selection existed, they will be deselected first.
|
|
74
|
+
*
|
|
75
|
+
* @param type - The type of hoverable object to select
|
|
76
|
+
* @param objectId - The object ID to select
|
|
77
|
+
* @param userData - Optional userData of the 3D object being selected
|
|
78
|
+
*/
|
|
79
|
+
selectOne(type: HoverableType, objectId: UUID, userData?: object | undefined): void;
|
|
80
|
+
/**
|
|
81
|
+
* Deselect the current selection
|
|
82
|
+
*/
|
|
83
|
+
deselect(): void;
|
|
84
|
+
/**
|
|
85
|
+
* Select multiple elements at once, replacing any existing selection
|
|
86
|
+
*
|
|
87
|
+
* Creates a MultiSelectionData with the provided element maps.
|
|
88
|
+
* Empty maps are allowed; passing all empty maps clears the selection.
|
|
89
|
+
*
|
|
90
|
+
* @param components - Map of component IDs to optional metadata
|
|
91
|
+
* @param enodes - Map of enode IDs to optional metadata
|
|
92
|
+
* @param wires - Map of wire IDs to optional metadata
|
|
93
|
+
*/
|
|
94
|
+
selectMultiple(components?: Map<UUID, string | null>, enodes?: Map<UUID, string | null>, wires?: Map<UUID, string | null>): void;
|
|
95
|
+
/**
|
|
96
|
+
* Add a single element to the current selection
|
|
97
|
+
*
|
|
98
|
+
* If current selection is null, creates a mono selection.
|
|
99
|
+
* If current selection is mono, converts to multi and adds element.
|
|
100
|
+
* If current selection is multi, adds element to appropriate map.
|
|
101
|
+
*
|
|
102
|
+
* No-op if element is already selected.
|
|
103
|
+
*
|
|
104
|
+
* @param type - Type of element to add
|
|
105
|
+
* @param objectId - UUID of element to add
|
|
106
|
+
* @param userData - Optional metadata for the element
|
|
107
|
+
*/
|
|
108
|
+
addToSelection(type: HoverableType, objectId: UUID, userData?: object): void;
|
|
109
|
+
/**
|
|
110
|
+
* Remove a single element from the current selection
|
|
111
|
+
*
|
|
112
|
+
* If element is in a mono selection, clears the selection.
|
|
113
|
+
* If element is in a multi selection, removes from appropriate map.
|
|
114
|
+
* If multi selection becomes single element, converts to mono.
|
|
115
|
+
*
|
|
116
|
+
* No-op if element is not selected.
|
|
117
|
+
*
|
|
118
|
+
* @param type - Type of element to remove
|
|
119
|
+
* @param objectId - UUID of element to remove
|
|
120
|
+
*/
|
|
121
|
+
removeFromSelection(type: HoverableType, objectId: UUID): void;
|
|
122
|
+
/**
|
|
123
|
+
* Get the total count of selected elements across all types
|
|
124
|
+
*
|
|
125
|
+
* @returns Number of selected elements (0 if no selection)
|
|
126
|
+
*/
|
|
127
|
+
getSelectionCount(): number;
|
|
128
|
+
/**
|
|
129
|
+
* Get all selected element IDs grouped by type
|
|
130
|
+
*
|
|
131
|
+
* Returns empty arrays if no selection.
|
|
132
|
+
* For mono selection, returns single-element array in appropriate category.
|
|
133
|
+
*
|
|
134
|
+
* @returns Object with arrays of selected IDs by type
|
|
135
|
+
*/
|
|
136
|
+
getSelectedIds(): {
|
|
137
|
+
components: UUID[];
|
|
138
|
+
enodes: UUID[];
|
|
139
|
+
wires: UUID[];
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* Register a callback for selection changes
|
|
143
|
+
*
|
|
144
|
+
* @param callback - Function to call when selection changes
|
|
145
|
+
* @returns Unsubscribe function
|
|
146
|
+
*/
|
|
147
|
+
onSelectionChange(callback: SelectionCallback): () => void;
|
|
148
|
+
/**
|
|
149
|
+
* Notify all registered callbacks of selection change
|
|
150
|
+
*
|
|
151
|
+
* @param newSelection - New selection
|
|
152
|
+
* @param previousSelection - Previous selection
|
|
153
|
+
*/
|
|
154
|
+
private notifyCallbacks;
|
|
155
|
+
/**
|
|
156
|
+
* Clean up resources
|
|
157
|
+
*/
|
|
158
|
+
dispose(): void;
|
|
159
|
+
}
|