@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,827 @@
|
|
|
1
|
+
import { createClass as _createClass, classCallCheck as _classCallCheck, asyncToGenerator as _asyncToGenerator, regenerator as _regenerator } from '../_virtual/_rollupPluginBabelHelpers.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Transform Controls Manager for Three.js
|
|
5
|
+
* Provides modular object transformation capabilities with position, rotation, and scale controls
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
var THREE;
|
|
9
|
+
var TransformControls;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Dynamically import ThreeJS and TransformControls when in browser environment
|
|
13
|
+
*/
|
|
14
|
+
function importDependencies() {
|
|
15
|
+
return _importDependencies.apply(this, arguments);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Class for managing object transform controls in a 3D scene
|
|
19
|
+
*/
|
|
20
|
+
function _importDependencies() {
|
|
21
|
+
_importDependencies = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
|
|
22
|
+
var transformModule, customModule, _t2;
|
|
23
|
+
return _regenerator().w(function (_context2) {
|
|
24
|
+
while (1) switch (_context2.n) {
|
|
25
|
+
case 0:
|
|
26
|
+
if (!(typeof window !== 'undefined')) {
|
|
27
|
+
_context2.n = 9;
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
_context2.p = 1;
|
|
31
|
+
_context2.n = 2;
|
|
32
|
+
return import('three');
|
|
33
|
+
case 2:
|
|
34
|
+
THREE = _context2.v;
|
|
35
|
+
_context2.p = 3;
|
|
36
|
+
_context2.n = 4;
|
|
37
|
+
return import('../node_modules/three/examples/jsm/controls/TransformControls.js');
|
|
38
|
+
case 4:
|
|
39
|
+
transformModule = _context2.v;
|
|
40
|
+
TransformControls = transformModule.TransformControls;
|
|
41
|
+
_context2.n = 7;
|
|
42
|
+
break;
|
|
43
|
+
case 5:
|
|
44
|
+
_context2.p = 5;
|
|
45
|
+
_context2.v;
|
|
46
|
+
console.log('Using fallback path for TransformControls');
|
|
47
|
+
// Fallback to the custom plugin path if available
|
|
48
|
+
if (!(typeof window.__transformControlsCustomPath === 'string')) {
|
|
49
|
+
_context2.n = 7;
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
_context2.n = 6;
|
|
53
|
+
return import(window.__transformControlsCustomPath);
|
|
54
|
+
case 6:
|
|
55
|
+
customModule = _context2.v;
|
|
56
|
+
TransformControls = customModule.TransformControls;
|
|
57
|
+
case 7:
|
|
58
|
+
_context2.n = 9;
|
|
59
|
+
break;
|
|
60
|
+
case 8:
|
|
61
|
+
_context2.p = 8;
|
|
62
|
+
_t2 = _context2.v;
|
|
63
|
+
console.error('Failed to load Transform Controls dependencies:', _t2);
|
|
64
|
+
throw new Error('TransformControlsManager: Required dependencies could not be loaded');
|
|
65
|
+
case 9:
|
|
66
|
+
return _context2.a(2);
|
|
67
|
+
}
|
|
68
|
+
}, _callee2, null, [[3, 5], [1, 8]]);
|
|
69
|
+
}));
|
|
70
|
+
return _importDependencies.apply(this, arguments);
|
|
71
|
+
}
|
|
72
|
+
var TransformControlsManager = /*#__PURE__*/function () {
|
|
73
|
+
/**
|
|
74
|
+
* Create a TransformControlsManager
|
|
75
|
+
* @param {THREE.Scene} scene - The Three.js scene
|
|
76
|
+
* @param {THREE.Camera} camera - The Three.js camera
|
|
77
|
+
* @param {THREE.WebGLRenderer} renderer - The Three.js renderer
|
|
78
|
+
* @param {THREE.OrbitControls} orbitControls - Optional orbit controls for camera
|
|
79
|
+
*/
|
|
80
|
+
function TransformControlsManager(scene, camera, renderer) {
|
|
81
|
+
var _this = this;
|
|
82
|
+
var orbitControls = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
|
|
83
|
+
_classCallCheck(this, TransformControlsManager);
|
|
84
|
+
this.scene = scene;
|
|
85
|
+
this.camera = camera;
|
|
86
|
+
this.renderer = renderer;
|
|
87
|
+
this.orbitControls = orbitControls;
|
|
88
|
+
|
|
89
|
+
// Transform control instance
|
|
90
|
+
this.transformControls = null;
|
|
91
|
+
|
|
92
|
+
// Bounding box helper for visual feedback
|
|
93
|
+
this.boundingBoxHelper = null;
|
|
94
|
+
|
|
95
|
+
// Cache for object bounding boxes to improve performance
|
|
96
|
+
this.boundingBoxCache = new WeakMap();
|
|
97
|
+
|
|
98
|
+
// Currently selected object
|
|
99
|
+
this.selectedObject = null;
|
|
100
|
+
|
|
101
|
+
// Transform mode: 'translate', 'rotate', 'scale'
|
|
102
|
+
this.currentMode = 'translate';
|
|
103
|
+
|
|
104
|
+
// Transform space: 'world' or 'local'
|
|
105
|
+
this.currentSpace = 'world';
|
|
106
|
+
|
|
107
|
+
// Flag to force controls to stay invisible (used during scene loading)
|
|
108
|
+
this.forceInvisible = false;
|
|
109
|
+
|
|
110
|
+
// Event handlers storage
|
|
111
|
+
this.eventHandlers = {
|
|
112
|
+
keydown: null,
|
|
113
|
+
pointerdown: null,
|
|
114
|
+
pointerup: null,
|
|
115
|
+
transformStart: null,
|
|
116
|
+
transformEnd: null,
|
|
117
|
+
transforming: null
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// Transform state tracking
|
|
121
|
+
this.transformState = {
|
|
122
|
+
isTransforming: false,
|
|
123
|
+
initialTransform: null,
|
|
124
|
+
currentTransform: null
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
// Configuration options
|
|
128
|
+
this.config = {
|
|
129
|
+
size: 1,
|
|
130
|
+
enabled: true,
|
|
131
|
+
showX: true,
|
|
132
|
+
showY: true,
|
|
133
|
+
showZ: true,
|
|
134
|
+
snap: null,
|
|
135
|
+
// Snap value for transformations
|
|
136
|
+
translationSnap: null,
|
|
137
|
+
rotationSnap: null,
|
|
138
|
+
scaleSnap: null,
|
|
139
|
+
showBoundingBox: true,
|
|
140
|
+
// Show bounding box on selection
|
|
141
|
+
boundingBoxColor: 0x00ff00,
|
|
142
|
+
// Green bounding box by default
|
|
143
|
+
useBoundingBoxSelection: true // Use bounding box-based selection instead of mesh selection
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
// Callbacks for external event handling
|
|
147
|
+
this.callbacks = {
|
|
148
|
+
onObjectSelect: null,
|
|
149
|
+
onTransformStart: null,
|
|
150
|
+
onTransform: null,
|
|
151
|
+
onTransformEnd: null,
|
|
152
|
+
onModeChange: null
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
// Initialize asynchronously if needed
|
|
156
|
+
if (typeof window !== 'undefined') {
|
|
157
|
+
importDependencies().then(function () {
|
|
158
|
+
return _this.init();
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Initialize the transform controls
|
|
165
|
+
*/
|
|
166
|
+
return _createClass(TransformControlsManager, [{
|
|
167
|
+
key: "init",
|
|
168
|
+
value: (function () {
|
|
169
|
+
var _init = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
|
|
170
|
+
return _regenerator().w(function (_context) {
|
|
171
|
+
while (1) switch (_context.n) {
|
|
172
|
+
case 0:
|
|
173
|
+
if (!(typeof window !== 'undefined' && !THREE)) {
|
|
174
|
+
_context.n = 1;
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
_context.n = 1;
|
|
178
|
+
return importDependencies();
|
|
179
|
+
case 1:
|
|
180
|
+
this.createTransformControls();
|
|
181
|
+
this.setupEventListeners();
|
|
182
|
+
this.setupKeyboardControls();
|
|
183
|
+
case 2:
|
|
184
|
+
return _context.a(2);
|
|
185
|
+
}
|
|
186
|
+
}, _callee, this);
|
|
187
|
+
}));
|
|
188
|
+
function init() {
|
|
189
|
+
return _init.apply(this, arguments);
|
|
190
|
+
}
|
|
191
|
+
return init;
|
|
192
|
+
}()
|
|
193
|
+
/**
|
|
194
|
+
* Register event callbacks
|
|
195
|
+
* @param {Object} callbacks - Object containing callback functions
|
|
196
|
+
*/
|
|
197
|
+
)
|
|
198
|
+
}, {
|
|
199
|
+
key: "on",
|
|
200
|
+
value: function on(callbacks) {
|
|
201
|
+
if (callbacks.onObjectSelect) {
|
|
202
|
+
this.callbacks.onObjectSelect = callbacks.onObjectSelect;
|
|
203
|
+
}
|
|
204
|
+
if (callbacks.onTransformStart) {
|
|
205
|
+
this.callbacks.onTransformStart = callbacks.onTransformStart;
|
|
206
|
+
}
|
|
207
|
+
if (callbacks.onTransform) {
|
|
208
|
+
this.callbacks.onTransform = callbacks.onTransform;
|
|
209
|
+
}
|
|
210
|
+
if (callbacks.onTransformEnd) {
|
|
211
|
+
this.callbacks.onTransformEnd = callbacks.onTransformEnd;
|
|
212
|
+
}
|
|
213
|
+
if (callbacks.onModeChange) {
|
|
214
|
+
this.callbacks.onModeChange = callbacks.onModeChange;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Create transform controls and add to scene
|
|
220
|
+
*/
|
|
221
|
+
}, {
|
|
222
|
+
key: "createTransformControls",
|
|
223
|
+
value: function createTransformControls() {
|
|
224
|
+
// Ensure THREE and TransformControls are available
|
|
225
|
+
if (!THREE || !TransformControls) {
|
|
226
|
+
console.warn('TransformControls cannot be created - THREE.js not loaded');
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Create transform controls if they don't exist
|
|
231
|
+
if (!this.transformControls) {
|
|
232
|
+
this.transformControls = new TransformControls(this.camera, this.renderer.domElement);
|
|
233
|
+
this.transformControls.size = this.config.size;
|
|
234
|
+
this.transformControls.enabled = this.config.enabled;
|
|
235
|
+
this.transformControls.visible = this.config.enabled && !this.forceInvisible;
|
|
236
|
+
|
|
237
|
+
// Set initial mode
|
|
238
|
+
this.transformControls.setMode(this.currentMode);
|
|
239
|
+
this.transformControls.setSpace(this.currentSpace);
|
|
240
|
+
|
|
241
|
+
// Mark with userData for easy identification
|
|
242
|
+
this.transformControls.userData = {
|
|
243
|
+
isTransformControls: true
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
// Add to scene
|
|
247
|
+
this.scene.add(this.transformControls);
|
|
248
|
+
console.log('✅ Transform controls created and added to scene');
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Set up event listeners for transform controls
|
|
254
|
+
*/
|
|
255
|
+
}, {
|
|
256
|
+
key: "setupEventListeners",
|
|
257
|
+
value: function setupEventListeners() {
|
|
258
|
+
var _this2 = this;
|
|
259
|
+
if (!this.transformControls) return;
|
|
260
|
+
|
|
261
|
+
// Clean up any existing listeners to avoid duplicates
|
|
262
|
+
this.removeEventListeners();
|
|
263
|
+
|
|
264
|
+
// Event handler for transform start
|
|
265
|
+
this.eventHandlers.transformStart = function (event) {
|
|
266
|
+
_this2.transformState.isTransforming = true;
|
|
267
|
+
if (_this2.selectedObject) {
|
|
268
|
+
// Store initial transform for history/undo purposes
|
|
269
|
+
_this2.transformState.initialTransform = _this2.captureObjectTransform(_this2.selectedObject);
|
|
270
|
+
|
|
271
|
+
// Notify via callback if registered
|
|
272
|
+
if (_this2.callbacks.onTransformStart) {
|
|
273
|
+
_this2.callbacks.onTransformStart(_this2.selectedObject, _this2.transformState.initialTransform);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
// Event handler for transform changes
|
|
279
|
+
this.eventHandlers.transforming = function (event) {
|
|
280
|
+
if (_this2.selectedObject && _this2.transformState.isTransforming) {
|
|
281
|
+
// Capture current transform
|
|
282
|
+
_this2.transformState.currentTransform = _this2.captureObjectTransform(_this2.selectedObject);
|
|
283
|
+
|
|
284
|
+
// Notify via callback if registered
|
|
285
|
+
if (_this2.callbacks.onTransform) {
|
|
286
|
+
_this2.callbacks.onTransform(_this2.selectedObject, _this2.transformState.currentTransform, _this2.transformState.initialTransform);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Update bounding box if shown
|
|
290
|
+
_this2.updateBoundingBox();
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
// Event handler for transform end
|
|
295
|
+
this.eventHandlers.transformEnd = function (event) {
|
|
296
|
+
if (_this2.selectedObject) {
|
|
297
|
+
// Capture final transform
|
|
298
|
+
var finalTransform = _this2.captureObjectTransform(_this2.selectedObject);
|
|
299
|
+
|
|
300
|
+
// Notify via callback if registered
|
|
301
|
+
if (_this2.callbacks.onTransformEnd) {
|
|
302
|
+
_this2.callbacks.onTransformEnd(_this2.selectedObject, finalTransform, _this2.transformState.initialTransform);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
_this2.transformState.isTransforming = false;
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
// Attach event listeners to transform controls
|
|
309
|
+
this.transformControls.addEventListener('mouseDown', this.eventHandlers.transformStart);
|
|
310
|
+
this.transformControls.addEventListener('objectChange', this.eventHandlers.transforming);
|
|
311
|
+
this.transformControls.addEventListener('mouseUp', this.eventHandlers.transformEnd);
|
|
312
|
+
|
|
313
|
+
// Disable orbit controls during transform (if orbit controls provided)
|
|
314
|
+
if (this.orbitControls) {
|
|
315
|
+
this.transformControls.addEventListener('dragging-changed', function (event) {
|
|
316
|
+
_this2.orbitControls.enabled = !event.value;
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Set up keyboard controls for transform operations
|
|
323
|
+
*/
|
|
324
|
+
}, {
|
|
325
|
+
key: "setupKeyboardControls",
|
|
326
|
+
value: function setupKeyboardControls() {
|
|
327
|
+
var _this3 = this;
|
|
328
|
+
// Skip if not in browser environment
|
|
329
|
+
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Clean up any existing listeners first
|
|
334
|
+
if (this.eventHandlers.keydown) {
|
|
335
|
+
document.removeEventListener('keydown', this.eventHandlers.keydown);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Keydown handler for keyboard shortcuts
|
|
339
|
+
this.eventHandlers.keydown = function (event) {
|
|
340
|
+
if (!_this3.config.enabled || !_this3.selectedObject) return;
|
|
341
|
+
switch (event.key.toLowerCase()) {
|
|
342
|
+
case 'g':
|
|
343
|
+
// Translate mode (grab)
|
|
344
|
+
_this3.setMode('translate');
|
|
345
|
+
break;
|
|
346
|
+
case 'r':
|
|
347
|
+
// Rotate mode
|
|
348
|
+
_this3.setMode('rotate');
|
|
349
|
+
break;
|
|
350
|
+
case 's':
|
|
351
|
+
// Scale mode
|
|
352
|
+
_this3.setMode('scale');
|
|
353
|
+
break;
|
|
354
|
+
case ' ':
|
|
355
|
+
// Toggle visibility
|
|
356
|
+
_this3.toggleVisibility();
|
|
357
|
+
break;
|
|
358
|
+
case 'escape':
|
|
359
|
+
// Deselect object
|
|
360
|
+
_this3.deselectObject();
|
|
361
|
+
break;
|
|
362
|
+
case 'x':
|
|
363
|
+
// X-axis constraint
|
|
364
|
+
if (event.shiftKey) {
|
|
365
|
+
// Shift + X to toggle X controls
|
|
366
|
+
_this3.config.showX = !_this3.config.showX;
|
|
367
|
+
_this3.updateAxisVisibility();
|
|
368
|
+
} else {
|
|
369
|
+
_this3.transformControls.showX = true;
|
|
370
|
+
_this3.transformControls.showY = false;
|
|
371
|
+
_this3.transformControls.showZ = false;
|
|
372
|
+
}
|
|
373
|
+
break;
|
|
374
|
+
case 'y':
|
|
375
|
+
// Y-axis constraint
|
|
376
|
+
if (event.shiftKey) {
|
|
377
|
+
// Shift + Y to toggle Y controls
|
|
378
|
+
_this3.config.showY = !_this3.config.showY;
|
|
379
|
+
_this3.updateAxisVisibility();
|
|
380
|
+
} else {
|
|
381
|
+
_this3.transformControls.showX = false;
|
|
382
|
+
_this3.transformControls.showY = true;
|
|
383
|
+
_this3.transformControls.showZ = false;
|
|
384
|
+
}
|
|
385
|
+
break;
|
|
386
|
+
case 'z':
|
|
387
|
+
// Z-axis constraint
|
|
388
|
+
if (event.shiftKey) {
|
|
389
|
+
// Shift + Z to toggle Z controls
|
|
390
|
+
_this3.config.showZ = !_this3.config.showZ;
|
|
391
|
+
_this3.updateAxisVisibility();
|
|
392
|
+
} else {
|
|
393
|
+
_this3.transformControls.showX = false;
|
|
394
|
+
_this3.transformControls.showY = false;
|
|
395
|
+
_this3.transformControls.showZ = true;
|
|
396
|
+
}
|
|
397
|
+
break;
|
|
398
|
+
case 'q':
|
|
399
|
+
// Toggle world/local space
|
|
400
|
+
_this3.toggleSpace();
|
|
401
|
+
break;
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
|
|
405
|
+
// Add keyboard event listener
|
|
406
|
+
document.addEventListener('keydown', this.eventHandlers.keydown);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Remove all event listeners
|
|
411
|
+
*/
|
|
412
|
+
}, {
|
|
413
|
+
key: "removeEventListeners",
|
|
414
|
+
value: function removeEventListeners() {
|
|
415
|
+
if (this.transformControls) {
|
|
416
|
+
// Remove transform control event listeners
|
|
417
|
+
this.transformControls.removeEventListener('mouseDown', this.eventHandlers.transformStart);
|
|
418
|
+
this.transformControls.removeEventListener('objectChange', this.eventHandlers.transforming);
|
|
419
|
+
this.transformControls.removeEventListener('mouseUp', this.eventHandlers.transformEnd);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// Remove document event listeners if in browser
|
|
423
|
+
if (typeof document !== 'undefined') {
|
|
424
|
+
if (this.eventHandlers.keydown) {
|
|
425
|
+
document.removeEventListener('keydown', this.eventHandlers.keydown);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Select an object for transformation
|
|
432
|
+
* @param {THREE.Object3D} object - The object to transform
|
|
433
|
+
*/
|
|
434
|
+
}, {
|
|
435
|
+
key: "selectObject",
|
|
436
|
+
value: function selectObject(object) {
|
|
437
|
+
if (!this.config.enabled || !this.transformControls || !object) return;
|
|
438
|
+
|
|
439
|
+
// Deselect current object if any
|
|
440
|
+
this.deselectObject();
|
|
441
|
+
|
|
442
|
+
// Set new selected object
|
|
443
|
+
this.selectedObject = object;
|
|
444
|
+
this.transformControls.attach(object);
|
|
445
|
+
|
|
446
|
+
// Show bounding box if enabled
|
|
447
|
+
if (this.config.showBoundingBox) {
|
|
448
|
+
this.showBoundingBox(object);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// Notify via callback if registered
|
|
452
|
+
if (this.callbacks.onObjectSelect) {
|
|
453
|
+
this.callbacks.onObjectSelect(object, true);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Make controls visible if not forced invisible
|
|
457
|
+
if (!this.forceInvisible) {
|
|
458
|
+
this.transformControls.visible = true;
|
|
459
|
+
}
|
|
460
|
+
return object;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Deselect the currently selected object
|
|
465
|
+
*/
|
|
466
|
+
}, {
|
|
467
|
+
key: "deselectObject",
|
|
468
|
+
value: function deselectObject() {
|
|
469
|
+
if (this.selectedObject) {
|
|
470
|
+
// Detach from transform controls
|
|
471
|
+
if (this.transformControls) {
|
|
472
|
+
this.transformControls.detach();
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// Hide bounding box
|
|
476
|
+
this.hideBoundingBox();
|
|
477
|
+
|
|
478
|
+
// Notify via callback if registered
|
|
479
|
+
if (this.callbacks.onObjectSelect) {
|
|
480
|
+
this.callbacks.onObjectSelect(this.selectedObject, false);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// Clear selection
|
|
484
|
+
var previousSelection = this.selectedObject;
|
|
485
|
+
this.selectedObject = null;
|
|
486
|
+
|
|
487
|
+
// Ensure transform controls are removed from scene
|
|
488
|
+
this.ensureSceneAttachment(false);
|
|
489
|
+
return previousSelection;
|
|
490
|
+
}
|
|
491
|
+
return null;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Set transformation mode
|
|
496
|
+
* @param {string} mode - The transform mode ('translate', 'rotate', or 'scale')
|
|
497
|
+
*/
|
|
498
|
+
}, {
|
|
499
|
+
key: "setMode",
|
|
500
|
+
value: function setMode(mode) {
|
|
501
|
+
if (!this.transformControls) return;
|
|
502
|
+
if (['translate', 'rotate', 'scale'].includes(mode)) {
|
|
503
|
+
this.currentMode = mode;
|
|
504
|
+
this.transformControls.setMode(mode);
|
|
505
|
+
|
|
506
|
+
// Update snap values based on mode
|
|
507
|
+
switch (mode) {
|
|
508
|
+
case 'translate':
|
|
509
|
+
this.transformControls.setTranslationSnap(this.config.translationSnap);
|
|
510
|
+
break;
|
|
511
|
+
case 'rotate':
|
|
512
|
+
this.transformControls.setRotationSnap(this.config.rotationSnap);
|
|
513
|
+
break;
|
|
514
|
+
case 'scale':
|
|
515
|
+
this.transformControls.setScaleSnap(this.config.scaleSnap);
|
|
516
|
+
break;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// Notify via callback if registered
|
|
520
|
+
if (this.callbacks.onModeChange) {
|
|
521
|
+
this.callbacks.onModeChange(mode);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* Toggle coordinate space between world and local
|
|
528
|
+
*/
|
|
529
|
+
}, {
|
|
530
|
+
key: "toggleSpace",
|
|
531
|
+
value: function toggleSpace() {
|
|
532
|
+
if (!this.transformControls) return;
|
|
533
|
+
this.currentSpace = this.currentSpace === 'world' ? 'local' : 'world';
|
|
534
|
+
this.transformControls.setSpace(this.currentSpace);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* Toggle visibility of transform controls
|
|
539
|
+
*/
|
|
540
|
+
}, {
|
|
541
|
+
key: "toggleVisibility",
|
|
542
|
+
value: function toggleVisibility() {
|
|
543
|
+
if (!this.transformControls) return;
|
|
544
|
+
if (!this.forceInvisible) {
|
|
545
|
+
this.transformControls.visible = !this.transformControls.visible;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* Set enabled state of transform controls
|
|
551
|
+
* @param {boolean} enabled - Whether transform controls should be enabled
|
|
552
|
+
*/
|
|
553
|
+
}, {
|
|
554
|
+
key: "setEnabled",
|
|
555
|
+
value: function setEnabled(enabled) {
|
|
556
|
+
this.config.enabled = enabled;
|
|
557
|
+
if (this.transformControls) {
|
|
558
|
+
this.transformControls.enabled = enabled;
|
|
559
|
+
if (!enabled) {
|
|
560
|
+
this.deselectObject();
|
|
561
|
+
this.transformControls.visible = false;
|
|
562
|
+
} else if (this.selectedObject && !this.forceInvisible) {
|
|
563
|
+
this.transformControls.visible = true;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Update axis visibility based on config
|
|
570
|
+
*/
|
|
571
|
+
}, {
|
|
572
|
+
key: "updateAxisVisibility",
|
|
573
|
+
value: function updateAxisVisibility() {
|
|
574
|
+
if (!this.transformControls) return;
|
|
575
|
+
this.transformControls.showX = this.config.showX;
|
|
576
|
+
this.transformControls.showY = this.config.showY;
|
|
577
|
+
this.transformControls.showZ = this.config.showZ;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Show bounding box for an object
|
|
582
|
+
* @param {THREE.Object3D} object - The object to show bounding box for
|
|
583
|
+
*/
|
|
584
|
+
}, {
|
|
585
|
+
key: "showBoundingBox",
|
|
586
|
+
value: function showBoundingBox(object) {
|
|
587
|
+
if (!object || !THREE) return;
|
|
588
|
+
this.hideBoundingBox();
|
|
589
|
+
|
|
590
|
+
// Get bounding box (from cache or compute it)
|
|
591
|
+
var boundingBox = this.boundingBoxCache.get(object);
|
|
592
|
+
if (!boundingBox) {
|
|
593
|
+
boundingBox = new THREE.Box3().setFromObject(object);
|
|
594
|
+
this.boundingBoxCache.set(object, boundingBox);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// Create helper if needed
|
|
598
|
+
if (!this.boundingBoxHelper) {
|
|
599
|
+
this.boundingBoxHelper = new THREE.Box3Helper(boundingBox, this.config.boundingBoxColor);
|
|
600
|
+
this.scene.add(this.boundingBoxHelper);
|
|
601
|
+
} else {
|
|
602
|
+
this.boundingBoxHelper.box = boundingBox;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// Store bounding box in object userData for easy access
|
|
606
|
+
object.userData.worldBoundingBox = boundingBox;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* Hide bounding box helper
|
|
611
|
+
*/
|
|
612
|
+
}, {
|
|
613
|
+
key: "hideBoundingBox",
|
|
614
|
+
value: function hideBoundingBox() {
|
|
615
|
+
if (this.boundingBoxHelper) {
|
|
616
|
+
this.scene.remove(this.boundingBoxHelper);
|
|
617
|
+
this.boundingBoxHelper = null;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* Update bounding box for selected object
|
|
623
|
+
*/
|
|
624
|
+
}, {
|
|
625
|
+
key: "updateBoundingBox",
|
|
626
|
+
value: function updateBoundingBox() {
|
|
627
|
+
if (this.selectedObject && this.config.showBoundingBox) {
|
|
628
|
+
// Update bounding box to reflect current transform
|
|
629
|
+
var boundingBox = new THREE.Box3().setFromObject(this.selectedObject);
|
|
630
|
+
|
|
631
|
+
// Update cache
|
|
632
|
+
this.boundingBoxCache.set(this.selectedObject, boundingBox);
|
|
633
|
+
|
|
634
|
+
// Update helper if exists
|
|
635
|
+
if (this.boundingBoxHelper) {
|
|
636
|
+
this.boundingBoxHelper.box = boundingBox;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// Update userData
|
|
640
|
+
this.selectedObject.userData.worldBoundingBox = boundingBox;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* Capture object transformation data
|
|
646
|
+
* @param {THREE.Object3D} object - The object to capture transform from
|
|
647
|
+
* @returns {Object} Object containing position, rotation and scale data
|
|
648
|
+
*/
|
|
649
|
+
}, {
|
|
650
|
+
key: "captureObjectTransform",
|
|
651
|
+
value: function captureObjectTransform(object) {
|
|
652
|
+
if (!object) return null;
|
|
653
|
+
return {
|
|
654
|
+
position: {
|
|
655
|
+
x: object.position.x,
|
|
656
|
+
y: object.position.y,
|
|
657
|
+
z: object.position.z
|
|
658
|
+
},
|
|
659
|
+
rotation: {
|
|
660
|
+
x: object.rotation.x,
|
|
661
|
+
y: object.rotation.y,
|
|
662
|
+
z: object.rotation.z
|
|
663
|
+
},
|
|
664
|
+
scale: {
|
|
665
|
+
x: object.scale.x,
|
|
666
|
+
y: object.scale.y,
|
|
667
|
+
z: object.scale.z
|
|
668
|
+
}
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
/**
|
|
673
|
+
* Set snap values for transformations
|
|
674
|
+
* @param {Object} options - Snap options
|
|
675
|
+
* @param {number} options.translation - Translation snap value
|
|
676
|
+
* @param {number} options.rotation - Rotation snap value in degrees
|
|
677
|
+
* @param {number} options.scale - Scale snap value
|
|
678
|
+
*/
|
|
679
|
+
}, {
|
|
680
|
+
key: "setSnapValues",
|
|
681
|
+
value: function setSnapValues() {
|
|
682
|
+
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
683
|
+
if (!this.transformControls) return;
|
|
684
|
+
if (options.translation !== undefined) {
|
|
685
|
+
this.config.translationSnap = options.translation;
|
|
686
|
+
if (this.currentMode === 'translate') {
|
|
687
|
+
this.transformControls.setTranslationSnap(options.translation);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
if (options.rotation !== undefined) {
|
|
691
|
+
// Convert degrees to radians for rotation snap
|
|
692
|
+
var rotationSnapRadians = options.rotation * (Math.PI / 180);
|
|
693
|
+
this.config.rotationSnap = rotationSnapRadians;
|
|
694
|
+
if (this.currentMode === 'rotate') {
|
|
695
|
+
this.transformControls.setRotationSnap(rotationSnapRadians);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
if (options.scale !== undefined) {
|
|
699
|
+
this.config.scaleSnap = options.scale;
|
|
700
|
+
if (this.currentMode === 'scale') {
|
|
701
|
+
this.transformControls.setScaleSnap(options.scale);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
/**
|
|
707
|
+
* Set size of transform controls
|
|
708
|
+
* @param {number} size - The size factor for transform controls
|
|
709
|
+
*/
|
|
710
|
+
}, {
|
|
711
|
+
key: "setSize",
|
|
712
|
+
value: function setSize(size) {
|
|
713
|
+
this.config.size = size;
|
|
714
|
+
if (this.transformControls) {
|
|
715
|
+
this.transformControls.size = size;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
/**
|
|
720
|
+
* Clean up resources and remove event listeners
|
|
721
|
+
*/
|
|
722
|
+
}, {
|
|
723
|
+
key: "dispose",
|
|
724
|
+
value: function dispose() {
|
|
725
|
+
this.removeEventListeners();
|
|
726
|
+
this.hideBoundingBox();
|
|
727
|
+
if (this.transformControls) {
|
|
728
|
+
this.transformControls.detach();
|
|
729
|
+
this.scene.remove(this.transformControls);
|
|
730
|
+
this.transformControls = null;
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
// Clear references
|
|
734
|
+
this.selectedObject = null;
|
|
735
|
+
this.boundingBoxCache = new WeakMap();
|
|
736
|
+
console.log('🧹 TransformControlsManager disposed');
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
/**
|
|
740
|
+
* Ensures transform controls are properly attached to the scene
|
|
741
|
+
* @param {boolean} allowVisible - Whether to allow controls to be visible when reattached
|
|
742
|
+
* @returns {boolean} - True if controls were reattached, false if already attached
|
|
743
|
+
*/
|
|
744
|
+
}, {
|
|
745
|
+
key: "ensureSceneAttachment",
|
|
746
|
+
value: function ensureSceneAttachment() {
|
|
747
|
+
var allowVisible = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
748
|
+
if (!this.transformControls || !this.scene) return false;
|
|
749
|
+
|
|
750
|
+
// Check if the controls are already in the scene
|
|
751
|
+
var isInScene = this.scene.children.includes(this.transformControls);
|
|
752
|
+
if (!isInScene) {
|
|
753
|
+
// Reattach to scene
|
|
754
|
+
this.scene.add(this.transformControls);
|
|
755
|
+
|
|
756
|
+
// Set visibility based on allowVisible parameter and forceInvisible flag
|
|
757
|
+
this.transformControls.visible = allowVisible && !this.forceInvisible && this.config.enabled;
|
|
758
|
+
return true; // Controls were reattached
|
|
759
|
+
}
|
|
760
|
+
return false; // Already properly attached
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
/**
|
|
764
|
+
* Get current transform data for the selected object
|
|
765
|
+
* @returns {Object|null} Object containing position, rotation, scale, and world coordinates
|
|
766
|
+
*/
|
|
767
|
+
}, {
|
|
768
|
+
key: "getTransformData",
|
|
769
|
+
value: function getTransformData() {
|
|
770
|
+
if (!this.selectedObject) return null;
|
|
771
|
+
var worldPosition = new THREE.Vector3();
|
|
772
|
+
this.selectedObject.getWorldPosition(worldPosition);
|
|
773
|
+
var worldQuaternion = new THREE.Quaternion();
|
|
774
|
+
this.selectedObject.getWorldQuaternion(worldQuaternion);
|
|
775
|
+
var worldEuler = new THREE.Euler().setFromQuaternion(worldQuaternion);
|
|
776
|
+
var worldScale = new THREE.Vector3();
|
|
777
|
+
this.selectedObject.getWorldScale(worldScale);
|
|
778
|
+
return {
|
|
779
|
+
uuid: this.selectedObject.uuid,
|
|
780
|
+
position: {
|
|
781
|
+
x: this.selectedObject.position.x,
|
|
782
|
+
y: this.selectedObject.position.y,
|
|
783
|
+
z: this.selectedObject.position.z
|
|
784
|
+
},
|
|
785
|
+
rotation: {
|
|
786
|
+
x: this.selectedObject.rotation.x,
|
|
787
|
+
y: this.selectedObject.rotation.y,
|
|
788
|
+
z: this.selectedObject.rotation.z
|
|
789
|
+
},
|
|
790
|
+
scale: {
|
|
791
|
+
x: this.selectedObject.scale.x,
|
|
792
|
+
y: this.selectedObject.scale.y,
|
|
793
|
+
z: this.selectedObject.scale.z
|
|
794
|
+
},
|
|
795
|
+
worldPosition: {
|
|
796
|
+
x: worldPosition.x,
|
|
797
|
+
y: worldPosition.y,
|
|
798
|
+
z: worldPosition.z
|
|
799
|
+
},
|
|
800
|
+
worldRotation: {
|
|
801
|
+
x: worldEuler.x,
|
|
802
|
+
y: worldEuler.y,
|
|
803
|
+
z: worldEuler.z
|
|
804
|
+
},
|
|
805
|
+
worldScale: {
|
|
806
|
+
x: worldScale.x,
|
|
807
|
+
y: worldScale.y,
|
|
808
|
+
z: worldScale.z
|
|
809
|
+
}
|
|
810
|
+
};
|
|
811
|
+
}
|
|
812
|
+
}]);
|
|
813
|
+
}();
|
|
814
|
+
|
|
815
|
+
/**
|
|
816
|
+
* Factory function to get TransformControlsManager instance
|
|
817
|
+
* @param {THREE.Scene} scene - The Three.js scene
|
|
818
|
+
* @param {THREE.Camera} camera - The Three.js camera
|
|
819
|
+
* @param {THREE.WebGLRenderer} renderer - The Three.js renderer
|
|
820
|
+
* @param {THREE.OrbitControls} orbitControls - Optional orbit controls for camera
|
|
821
|
+
* @returns {TransformControlsManager} TransformControlsManager instance
|
|
822
|
+
*/
|
|
823
|
+
function getTransformControlsManager(scene, camera, renderer, orbitControls) {
|
|
824
|
+
return new TransformControlsManager(scene, camera, renderer, orbitControls);
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
export { TransformControlsManager, TransformControlsManager as default, getTransformControlsManager };
|