@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.
Files changed (54) hide show
  1. package/README.md +0 -0
  2. package/dist/bundle/index.js +14259 -0
  3. package/dist/cjs/_virtual/_rollupPluginBabelHelpers.js +353 -0
  4. package/dist/cjs/node_modules/three/examples/jsm/controls/OrbitControls.js +1292 -0
  5. package/dist/cjs/node_modules/three/examples/jsm/controls/TransformControls.js +1543 -0
  6. package/dist/cjs/node_modules/three/examples/jsm/loaders/GLTFLoader.js +4374 -0
  7. package/dist/cjs/node_modules/three/examples/jsm/loaders/RGBELoader.js +465 -0
  8. package/dist/cjs/node_modules/three/examples/jsm/utils/BufferGeometryUtils.js +117 -0
  9. package/dist/cjs/src/ConnectionManager.js +114 -0
  10. package/dist/cjs/src/Pathfinder.js +88 -0
  11. package/dist/cjs/src/animationManager.js +121 -0
  12. package/dist/cjs/src/componentManager.js +151 -0
  13. package/dist/cjs/src/debugLogger.js +176 -0
  14. package/dist/cjs/src/disposalManager.js +185 -0
  15. package/dist/cjs/src/environmentManager.js +1015 -0
  16. package/dist/cjs/src/hotReloadManager.js +252 -0
  17. package/dist/cjs/src/index.js +126 -0
  18. package/dist/cjs/src/keyboardControlsManager.js +206 -0
  19. package/dist/cjs/src/modelPreloader.js +360 -0
  20. package/dist/cjs/src/nameUtils.js +106 -0
  21. package/dist/cjs/src/pathfindingManager.js +321 -0
  22. package/dist/cjs/src/performanceMonitor.js +718 -0
  23. package/dist/cjs/src/sceneExportManager.js +292 -0
  24. package/dist/cjs/src/sceneInitializationManager.js +540 -0
  25. package/dist/cjs/src/sceneOperationsManager.js +560 -0
  26. package/dist/cjs/src/textureConfig.js +195 -0
  27. package/dist/cjs/src/transformControlsManager.js +851 -0
  28. package/dist/esm/_virtual/_rollupPluginBabelHelpers.js +328 -0
  29. package/dist/esm/node_modules/three/examples/jsm/controls/OrbitControls.js +1287 -0
  30. package/dist/esm/node_modules/three/examples/jsm/controls/TransformControls.js +1537 -0
  31. package/dist/esm/node_modules/three/examples/jsm/loaders/GLTFLoader.js +4370 -0
  32. package/dist/esm/node_modules/three/examples/jsm/loaders/RGBELoader.js +461 -0
  33. package/dist/esm/node_modules/three/examples/jsm/utils/BufferGeometryUtils.js +113 -0
  34. package/dist/esm/src/ConnectionManager.js +110 -0
  35. package/dist/esm/src/Pathfinder.js +84 -0
  36. package/dist/esm/src/animationManager.js +112 -0
  37. package/dist/esm/src/componentManager.js +123 -0
  38. package/dist/esm/src/debugLogger.js +167 -0
  39. package/dist/esm/src/disposalManager.js +155 -0
  40. package/dist/esm/src/environmentManager.js +989 -0
  41. package/dist/esm/src/hotReloadManager.js +244 -0
  42. package/dist/esm/src/index.js +117 -0
  43. package/dist/esm/src/keyboardControlsManager.js +196 -0
  44. package/dist/esm/src/modelPreloader.js +337 -0
  45. package/dist/esm/src/nameUtils.js +99 -0
  46. package/dist/esm/src/pathfindingManager.js +295 -0
  47. package/dist/esm/src/performanceMonitor.js +712 -0
  48. package/dist/esm/src/sceneExportManager.js +286 -0
  49. package/dist/esm/src/sceneInitializationManager.js +513 -0
  50. package/dist/esm/src/sceneOperationsManager.js +536 -0
  51. package/dist/esm/src/textureConfig.js +168 -0
  52. package/dist/esm/src/transformControlsManager.js +827 -0
  53. package/dist/index.d.ts +259 -0
  54. package/package.json +53 -0
