@2112-lab/central-plant 0.1.0
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/README.md +0 -0
- package/dist/bundle/index.js +14259 -0
- package/dist/cjs/_virtual/_rollupPluginBabelHelpers.js +353 -0
- package/dist/cjs/node_modules/three/examples/jsm/controls/OrbitControls.js +1292 -0
- package/dist/cjs/node_modules/three/examples/jsm/controls/TransformControls.js +1543 -0
- package/dist/cjs/node_modules/three/examples/jsm/loaders/GLTFLoader.js +4374 -0
- package/dist/cjs/node_modules/three/examples/jsm/loaders/RGBELoader.js +465 -0
- package/dist/cjs/node_modules/three/examples/jsm/utils/BufferGeometryUtils.js +117 -0
- package/dist/cjs/src/ConnectionManager.js +114 -0
- package/dist/cjs/src/Pathfinder.js +88 -0
- package/dist/cjs/src/animationManager.js +121 -0
- package/dist/cjs/src/componentManager.js +151 -0
- package/dist/cjs/src/debugLogger.js +176 -0
- package/dist/cjs/src/disposalManager.js +185 -0
- package/dist/cjs/src/environmentManager.js +1015 -0
- package/dist/cjs/src/hotReloadManager.js +252 -0
- package/dist/cjs/src/index.js +126 -0
- package/dist/cjs/src/keyboardControlsManager.js +206 -0
- package/dist/cjs/src/modelPreloader.js +360 -0
- package/dist/cjs/src/nameUtils.js +106 -0
- package/dist/cjs/src/pathfindingManager.js +321 -0
- package/dist/cjs/src/performanceMonitor.js +718 -0
- package/dist/cjs/src/sceneExportManager.js +292 -0
- package/dist/cjs/src/sceneInitializationManager.js +540 -0
- package/dist/cjs/src/sceneOperationsManager.js +560 -0
- package/dist/cjs/src/textureConfig.js +195 -0
- package/dist/cjs/src/transformControlsManager.js +851 -0
- package/dist/esm/_virtual/_rollupPluginBabelHelpers.js +328 -0
- package/dist/esm/node_modules/three/examples/jsm/controls/OrbitControls.js +1287 -0
- package/dist/esm/node_modules/three/examples/jsm/controls/TransformControls.js +1537 -0
- package/dist/esm/node_modules/three/examples/jsm/loaders/GLTFLoader.js +4370 -0
- package/dist/esm/node_modules/three/examples/jsm/loaders/RGBELoader.js +461 -0
- package/dist/esm/node_modules/three/examples/jsm/utils/BufferGeometryUtils.js +113 -0
- package/dist/esm/src/ConnectionManager.js +110 -0
- package/dist/esm/src/Pathfinder.js +84 -0
- package/dist/esm/src/animationManager.js +112 -0
- package/dist/esm/src/componentManager.js +123 -0
- package/dist/esm/src/debugLogger.js +167 -0
- package/dist/esm/src/disposalManager.js +155 -0
- package/dist/esm/src/environmentManager.js +989 -0
- package/dist/esm/src/hotReloadManager.js +244 -0
- package/dist/esm/src/index.js +117 -0
- package/dist/esm/src/keyboardControlsManager.js +196 -0
- package/dist/esm/src/modelPreloader.js +337 -0
- package/dist/esm/src/nameUtils.js +99 -0
- package/dist/esm/src/pathfindingManager.js +295 -0
- package/dist/esm/src/performanceMonitor.js +712 -0
- package/dist/esm/src/sceneExportManager.js +286 -0
- package/dist/esm/src/sceneInitializationManager.js +513 -0
- package/dist/esm/src/sceneOperationsManager.js +536 -0
- package/dist/esm/src/textureConfig.js +168 -0
- package/dist/esm/src/transformControlsManager.js +827 -0
- package/dist/index.d.ts +259 -0
- package/package.json +53 -0
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { createClass as _createClass, classCallCheck as _classCallCheck } from '../_virtual/_rollupPluginBabelHelpers.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Hot-Reload Manager Module
|
|
5
|
+
* Handles development environment hot-reload detection and cleanup
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Check if we're in a browser environment
|
|
9
|
+
var isBrowser = typeof window !== 'undefined';
|
|
10
|
+
var isDev = isBrowser && process.env.NODE_ENV === 'development';
|
|
11
|
+
var HotReloadManager = /*#__PURE__*/function () {
|
|
12
|
+
function HotReloadManager(componentInstance) {
|
|
13
|
+
_classCallCheck(this, HotReloadManager);
|
|
14
|
+
this.component = componentInstance;
|
|
15
|
+
this.isDev = isDev;
|
|
16
|
+
this.instanceId = Date.now() + Math.random();
|
|
17
|
+
|
|
18
|
+
// Event handlers
|
|
19
|
+
this.hotReloadCleanupHandler = null;
|
|
20
|
+
this.visibilityChangeHandler = null;
|
|
21
|
+
this.nuxtHotReloadHandler = null;
|
|
22
|
+
this.memoryCheckInterval = null;
|
|
23
|
+
|
|
24
|
+
// Async operation tracking
|
|
25
|
+
this.timeoutIds = new Set();
|
|
26
|
+
this.intervalIds = new Set();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Setup hot-reload handling for development environment
|
|
31
|
+
*/
|
|
32
|
+
return _createClass(HotReloadManager, [{
|
|
33
|
+
key: "setupHotReloadHandling",
|
|
34
|
+
value: function setupHotReloadHandling() {
|
|
35
|
+
var _this = this;
|
|
36
|
+
if (!isBrowser || !this.isDev) {
|
|
37
|
+
console.log('Not in browser or development mode, skipping hot-reload setup');
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
console.log('Setting up hot-reload handling...');
|
|
41
|
+
|
|
42
|
+
// Initialize global instance tracking
|
|
43
|
+
if (!window._sceneViewerInstances) {
|
|
44
|
+
window._sceneViewerInstances = new Set();
|
|
45
|
+
console.log('🔧 [Hot-Reload] Initialized global instance tracking');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Add this instance to global tracking
|
|
49
|
+
window._sceneViewerInstances.add(this.component);
|
|
50
|
+
console.log('📍 [Hot-Reload] Instance registered:', {
|
|
51
|
+
instanceId: this.instanceId,
|
|
52
|
+
totalInstances: window._sceneViewerInstances.size
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Enhanced beforeunload handler for development
|
|
56
|
+
this.hotReloadCleanupHandler = function () {
|
|
57
|
+
console.log('🔄 [Hot-Reload] Page unload detected, performing enhanced cleanup');
|
|
58
|
+
if (_this.component && typeof _this.component.enhancedDisposal === 'function') {
|
|
59
|
+
_this.component.enhancedDisposal();
|
|
60
|
+
}
|
|
61
|
+
if (window._sceneViewerInstances) {
|
|
62
|
+
window._sceneViewerInstances.delete(_this.component);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// Add event listeners
|
|
67
|
+
window.addEventListener('beforeunload', this.hotReloadCleanupHandler);
|
|
68
|
+
window.addEventListener('pagehide', this.hotReloadCleanupHandler);
|
|
69
|
+
console.log('✅ [Hot-Reload] Hot-reload handling setup completed');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Cleanup hot-reload handlers (development only)
|
|
74
|
+
*/
|
|
75
|
+
}, {
|
|
76
|
+
key: "cleanupHotReloadHandlers",
|
|
77
|
+
value: function cleanupHotReloadHandlers() {
|
|
78
|
+
if (!isBrowser || !this.isDev) return;
|
|
79
|
+
|
|
80
|
+
// Remove event listeners
|
|
81
|
+
if (this.hotReloadCleanupHandler) {
|
|
82
|
+
window.removeEventListener('beforeunload', this.hotReloadCleanupHandler);
|
|
83
|
+
window.removeEventListener('pagehide', this.hotReloadCleanupHandler);
|
|
84
|
+
this.hotReloadCleanupHandler = null;
|
|
85
|
+
}
|
|
86
|
+
if (this.visibilityChangeHandler) {
|
|
87
|
+
document.removeEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
88
|
+
this.visibilityChangeHandler = null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Remove Nuxt hot-reload handlers
|
|
92
|
+
if (this.nuxtHotReloadHandler && window.$nuxt && window.$nuxt.$off) {
|
|
93
|
+
window.$nuxt.$off('routeChanged', this.nuxtHotReloadHandler);
|
|
94
|
+
window.$nuxt.$off('$nuxtReady', this.nuxtHotReloadHandler);
|
|
95
|
+
this.nuxtHotReloadHandler = null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Clear memory monitoring interval
|
|
99
|
+
if (this.memoryCheckInterval) {
|
|
100
|
+
clearInterval(this.memoryCheckInterval);
|
|
101
|
+
this.memoryCheckInterval = null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Remove from global instance tracking
|
|
105
|
+
if (window._sceneViewerInstances) {
|
|
106
|
+
window._sceneViewerInstances.delete(this.component);
|
|
107
|
+
console.log('📍 [Hot-Reload] Instance removed from tracking:', {
|
|
108
|
+
instanceId: this.instanceId,
|
|
109
|
+
remainingInstances: window._sceneViewerInstances.size
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Track a timeout ID for cleanup on component destruction
|
|
116
|
+
*/
|
|
117
|
+
}, {
|
|
118
|
+
key: "trackTimeout",
|
|
119
|
+
value: function trackTimeout(timeoutId) {
|
|
120
|
+
if (timeoutId) {
|
|
121
|
+
this.timeoutIds.add(timeoutId);
|
|
122
|
+
}
|
|
123
|
+
return timeoutId;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Track an interval ID for cleanup on component destruction
|
|
128
|
+
*/
|
|
129
|
+
}, {
|
|
130
|
+
key: "trackInterval",
|
|
131
|
+
value: function trackInterval(intervalId) {
|
|
132
|
+
if (intervalId) {
|
|
133
|
+
this.intervalIds.add(intervalId);
|
|
134
|
+
}
|
|
135
|
+
return intervalId;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Clear a tracked timeout and remove from tracking
|
|
140
|
+
*/
|
|
141
|
+
}, {
|
|
142
|
+
key: "clearTrackedTimeout",
|
|
143
|
+
value: function clearTrackedTimeout(timeoutId) {
|
|
144
|
+
if (this.timeoutIds.has(timeoutId)) {
|
|
145
|
+
clearTimeout(timeoutId);
|
|
146
|
+
this.timeoutIds.delete(timeoutId);
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Clear a tracked interval and remove from tracking
|
|
154
|
+
*/
|
|
155
|
+
}, {
|
|
156
|
+
key: "clearTrackedInterval",
|
|
157
|
+
value: function clearTrackedInterval(intervalId) {
|
|
158
|
+
if (this.intervalIds.has(intervalId)) {
|
|
159
|
+
clearInterval(intervalId);
|
|
160
|
+
this.intervalIds.delete(intervalId);
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Clear all tracked timeouts and intervals
|
|
168
|
+
*/
|
|
169
|
+
}, {
|
|
170
|
+
key: "clearAllTrackedTimers",
|
|
171
|
+
value: function clearAllTrackedTimers() {
|
|
172
|
+
// Clear all timeouts
|
|
173
|
+
this.timeoutIds.forEach(function (id) {
|
|
174
|
+
clearTimeout(id);
|
|
175
|
+
});
|
|
176
|
+
this.timeoutIds.clear();
|
|
177
|
+
|
|
178
|
+
// Clear all intervals
|
|
179
|
+
this.intervalIds.forEach(function (id) {
|
|
180
|
+
clearInterval(id);
|
|
181
|
+
});
|
|
182
|
+
this.intervalIds.clear();
|
|
183
|
+
console.log('🧹 [Hot-Reload] Cleared all tracked timers');
|
|
184
|
+
}
|
|
185
|
+
}]);
|
|
186
|
+
}();
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Simple utility to handle hot-reload for componentId
|
|
190
|
+
* @param {string} instanceId - Unique instance identifier for the component
|
|
191
|
+
* @param {Function} cleanupMethod - Method to call to clean up resources
|
|
192
|
+
*/
|
|
193
|
+
function handleHotReload(instanceId, cleanupMethod) {
|
|
194
|
+
if (!isBrowser || !isDev) return;
|
|
195
|
+
|
|
196
|
+
// Initialize registry if needed
|
|
197
|
+
if (!window._hotReloadRegistry) {
|
|
198
|
+
window._hotReloadRegistry = new Map();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// If we're reloading and have a previous instance with the same ID, clean it up
|
|
202
|
+
var existingInstance = window._hotReloadRegistry.get(instanceId);
|
|
203
|
+
if (existingInstance) {
|
|
204
|
+
console.log("\uD83D\uDD25 [Hot-Reload] Detected hot reload for instance: ".concat(instanceId));
|
|
205
|
+
if (typeof existingInstance.cleanup === 'function') {
|
|
206
|
+
existingInstance.cleanup();
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Register new instance
|
|
211
|
+
window._hotReloadRegistry.set(instanceId, {
|
|
212
|
+
timestamp: Date.now(),
|
|
213
|
+
cleanup: cleanupMethod
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Check if we're currently hot-reloading
|
|
219
|
+
*/
|
|
220
|
+
function isHotReloading() {
|
|
221
|
+
return isDev && isBrowser && window._hotReloadRegistry && window._hotReloadRegistry.size > 0;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Clean up resources for a component before hot-reload
|
|
226
|
+
* @param {string} instanceId - ID of the component instance to clean up
|
|
227
|
+
*/
|
|
228
|
+
function cleanupForHotReload(instanceId) {
|
|
229
|
+
if (!isBrowser || !isDev || !window._hotReloadRegistry) return;
|
|
230
|
+
var instance = window._hotReloadRegistry.get(instanceId);
|
|
231
|
+
if (instance && typeof instance.cleanup === 'function') {
|
|
232
|
+
instance.cleanup();
|
|
233
|
+
window._hotReloadRegistry.delete(instanceId);
|
|
234
|
+
console.log("\uD83E\uDDF9 [Hot-Reload] Cleaned up instance: ".concat(instanceId));
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
var hotReloadManager = {
|
|
238
|
+
HotReloadManager: HotReloadManager,
|
|
239
|
+
handleHotReload: handleHotReload,
|
|
240
|
+
isHotReloading: isHotReloading,
|
|
241
|
+
cleanupForHotReload: cleanupForHotReload
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
export { HotReloadManager, cleanupForHotReload, hotReloadManager as default, handleHotReload, isHotReloading };
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import * as animationManager from './animationManager.js';
|
|
2
|
+
export { animationManager };
|
|
3
|
+
import * as componentManager from './componentManager.js';
|
|
4
|
+
export { componentManager };
|
|
5
|
+
import * as debugLogger from './debugLogger.js';
|
|
6
|
+
export { debugLogger };
|
|
7
|
+
export { logger, modelLogger, pathfinderLogger, transformLogger } from './debugLogger.js';
|
|
8
|
+
import * as disposalManager from './disposalManager.js';
|
|
9
|
+
export { disposalManager };
|
|
10
|
+
import * as environmentManager from './environmentManager.js';
|
|
11
|
+
export { environmentManager };
|
|
12
|
+
import * as hotReloadManager from './hotReloadManager.js';
|
|
13
|
+
export { hotReloadManager };
|
|
14
|
+
import * as keyboardControlsManager from './keyboardControlsManager.js';
|
|
15
|
+
export { keyboardControlsManager };
|
|
16
|
+
import * as modelPreloader from './modelPreloader.js';
|
|
17
|
+
export { modelPreloader };
|
|
18
|
+
import * as nameUtils from './nameUtils.js';
|
|
19
|
+
export { nameUtils };
|
|
20
|
+
export { findObjectByHardcodedUuid, generateUuidFromName, getHardcodedUuid } from './nameUtils.js';
|
|
21
|
+
import * as pathfindingManager from './pathfindingManager.js';
|
|
22
|
+
export { pathfindingManager };
|
|
23
|
+
import * as performanceMonitor from './performanceMonitor.js';
|
|
24
|
+
export { performanceMonitor };
|
|
25
|
+
import * as sceneExportManager from './sceneExportManager.js';
|
|
26
|
+
export { sceneExportManager };
|
|
27
|
+
export { getSceneExportManager } from './sceneExportManager.js';
|
|
28
|
+
import * as sceneInitializationManager from './sceneInitializationManager.js';
|
|
29
|
+
export { sceneInitializationManager };
|
|
30
|
+
import * as sceneOperationsManager from './sceneOperationsManager.js';
|
|
31
|
+
export { sceneOperationsManager };
|
|
32
|
+
export { getSceneOperationsManager } from './sceneOperationsManager.js';
|
|
33
|
+
import * as textureConfig from './textureConfig.js';
|
|
34
|
+
export { textureConfig };
|
|
35
|
+
import * as transformControlsManager from './transformControlsManager.js';
|
|
36
|
+
export { transformControlsManager };
|
|
37
|
+
export { getTransformControlsManager } from './transformControlsManager.js';
|
|
38
|
+
import * as Pathfinder from './Pathfinder.js';
|
|
39
|
+
export { Pathfinder };
|
|
40
|
+
import * as ConnectionManager from './ConnectionManager.js';
|
|
41
|
+
export { ConnectionManager };
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @module CentralPlant/Utils
|
|
45
|
+
* @description Central Plant Utilities Module
|
|
46
|
+
*
|
|
47
|
+
* This is the main entry point for all utility functions and classes
|
|
48
|
+
* used in the Central Plant application. Import this module to access
|
|
49
|
+
* all utility functions through a single interface.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* // Import the entire utilities module
|
|
53
|
+
* import CentralPlant from 'central-plant';
|
|
54
|
+
*
|
|
55
|
+
* // Use a specific utility
|
|
56
|
+
* CentralPlant.modelPreloader.preloadAllModels(...);
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* // Import specific modules
|
|
60
|
+
* import { modelPreloader, nameUtils } from 'CentralPlant';
|
|
61
|
+
*
|
|
62
|
+
* // Use them directly
|
|
63
|
+
* modelPreloader.preloadAllModels(...);
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* // Import common functions directly
|
|
67
|
+
* import { getHardcodedUuid, logger } from 'CentralPlant';
|
|
68
|
+
*
|
|
69
|
+
* // Use functions directly
|
|
70
|
+
* const uuid = getHardcodedUuid(object);
|
|
71
|
+
* logger.info('Operation completed');
|
|
72
|
+
*/
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Central API object that provides access to all utility modules
|
|
76
|
+
* @type {Object}
|
|
77
|
+
* @property {Object} animation - Animation management utilities
|
|
78
|
+
* @property {Object} component - Component management utilities
|
|
79
|
+
* @property {Object} debug - Debugging and logging utilities
|
|
80
|
+
* @property {Object} disposal - Resource disposal utilities
|
|
81
|
+
* @property {Object} environment - 3D environment management utilities
|
|
82
|
+
* @property {Object} hotReload - Hot reload handling utilities
|
|
83
|
+
* @property {Object} keyboardControls - Keyboard controls management
|
|
84
|
+
* @property {Object} modelPreloader - Model preloading utilities
|
|
85
|
+
* @property {Object} name - Name and UUID management utilities
|
|
86
|
+
* @property {Object} pathfinding - Pathfinding utilities
|
|
87
|
+
* @property {Object} performance - Performance monitoring utilities
|
|
88
|
+
* @property {Object} sceneExport - Scene export utilities
|
|
89
|
+
* @property {Object} sceneInitialization - Scene initialization utilities
|
|
90
|
+
* @property {Object} sceneOperations - Scene operations utilities
|
|
91
|
+
* @property {Object} texture - Texture management utilities
|
|
92
|
+
* @property {Object} transformControls - Transform controls utilities
|
|
93
|
+
* @property {Object} pathfinder - Pathfinder utilities
|
|
94
|
+
* @property {Object} connectionManager - Connection management utilities
|
|
95
|
+
*/
|
|
96
|
+
var CentralPlantUtils = {
|
|
97
|
+
animation: animationManager,
|
|
98
|
+
component: componentManager,
|
|
99
|
+
debug: debugLogger,
|
|
100
|
+
disposal: disposalManager,
|
|
101
|
+
environment: environmentManager,
|
|
102
|
+
hotReload: hotReloadManager,
|
|
103
|
+
keyboardControls: keyboardControlsManager,
|
|
104
|
+
modelPreloader: modelPreloader,
|
|
105
|
+
name: nameUtils,
|
|
106
|
+
pathfinding: pathfindingManager,
|
|
107
|
+
performance: performanceMonitor,
|
|
108
|
+
sceneExport: sceneExportManager,
|
|
109
|
+
sceneInitialization: sceneInitializationManager,
|
|
110
|
+
sceneOperations: sceneOperationsManager,
|
|
111
|
+
texture: textureConfig,
|
|
112
|
+
transformControls: transformControlsManager,
|
|
113
|
+
pathfinder: Pathfinder,
|
|
114
|
+
connectionManager: ConnectionManager
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
export { CentralPlantUtils as default };
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { logger } from './debugLogger.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Keyboard Controls Manager
|
|
5
|
+
* Manages keyboard shortcuts and controls
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Store registered key handlers
|
|
9
|
+
var keyHandlers = new Map();
|
|
10
|
+
var isListening = false;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Initialize keyboard controls
|
|
14
|
+
*/
|
|
15
|
+
function initKeyboardControls() {
|
|
16
|
+
if (typeof window === 'undefined') {
|
|
17
|
+
logger.warn('Cannot initialize keyboard controls: window is not defined');
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Only add event listener once
|
|
22
|
+
if (isListening) return;
|
|
23
|
+
|
|
24
|
+
// Handle keydown events
|
|
25
|
+
window.addEventListener('keydown', handleKeyDown);
|
|
26
|
+
window.addEventListener('keyup', handleKeyUp);
|
|
27
|
+
isListening = true;
|
|
28
|
+
logger.info('Keyboard controls initialized');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Clean up keyboard controls
|
|
33
|
+
*/
|
|
34
|
+
function cleanupKeyboardControls() {
|
|
35
|
+
if (typeof window === 'undefined' || !isListening) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
window.removeEventListener('keydown', handleKeyDown);
|
|
39
|
+
window.removeEventListener('keyup', handleKeyUp);
|
|
40
|
+
keyHandlers.clear();
|
|
41
|
+
isListening = false;
|
|
42
|
+
logger.info('Keyboard controls cleaned up');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Handler for keydown events
|
|
47
|
+
*/
|
|
48
|
+
function handleKeyDown(event) {
|
|
49
|
+
// Get key or combination
|
|
50
|
+
var keyCombo = getKeyCombo(event);
|
|
51
|
+
|
|
52
|
+
// Get handler for this key
|
|
53
|
+
var handler = keyHandlers.get(keyCombo);
|
|
54
|
+
if (handler) {
|
|
55
|
+
event.preventDefault();
|
|
56
|
+
handler.callback(event);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Handler for keyup events
|
|
62
|
+
*/
|
|
63
|
+
function handleKeyUp(event) {
|
|
64
|
+
var keyCombo = getKeyCombo(event);
|
|
65
|
+
|
|
66
|
+
// Get handler for this key
|
|
67
|
+
var handler = keyHandlers.get(keyCombo);
|
|
68
|
+
if (handler && handler.onKeyUp) {
|
|
69
|
+
event.preventDefault();
|
|
70
|
+
handler.onKeyUp(event);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Register a key handler
|
|
76
|
+
*/
|
|
77
|
+
function registerKeyHandler(key, callback) {
|
|
78
|
+
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
79
|
+
// Normalize key format
|
|
80
|
+
var normalizedKey = normalizeKey(key);
|
|
81
|
+
|
|
82
|
+
// Register handler
|
|
83
|
+
keyHandlers.set(normalizedKey, {
|
|
84
|
+
callback: callback,
|
|
85
|
+
onKeyUp: options.onKeyUp || null,
|
|
86
|
+
description: options.description || ''
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// Initialize controls if not already done
|
|
90
|
+
if (!isListening) {
|
|
91
|
+
initKeyboardControls();
|
|
92
|
+
}
|
|
93
|
+
return normalizedKey;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Unregister a key handler
|
|
98
|
+
*/
|
|
99
|
+
function unregisterKeyHandler(key) {
|
|
100
|
+
var normalizedKey = normalizeKey(key);
|
|
101
|
+
return keyHandlers.delete(normalizedKey);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Get all registered key handlers
|
|
106
|
+
*/
|
|
107
|
+
function getRegisteredKeyHandlers() {
|
|
108
|
+
var handlers = [];
|
|
109
|
+
keyHandlers.forEach(function (handler, key) {
|
|
110
|
+
handlers.push({
|
|
111
|
+
key: key,
|
|
112
|
+
description: handler.description
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
return handlers;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Helper function to normalize key format
|
|
120
|
+
*/
|
|
121
|
+
function normalizeKey(key) {
|
|
122
|
+
return key.toLowerCase();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Helper function to get key combo string from event
|
|
127
|
+
*/
|
|
128
|
+
function getKeyCombo(event) {
|
|
129
|
+
var combo = '';
|
|
130
|
+
if (event.ctrlKey) combo += 'ctrl+';
|
|
131
|
+
if (event.altKey) combo += 'alt+';
|
|
132
|
+
if (event.shiftKey) combo += 'shift+';
|
|
133
|
+
if (event.metaKey) combo += 'meta+';
|
|
134
|
+
combo += event.key.toLowerCase();
|
|
135
|
+
return combo;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Setup common keyboard controls for a Three.js scene
|
|
140
|
+
*/
|
|
141
|
+
function setupCommonControls(component) {
|
|
142
|
+
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
143
|
+
// Reset view
|
|
144
|
+
registerKeyHandler('r', function () {
|
|
145
|
+
if (component.camera && component.controls) {
|
|
146
|
+
component.camera.position.set(-10, 10, 10);
|
|
147
|
+
component.controls.target.set(0, 0, 0);
|
|
148
|
+
component.controls.update();
|
|
149
|
+
logger.info('Camera reset');
|
|
150
|
+
}
|
|
151
|
+
}, {
|
|
152
|
+
description: 'Reset camera view'
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// Toggle wireframe mode
|
|
156
|
+
registerKeyHandler('w', function () {
|
|
157
|
+
if (component.scene) {
|
|
158
|
+
var wireframeEnabled = !options.wireframeEnabled;
|
|
159
|
+
options.wireframeEnabled = wireframeEnabled;
|
|
160
|
+
component.scene.traverse(function (object) {
|
|
161
|
+
if (object.isMesh && object.material) {
|
|
162
|
+
if (Array.isArray(object.material)) {
|
|
163
|
+
object.material.forEach(function (mat) {
|
|
164
|
+
mat.wireframe = wireframeEnabled;
|
|
165
|
+
});
|
|
166
|
+
} else {
|
|
167
|
+
object.material.wireframe = wireframeEnabled;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
logger.info("Wireframe mode: ".concat(wireframeEnabled ? 'enabled' : 'disabled'));
|
|
172
|
+
}
|
|
173
|
+
}, {
|
|
174
|
+
description: 'Toggle wireframe mode'
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// Toggle performance monitor
|
|
178
|
+
registerKeyHandler('p', function () {
|
|
179
|
+
if (component.performanceUI) {
|
|
180
|
+
component.performanceUI.toggle();
|
|
181
|
+
}
|
|
182
|
+
}, {
|
|
183
|
+
description: 'Toggle performance monitor'
|
|
184
|
+
});
|
|
185
|
+
logger.info('Common keyboard controls setup');
|
|
186
|
+
}
|
|
187
|
+
var keyboardControlsManager = {
|
|
188
|
+
initKeyboardControls: initKeyboardControls,
|
|
189
|
+
cleanupKeyboardControls: cleanupKeyboardControls,
|
|
190
|
+
registerKeyHandler: registerKeyHandler,
|
|
191
|
+
unregisterKeyHandler: unregisterKeyHandler,
|
|
192
|
+
getRegisteredKeyHandlers: getRegisteredKeyHandlers,
|
|
193
|
+
setupCommonControls: setupCommonControls
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
export { cleanupKeyboardControls, keyboardControlsManager as default, getRegisteredKeyHandlers, initKeyboardControls, registerKeyHandler, setupCommonControls, unregisterKeyHandler };
|