@@ -0,0 +1,1543 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var THREE = require('three');
6
+
7
+ const _raycaster = new THREE.Raycaster();
8
+
9
+ const _tempVector = new THREE.Vector3();
10
+ const _tempVector2 = new THREE.Vector3();
11
+ const _tempQuaternion = new THREE.Quaternion();
12
+ const _unit = {
13
+ X: new THREE.Vector3( 1, 0, 0 ),
14
+ Y: new THREE.Vector3( 0, 1, 0 ),
15
+ Z: new THREE.Vector3( 0, 0, 1 )
16
+ };
17
+
18
+ const _changeEvent = { type: 'change' };
19
+ const _mouseDownEvent = { type: 'mouseDown' };
20
+ const _mouseUpEvent = { type: 'mouseUp', mode: null };
21
+ const _objectChangeEvent = { type: 'objectChange' };
22
+
23
+ class TransformControls extends THREE.Object3D {
24
+
25
+ constructor( camera, domElement ) {
26
+
27
+ super();
28
+
29
+ if ( domElement === undefined ) {
30
+
31
+ console.warn( 'THREE.TransformControls: The second parameter "domElement" is now mandatory.' );
32
+ domElement = document;
33
+
34
+ }
35
+
36
+ this.isTransformControls = true;
37
+
38
+ this.visible = false;
39
+ this.domElement = domElement;
40
+ this.domElement.style.touchAction = 'none'; // disable touch scroll
41
+
42
+ const _gizmo = new TransformControlsGizmo();
43
+ this._gizmo = _gizmo;
44
+ this.add( _gizmo );
45
+
46
+ const _plane = new TransformControlsPlane();
47
+ this._plane = _plane;
48
+ this.add( _plane );
49
+
50
+ const scope = this;
51
+
52
+ // Defined getter, setter and store for a property
53
+ function defineProperty( propName, defaultValue ) {
54
+
55
+ let propValue = defaultValue;
56
+
57
+ Object.defineProperty( scope, propName, {
58
+
59
+ get: function () {
60
+
61
+ return propValue !== undefined ? propValue : defaultValue;
62
+
63
+ },
64
+
65
+ set: function ( value ) {
66
+
67
+ if ( propValue !== value ) {
68
+
69
+ propValue = value;
70
+ _plane[ propName ] = value;
71
+ _gizmo[ propName ] = value;
72
+
73
+ scope.dispatchEvent( { type: propName + '-changed', value: value } );
74
+ scope.dispatchEvent( _changeEvent );
75
+
76
+ }
77
+
78
+ }
79
+
80
+ } );
81
+
82
+ scope[ propName ] = defaultValue;
83
+ _plane[ propName ] = defaultValue;
84
+ _gizmo[ propName ] = defaultValue;
85
+
86
+ }
87
+
88
+ // Define properties with getters/setter
89
+ // Setting the defined property will automatically trigger change event
90
+ // Defined properties are passed down to gizmo and plane
91
+
92
+ defineProperty( 'camera', camera );
93
+ defineProperty( 'object', undefined );
94
+ defineProperty( 'enabled', true );
95
+ defineProperty( 'axis', null );
96
+ defineProperty( 'mode', 'translate' );
97
+ defineProperty( 'translationSnap', null );
98
+ defineProperty( 'rotationSnap', null );
99
+ defineProperty( 'scaleSnap', null );
100
+ defineProperty( 'space', 'world' );
101
+ defineProperty( 'size', 1 );
102
+ defineProperty( 'dragging', false );
103
+ defineProperty( 'showX', true );
104
+ defineProperty( 'showY', true );
105
+ defineProperty( 'showZ', true );
106
+
107
+ // Reusable utility variables
108
+
109
+ const worldPosition = new THREE.Vector3();
110
+ const worldPositionStart = new THREE.Vector3();
111
+ const worldQuaternion = new THREE.Quaternion();
112
+ const worldQuaternionStart = new THREE.Quaternion();
113
+ const cameraPosition = new THREE.Vector3();
114
+ const cameraQuaternion = new THREE.Quaternion();
115
+ const pointStart = new THREE.Vector3();
116
+ const pointEnd = new THREE.Vector3();
117
+ const rotationAxis = new THREE.Vector3();
118
+ const rotationAngle = 0;
119
+ const eye = new THREE.Vector3();
120
+
121
+ // TODO: remove properties unused in plane and gizmo
122
+
123
+ defineProperty( 'worldPosition', worldPosition );
124
+ defineProperty( 'worldPositionStart', worldPositionStart );
125
+ defineProperty( 'worldQuaternion', worldQuaternion );
126
+ defineProperty( 'worldQuaternionStart', worldQuaternionStart );
127
+ defineProperty( 'cameraPosition', cameraPosition );
128
+ defineProperty( 'cameraQuaternion', cameraQuaternion );
129
+ defineProperty( 'pointStart', pointStart );
130
+ defineProperty( 'pointEnd', pointEnd );
131
+ defineProperty( 'rotationAxis', rotationAxis );
132
+ defineProperty( 'rotationAngle', rotationAngle );
133
+ defineProperty( 'eye', eye );
134
+
135
+ this._offset = new THREE.Vector3();
136
+ this._startNorm = new THREE.Vector3();
137
+ this._endNorm = new THREE.Vector3();
138
+ this._cameraScale = new THREE.Vector3();
139
+
140
+ this._parentPosition = new THREE.Vector3();
141
+ this._parentQuaternion = new THREE.Quaternion();
142
+ this._parentQuaternionInv = new THREE.Quaternion();
143
+ this._parentScale = new THREE.Vector3();
144
+
145
+ this._worldScaleStart = new THREE.Vector3();
146
+ this._worldQuaternionInv = new THREE.Quaternion();
147
+ this._worldScale = new THREE.Vector3();
148
+
149
+ this._positionStart = new THREE.Vector3();
150
+ this._quaternionStart = new THREE.Quaternion();
151
+ this._scaleStart = new THREE.Vector3();
152
+
153
+ this._getPointer = getPointer.bind( this );
154
+ this._onPointerDown = onPointerDown.bind( this );
155
+ this._onPointerHover = onPointerHover.bind( this );
156
+ this._onPointerMove = onPointerMove.bind( this );
157
+ this._onPointerUp = onPointerUp.bind( this );
158
+
159
+ this.domElement.addEventListener( 'pointerdown', this._onPointerDown );
160
+ this.domElement.addEventListener( 'pointermove', this._onPointerHover );
161
+ this.domElement.addEventListener( 'pointerup', this._onPointerUp );
162
+
163
+ }
164
+
165
+ // updateMatrixWorld updates key transformation variables
166
+ updateMatrixWorld() {
167
+
168
+ if ( this.object !== undefined ) {
169
+
170
+ this.object.updateMatrixWorld();
171
+
172
+ if ( this.object.parent === null ) {
173
+
174
+ console.error( 'TransformControls: The attached 3D object must be a part of the scene graph.' );
175
+
176
+ } else {
177
+
178
+ this.object.parent.matrixWorld.decompose( this._parentPosition, this._parentQuaternion, this._parentScale );
179
+
180
+ }
181
+
182
+ this.object.matrixWorld.decompose( this.worldPosition, this.worldQuaternion, this._worldScale );
183
+
184
+ this._parentQuaternionInv.copy( this._parentQuaternion ).invert();
185
+ this._worldQuaternionInv.copy( this.worldQuaternion ).invert();
186
+
187
+ }
188
+
189
+ this.camera.updateMatrixWorld();
190
+ this.camera.matrixWorld.decompose( this.cameraPosition, this.cameraQuaternion, this._cameraScale );
191
+
192
+ if ( this.camera.isOrthographicCamera ) {
193
+
194
+ this.camera.getWorldDirection( this.eye ).negate();
195
+
196
+ } else {
197
+
198
+ this.eye.copy( this.cameraPosition ).sub( this.worldPosition ).normalize();
199
+
200
+ }
201
+
202
+ super.updateMatrixWorld( this );
203
+
204
+ }
205
+
206
+ pointerHover( pointer ) {
207
+
208
+ if ( this.object === undefined || this.dragging === true ) return;
209
+
210
+ _raycaster.setFromCamera( pointer, this.camera );
211
+
212
+ const intersect = intersectObjectWithRay( this._gizmo.picker[ this.mode ], _raycaster );
213
+
214
+ if ( intersect ) {
215
+
216
+ this.axis = intersect.object.name;
217
+
218
+ } else {
219
+
220
+ this.axis = null;
221
+
222
+ }
223
+
224
+ }
225
+
226
+ pointerDown( pointer ) {
227
+
228
+ if ( this.object === undefined || this.dragging === true || pointer.button !== 0 ) return;
229
+
230
+ if ( this.axis !== null ) {
231
+
232
+ _raycaster.setFromCamera( pointer, this.camera );
233
+
234
+ const planeIntersect = intersectObjectWithRay( this._plane, _raycaster, true );
235
+
236
+ if ( planeIntersect ) {
237
+
238
+ this.object.updateMatrixWorld();
239
+ this.object.parent.updateMatrixWorld();
240
+
241
+ this._positionStart.copy( this.object.position );
242
+ this._quaternionStart.copy( this.object.quaternion );
243
+ this._scaleStart.copy( this.object.scale );
244
+
245
+ this.object.matrixWorld.decompose( this.worldPositionStart, this.worldQuaternionStart, this._worldScaleStart );
246
+
247
+ this.pointStart.copy( planeIntersect.point ).sub( this.worldPositionStart );
248
+
249
+ }
250
+
251
+ this.dragging = true;
252
+ _mouseDownEvent.mode = this.mode;
253
+ this.dispatchEvent( _mouseDownEvent );
254
+
255
+ }
256
+
257
+ }
258
+
259
+ pointerMove( pointer ) {
260
+
261
+ const axis = this.axis;
262
+ const mode = this.mode;
263
+ const object = this.object;
264
+ let space = this.space;
265
+
266
+ if ( mode === 'scale' ) {
267
+
268
+ space = 'local';
269
+
270
+ } else if ( axis === 'E' || axis === 'XYZE' || axis === 'XYZ' ) {
271
+
272
+ space = 'world';
273
+
274
+ }
275
+
276
+ if ( object === undefined || axis === null || this.dragging === false || pointer.button !== - 1 ) return;
277
+
278
+ _raycaster.setFromCamera( pointer, this.camera );
279
+
280
+ const planeIntersect = intersectObjectWithRay( this._plane, _raycaster, true );
281
+
282
+ if ( ! planeIntersect ) return;
283
+
284
+ this.pointEnd.copy( planeIntersect.point ).sub( this.worldPositionStart );
285
+
286
+ if ( mode === 'translate' ) {
287
+
288
+ // Apply translate
289
+
290
+ this._offset.copy( this.pointEnd ).sub( this.pointStart );
291
+
292
+ if ( space === 'local' && axis !== 'XYZ' ) {
293
+
294
+ this._offset.applyQuaternion( this._worldQuaternionInv );
295
+
296
+ }
297
+
298
+ if ( axis.indexOf( 'X' ) === - 1 ) this._offset.x = 0;
299
+ if ( axis.indexOf( 'Y' ) === - 1 ) this._offset.y = 0;
300
+ if ( axis.indexOf( 'Z' ) === - 1 ) this._offset.z = 0;
301
+
302
+ if ( space === 'local' && axis !== 'XYZ' ) {
303
+
304
+ this._offset.applyQuaternion( this._quaternionStart ).divide( this._parentScale );
305
+
306
+ } else {
307
+
308
+ this._offset.applyQuaternion( this._parentQuaternionInv ).divide( this._parentScale );
309
+
310
+ }
311
+
312
+ object.position.copy( this._offset ).add( this._positionStart );
313
+
314
+ // Apply translation snap
315
+
316
+ if ( this.translationSnap ) {
317
+
318
+ if ( space === 'local' ) {
319
+
320
+ object.position.applyQuaternion( _tempQuaternion.copy( this._quaternionStart ).invert() );
321
+
322
+ if ( axis.search( 'X' ) !== - 1 ) {
323
+
324
+ object.position.x = Math.round( object.position.x / this.translationSnap ) * this.translationSnap;
325
+
326
+ }
327
+
328
+ if ( axis.search( 'Y' ) !== - 1 ) {
329
+
330
+ object.position.y = Math.round( object.position.y / this.translationSnap ) * this.translationSnap;
331
+
332
+ }
333
+
334
+ if ( axis.search( 'Z' ) !== - 1 ) {
335
+
336
+ object.position.z = Math.round( object.position.z / this.translationSnap ) * this.translationSnap;
337
+
338
+ }
339
+
340
+ object.position.applyQuaternion( this._quaternionStart );
341
+
342
+ }
343
+
344
+ if ( space === 'world' ) {
345
+
346
+ if ( object.parent ) {
347
+
348
+ object.position.add( _tempVector.setFromMatrixPosition( object.parent.matrixWorld ) );
349
+
350
+ }
351
+
352
+ if ( axis.search( 'X' ) !== - 1 ) {
353
+
354
+ object.position.x = Math.round( object.position.x / this.translationSnap ) * this.translationSnap;
355
+
356
+ }
357
+
358
+ if ( axis.search( 'Y' ) !== - 1 ) {
359
+
360
+ object.position.y = Math.round( object.position.y / this.translationSnap ) * this.translationSnap;
361
+
362
+ }
363
+
364
+ if ( axis.search( 'Z' ) !== - 1 ) {
365
+
366
+ object.position.z = Math.round( object.position.z / this.translationSnap ) * this.translationSnap;
367
+
368
+ }
369
+
370
+ if ( object.parent ) {
371
+
372
+ object.position.sub( _tempVector.setFromMatrixPosition( object.parent.matrixWorld ) );
373
+
374
+ }
375
+
376
+ }
377
+
378
+ }
379
+
380
+ } else if ( mode === 'scale' ) {
381
+
382
+ if ( axis.search( 'XYZ' ) !== - 1 ) {
383
+
384
+ let d = this.pointEnd.length() / this.pointStart.length();
385
+
386
+ if ( this.pointEnd.dot( this.pointStart ) < 0 ) d *= - 1;
387
+
388
+ _tempVector2.set( d, d, d );
389
+
390
+ } else {
391
+
392
+ _tempVector.copy( this.pointStart );
393
+ _tempVector2.copy( this.pointEnd );
394
+
395
+ _tempVector.applyQuaternion( this._worldQuaternionInv );
396
+ _tempVector2.applyQuaternion( this._worldQuaternionInv );
397
+
398
+ _tempVector2.divide( _tempVector );
399
+
400
+ if ( axis.search( 'X' ) === - 1 ) {
401
+
402
+ _tempVector2.x = 1;
403
+
404
+ }
405
+
406
+ if ( axis.search( 'Y' ) === - 1 ) {
407
+
408
+ _tempVector2.y = 1;
409
+
410
+ }
411
+
412
+ if ( axis.search( 'Z' ) === - 1 ) {
413
+
414
+ _tempVector2.z = 1;
415
+
416
+ }
417
+
418
+ }
419
+
420
+ // Apply scale
421
+
422
+ object.scale.copy( this._scaleStart ).multiply( _tempVector2 );
423
+
424
+ if ( this.scaleSnap ) {
425
+
426
+ if ( axis.search( 'X' ) !== - 1 ) {
427
+
428
+ object.scale.x = Math.round( object.scale.x / this.scaleSnap ) * this.scaleSnap || this.scaleSnap;
429
+
430
+ }
431
+
432
+ if ( axis.search( 'Y' ) !== - 1 ) {
433
+
434
+ object.scale.y = Math.round( object.scale.y / this.scaleSnap ) * this.scaleSnap || this.scaleSnap;
435
+
436
+ }
437
+
438
+ if ( axis.search( 'Z' ) !== - 1 ) {
439
+
440
+ object.scale.z = Math.round( object.scale.z / this.scaleSnap ) * this.scaleSnap || this.scaleSnap;
441
+
442
+ }
443
+
444
+ }
445
+
446
+ } else if ( mode === 'rotate' ) {
447
+
448
+ this._offset.copy( this.pointEnd ).sub( this.pointStart );
449
+
450
+ const ROTATION_SPEED = 20 / this.worldPosition.distanceTo( _tempVector.setFromMatrixPosition( this.camera.matrixWorld ) );
451
+
452
+ if ( axis === 'E' ) {
453
+
454
+ this.rotationAxis.copy( this.eye );
455
+ this.rotationAngle = this.pointEnd.angleTo( this.pointStart );
456
+
457
+ this._startNorm.copy( this.pointStart ).normalize();
458
+ this._endNorm.copy( this.pointEnd ).normalize();
459
+
460
+ this.rotationAngle *= ( this._endNorm.cross( this._startNorm ).dot( this.eye ) < 0 ? 1 : - 1 );
461
+
462
+ } else if ( axis === 'XYZE' ) {
463
+
464
+ this.rotationAxis.copy( this._offset ).cross( this.eye ).normalize();
465
+ this.rotationAngle = this._offset.dot( _tempVector.copy( this.rotationAxis ).cross( this.eye ) ) * ROTATION_SPEED;
466
+
467
+ } else if ( axis === 'X' || axis === 'Y' || axis === 'Z' ) {
468
+
469
+ this.rotationAxis.copy( _unit[ axis ] );
470
+
471
+ _tempVector.copy( _unit[ axis ] );
472
+
473
+ if ( space === 'local' ) {
474
+
475
+ _tempVector.applyQuaternion( this.worldQuaternion );
476
+
477
+ }
478
+
479
+ this.rotationAngle = this._offset.dot( _tempVector.cross( this.eye ).normalize() ) * ROTATION_SPEED;
480
+
481
+ }
482
+
483
+ // Apply rotation snap
484
+
485
+ if ( this.rotationSnap ) this.rotationAngle = Math.round( this.rotationAngle / this.rotationSnap ) * this.rotationSnap;
486
+
487
+ // Apply rotate
488
+ if ( space === 'local' && axis !== 'E' && axis !== 'XYZE' ) {
489
+
490
+ object.quaternion.copy( this._quaternionStart );
491
+ object.quaternion.multiply( _tempQuaternion.setFromAxisAngle( this.rotationAxis, this.rotationAngle ) ).normalize();
492
+
493
+ } else {
494
+
495
+ this.rotationAxis.applyQuaternion( this._parentQuaternionInv );
496
+ object.quaternion.copy( _tempQuaternion.setFromAxisAngle( this.rotationAxis, this.rotationAngle ) );
497
+ object.quaternion.multiply( this._quaternionStart ).normalize();
498
+
499
+ }
500
+
501
+ }
502
+
503
+ this.dispatchEvent( _changeEvent );
504
+ this.dispatchEvent( _objectChangeEvent );
505
+
506
+ }
507
+
508
+ pointerUp( pointer ) {
509
+
510
+ if ( pointer.button !== 0 ) return;
511
+
512
+ if ( this.dragging && ( this.axis !== null ) ) {
513
+
514
+ _mouseUpEvent.mode = this.mode;
515
+ this.dispatchEvent( _mouseUpEvent );
516
+
517
+ }
518
+
519
+ this.dragging = false;
520
+ this.axis = null;
521
+
522
+ }
523
+
524
+ dispose() {
525
+
526
+ this.domElement.removeEventListener( 'pointerdown', this._onPointerDown );
527
+ this.domElement.removeEventListener( 'pointermove', this._onPointerHover );
528
+ this.domElement.removeEventListener( 'pointermove', this._onPointerMove );
529
+ this.domElement.removeEventListener( 'pointerup', this._onPointerUp );
530
+
531
+ this.traverse( function ( child ) {
532
+
533
+ if ( child.geometry ) child.geometry.dispose();
534
+ if ( child.material ) child.material.dispose();
535
+
536
+ } );
537
+
538
+ }
539
+
540
+ // Set current object
541
+ attach( object ) {
542
+
543
+ this.object = object;
544
+ this.visible = true;
545
+
546
+ return this;
547
+
548
+ }
549
+
550
+ // Detach from object
551
+ detach() {
552
+
553
+ this.object = undefined;
554
+ this.visible = false;
555
+ this.axis = null;
556
+
557
+ return this;
558
+
559
+ }
560
+
561
+ reset() {
562
+
563
+ if ( ! this.enabled ) return;
564
+
565
+ if ( this.dragging ) {
566
+
567
+ this.object.position.copy( this._positionStart );
568
+ this.object.quaternion.copy( this._quaternionStart );
569
+ this.object.scale.copy( this._scaleStart );
570
+
571
+ this.dispatchEvent( _changeEvent );
572
+ this.dispatchEvent( _objectChangeEvent );
573
+
574
+ this.pointStart.copy( this.pointEnd );
575
+
576
+ }
577
+
578
+ }
579
+
580
+ getRaycaster() {
581
+
582
+ return _raycaster;
583
+
584
+ }
585
+
586
+ // TODO: deprecate
587
+
588
+ getMode() {
589
+
590
+ return this.mode;
591
+
592
+ }
593
+
594
+ setMode( mode ) {
595
+
596
+ this.mode = mode;
597
+
598
+ }
599
+
600
+ setTranslationSnap( translationSnap ) {
601
+
602
+ this.translationSnap = translationSnap;
603
+
604
+ }
605
+
606
+ setRotationSnap( rotationSnap ) {
607
+
608
+ this.rotationSnap = rotationSnap;
609
+
610
+ }
611
+
612
+ setScaleSnap( scaleSnap ) {
613
+
614
+ this.scaleSnap = scaleSnap;
615
+
616
+ }
617
+
618
+ setSize( size ) {
619
+
620
+ this.size = size;
621
+
622
+ }
623
+
624
+ setSpace( space ) {
625
+
626
+ this.space = space;
627
+
628
+ }
629
+
630
+ }
631
+
632
+ // mouse / touch event handlers
633
+
634
+ function getPointer( event ) {
635
+
636
+ if ( this.domElement.ownerDocument.pointerLockElement ) {
637
+
638
+ return {
639
+ x: 0,
640
+ y: 0,
641
+ button: event.button
642
+ };
643
+
644
+ } else {
645
+
646
+ const rect = this.domElement.getBoundingClientRect();
647
+
648
+ return {
649
+ x: ( event.clientX - rect.left ) / rect.width * 2 - 1,
650
+ y: - ( event.clientY - rect.top ) / rect.height * 2 + 1,
651
+ button: event.button
652
+ };
653
+
654
+ }
655
+
656
+ }
657
+
658
+ function onPointerHover( event ) {
659
+
660
+ if ( ! this.enabled ) return;
661
+
662
+ switch ( event.pointerType ) {
663
+
664
+ case 'mouse':
665
+ case 'pen':
666
+ this.pointerHover( this._getPointer( event ) );
667
+ break;
668
+
669
+ }
670
+
671
+ }
672
+
673
+ function onPointerDown( event ) {
674
+
675
+ if ( ! this.enabled ) return;
676
+
677
+ if ( ! document.pointerLockElement ) {
678
+
679
+ this.domElement.setPointerCapture( event.pointerId );
680
+
681
+ }
682
+
683
+ this.domElement.addEventListener( 'pointermove', this._onPointerMove );
684
+
685
+ this.pointerHover( this._getPointer( event ) );
686
+ this.pointerDown( this._getPointer( event ) );
687
+
688
+ }
689
+
690
+ function onPointerMove( event ) {
691
+
692
+ if ( ! this.enabled ) return;
693
+
694
+ this.pointerMove( this._getPointer( event ) );
695
+
696
+ }
697
+
698
+ function onPointerUp( event ) {
699
+
700
+ if ( ! this.enabled ) return;
701
+
702
+ this.domElement.releasePointerCapture( event.pointerId );
703
+
704
+ this.domElement.removeEventListener( 'pointermove', this._onPointerMove );
705
+
706
+ this.pointerUp( this._getPointer( event ) );
707
+
708
+ }
709
+
710
+ function intersectObjectWithRay( object, raycaster, includeInvisible ) {
711
+
712
+ const allIntersections = raycaster.intersectObject( object, true );
713
+
714
+ for ( let i = 0; i < allIntersections.length; i ++ ) {
715
+
716
+ if ( allIntersections[ i ].object.visible || includeInvisible ) {
717
+
718
+ return allIntersections[ i ];
719
+
720
+ }
721
+
722
+ }
723
+
724
+ return false;
725
+
726
+ }
727
+
728
+ //
729
+
730
+ // Reusable utility variables
731
+
732
+ const _tempEuler = new THREE.Euler();
733
+ const _alignVector = new THREE.Vector3( 0, 1, 0 );
734
+ const _zeroVector = new THREE.Vector3( 0, 0, 0 );
735
+ const _lookAtMatrix = new THREE.Matrix4();
736
+ const _tempQuaternion2 = new THREE.Quaternion();
737
+ const _identityQuaternion = new THREE.Quaternion();
738
+ const _dirVector = new THREE.Vector3();
739
+ const _tempMatrix = new THREE.Matrix4();
740
+
741
+ const _unitX = new THREE.Vector3( 1, 0, 0 );
742
+ const _unitY = new THREE.Vector3( 0, 1, 0 );
743
+ const _unitZ = new THREE.Vector3( 0, 0, 1 );
744
+
745
+ const _v1 = new THREE.Vector3();
746
+ const _v2 = new THREE.Vector3();
747
+ const _v3 = new THREE.Vector3();
748
+
749
+ class TransformControlsGizmo extends THREE.Object3D {
750
+
751
+ constructor() {
752
+
753
+ super();
754
+
755
+ this.isTransformControlsGizmo = true;
756
+
757
+ this.type = 'TransformControlsGizmo';
758
+
759
+ // shared materials
760
+
761
+ const gizmoMaterial = new THREE.MeshBasicMaterial( {
762
+ depthTest: false,
763
+ depthWrite: false,
764
+ fog: false,
765
+ toneMapped: false,
766
+ transparent: true
767
+ } );
768
+
769
+ const gizmoLineMaterial = new THREE.LineBasicMaterial( {
770
+ depthTest: false,
771
+ depthWrite: false,
772
+ fog: false,
773
+ toneMapped: false,
774
+ transparent: true
775
+ } );
776
+
777
+ // Make unique material for each axis/color
778
+
779
+ const matInvisible = gizmoMaterial.clone();
780
+ matInvisible.opacity = 0.15;
781
+
782
+ const matHelper = gizmoLineMaterial.clone();
783
+ matHelper.opacity = 0.5;
784
+
785
+ const matRed = gizmoMaterial.clone();
786
+ matRed.color.setHex( 0xff0000 );
787
+
788
+ const matGreen = gizmoMaterial.clone();
789
+ matGreen.color.setHex( 0x00ff00 );
790
+
791
+ const matBlue = gizmoMaterial.clone();
792
+ matBlue.color.setHex( 0x0000ff );
793
+
794
+ const matRedTransparent = gizmoMaterial.clone();
795
+ matRedTransparent.color.setHex( 0xff0000 );
796
+ matRedTransparent.opacity = 0.5;
797
+
798
+ const matGreenTransparent = gizmoMaterial.clone();
799
+ matGreenTransparent.color.setHex( 0x00ff00 );
800
+ matGreenTransparent.opacity = 0.5;
801
+
802
+ const matBlueTransparent = gizmoMaterial.clone();
803
+ matBlueTransparent.color.setHex( 0x0000ff );
804
+ matBlueTransparent.opacity = 0.5;
805
+
806
+ const matWhiteTransparent = gizmoMaterial.clone();
807
+ matWhiteTransparent.opacity = 0.25;
808
+
809
+ const matYellowTransparent = gizmoMaterial.clone();
810
+ matYellowTransparent.color.setHex( 0xffff00 );
811
+ matYellowTransparent.opacity = 0.25;
812
+
813
+ const matYellow = gizmoMaterial.clone();
814
+ matYellow.color.setHex( 0xffff00 );
815
+
816
+ const matGray = gizmoMaterial.clone();
817
+ matGray.color.setHex( 0x787878 );
818
+
819
+ // reusable geometry
820
+
821
+ const arrowGeometry = new THREE.CylinderGeometry( 0, 0.04, 0.1, 12 );
822
+ arrowGeometry.translate( 0, 0.05, 0 );
823
+
824
+ const scaleHandleGeometry = new THREE.BoxGeometry( 0.08, 0.08, 0.08 );
825
+ scaleHandleGeometry.translate( 0, 0.04, 0 );
826
+
827
+ const lineGeometry = new THREE.BufferGeometry();
828
+ lineGeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 1, 0, 0 ], 3 ) );
829
+
830
+ const lineGeometry2 = new THREE.CylinderGeometry( 0.0075, 0.0075, 0.5, 3 );
831
+ lineGeometry2.translate( 0, 0.25, 0 );
832
+
833
+ function CircleGeometry( radius, arc ) {
834
+
835
+ const geometry = new THREE.TorusGeometry( radius, 0.0075, 3, 64, arc * Math.PI * 2 );
836
+ geometry.rotateY( Math.PI / 2 );
837
+ geometry.rotateX( Math.PI / 2 );
838
+ return geometry;
839
+
840
+ }
841
+
842
+ // Special geometry for transform helper. If scaled with position vector it spans from [0,0,0] to position
843
+
844
+ function TranslateHelperGeometry() {
845
+
846
+ const geometry = new THREE.BufferGeometry();
847
+
848
+ geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 1, 1, 1 ], 3 ) );
849
+
850
+ return geometry;
851
+
852
+ }
853
+
854
+ // Gizmo definitions - custom hierarchy definitions for setupGizmo() function
855
+
856
+ const gizmoTranslate = {
857
+ X: [
858
+ [ new THREE.Mesh( arrowGeometry, matRed ), [ 0.5, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],
859
+ [ new THREE.Mesh( arrowGeometry, matRed ), [ - 0.5, 0, 0 ], [ 0, 0, Math.PI / 2 ]],
860
+ [ new THREE.Mesh( lineGeometry2, matRed ), [ 0, 0, 0 ], [ 0, 0, - Math.PI / 2 ]]
861
+ ],
862
+ Y: [
863
+ [ new THREE.Mesh( arrowGeometry, matGreen ), [ 0, 0.5, 0 ]],
864
+ [ new THREE.Mesh( arrowGeometry, matGreen ), [ 0, - 0.5, 0 ], [ Math.PI, 0, 0 ]],
865
+ [ new THREE.Mesh( lineGeometry2, matGreen ) ]
866
+ ],
867
+ Z: [
868
+ [ new THREE.Mesh( arrowGeometry, matBlue ), [ 0, 0, 0.5 ], [ Math.PI / 2, 0, 0 ]],
869
+ [ new THREE.Mesh( arrowGeometry, matBlue ), [ 0, 0, - 0.5 ], [ - Math.PI / 2, 0, 0 ]],
870
+ [ new THREE.Mesh( lineGeometry2, matBlue ), null, [ Math.PI / 2, 0, 0 ]]
871
+ ],
872
+ XYZ: [
873
+ [ new THREE.Mesh( new THREE.OctahedronGeometry( 0.1, 0 ), matWhiteTransparent.clone() ), [ 0, 0, 0 ]]
874
+ ],
875
+ XY: [
876
+ [ new THREE.Mesh( new THREE.BoxGeometry( 0.15, 0.15, 0.01 ), matBlueTransparent.clone() ), [ 0.15, 0.15, 0 ]]
877
+ ],
878
+ YZ: [
879
+ [ new THREE.Mesh( new THREE.BoxGeometry( 0.15, 0.15, 0.01 ), matRedTransparent.clone() ), [ 0, 0.15, 0.15 ], [ 0, Math.PI / 2, 0 ]]
880
+ ],
881
+ XZ: [
882
+ [ new THREE.Mesh( new THREE.BoxGeometry( 0.15, 0.15, 0.01 ), matGreenTransparent.clone() ), [ 0.15, 0, 0.15 ], [ - Math.PI / 2, 0, 0 ]]
883
+ ]
884
+ };
885
+
886
+ const pickerTranslate = {
887
+ X: [
888
+ [ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0.3, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],
889
+ [ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ - 0.3, 0, 0 ], [ 0, 0, Math.PI / 2 ]]
890
+ ],
891
+ Y: [
892
+ [ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, 0.3, 0 ]],
893
+ [ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, - 0.3, 0 ], [ 0, 0, Math.PI ]]
894
+ ],
895
+ Z: [
896
+ [ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, 0, 0.3 ], [ Math.PI / 2, 0, 0 ]],
897
+ [ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, 0, - 0.3 ], [ - Math.PI / 2, 0, 0 ]]
898
+ ],
899
+ XYZ: [
900
+ [ new THREE.Mesh( new THREE.OctahedronGeometry( 0.2, 0 ), matInvisible ) ]
901
+ ],
902
+ XY: [
903
+ [ new THREE.Mesh( new THREE.BoxGeometry( 0.2, 0.2, 0.01 ), matInvisible ), [ 0.15, 0.15, 0 ]]
904
+ ],
905
+ YZ: [
906
+ [ new THREE.Mesh( new THREE.BoxGeometry( 0.2, 0.2, 0.01 ), matInvisible ), [ 0, 0.15, 0.15 ], [ 0, Math.PI / 2, 0 ]]
907
+ ],
908
+ XZ: [
909
+ [ new THREE.Mesh( new THREE.BoxGeometry( 0.2, 0.2, 0.01 ), matInvisible ), [ 0.15, 0, 0.15 ], [ - Math.PI / 2, 0, 0 ]]
910
+ ]
911
+ };
912
+
913
+ const helperTranslate = {
914
+ START: [
915
+ [ new THREE.Mesh( new THREE.OctahedronGeometry( 0.01, 2 ), matHelper ), null, null, null, 'helper' ]
916
+ ],
917
+ END: [
918
+ [ new THREE.Mesh( new THREE.OctahedronGeometry( 0.01, 2 ), matHelper ), null, null, null, 'helper' ]
919
+ ],
920
+ DELTA: [
921
+ [ new THREE.Line( TranslateHelperGeometry(), matHelper ), null, null, null, 'helper' ]
922
+ ],
923
+ X: [
924
+ [ new THREE.Line( lineGeometry, matHelper.clone() ), [ - 1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ]
925
+ ],
926
+ Y: [
927
+ [ new THREE.Line( lineGeometry, matHelper.clone() ), [ 0, - 1e3, 0 ], [ 0, 0, Math.PI / 2 ], [ 1e6, 1, 1 ], 'helper' ]
928
+ ],
929
+ Z: [
930
+ [ new THREE.Line( lineGeometry, matHelper.clone() ), [ 0, 0, - 1e3 ], [ 0, - Math.PI / 2, 0 ], [ 1e6, 1, 1 ], 'helper' ]
931
+ ]
932
+ };
933
+
934
+ const gizmoRotate = {
935
+ XYZE: [
936
+ [ new THREE.Mesh( CircleGeometry( 0.5, 1 ), matGray ), null, [ 0, Math.PI / 2, 0 ]]
937
+ ],
938
+ X: [
939
+ [ new THREE.Mesh( CircleGeometry( 0.5, 0.5 ), matRed ) ]
940
+ ],
941
+ Y: [
942
+ [ new THREE.Mesh( CircleGeometry( 0.5, 0.5 ), matGreen ), null, [ 0, 0, - Math.PI / 2 ]]
943
+ ],
944
+ Z: [
945
+ [ new THREE.Mesh( CircleGeometry( 0.5, 0.5 ), matBlue ), null, [ 0, Math.PI / 2, 0 ]]
946
+ ],
947
+ E: [
948
+ [ new THREE.Mesh( CircleGeometry( 0.75, 1 ), matYellowTransparent ), null, [ 0, Math.PI / 2, 0 ]]
949
+ ]
950
+ };
951
+
952
+ const helperRotate = {
953
+ AXIS: [
954
+ [ new THREE.Line( lineGeometry, matHelper.clone() ), [ - 1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ]
955
+ ]
956
+ };
957
+
958
+ const pickerRotate = {
959
+ XYZE: [
960
+ [ new THREE.Mesh( new THREE.SphereGeometry( 0.25, 10, 8 ), matInvisible ) ]
961
+ ],
962
+ X: [
963
+ [ new THREE.Mesh( new THREE.TorusGeometry( 0.5, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ 0, - Math.PI / 2, - Math.PI / 2 ]],
964
+ ],
965
+ Y: [
966
+ [ new THREE.Mesh( new THREE.TorusGeometry( 0.5, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ Math.PI / 2, 0, 0 ]],
967
+ ],
968
+ Z: [
969
+ [ new THREE.Mesh( new THREE.TorusGeometry( 0.5, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],
970
+ ],
971
+ E: [
972
+ [ new THREE.Mesh( new THREE.TorusGeometry( 0.75, 0.1, 2, 24 ), matInvisible ) ]
973
+ ]
974
+ };
975
+
976
+ const gizmoScale = {
977
+ X: [
978
+ [ new THREE.Mesh( scaleHandleGeometry, matRed ), [ 0.5, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],
979
+ [ new THREE.Mesh( lineGeometry2, matRed ), [ 0, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],
980
+ [ new THREE.Mesh( scaleHandleGeometry, matRed ), [ - 0.5, 0, 0 ], [ 0, 0, Math.PI / 2 ]],
981
+ ],
982
+ Y: [
983
+ [ new THREE.Mesh( scaleHandleGeometry, matGreen ), [ 0, 0.5, 0 ]],
984
+ [ new THREE.Mesh( lineGeometry2, matGreen ) ],
985
+ [ new THREE.Mesh( scaleHandleGeometry, matGreen ), [ 0, - 0.5, 0 ], [ 0, 0, Math.PI ]],
986
+ ],
987
+ Z: [
988
+ [ new THREE.Mesh( scaleHandleGeometry, matBlue ), [ 0, 0, 0.5 ], [ Math.PI / 2, 0, 0 ]],
989
+ [ new THREE.Mesh( lineGeometry2, matBlue ), [ 0, 0, 0 ], [ Math.PI / 2, 0, 0 ]],
990
+ [ new THREE.Mesh( scaleHandleGeometry, matBlue ), [ 0, 0, - 0.5 ], [ - Math.PI / 2, 0, 0 ]]
991
+ ],
992
+ XY: [
993
+ [ new THREE.Mesh( new THREE.BoxGeometry( 0.15, 0.15, 0.01 ), matBlueTransparent ), [ 0.15, 0.15, 0 ]]
994
+ ],
995
+ YZ: [
996
+ [ new THREE.Mesh( new THREE.BoxGeometry( 0.15, 0.15, 0.01 ), matRedTransparent ), [ 0, 0.15, 0.15 ], [ 0, Math.PI / 2, 0 ]]
997
+ ],
998
+ XZ: [
999
+ [ new THREE.Mesh( new THREE.BoxGeometry( 0.15, 0.15, 0.01 ), matGreenTransparent ), [ 0.15, 0, 0.15 ], [ - Math.PI / 2, 0, 0 ]]
1000
+ ],
1001
+ XYZ: [
1002
+ [ new THREE.Mesh( new THREE.BoxGeometry( 0.1, 0.1, 0.1 ), matWhiteTransparent.clone() ) ],
1003
+ ]
1004
+ };
1005
+
1006
+ const pickerScale = {
1007
+ X: [
1008
+ [ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0.3, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],
1009
+ [ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ - 0.3, 0, 0 ], [ 0, 0, Math.PI / 2 ]]
1010
+ ],
1011
+ Y: [
1012
+ [ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, 0.3, 0 ]],
1013
+ [ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, - 0.3, 0 ], [ 0, 0, Math.PI ]]
1014
+ ],
1015
+ Z: [
1016
+ [ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, 0, 0.3 ], [ Math.PI / 2, 0, 0 ]],
1017
+ [ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, 0, - 0.3 ], [ - Math.PI / 2, 0, 0 ]]
1018
+ ],
1019
+ XY: [
1020
+ [ new THREE.Mesh( new THREE.BoxGeometry( 0.2, 0.2, 0.01 ), matInvisible ), [ 0.15, 0.15, 0 ]],
1021
+ ],
1022
+ YZ: [
1023
+ [ new THREE.Mesh( new THREE.BoxGeometry( 0.2, 0.2, 0.01 ), matInvisible ), [ 0, 0.15, 0.15 ], [ 0, Math.PI / 2, 0 ]],
1024
+ ],
1025
+ XZ: [
1026
+ [ new THREE.Mesh( new THREE.BoxGeometry( 0.2, 0.2, 0.01 ), matInvisible ), [ 0.15, 0, 0.15 ], [ - Math.PI / 2, 0, 0 ]],
1027
+ ],
1028
+ XYZ: [
1029
+ [ new THREE.Mesh( new THREE.BoxGeometry( 0.2, 0.2, 0.2 ), matInvisible ), [ 0, 0, 0 ]],
1030
+ ]
1031
+ };
1032
+
1033
+ const helperScale = {
1034
+ X: [
1035
+ [ new THREE.Line( lineGeometry, matHelper.clone() ), [ - 1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ]
1036
+ ],
1037
+ Y: [
1038
+ [ new THREE.Line( lineGeometry, matHelper.clone() ), [ 0, - 1e3, 0 ], [ 0, 0, Math.PI / 2 ], [ 1e6, 1, 1 ], 'helper' ]
1039
+ ],
1040
+ Z: [
1041
+ [ new THREE.Line( lineGeometry, matHelper.clone() ), [ 0, 0, - 1e3 ], [ 0, - Math.PI / 2, 0 ], [ 1e6, 1, 1 ], 'helper' ]
1042
+ ]
1043
+ };
1044
+
1045
+ // Creates an Object3D with gizmos described in custom hierarchy definition.
1046
+
1047
+ function setupGizmo( gizmoMap ) {
1048
+
1049
+ const gizmo = new THREE.Object3D();
1050
+
1051
+ for ( const name in gizmoMap ) {
1052
+
1053
+ for ( let i = gizmoMap[ name ].length; i --; ) {
1054
+
1055
+ const object = gizmoMap[ name ][ i ][ 0 ].clone();
1056
+ const position = gizmoMap[ name ][ i ][ 1 ];
1057
+ const rotation = gizmoMap[ name ][ i ][ 2 ];
1058
+ const scale = gizmoMap[ name ][ i ][ 3 ];
1059
+ const tag = gizmoMap[ name ][ i ][ 4 ];
1060
+
1061
+ // name and tag properties are essential for picking and updating logic.
1062
+ object.name = name;
1063
+ object.tag = tag;
1064
+
1065
+ if ( position ) {
1066
+
1067
+ object.position.set( position[ 0 ], position[ 1 ], position[ 2 ] );
1068
+
1069
+ }
1070
+
1071
+ if ( rotation ) {
1072
+
1073
+ object.rotation.set( rotation[ 0 ], rotation[ 1 ], rotation[ 2 ] );
1074
+
1075
+ }
1076
+
1077
+ if ( scale ) {
1078
+
1079
+ object.scale.set( scale[ 0 ], scale[ 1 ], scale[ 2 ] );
1080
+
1081
+ }
1082
+
1083
+ object.updateMatrix();
1084
+
1085
+ const tempGeometry = object.geometry.clone();
1086
+ tempGeometry.applyMatrix4( object.matrix );
1087
+ object.geometry = tempGeometry;
1088
+ object.renderOrder = Infinity;
1089
+
1090
+ object.position.set( 0, 0, 0 );
1091
+ object.rotation.set( 0, 0, 0 );
1092
+ object.scale.set( 1, 1, 1 );
1093
+
1094
+ gizmo.add( object );
1095
+
1096
+ }
1097
+
1098
+ }
1099
+
1100
+ return gizmo;
1101
+
1102
+ }
1103
+
1104
+ // Gizmo creation
1105
+
1106
+ this.gizmo = {};
1107
+ this.picker = {};
1108
+ this.helper = {};
1109
+
1110
+ this.add( this.gizmo[ 'translate' ] = setupGizmo( gizmoTranslate ) );
1111
+ this.add( this.gizmo[ 'rotate' ] = setupGizmo( gizmoRotate ) );
1112
+ this.add( this.gizmo[ 'scale' ] = setupGizmo( gizmoScale ) );
1113
+ this.add( this.picker[ 'translate' ] = setupGizmo( pickerTranslate ) );
1114
+ this.add( this.picker[ 'rotate' ] = setupGizmo( pickerRotate ) );
1115
+ this.add( this.picker[ 'scale' ] = setupGizmo( pickerScale ) );
1116
+ this.add( this.helper[ 'translate' ] = setupGizmo( helperTranslate ) );
1117
+ this.add( this.helper[ 'rotate' ] = setupGizmo( helperRotate ) );
1118
+ this.add( this.helper[ 'scale' ] = setupGizmo( helperScale ) );
1119
+
1120
+ // Pickers should be hidden always
1121
+
1122
+ this.picker[ 'translate' ].visible = false;
1123
+ this.picker[ 'rotate' ].visible = false;
1124
+ this.picker[ 'scale' ].visible = false;
1125
+
1126
+ }
1127
+
1128
+ // updateMatrixWorld will update transformations and appearance of individual handles
1129
+
1130
+ updateMatrixWorld( force ) {
1131
+
1132
+ const space = ( this.mode === 'scale' ) ? 'local' : this.space; // scale always oriented to local rotation
1133
+
1134
+ const quaternion = ( space === 'local' ) ? this.worldQuaternion : _identityQuaternion;
1135
+
1136
+ // Show only gizmos for current transform mode
1137
+
1138
+ this.gizmo[ 'translate' ].visible = this.mode === 'translate';
1139
+ this.gizmo[ 'rotate' ].visible = this.mode === 'rotate';
1140
+ this.gizmo[ 'scale' ].visible = this.mode === 'scale';
1141
+
1142
+ this.helper[ 'translate' ].visible = this.mode === 'translate';
1143
+ this.helper[ 'rotate' ].visible = this.mode === 'rotate';
1144
+ this.helper[ 'scale' ].visible = this.mode === 'scale';
1145
+
1146
+
1147
+ let handles = [];
1148
+ handles = handles.concat( this.picker[ this.mode ].children );
1149
+ handles = handles.concat( this.gizmo[ this.mode ].children );
1150
+ handles = handles.concat( this.helper[ this.mode ].children );
1151
+
1152
+ for ( let i = 0; i < handles.length; i ++ ) {
1153
+
1154
+ const handle = handles[ i ];
1155
+
1156
+ // hide aligned to camera
1157
+
1158
+ handle.visible = true;
1159
+ handle.rotation.set( 0, 0, 0 );
1160
+ handle.position.copy( this.worldPosition );
1161
+
1162
+ let factor;
1163
+
1164
+ if ( this.camera.isOrthographicCamera ) {
1165
+
1166
+ factor = ( this.camera.top - this.camera.bottom ) / this.camera.zoom;
1167
+
1168
+ } else {
1169
+
1170
+ factor = this.worldPosition.distanceTo( this.cameraPosition ) * Math.min( 1.9 * Math.tan( Math.PI * this.camera.fov / 360 ) / this.camera.zoom, 7 );
1171
+
1172
+ }
1173
+
1174
+ handle.scale.set( 1, 1, 1 ).multiplyScalar( factor * this.size / 4 );
1175
+
1176
+ // TODO: simplify helpers and consider decoupling from gizmo
1177
+
1178
+ if ( handle.tag === 'helper' ) {
1179
+
1180
+ handle.visible = false;
1181
+
1182
+ if ( handle.name === 'AXIS' ) {
1183
+
1184
+ handle.visible = !! this.axis;
1185
+
1186
+ if ( this.axis === 'X' ) {
1187
+
1188
+ _tempQuaternion.setFromEuler( _tempEuler.set( 0, 0, 0 ) );
1189
+ handle.quaternion.copy( quaternion ).multiply( _tempQuaternion );
1190
+
1191
+ if ( Math.abs( _alignVector.copy( _unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) {
1192
+
1193
+ handle.visible = false;
1194
+
1195
+ }
1196
+
1197
+ }
1198
+
1199
+ if ( this.axis === 'Y' ) {
1200
+
1201
+ _tempQuaternion.setFromEuler( _tempEuler.set( 0, 0, Math.PI / 2 ) );
1202
+ handle.quaternion.copy( quaternion ).multiply( _tempQuaternion );
1203
+
1204
+ if ( Math.abs( _alignVector.copy( _unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) {
1205
+
1206
+ handle.visible = false;
1207
+
1208
+ }
1209
+
1210
+ }
1211
+
1212
+ if ( this.axis === 'Z' ) {
1213
+
1214
+ _tempQuaternion.setFromEuler( _tempEuler.set( 0, Math.PI / 2, 0 ) );
1215
+ handle.quaternion.copy( quaternion ).multiply( _tempQuaternion );
1216
+
1217
+ if ( Math.abs( _alignVector.copy( _unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) {
1218
+
1219
+ handle.visible = false;
1220
+
1221
+ }
1222
+
1223
+ }
1224
+
1225
+ if ( this.axis === 'XYZE' ) {
1226
+
1227
+ _tempQuaternion.setFromEuler( _tempEuler.set( 0, Math.PI / 2, 0 ) );
1228
+ _alignVector.copy( this.rotationAxis );
1229
+ handle.quaternion.setFromRotationMatrix( _lookAtMatrix.lookAt( _zeroVector, _alignVector, _unitY ) );
1230
+ handle.quaternion.multiply( _tempQuaternion );
1231
+ handle.visible = this.dragging;
1232
+
1233
+ }
1234
+
1235
+ if ( this.axis === 'E' ) {
1236
+
1237
+ handle.visible = false;
1238
+
1239
+ }
1240
+
1241
+
1242
+ } else if ( handle.name === 'START' ) {
1243
+
1244
+ handle.position.copy( this.worldPositionStart );
1245
+ handle.visible = this.dragging;
1246
+
1247
+ } else if ( handle.name === 'END' ) {
1248
+
1249
+ handle.position.copy( this.worldPosition );
1250
+ handle.visible = this.dragging;
1251
+
1252
+ } else if ( handle.name === 'DELTA' ) {
1253
+
1254
+ handle.position.copy( this.worldPositionStart );
1255
+ handle.quaternion.copy( this.worldQuaternionStart );
1256
+ _tempVector.set( 1e-10, 1e-10, 1e-10 ).add( this.worldPositionStart ).sub( this.worldPosition ).multiplyScalar( - 1 );
1257
+ _tempVector.applyQuaternion( this.worldQuaternionStart.clone().invert() );
1258
+ handle.scale.copy( _tempVector );
1259
+ handle.visible = this.dragging;
1260
+
1261
+ } else {
1262
+
1263
+ handle.quaternion.copy( quaternion );
1264
+
1265
+ if ( this.dragging ) {
1266
+
1267
+ handle.position.copy( this.worldPositionStart );
1268
+
1269
+ } else {
1270
+
1271
+ handle.position.copy( this.worldPosition );
1272
+
1273
+ }
1274
+
1275
+ if ( this.axis ) {
1276
+
1277
+ handle.visible = this.axis.search( handle.name ) !== - 1;
1278
+
1279
+ }
1280
+
1281
+ }
1282
+
1283
+ // If updating helper, skip rest of the loop
1284
+ continue;
1285
+
1286
+ }
1287
+
1288
+ // Align handles to current local or world rotation
1289
+
1290
+ handle.quaternion.copy( quaternion );
1291
+
1292
+ if ( this.mode === 'translate' || this.mode === 'scale' ) {
1293
+
1294
+ // Hide translate and scale axis facing the camera
1295
+
1296
+ const AXIS_HIDE_THRESHOLD = 0.99;
1297
+ const PLANE_HIDE_THRESHOLD = 0.2;
1298
+
1299
+ if ( handle.name === 'X' ) {
1300
+
1301
+ if ( Math.abs( _alignVector.copy( _unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_THRESHOLD ) {
1302
+
1303
+ handle.scale.set( 1e-10, 1e-10, 1e-10 );
1304
+ handle.visible = false;
1305
+
1306
+ }
1307
+
1308
+ }
1309
+
1310
+ if ( handle.name === 'Y' ) {
1311
+
1312
+ if ( Math.abs( _alignVector.copy( _unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_THRESHOLD ) {
1313
+
1314
+ handle.scale.set( 1e-10, 1e-10, 1e-10 );
1315
+ handle.visible = false;
1316
+
1317
+ }
1318
+
1319
+ }
1320
+
1321
+ if ( handle.name === 'Z' ) {
1322
+
1323
+ if ( Math.abs( _alignVector.copy( _unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_THRESHOLD ) {
1324
+
1325
+ handle.scale.set( 1e-10, 1e-10, 1e-10 );
1326
+ handle.visible = false;
1327
+
1328
+ }
1329
+
1330
+ }
1331
+
1332
+ if ( handle.name === 'XY' ) {
1333
+
1334
+ if ( Math.abs( _alignVector.copy( _unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_THRESHOLD ) {
1335
+
1336
+ handle.scale.set( 1e-10, 1e-10, 1e-10 );
1337
+ handle.visible = false;
1338
+
1339
+ }
1340
+
1341
+ }
1342
+
1343
+ if ( handle.name === 'YZ' ) {
1344
+
1345
+ if ( Math.abs( _alignVector.copy( _unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_THRESHOLD ) {
1346
+
1347
+ handle.scale.set( 1e-10, 1e-10, 1e-10 );
1348
+ handle.visible = false;
1349
+
1350
+ }
1351
+
1352
+ }
1353
+
1354
+ if ( handle.name === 'XZ' ) {
1355
+
1356
+ if ( Math.abs( _alignVector.copy( _unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_THRESHOLD ) {
1357
+
1358
+ handle.scale.set( 1e-10, 1e-10, 1e-10 );
1359
+ handle.visible = false;
1360
+
1361
+ }
1362
+
1363
+ }
1364
+
1365
+ } else if ( this.mode === 'rotate' ) {
1366
+
1367
+ // Align handles to current local or world rotation
1368
+
1369
+ _tempQuaternion2.copy( quaternion );
1370
+ _alignVector.copy( this.eye ).applyQuaternion( _tempQuaternion.copy( quaternion ).invert() );
1371
+
1372
+ if ( handle.name.search( 'E' ) !== - 1 ) {
1373
+
1374
+ handle.quaternion.setFromRotationMatrix( _lookAtMatrix.lookAt( this.eye, _zeroVector, _unitY ) );
1375
+
1376
+ }
1377
+
1378
+ if ( handle.name === 'X' ) {
1379
+
1380
+ _tempQuaternion.setFromAxisAngle( _unitX, Math.atan2( - _alignVector.y, _alignVector.z ) );
1381
+ _tempQuaternion.multiplyQuaternions( _tempQuaternion2, _tempQuaternion );
1382
+ handle.quaternion.copy( _tempQuaternion );
1383
+
1384
+ }
1385
+
1386
+ if ( handle.name === 'Y' ) {
1387
+
1388
+ _tempQuaternion.setFromAxisAngle( _unitY, Math.atan2( _alignVector.x, _alignVector.z ) );
1389
+ _tempQuaternion.multiplyQuaternions( _tempQuaternion2, _tempQuaternion );
1390
+ handle.quaternion.copy( _tempQuaternion );
1391
+
1392
+ }
1393
+
1394
+ if ( handle.name === 'Z' ) {
1395
+
1396
+ _tempQuaternion.setFromAxisAngle( _unitZ, Math.atan2( _alignVector.y, _alignVector.x ) );
1397
+ _tempQuaternion.multiplyQuaternions( _tempQuaternion2, _tempQuaternion );
1398
+ handle.quaternion.copy( _tempQuaternion );
1399
+
1400
+ }
1401
+
1402
+ }
1403
+
1404
+ // Hide disabled axes
1405
+ handle.visible = handle.visible && ( handle.name.indexOf( 'X' ) === - 1 || this.showX );
1406
+ handle.visible = handle.visible && ( handle.name.indexOf( 'Y' ) === - 1 || this.showY );
1407
+ handle.visible = handle.visible && ( handle.name.indexOf( 'Z' ) === - 1 || this.showZ );
1408
+ handle.visible = handle.visible && ( handle.name.indexOf( 'E' ) === - 1 || ( this.showX && this.showY && this.showZ ) );
1409
+
1410
+ // highlight selected axis
1411
+
1412
+ handle.material._color = handle.material._color || handle.material.color.clone();
1413
+ handle.material._opacity = handle.material._opacity || handle.material.opacity;
1414
+
1415
+ handle.material.color.copy( handle.material._color );
1416
+ handle.material.opacity = handle.material._opacity;
1417
+
1418
+ if ( this.enabled && this.axis ) {
1419
+
1420
+ if ( handle.name === this.axis ) {
1421
+
1422
+ handle.material.color.setHex( 0xffff00 );
1423
+ handle.material.opacity = 1.0;
1424
+
1425
+ } else if ( this.axis.split( '' ).some( function ( a ) {
1426
+
1427
+ return handle.name === a;
1428
+
1429
+ } ) ) {
1430
+
1431
+ handle.material.color.setHex( 0xffff00 );
1432
+ handle.material.opacity = 1.0;
1433
+
1434
+ }
1435
+
1436
+ }
1437
+
1438
+ }
1439
+
1440
+ super.updateMatrixWorld( force );
1441
+
1442
+ }
1443
+
1444
+ }
1445
+
1446
+ //
1447
+
1448
+ class TransformControlsPlane extends THREE.Mesh {
1449
+
1450
+ constructor() {
1451
+
1452
+ super(
1453
+ new THREE.PlaneGeometry( 100000, 100000, 2, 2 ),
1454
+ new THREE.MeshBasicMaterial( { visible: false, wireframe: true, side: THREE.DoubleSide, transparent: true, opacity: 0.1, toneMapped: false } )
1455
+ );
1456
+
1457
+ this.isTransformControlsPlane = true;
1458
+
1459
+ this.type = 'TransformControlsPlane';
1460
+
1461
+ }
1462
+
1463
+ updateMatrixWorld( force ) {
1464
+
1465
+ let space = this.space;
1466
+
1467
+ this.position.copy( this.worldPosition );
1468
+
1469
+ if ( this.mode === 'scale' ) space = 'local'; // scale always oriented to local rotation
1470
+
1471
+ _v1.copy( _unitX ).applyQuaternion( space === 'local' ? this.worldQuaternion : _identityQuaternion );
1472
+ _v2.copy( _unitY ).applyQuaternion( space === 'local' ? this.worldQuaternion : _identityQuaternion );
1473
+ _v3.copy( _unitZ ).applyQuaternion( space === 'local' ? this.worldQuaternion : _identityQuaternion );
1474
+
1475
+ // Align the plane for current transform mode, axis and space.
1476
+
1477
+ _alignVector.copy( _v2 );
1478
+
1479
+ switch ( this.mode ) {
1480
+
1481
+ case 'translate':
1482
+ case 'scale':
1483
+ switch ( this.axis ) {
1484
+
1485
+ case 'X':
1486
+ _alignVector.copy( this.eye ).cross( _v1 );
1487
+ _dirVector.copy( _v1 ).cross( _alignVector );
1488
+ break;
1489
+ case 'Y':
1490
+ _alignVector.copy( this.eye ).cross( _v2 );
1491
+ _dirVector.copy( _v2 ).cross( _alignVector );
1492
+ break;
1493
+ case 'Z':
1494
+ _alignVector.copy( this.eye ).cross( _v3 );
1495
+ _dirVector.copy( _v3 ).cross( _alignVector );
1496
+ break;
1497
+ case 'XY':
1498
+ _dirVector.copy( _v3 );
1499
+ break;
1500
+ case 'YZ':
1501
+ _dirVector.copy( _v1 );
1502
+ break;
1503
+ case 'XZ':
1504
+ _alignVector.copy( _v3 );
1505
+ _dirVector.copy( _v2 );
1506
+ break;
1507
+ case 'XYZ':
1508
+ case 'E':
1509
+ _dirVector.set( 0, 0, 0 );
1510
+ break;
1511
+
1512
+ }
1513
+
1514
+ break;
1515
+ case 'rotate':
1516
+ default:
1517
+ // special case for rotate
1518
+ _dirVector.set( 0, 0, 0 );
1519
+
1520
+ }
1521
+
1522
+ if ( _dirVector.length() === 0 ) {
1523
+
1524
+ // If in rotate mode, make the plane parallel to camera
1525
+ this.quaternion.copy( this.cameraQuaternion );
1526
+
1527
+ } else {
1528
+
1529
+ _tempMatrix.lookAt( _tempVector.set( 0, 0, 0 ), _dirVector, _alignVector );
1530
+
1531
+ this.quaternion.setFromRotationMatrix( _tempMatrix );
1532
+
1533
+ }
1534
+
1535
+ super.updateMatrixWorld( force );
1536
+
1537
+ }
1538
+
1539
+ }
1540
+
1541
+ exports.TransformControls = TransformControls;
1542
+ exports.TransformControlsGizmo = TransformControlsGizmo;
1543
+ exports.TransformControlsPlane = TransformControlsPlane;