senangwebs-aframe-editor 1.6.5

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 (104) hide show
  1. package/.babelrc +3 -0
  2. package/.editorconfig +12 -0
  3. package/.eslintignore +2 -0
  4. package/.eslintrc +40 -0
  5. package/.github/workflows/ci.yml +39 -0
  6. package/.husky/pre-commit +4 -0
  7. package/.prettierignore +1 -0
  8. package/.prettierrc.json +5 -0
  9. package/.stylelintrc +12 -0
  10. package/LICENSE +21 -0
  11. package/README.md +75 -0
  12. package/assets/gltf.svg +49 -0
  13. package/dist/aframe-inspector.js +106250 -0
  14. package/dist/aframe-inspector.js.map +1 -0
  15. package/dist/aframe-inspector.min.js +29040 -0
  16. package/dist/aframe-inspector.min.js.LICENSE.txt +56 -0
  17. package/dist/aframe-inspector.min.js.map +1 -0
  18. package/examples/360video.html +48 -0
  19. package/examples/colors.html +18 -0
  20. package/examples/controllers.html +60 -0
  21. package/examples/embedded-zoom.html +78 -0
  22. package/examples/embedded.html +79 -0
  23. package/examples/empty.html +13 -0
  24. package/examples/index-aframe.html +66 -0
  25. package/examples/index.html +71 -0
  26. package/examples/supercraft.html +6 -0
  27. package/index.html +8 -0
  28. package/package.json +84 -0
  29. package/senangwebs-webverse-editor.png +0 -0
  30. package/src/components/AwesomeIcon.js +53 -0
  31. package/src/components/Collapsible.js +57 -0
  32. package/src/components/EntityRepresentation.js +83 -0
  33. package/src/components/Main.js +222 -0
  34. package/src/components/__tests__/Collapsible.test.js +30 -0
  35. package/src/components/components/AddComponent.js +104 -0
  36. package/src/components/components/CommonComponents.js +160 -0
  37. package/src/components/components/Component.js +151 -0
  38. package/src/components/components/ComponentsContainer.js +52 -0
  39. package/src/components/components/DefaultComponents.js +1 -0
  40. package/src/components/components/Mixins.js +83 -0
  41. package/src/components/components/PropertyRow.js +145 -0
  42. package/src/components/components/Sidebar.js +51 -0
  43. package/src/components/icons/BackViewIcon.js +27 -0
  44. package/src/components/icons/BottomViewIcon.js +26 -0
  45. package/src/components/icons/FrontViewIcon.js +23 -0
  46. package/src/components/icons/LeftViewIcon.js +24 -0
  47. package/src/components/icons/PerspectiveIcon.js +23 -0
  48. package/src/components/icons/PrimitiveBoxIcon.js +143 -0
  49. package/src/components/icons/PrimitiveConeIcon.js +44 -0
  50. package/src/components/icons/PrimitiveCylinderIcon.js +51 -0
  51. package/src/components/icons/PrimitiveEmptyEntityIcon.js +78 -0
  52. package/src/components/icons/PrimitiveImageIcon.js +86 -0
  53. package/src/components/icons/PrimitiveLightIcon.js +107 -0
  54. package/src/components/icons/PrimitivePlaneIcon.js +87 -0
  55. package/src/components/icons/PrimitiveSphereIcon.js +39 -0
  56. package/src/components/icons/PrimitiveTextIcon.js +89 -0
  57. package/src/components/icons/PrimitiveTorusIcon.js +31 -0
  58. package/src/components/icons/RightViewIcon.js +24 -0
  59. package/src/components/icons/TopViewIcon.js +24 -0
  60. package/src/components/modals/Modal.js +107 -0
  61. package/src/components/modals/ModalHelp.js +97 -0
  62. package/src/components/modals/ModalPrimitive.js +114 -0
  63. package/src/components/modals/ModalTextures.js +430 -0
  64. package/src/components/scenegraph/Entity.js +142 -0
  65. package/src/components/scenegraph/SceneGraph.js +337 -0
  66. package/src/components/scenegraph/Toolbar.js +147 -0
  67. package/src/components/viewport/CameraToolbar.js +122 -0
  68. package/src/components/viewport/TransformToolbar.js +102 -0
  69. package/src/components/viewport/ViewportHUD.js +33 -0
  70. package/src/components/widgets/BooleanWidget.js +49 -0
  71. package/src/components/widgets/ColorWidget.js +89 -0
  72. package/src/components/widgets/InputWidget.js +42 -0
  73. package/src/components/widgets/NumberWidget.js +179 -0
  74. package/src/components/widgets/SelectWidget.js +58 -0
  75. package/src/components/widgets/TextureWidget.js +252 -0
  76. package/src/components/widgets/Vec2Widget.js +55 -0
  77. package/src/components/widgets/Vec3Widget.js +58 -0
  78. package/src/components/widgets/Vec4Widget.js +61 -0
  79. package/src/components/widgets/index.js +9 -0
  80. package/src/index.js +301 -0
  81. package/src/lib/EditorControls.js +336 -0
  82. package/src/lib/Events.js +6 -0
  83. package/src/lib/TransformControls.js +1365 -0
  84. package/src/lib/assetsLoader.js +43 -0
  85. package/src/lib/assetsUtils.js +30 -0
  86. package/src/lib/cameras.js +121 -0
  87. package/src/lib/entity.js +556 -0
  88. package/src/lib/history.js +30 -0
  89. package/src/lib/raycaster.js +129 -0
  90. package/src/lib/shortcuts.js +211 -0
  91. package/src/lib/utils.js +118 -0
  92. package/src/lib/viewport.js +268 -0
  93. package/src/style/components.styl +275 -0
  94. package/src/style/entity.styl +22 -0
  95. package/src/style/help.styl +40 -0
  96. package/src/style/index.styl +358 -0
  97. package/src/style/lib.styl +41 -0
  98. package/src/style/primitiveModal.styl +90 -0
  99. package/src/style/scenegraph.styl +173 -0
  100. package/src/style/select.styl +71 -0
  101. package/src/style/textureModal.styl +220 -0
  102. package/src/style/viewport.styl +168 -0
  103. package/src/style/widgets.styl +71 -0
  104. package/webpack.config.js +65 -0
@@ -0,0 +1,1365 @@
1
+ /* eslint-disable curly, dot-notation */
2
+ /**
3
+ * @author arodic / https://github.com/arodic
4
+ */
5
+
6
+ (function() {
7
+ 'use strict';
8
+
9
+ class GizmoMaterial extends THREE.MeshBasicMaterial {
10
+ constructor(parameters) {
11
+ super();
12
+
13
+ this.depthTest = false;
14
+ this.depthWrite = false;
15
+ this.fog = false;
16
+ this.side = THREE.FrontSide;
17
+ this.transparent = true;
18
+
19
+ this.setValues(parameters);
20
+
21
+ this.oldColor = this.color.clone();
22
+ this.oldOpacity = this.opacity;
23
+
24
+ this.highlight = function(highlighted) {
25
+ if (highlighted) {
26
+ this.color.setRGB(1, 1, 0);
27
+ this.opacity = 1;
28
+ } else {
29
+ this.color.copy(this.oldColor);
30
+ this.opacity = this.oldOpacity;
31
+ }
32
+ };
33
+ }
34
+ }
35
+
36
+ class GizmoLineMaterial extends THREE.LineBasicMaterial {
37
+ constructor(parameters) {
38
+ super();
39
+
40
+ this.depthTest = false;
41
+ this.depthWrite = false;
42
+ this.fog = false;
43
+ this.transparent = true;
44
+ this.linewidth = 1;
45
+
46
+ this.setValues(parameters);
47
+
48
+ this.oldColor = this.color.clone();
49
+ this.oldOpacity = this.opacity;
50
+
51
+ this.highlight = function(highlighted) {
52
+ if (highlighted) {
53
+ this.color.setRGB(1, 1, 0);
54
+ this.opacity = 1;
55
+ } else {
56
+ this.color.copy(this.oldColor);
57
+ this.opacity = this.oldOpacity;
58
+ }
59
+ };
60
+ }
61
+ }
62
+
63
+ var pickerMaterial = new GizmoMaterial({
64
+ visible: false,
65
+ transparent: false
66
+ });
67
+
68
+ THREE.TransformGizmo = class TransformGizmo extends THREE.Object3D {
69
+ init() {
70
+ this.handles = new THREE.Object3D();
71
+ this.pickers = new THREE.Object3D();
72
+ this.planes = new THREE.Object3D();
73
+
74
+ this.add(this.handles);
75
+ this.add(this.pickers);
76
+ this.add(this.planes);
77
+
78
+ // PLANES
79
+
80
+ var planeGeometry = new THREE.PlaneGeometry(50, 50, 2, 2);
81
+ var planeMaterial = new THREE.MeshBasicMaterial({
82
+ visible: false,
83
+ side: THREE.DoubleSide
84
+ });
85
+
86
+ var planes = {
87
+ XY: new THREE.Mesh(planeGeometry, planeMaterial),
88
+ YZ: new THREE.Mesh(planeGeometry, planeMaterial),
89
+ XZ: new THREE.Mesh(planeGeometry, planeMaterial),
90
+ XYZE: new THREE.Mesh(planeGeometry, planeMaterial)
91
+ };
92
+
93
+ this.activePlane = planes['XYZE'];
94
+
95
+ planes['YZ'].rotation.set(0, Math.PI / 2, 0);
96
+ planes['XZ'].rotation.set(-Math.PI / 2, 0, 0);
97
+
98
+ for (var i in planes) {
99
+ planes[i].name = i;
100
+ this.planes.add(planes[i]);
101
+ this.planes[i] = planes[i];
102
+ }
103
+
104
+ // HANDLES AND PICKERS
105
+
106
+ var setupGizmos = function(gizmoMap, parent) {
107
+ for (var name in gizmoMap) {
108
+ for (i = gizmoMap[name].length; i--;) {
109
+ var object = gizmoMap[name][i][0];
110
+ var position = gizmoMap[name][i][1];
111
+ var rotation = gizmoMap[name][i][2];
112
+
113
+ object.name = name;
114
+
115
+ object.renderOrder = Infinity; // avoid being hidden by other transparent objects
116
+
117
+ if (position)
118
+ object.position.set(position[0], position[1], position[2]);
119
+ if (rotation)
120
+ object.rotation.set(rotation[0], rotation[1], rotation[2]);
121
+
122
+ parent.add(object);
123
+ }
124
+ }
125
+ };
126
+
127
+ setupGizmos(this.handleGizmos, this.handles);
128
+ setupGizmos(this.pickerGizmos, this.pickers);
129
+
130
+ // reset Transformations
131
+
132
+ this.traverse(function(child) {
133
+ if (child instanceof THREE.Mesh) {
134
+ child.updateMatrix();
135
+
136
+ var tempGeometry = child.geometry.clone();
137
+ tempGeometry.applyMatrix4(child.matrix);
138
+ child.geometry = tempGeometry;
139
+
140
+ child.position.set(0, 0, 0);
141
+ child.rotation.set(0, 0, 0);
142
+ child.scale.set(1, 1, 1);
143
+ }
144
+ });
145
+ }
146
+
147
+ highlight(axis) {
148
+ this.traverse(function(child) {
149
+ if (child.material && child.material.highlight) {
150
+ if (child.name === axis) {
151
+ child.material.highlight(true);
152
+ } else {
153
+ child.material.highlight(false);
154
+ }
155
+ }
156
+ });
157
+ }
158
+
159
+ update(rotation, eye) {
160
+ var vec1 = new THREE.Vector3(0, 0, 0);
161
+ var vec2 = new THREE.Vector3(0, 1, 0);
162
+ var lookAtMatrix = new THREE.Matrix4();
163
+
164
+ this.traverse(function(child) {
165
+ if (child.name.search('E') !== -1) {
166
+ child.quaternion.setFromRotationMatrix(
167
+ lookAtMatrix.lookAt(eye, vec1, vec2)
168
+ );
169
+ } else if (
170
+ child.name.search('X') !== -1 ||
171
+ child.name.search('Y') !== -1 ||
172
+ child.name.search('Z') !== -1
173
+ ) {
174
+ child.quaternion.setFromEuler(rotation);
175
+ }
176
+ });
177
+ }
178
+ };
179
+
180
+ THREE.TransformGizmoTranslate = class TransformGizmoTranslate extends THREE.TransformGizmo {
181
+ constructor() {
182
+ super();
183
+
184
+ var arrowGeometry = new THREE.ConeGeometry(0.05, 0.2, 12, 1, false);
185
+ arrowGeometry.translate(0, 0.5, 0);
186
+
187
+ var lineXGeometry = new THREE.BufferGeometry();
188
+ lineXGeometry.setAttribute(
189
+ 'position',
190
+ new THREE.Float32BufferAttribute([0, 0, 0, 1, 0, 0], 3)
191
+ );
192
+
193
+ var lineYGeometry = new THREE.BufferGeometry();
194
+ lineYGeometry.setAttribute(
195
+ 'position',
196
+ new THREE.Float32BufferAttribute([0, 0, 0, 0, 1, 0], 3)
197
+ );
198
+
199
+ var lineZGeometry = new THREE.BufferGeometry();
200
+ lineZGeometry.setAttribute(
201
+ 'position',
202
+ new THREE.Float32BufferAttribute([0, 0, 0, 0, 0, 1], 3)
203
+ );
204
+
205
+ this.handleGizmos = {
206
+ X: [
207
+ [
208
+ new THREE.Mesh(arrowGeometry, new GizmoMaterial({ color: 0xff0000 })),
209
+ [0.5, 0, 0],
210
+ [0, 0, -Math.PI / 2]
211
+ ],
212
+ [
213
+ new THREE.Line(
214
+ lineXGeometry,
215
+ new GizmoLineMaterial({ color: 0xff0000 })
216
+ )
217
+ ]
218
+ ],
219
+
220
+ Y: [
221
+ [
222
+ new THREE.Mesh(arrowGeometry, new GizmoMaterial({ color: 0x00ff00 })),
223
+ [0, 0.5, 0]
224
+ ],
225
+ [
226
+ new THREE.Line(
227
+ lineYGeometry,
228
+ new GizmoLineMaterial({ color: 0x00ff00 })
229
+ )
230
+ ]
231
+ ],
232
+
233
+ Z: [
234
+ [
235
+ new THREE.Mesh(arrowGeometry, new GizmoMaterial({ color: 0x0000ff })),
236
+ [0, 0, 0.5],
237
+ [Math.PI / 2, 0, 0]
238
+ ],
239
+ [
240
+ new THREE.Line(
241
+ lineZGeometry,
242
+ new GizmoLineMaterial({ color: 0x0000ff })
243
+ )
244
+ ]
245
+ ],
246
+
247
+ XYZ: [
248
+ [
249
+ new THREE.Mesh(
250
+ new THREE.OctahedronGeometry(0.1, 0),
251
+ new GizmoMaterial({ color: 0xffffff, opacity: 0.25 })
252
+ ),
253
+ [0, 0, 0],
254
+ [0, 0, 0]
255
+ ]
256
+ ],
257
+
258
+ XY: [
259
+ [
260
+ new THREE.Mesh(
261
+ new THREE.PlaneGeometry(0.29, 0.29),
262
+ new GizmoMaterial({ color: 0xffff00, opacity: 0.25 })
263
+ ),
264
+ [0.15, 0.15, 0]
265
+ ]
266
+ ],
267
+
268
+ YZ: [
269
+ [
270
+ new THREE.Mesh(
271
+ new THREE.PlaneGeometry(0.29, 0.29),
272
+ new GizmoMaterial({ color: 0x00ffff, opacity: 0.25 })
273
+ ),
274
+ [0, 0.15, 0.15],
275
+ [0, Math.PI / 2, 0]
276
+ ]
277
+ ],
278
+
279
+ XZ: [
280
+ [
281
+ new THREE.Mesh(
282
+ new THREE.PlaneGeometry(0.29, 0.29),
283
+ new GizmoMaterial({ color: 0xff00ff, opacity: 0.25 })
284
+ ),
285
+ [0.15, 0, 0.15],
286
+ [-Math.PI / 2, 0, 0]
287
+ ]
288
+ ]
289
+ };
290
+
291
+ this.pickerGizmos = {
292
+ X: [
293
+ [
294
+ new THREE.Mesh(
295
+ new THREE.CylinderGeometry(0.2, 0, 1, 4, 1, false),
296
+ pickerMaterial
297
+ ),
298
+ [0.6, 0, 0],
299
+ [0, 0, -Math.PI / 2]
300
+ ]
301
+ ],
302
+
303
+ Y: [
304
+ [
305
+ new THREE.Mesh(
306
+ new THREE.CylinderGeometry(0.2, 0, 1, 4, 1, false),
307
+ pickerMaterial
308
+ ),
309
+ [0, 0.6, 0]
310
+ ]
311
+ ],
312
+
313
+ Z: [
314
+ [
315
+ new THREE.Mesh(
316
+ new THREE.CylinderGeometry(0.2, 0, 1, 4, 1, false),
317
+ pickerMaterial
318
+ ),
319
+ [0, 0, 0.6],
320
+ [Math.PI / 2, 0, 0]
321
+ ]
322
+ ],
323
+
324
+ XYZ: [
325
+ [new THREE.Mesh(new THREE.OctahedronGeometry(0.2, 0), pickerMaterial)]
326
+ ],
327
+
328
+ XY: [
329
+ [
330
+ new THREE.Mesh(
331
+ new THREE.PlaneGeometry(0.4, 0.4),
332
+ pickerMaterial
333
+ ),
334
+ [0.2, 0.2, 0]
335
+ ]
336
+ ],
337
+
338
+ YZ: [
339
+ [
340
+ new THREE.Mesh(
341
+ new THREE.PlaneGeometry(0.4, 0.4),
342
+ pickerMaterial
343
+ ),
344
+ [0, 0.2, 0.2],
345
+ [0, Math.PI / 2, 0]
346
+ ]
347
+ ],
348
+
349
+ XZ: [
350
+ [
351
+ new THREE.Mesh(
352
+ new THREE.PlaneGeometry(0.4, 0.4),
353
+ pickerMaterial
354
+ ),
355
+ [0.2, 0, 0.2],
356
+ [-Math.PI / 2, 0, 0]
357
+ ]
358
+ ]
359
+ };
360
+
361
+ this.init();
362
+ }
363
+
364
+ setActivePlane(axis, eye) {
365
+ var tempMatrix = new THREE.Matrix4();
366
+ eye.applyMatrix4(
367
+ tempMatrix
368
+ .copy(tempMatrix.extractRotation(this.planes['XY'].matrixWorld))
369
+ .invert()
370
+ );
371
+
372
+ if (axis === 'X') {
373
+ this.activePlane = this.planes['XY'];
374
+
375
+ if (Math.abs(eye.y) > Math.abs(eye.z))
376
+ this.activePlane = this.planes['XZ'];
377
+ }
378
+
379
+ if (axis === 'Y') {
380
+ this.activePlane = this.planes['XY'];
381
+
382
+ if (Math.abs(eye.x) > Math.abs(eye.z))
383
+ this.activePlane = this.planes['YZ'];
384
+ }
385
+
386
+ if (axis === 'Z') {
387
+ this.activePlane = this.planes['XZ'];
388
+
389
+ if (Math.abs(eye.x) > Math.abs(eye.y))
390
+ this.activePlane = this.planes['YZ'];
391
+ }
392
+
393
+ if (axis === 'XYZ') this.activePlane = this.planes['XYZE'];
394
+
395
+ if (axis === 'XY') this.activePlane = this.planes['XY'];
396
+
397
+ if (axis === 'YZ') this.activePlane = this.planes['YZ'];
398
+
399
+ if (axis === 'XZ') this.activePlane = this.planes['XZ'];
400
+ }
401
+ };
402
+
403
+ THREE.TransformGizmoRotate = class TransformGizmoRotate extends THREE.TransformGizmo {
404
+ constructor() {
405
+ super();
406
+
407
+ var CircleGeometry = function(radius, facing, arc) {
408
+ var geometry = new THREE.BufferGeometry();
409
+ var vertices = [];
410
+ arc = arc || 1;
411
+
412
+ for (var i = 0; i <= 64 * arc; ++i) {
413
+ if (facing === 'x')
414
+ vertices.push(
415
+ 0,
416
+ Math.cos((i / 32) * Math.PI) * radius,
417
+ Math.sin((i / 32) * Math.PI) * radius
418
+ );
419
+ if (facing === 'y')
420
+ vertices.push(
421
+ Math.cos((i / 32) * Math.PI) * radius,
422
+ 0,
423
+ Math.sin((i / 32) * Math.PI) * radius
424
+ );
425
+ if (facing === 'z')
426
+ vertices.push(
427
+ Math.sin((i / 32) * Math.PI) * radius,
428
+ Math.cos((i / 32) * Math.PI) * radius,
429
+ 0
430
+ );
431
+ }
432
+
433
+ geometry.setAttribute(
434
+ 'position',
435
+ new THREE.Float32BufferAttribute(vertices, 3)
436
+ );
437
+ return geometry;
438
+ };
439
+
440
+ this.handleGizmos = {
441
+ X: [
442
+ [
443
+ new THREE.Line(
444
+ new CircleGeometry(1, 'x', 0.5),
445
+ new GizmoLineMaterial({ color: 0xff0000 })
446
+ )
447
+ ]
448
+ ],
449
+
450
+ Y: [
451
+ [
452
+ new THREE.Line(
453
+ new CircleGeometry(1, 'y', 0.5),
454
+ new GizmoLineMaterial({ color: 0x00ff00 })
455
+ )
456
+ ]
457
+ ],
458
+
459
+ Z: [
460
+ [
461
+ new THREE.Line(
462
+ new CircleGeometry(1, 'z', 0.5),
463
+ new GizmoLineMaterial({ color: 0x0000ff })
464
+ )
465
+ ]
466
+ ],
467
+
468
+ E: [
469
+ [
470
+ new THREE.Line(
471
+ new CircleGeometry(1.25, 'z', 1),
472
+ new GizmoLineMaterial({ color: 0xcccc00 })
473
+ )
474
+ ]
475
+ ],
476
+
477
+ XYZE: [
478
+ [
479
+ new THREE.Line(
480
+ new CircleGeometry(1, 'z', 1),
481
+ new GizmoLineMaterial({ color: 0x787878 })
482
+ )
483
+ ]
484
+ ]
485
+ };
486
+
487
+ this.pickerGizmos = {
488
+ X: [
489
+ [
490
+ new THREE.Mesh(
491
+ new THREE.TorusGeometry(1, 0.12, 4, 12, Math.PI),
492
+ pickerMaterial
493
+ ),
494
+ [0, 0, 0],
495
+ [0, -Math.PI / 2, -Math.PI / 2]
496
+ ]
497
+ ],
498
+
499
+ Y: [
500
+ [
501
+ new THREE.Mesh(
502
+ new THREE.TorusGeometry(1, 0.12, 4, 12, Math.PI),
503
+ pickerMaterial
504
+ ),
505
+ [0, 0, 0],
506
+ [Math.PI / 2, 0, 0]
507
+ ]
508
+ ],
509
+
510
+ Z: [
511
+ [
512
+ new THREE.Mesh(
513
+ new THREE.TorusGeometry(1, 0.12, 4, 12, Math.PI),
514
+ pickerMaterial
515
+ ),
516
+ [0, 0, 0],
517
+ [0, 0, -Math.PI / 2]
518
+ ]
519
+ ],
520
+
521
+ E: [
522
+ [
523
+ new THREE.Mesh(
524
+ new THREE.TorusGeometry(1.25, 0.12, 2, 24),
525
+ pickerMaterial
526
+ )
527
+ ]
528
+ ],
529
+
530
+ XYZE: [
531
+ [
532
+ new THREE.Mesh(
533
+ new THREE.TorusGeometry(1, 0.12, 2, 24),
534
+ pickerMaterial
535
+ )
536
+ ]
537
+ ]
538
+ };
539
+
540
+ this.pickerGizmos.XYZE[0][0].visible = false; // disable XYZE picker gizmo
541
+
542
+ this.init();
543
+ }
544
+
545
+ setActivePlane(axis) {
546
+ if (axis === 'E') this.activePlane = this.planes['XYZE'];
547
+
548
+ if (axis === 'X') this.activePlane = this.planes['YZ'];
549
+
550
+ if (axis === 'Y') this.activePlane = this.planes['XZ'];
551
+
552
+ if (axis === 'Z') this.activePlane = this.planes['XY'];
553
+ }
554
+
555
+ update(rotation, eye2) {
556
+ super.update(rotation, eye2);
557
+
558
+ var tempMatrix = new THREE.Matrix4();
559
+ var worldRotation = new THREE.Euler(0, 0, 1);
560
+ var tempQuaternion = new THREE.Quaternion();
561
+ var unitX = new THREE.Vector3(1, 0, 0);
562
+ var unitY = new THREE.Vector3(0, 1, 0);
563
+ var unitZ = new THREE.Vector3(0, 0, 1);
564
+ var quaternionX = new THREE.Quaternion();
565
+ var quaternionY = new THREE.Quaternion();
566
+ var quaternionZ = new THREE.Quaternion();
567
+ var eye = eye2.clone();
568
+
569
+ worldRotation.copy(this.planes['XY'].rotation);
570
+ tempQuaternion.setFromEuler(worldRotation);
571
+
572
+ tempMatrix
573
+ .makeRotationFromQuaternion(tempQuaternion)
574
+ .copy(tempMatrix)
575
+ .invert();
576
+ eye.applyMatrix4(tempMatrix);
577
+
578
+ this.traverse(function(child) {
579
+ tempQuaternion.setFromEuler(worldRotation);
580
+
581
+ if (child.name === 'X') {
582
+ quaternionX.setFromAxisAngle(unitX, Math.atan2(-eye.y, eye.z));
583
+ tempQuaternion.multiplyQuaternions(tempQuaternion, quaternionX);
584
+ child.quaternion.copy(tempQuaternion);
585
+ }
586
+
587
+ if (child.name === 'Y') {
588
+ quaternionY.setFromAxisAngle(unitY, Math.atan2(eye.x, eye.z));
589
+ tempQuaternion.multiplyQuaternions(tempQuaternion, quaternionY);
590
+ child.quaternion.copy(tempQuaternion);
591
+ }
592
+
593
+ if (child.name === 'Z') {
594
+ quaternionZ.setFromAxisAngle(unitZ, Math.atan2(eye.y, eye.x));
595
+ tempQuaternion.multiplyQuaternions(tempQuaternion, quaternionZ);
596
+ child.quaternion.copy(tempQuaternion);
597
+ }
598
+ });
599
+ }
600
+ };
601
+
602
+ THREE.TransformGizmoScale = class TransformGizmoScale extends THREE.TransformGizmo {
603
+ constructor() {
604
+ super();
605
+
606
+ var arrowGeometry = new THREE.BoxGeometry(0.125, 0.125, 0.125);
607
+ arrowGeometry.translate(0, 0.5, 0);
608
+
609
+ var lineXGeometry = new THREE.BufferGeometry();
610
+ lineXGeometry.setAttribute(
611
+ 'position',
612
+ new THREE.Float32BufferAttribute([0, 0, 0, 1, 0, 0], 3)
613
+ );
614
+
615
+ var lineYGeometry = new THREE.BufferGeometry();
616
+ lineYGeometry.setAttribute(
617
+ 'position',
618
+ new THREE.Float32BufferAttribute([0, 0, 0, 0, 1, 0], 3)
619
+ );
620
+
621
+ var lineZGeometry = new THREE.BufferGeometry();
622
+ lineZGeometry.setAttribute(
623
+ 'position',
624
+ new THREE.Float32BufferAttribute([0, 0, 0, 0, 0, 1], 3)
625
+ );
626
+
627
+ this.handleGizmos = {
628
+ X: [
629
+ [
630
+ new THREE.Mesh(arrowGeometry, new GizmoMaterial({ color: 0xff0000 })),
631
+ [0.5, 0, 0],
632
+ [0, 0, -Math.PI / 2]
633
+ ],
634
+ [
635
+ new THREE.Line(
636
+ lineXGeometry,
637
+ new GizmoLineMaterial({ color: 0xff0000 })
638
+ )
639
+ ]
640
+ ],
641
+
642
+ Y: [
643
+ [
644
+ new THREE.Mesh(arrowGeometry, new GizmoMaterial({ color: 0x00ff00 })),
645
+ [0, 0.5, 0]
646
+ ],
647
+ [
648
+ new THREE.Line(
649
+ lineYGeometry,
650
+ new GizmoLineMaterial({ color: 0x00ff00 })
651
+ )
652
+ ]
653
+ ],
654
+
655
+ Z: [
656
+ [
657
+ new THREE.Mesh(arrowGeometry, new GizmoMaterial({ color: 0x0000ff })),
658
+ [0, 0, 0.5],
659
+ [Math.PI / 2, 0, 0]
660
+ ],
661
+ [
662
+ new THREE.Line(
663
+ lineZGeometry,
664
+ new GizmoLineMaterial({ color: 0x0000ff })
665
+ )
666
+ ]
667
+ ],
668
+
669
+ XYZ: [
670
+ [
671
+ new THREE.Mesh(
672
+ new THREE.BoxGeometry(0.125, 0.125, 0.125),
673
+ new GizmoMaterial({ color: 0xffffff, opacity: 0.25 })
674
+ )
675
+ ]
676
+ ]
677
+ };
678
+
679
+ this.pickerGizmos = {
680
+ X: [
681
+ [
682
+ new THREE.Mesh(
683
+ new THREE.CylinderGeometry(0.2, 0, 1, 4, 1, false),
684
+ pickerMaterial
685
+ ),
686
+ [0.6, 0, 0],
687
+ [0, 0, -Math.PI / 2]
688
+ ]
689
+ ],
690
+
691
+ Y: [
692
+ [
693
+ new THREE.Mesh(
694
+ new THREE.CylinderGeometry(0.2, 0, 1, 4, 1, false),
695
+ pickerMaterial
696
+ ),
697
+ [0, 0.6, 0]
698
+ ]
699
+ ],
700
+
701
+ Z: [
702
+ [
703
+ new THREE.Mesh(
704
+ new THREE.CylinderGeometry(0.2, 0, 1, 4, 1, false),
705
+ pickerMaterial
706
+ ),
707
+ [0, 0, 0.6],
708
+ [Math.PI / 2, 0, 0]
709
+ ]
710
+ ],
711
+
712
+ XYZ: [
713
+ [
714
+ new THREE.Mesh(
715
+ new THREE.BoxGeometry(0.4, 0.4, 0.4),
716
+ pickerMaterial
717
+ )
718
+ ]
719
+ ]
720
+ };
721
+
722
+ this.init();
723
+ }
724
+
725
+ setActivePlane (axis, eye) {
726
+ var tempMatrix = new THREE.Matrix4();
727
+ eye.applyMatrix4(
728
+ tempMatrix
729
+ .copy(tempMatrix.extractRotation(this.planes['XY'].matrixWorld))
730
+ .invert()
731
+ );
732
+
733
+ if (axis === 'X') {
734
+ this.activePlane = this.planes['XY'];
735
+ if (Math.abs(eye.y) > Math.abs(eye.z))
736
+ this.activePlane = this.planes['XZ'];
737
+ }
738
+
739
+ if (axis === 'Y') {
740
+ this.activePlane = this.planes['XY'];
741
+ if (Math.abs(eye.x) > Math.abs(eye.z))
742
+ this.activePlane = this.planes['YZ'];
743
+ }
744
+
745
+ if (axis === 'Z') {
746
+ this.activePlane = this.planes['XZ'];
747
+ if (Math.abs(eye.x) > Math.abs(eye.y))
748
+ this.activePlane = this.planes['YZ'];
749
+ }
750
+
751
+ if (axis === 'XYZ') this.activePlane = this.planes['XYZE'];
752
+ }
753
+ };
754
+
755
+ THREE.TransformControls = class TransformControls extends THREE.Object3D {
756
+ constructor(_camera, domElement) {
757
+ // TODO: Make non-uniform scale and rotate play nice in hierarchies
758
+ // TODO: ADD RXYZ contol
759
+
760
+ super();
761
+
762
+ domElement = domElement !== undefined ? domElement : document;
763
+
764
+ this.object = undefined;
765
+ this.visible = false;
766
+ this.translationSnap = null;
767
+ this.rotationSnap = null;
768
+ this.space = 'world';
769
+ this.size = 1;
770
+ this.axis = null;
771
+
772
+ var camera = _camera;
773
+ var scope = this;
774
+
775
+ var _mode = 'translate';
776
+ var _dragging = false;
777
+ var _gizmo = {
778
+ translate: new THREE.TransformGizmoTranslate(),
779
+ rotate: new THREE.TransformGizmoRotate(),
780
+ scale: new THREE.TransformGizmoScale()
781
+ };
782
+
783
+ for (var type in _gizmo) {
784
+ var gizmoObj = _gizmo[type];
785
+
786
+ gizmoObj.visible = type === _mode;
787
+ this.add(gizmoObj);
788
+ }
789
+
790
+ var changeEvent = { type: 'change' };
791
+ var mouseDownEvent = { type: 'mouseDown' };
792
+ var mouseUpEvent = { type: 'mouseUp', mode: _mode };
793
+ var objectChangeEvent = { type: 'objectChange' };
794
+
795
+ var ray = new THREE.Raycaster();
796
+ var pointerVector = new THREE.Vector2();
797
+
798
+ var point = new THREE.Vector3();
799
+ var offset = new THREE.Vector3();
800
+
801
+ var rotation = new THREE.Vector3();
802
+ var offsetRotation = new THREE.Vector3();
803
+ var scale = 1;
804
+
805
+ var lookAtMatrix = new THREE.Matrix4();
806
+ var eye = new THREE.Vector3();
807
+
808
+ var tempMatrix = new THREE.Matrix4();
809
+ var tempVector = new THREE.Vector3();
810
+ var tempQuaternion = new THREE.Quaternion();
811
+ var tempEuler = new THREE.Euler();
812
+ var unitX = new THREE.Vector3(1, 0, 0);
813
+ var unitY = new THREE.Vector3(0, 1, 0);
814
+ var unitZ = new THREE.Vector3(0, 0, 1);
815
+
816
+ var quaternionXYZ = new THREE.Quaternion();
817
+ var quaternionX = new THREE.Quaternion();
818
+ var quaternionY = new THREE.Quaternion();
819
+ var quaternionZ = new THREE.Quaternion();
820
+ var quaternionE = new THREE.Quaternion();
821
+
822
+ var oldPosition = new THREE.Vector3();
823
+ var oldScale = new THREE.Vector3();
824
+ var oldRotationMatrix = new THREE.Matrix4();
825
+
826
+ var parentRotationMatrix = new THREE.Matrix4();
827
+ var parentScale = new THREE.Vector3();
828
+
829
+ var worldPosition = new THREE.Vector3();
830
+ var worldRotation = new THREE.Euler();
831
+ var worldRotationMatrix = new THREE.Matrix4();
832
+ var camPosition = new THREE.Vector3();
833
+ var camRotation = new THREE.Euler();
834
+
835
+ this.setCamera = function (_camera) {
836
+ camera = _camera;
837
+ };
838
+
839
+ this.activate = function() {
840
+ domElement.addEventListener('mousedown', onPointerDown, false);
841
+ domElement.addEventListener('touchstart', onPointerDown, false);
842
+
843
+ domElement.addEventListener('mousemove', onPointerHover, false);
844
+ domElement.addEventListener('touchmove', onPointerHover, false);
845
+
846
+ domElement.addEventListener('mousemove', onPointerMove, false);
847
+ domElement.addEventListener('touchmove', onPointerMove, false);
848
+
849
+ domElement.addEventListener('mouseup', onPointerUp, false);
850
+ domElement.addEventListener('mouseout', onPointerUp, false);
851
+ domElement.addEventListener('touchend', onPointerUp, false);
852
+ domElement.addEventListener('touchcancel', onPointerUp, false);
853
+ domElement.addEventListener('touchleave', onPointerUp, false);
854
+ };
855
+
856
+ this.activate();
857
+
858
+ this.dispose = function() {
859
+ domElement.removeEventListener('mousedown', onPointerDown);
860
+ domElement.removeEventListener('touchstart', onPointerDown);
861
+
862
+ domElement.removeEventListener('mousemove', onPointerHover);
863
+ domElement.removeEventListener('touchmove', onPointerHover);
864
+
865
+ domElement.removeEventListener('mousemove', onPointerMove);
866
+ domElement.removeEventListener('touchmove', onPointerMove);
867
+
868
+ domElement.removeEventListener('mouseup', onPointerUp);
869
+ domElement.removeEventListener('mouseout', onPointerUp);
870
+ domElement.removeEventListener('touchend', onPointerUp);
871
+ domElement.removeEventListener('touchcancel', onPointerUp);
872
+ domElement.removeEventListener('touchleave', onPointerUp);
873
+ };
874
+
875
+ this.attach = function(object) {
876
+ this.object = object;
877
+ this.visible = true;
878
+ this.update(true);
879
+ };
880
+
881
+ this.detach = function() {
882
+ this.object = undefined;
883
+ this.visible = false;
884
+ this.axis = null;
885
+ };
886
+
887
+ this.getMode = function() {
888
+ return _mode;
889
+ };
890
+
891
+ this.setMode = function(mode) {
892
+ _mode = mode || _mode;
893
+
894
+ if (_mode === 'scale') scope.space = 'local';
895
+
896
+ for (var type in _gizmo) _gizmo[type].visible = type === _mode;
897
+
898
+ this.update();
899
+ scope.dispatchEvent(changeEvent);
900
+ };
901
+
902
+ this.setTranslationSnap = function(translationSnap) {
903
+ scope.translationSnap = translationSnap;
904
+ };
905
+
906
+ this.setRotationSnap = function(rotationSnap) {
907
+ scope.rotationSnap = rotationSnap;
908
+ };
909
+
910
+ this.setSize = function(size) {
911
+ scope.size = size;
912
+ this.update(true);
913
+ scope.dispatchEvent(changeEvent);
914
+ };
915
+
916
+ this.setSpace = function(space) {
917
+ scope.space = space;
918
+ this.update();
919
+ scope.dispatchEvent(changeEvent);
920
+ };
921
+
922
+ this.update = function(updateScale) {
923
+ if (scope.object === undefined) return;
924
+
925
+ scope.object.updateMatrixWorld();
926
+ worldPosition.setFromMatrixPosition(scope.object.matrixWorld);
927
+ worldRotation.setFromRotationMatrix(
928
+ tempMatrix.extractRotation(scope.object.matrixWorld)
929
+ );
930
+
931
+ camera.updateMatrixWorld();
932
+ camPosition.setFromMatrixPosition(camera.matrixWorld);
933
+ camRotation.setFromRotationMatrix(
934
+ tempMatrix.extractRotation(camera.matrixWorld)
935
+ );
936
+
937
+ scale = (worldPosition.distanceTo(camPosition) / 6) * scope.size;
938
+ this.position.copy(worldPosition);
939
+ if (updateScale) {
940
+ this.scale.set(scale, scale, scale);
941
+ }
942
+
943
+ if (camera instanceof THREE.PerspectiveCamera) {
944
+ eye
945
+ .copy(camPosition)
946
+ .sub(worldPosition)
947
+ .normalize();
948
+ } else if (camera instanceof THREE.OrthographicCamera) {
949
+ eye.copy(camPosition).normalize();
950
+ }
951
+
952
+ if (scope.space === 'local') {
953
+ _gizmo[_mode].update(worldRotation, eye);
954
+ } else if (scope.space === 'world') {
955
+ _gizmo[_mode].update(new THREE.Euler(), eye);
956
+ }
957
+
958
+ _gizmo[_mode].highlight(scope.axis);
959
+ };
960
+
961
+ function onPointerHover(event) {
962
+ if (
963
+ scope.object === undefined ||
964
+ _dragging === true ||
965
+ (event.button !== undefined && event.button !== 0)
966
+ )
967
+ return;
968
+
969
+ var pointer = event.changedTouches ? event.changedTouches[0] : event;
970
+
971
+ var intersect = intersectObjects(pointer, _gizmo[_mode].pickers.children);
972
+
973
+ var axis = null;
974
+
975
+ if (intersect) {
976
+ axis = intersect.object.name;
977
+
978
+ event.preventDefault();
979
+ }
980
+
981
+ if (scope.axis !== axis) {
982
+ scope.axis = axis;
983
+ scope.update();
984
+ scope.dispatchEvent(changeEvent);
985
+ }
986
+ }
987
+
988
+ function onPointerDown(event) {
989
+ if (
990
+ scope.object === undefined ||
991
+ _dragging === true ||
992
+ (event.button !== undefined && event.button !== 0)
993
+ )
994
+ return;
995
+
996
+ var pointer = event.changedTouches ? event.changedTouches[0] : event;
997
+
998
+ if (pointer.button === 0 || pointer.button === undefined) {
999
+ var intersect = intersectObjects(
1000
+ pointer,
1001
+ _gizmo[_mode].pickers.children
1002
+ );
1003
+
1004
+ if (intersect) {
1005
+ event.preventDefault();
1006
+ event.stopPropagation();
1007
+
1008
+ scope.axis = intersect.object.name;
1009
+
1010
+ scope.dispatchEvent(mouseDownEvent);
1011
+
1012
+ scope.update();
1013
+
1014
+ eye
1015
+ .copy(camPosition)
1016
+ .sub(worldPosition)
1017
+ .normalize();
1018
+
1019
+ _gizmo[_mode].setActivePlane(scope.axis, eye);
1020
+
1021
+ var planeIntersect = intersectObjects(pointer, [
1022
+ _gizmo[_mode].activePlane
1023
+ ]);
1024
+
1025
+ if (planeIntersect) {
1026
+ oldPosition.copy(scope.object.position);
1027
+ oldScale.copy(scope.object.scale);
1028
+
1029
+ oldRotationMatrix.extractRotation(scope.object.matrix);
1030
+ worldRotationMatrix.extractRotation(scope.object.matrixWorld);
1031
+
1032
+ parentRotationMatrix.extractRotation(
1033
+ scope.object.parent.matrixWorld
1034
+ );
1035
+ parentScale.setFromMatrixScale(
1036
+ tempMatrix.copy(scope.object.parent.matrixWorld).invert()
1037
+ );
1038
+
1039
+ offset.copy(planeIntersect.point);
1040
+ }
1041
+ }
1042
+ }
1043
+
1044
+ _dragging = true;
1045
+ }
1046
+
1047
+ function onPointerMove(event) {
1048
+ if (
1049
+ scope.object === undefined ||
1050
+ scope.axis === null ||
1051
+ _dragging === false ||
1052
+ (event.button !== undefined && event.button !== 0)
1053
+ )
1054
+ return;
1055
+
1056
+ var pointer = event.changedTouches ? event.changedTouches[0] : event;
1057
+
1058
+ var planeIntersect = intersectObjects(pointer, [
1059
+ _gizmo[_mode].activePlane
1060
+ ]);
1061
+
1062
+ if (planeIntersect === false) return;
1063
+
1064
+ event.preventDefault();
1065
+ event.stopPropagation();
1066
+
1067
+ point.copy(planeIntersect.point);
1068
+
1069
+ if (_mode === 'translate') {
1070
+ point.sub(offset);
1071
+ point.multiply(parentScale);
1072
+
1073
+ if (scope.space === 'local') {
1074
+ point.applyMatrix4(tempMatrix.copy(worldRotationMatrix).invert());
1075
+
1076
+ if (scope.axis.search('X') === -1) point.x = 0;
1077
+ if (scope.axis.search('Y') === -1) point.y = 0;
1078
+ if (scope.axis.search('Z') === -1) point.z = 0;
1079
+
1080
+ point.applyMatrix4(oldRotationMatrix);
1081
+
1082
+ scope.object.position.copy(oldPosition);
1083
+ scope.object.position.add(point);
1084
+ }
1085
+
1086
+ if (scope.space === 'world' || scope.axis.search('XYZ') !== -1) {
1087
+ if (scope.axis.search('X') === -1) point.x = 0;
1088
+ if (scope.axis.search('Y') === -1) point.y = 0;
1089
+ if (scope.axis.search('Z') === -1) point.z = 0;
1090
+
1091
+ point.applyMatrix4(tempMatrix.copy(parentRotationMatrix).invert());
1092
+
1093
+ scope.object.position.copy(oldPosition);
1094
+ scope.object.position.add(point);
1095
+ }
1096
+
1097
+ if (scope.translationSnap !== null) {
1098
+ if (scope.space === 'local') {
1099
+ scope.object.position.applyMatrix4(
1100
+ tempMatrix.copy(worldRotationMatrix).invert()
1101
+ );
1102
+ }
1103
+
1104
+ if (scope.axis.search('X') !== -1)
1105
+ scope.object.position.x =
1106
+ Math.round(scope.object.position.x / scope.translationSnap) *
1107
+ scope.translationSnap;
1108
+ if (scope.axis.search('Y') !== -1)
1109
+ scope.object.position.y =
1110
+ Math.round(scope.object.position.y / scope.translationSnap) *
1111
+ scope.translationSnap;
1112
+ if (scope.axis.search('Z') !== -1)
1113
+ scope.object.position.z =
1114
+ Math.round(scope.object.position.z / scope.translationSnap) *
1115
+ scope.translationSnap;
1116
+
1117
+ if (scope.space === 'local') {
1118
+ scope.object.position.applyMatrix4(worldRotationMatrix);
1119
+ }
1120
+ }
1121
+ } else if (_mode === 'scale') {
1122
+ point.sub(offset);
1123
+ point.multiply(parentScale);
1124
+
1125
+ if (scope.space === 'local') {
1126
+ if (scope.axis === 'XYZ') {
1127
+ scale = 1 + point.y / Math.max(oldScale.x, oldScale.y, oldScale.z);
1128
+
1129
+ scope.object.scale.x = oldScale.x * scale;
1130
+ scope.object.scale.y = oldScale.y * scale;
1131
+ scope.object.scale.z = oldScale.z * scale;
1132
+ } else {
1133
+ point.applyMatrix4(tempMatrix.copy(worldRotationMatrix).invert());
1134
+
1135
+ if (scope.axis === 'X')
1136
+ scope.object.scale.x = oldScale.x * (1 + point.x / oldScale.x);
1137
+ if (scope.axis === 'Y')
1138
+ scope.object.scale.y = oldScale.y * (1 + point.y / oldScale.y);
1139
+ if (scope.axis === 'Z')
1140
+ scope.object.scale.z = oldScale.z * (1 + point.z / oldScale.z);
1141
+ }
1142
+ }
1143
+ } else if (_mode === 'rotate') {
1144
+ point.sub(worldPosition);
1145
+ point.multiply(parentScale);
1146
+ tempVector.copy(offset).sub(worldPosition);
1147
+ tempVector.multiply(parentScale);
1148
+
1149
+ if (scope.axis === 'E') {
1150
+ point.applyMatrix4(tempMatrix.copy(lookAtMatrix).invert());
1151
+ tempVector.applyMatrix4(tempMatrix.copy(lookAtMatrix).invert());
1152
+
1153
+ rotation.set(
1154
+ Math.atan2(point.z, point.y),
1155
+ Math.atan2(point.x, point.z),
1156
+ Math.atan2(point.y, point.x)
1157
+ );
1158
+ offsetRotation.set(
1159
+ Math.atan2(tempVector.z, tempVector.y),
1160
+ Math.atan2(tempVector.x, tempVector.z),
1161
+ Math.atan2(tempVector.y, tempVector.x)
1162
+ );
1163
+
1164
+ tempQuaternion.setFromRotationMatrix(
1165
+ tempMatrix.copy(parentRotationMatrix).invert()
1166
+ );
1167
+
1168
+ quaternionE.setFromAxisAngle(eye, rotation.z - offsetRotation.z);
1169
+ quaternionXYZ.setFromRotationMatrix(worldRotationMatrix);
1170
+
1171
+ tempQuaternion.multiplyQuaternions(tempQuaternion, quaternionE);
1172
+ tempQuaternion.multiplyQuaternions(tempQuaternion, quaternionXYZ);
1173
+
1174
+ scope.object.quaternion.copy(tempQuaternion);
1175
+ } else if (scope.axis === 'XYZE') {
1176
+ var p = point
1177
+ .clone()
1178
+ .cross(tempVector)
1179
+ .normalize();
1180
+ quaternionE.setFromEuler(tempEuler.set(p.x, p.y, p.z)); // rotation axis
1181
+
1182
+ tempQuaternion.setFromRotationMatrix(
1183
+ tempMatrix.copy(parentRotationMatrix).invert()
1184
+ );
1185
+ quaternionX.setFromAxisAngle(
1186
+ quaternionE,
1187
+ -point.clone().angleTo(tempVector)
1188
+ );
1189
+ quaternionXYZ.setFromRotationMatrix(worldRotationMatrix);
1190
+
1191
+ tempQuaternion.multiplyQuaternions(tempQuaternion, quaternionX);
1192
+ tempQuaternion.multiplyQuaternions(tempQuaternion, quaternionXYZ);
1193
+
1194
+ scope.object.quaternion.copy(tempQuaternion);
1195
+ } else if (scope.space === 'local') {
1196
+ point.applyMatrix4(tempMatrix.copy(worldRotationMatrix).invert());
1197
+
1198
+ tempVector.applyMatrix4(tempMatrix.copy(worldRotationMatrix).invert());
1199
+
1200
+ rotation.set(
1201
+ Math.atan2(point.z, point.y),
1202
+ Math.atan2(point.x, point.z),
1203
+ Math.atan2(point.y, point.x)
1204
+ );
1205
+ offsetRotation.set(
1206
+ Math.atan2(tempVector.z, tempVector.y),
1207
+ Math.atan2(tempVector.x, tempVector.z),
1208
+ Math.atan2(tempVector.y, tempVector.x)
1209
+ );
1210
+
1211
+ quaternionXYZ.setFromRotationMatrix(oldRotationMatrix);
1212
+
1213
+ if (scope.rotationSnap !== null) {
1214
+ quaternionX.setFromAxisAngle(
1215
+ unitX,
1216
+ Math.round((rotation.x - offsetRotation.x) / scope.rotationSnap) *
1217
+ scope.rotationSnap
1218
+ );
1219
+ quaternionY.setFromAxisAngle(
1220
+ unitY,
1221
+ Math.round((rotation.y - offsetRotation.y) / scope.rotationSnap) *
1222
+ scope.rotationSnap
1223
+ );
1224
+ quaternionZ.setFromAxisAngle(
1225
+ unitZ,
1226
+ Math.round((rotation.z - offsetRotation.z) / scope.rotationSnap) *
1227
+ scope.rotationSnap
1228
+ );
1229
+ } else {
1230
+ quaternionX.setFromAxisAngle(unitX, rotation.x - offsetRotation.x);
1231
+ quaternionY.setFromAxisAngle(unitY, rotation.y - offsetRotation.y);
1232
+ quaternionZ.setFromAxisAngle(unitZ, rotation.z - offsetRotation.z);
1233
+ }
1234
+
1235
+ if (scope.axis === 'X')
1236
+ quaternionXYZ.multiplyQuaternions(quaternionXYZ, quaternionX);
1237
+ if (scope.axis === 'Y')
1238
+ quaternionXYZ.multiplyQuaternions(quaternionXYZ, quaternionY);
1239
+ if (scope.axis === 'Z')
1240
+ quaternionXYZ.multiplyQuaternions(quaternionXYZ, quaternionZ);
1241
+
1242
+ scope.object.quaternion.copy(quaternionXYZ);
1243
+ } else if (scope.space === 'world') {
1244
+ rotation.set(
1245
+ Math.atan2(point.z, point.y),
1246
+ Math.atan2(point.x, point.z),
1247
+ Math.atan2(point.y, point.x)
1248
+ );
1249
+ offsetRotation.set(
1250
+ Math.atan2(tempVector.z, tempVector.y),
1251
+ Math.atan2(tempVector.x, tempVector.z),
1252
+ Math.atan2(tempVector.y, tempVector.x)
1253
+ );
1254
+
1255
+ tempQuaternion.setFromRotationMatrix(
1256
+ tempMatrix.copy(parentRotationMatrix).invert()
1257
+ );
1258
+
1259
+ if (scope.rotationSnap !== null) {
1260
+ quaternionX.setFromAxisAngle(
1261
+ unitX,
1262
+ Math.round((rotation.x - offsetRotation.x) / scope.rotationSnap) *
1263
+ scope.rotationSnap
1264
+ );
1265
+ quaternionY.setFromAxisAngle(
1266
+ unitY,
1267
+ Math.round((rotation.y - offsetRotation.y) / scope.rotationSnap) *
1268
+ scope.rotationSnap
1269
+ );
1270
+ quaternionZ.setFromAxisAngle(
1271
+ unitZ,
1272
+ Math.round((rotation.z - offsetRotation.z) / scope.rotationSnap) *
1273
+ scope.rotationSnap
1274
+ );
1275
+ } else {
1276
+ quaternionX.setFromAxisAngle(unitX, rotation.x - offsetRotation.x);
1277
+ quaternionY.setFromAxisAngle(unitY, rotation.y - offsetRotation.y);
1278
+ quaternionZ.setFromAxisAngle(unitZ, rotation.z - offsetRotation.z);
1279
+ }
1280
+
1281
+ quaternionXYZ.setFromRotationMatrix(worldRotationMatrix);
1282
+
1283
+ if (scope.axis === 'X')
1284
+ tempQuaternion.multiplyQuaternions(tempQuaternion, quaternionX);
1285
+ if (scope.axis === 'Y')
1286
+ tempQuaternion.multiplyQuaternions(tempQuaternion, quaternionY);
1287
+ if (scope.axis === 'Z')
1288
+ tempQuaternion.multiplyQuaternions(tempQuaternion, quaternionZ);
1289
+
1290
+ tempQuaternion.multiplyQuaternions(tempQuaternion, quaternionXYZ);
1291
+
1292
+ scope.object.quaternion.copy(tempQuaternion);
1293
+ }
1294
+ }
1295
+
1296
+ // Trim decimals.
1297
+ if (_mode === 'translate') {
1298
+ scope.object.position.x = parseFloat(
1299
+ scope.object.position.x.toFixed(5)
1300
+ );
1301
+ scope.object.position.y = parseFloat(
1302
+ scope.object.position.y.toFixed(5)
1303
+ );
1304
+ scope.object.position.z = parseFloat(
1305
+ scope.object.position.z.toFixed(5)
1306
+ );
1307
+ } else if (_mode === 'rotate') {
1308
+ scope.object.rotation.x = parseFloat(
1309
+ scope.object.rotation.x.toFixed(5)
1310
+ );
1311
+ scope.object.rotation.y = parseFloat(
1312
+ scope.object.rotation.y.toFixed(5)
1313
+ );
1314
+ scope.object.rotation.z = parseFloat(
1315
+ scope.object.rotation.z.toFixed(5)
1316
+ );
1317
+ } else {
1318
+ scope.object.scale.x = parseFloat(scope.object.scale.x.toFixed(5));
1319
+ scope.object.scale.y = parseFloat(scope.object.scale.y.toFixed(5));
1320
+ scope.object.scale.z = parseFloat(scope.object.scale.z.toFixed(5));
1321
+ }
1322
+
1323
+ scope.update();
1324
+ scope.dispatchEvent(changeEvent);
1325
+ objectChangeEvent.mode = _mode;
1326
+ scope.dispatchEvent(objectChangeEvent);
1327
+ }
1328
+
1329
+ function onPointerUp(event) {
1330
+ event.preventDefault(); // Prevent MouseEvent on mobile
1331
+
1332
+ if (event.button !== undefined && event.button !== 0) return;
1333
+
1334
+ if (_dragging && scope.axis !== null) {
1335
+ mouseUpEvent.mode = _mode;
1336
+ scope.dispatchEvent(mouseUpEvent);
1337
+ }
1338
+
1339
+ _dragging = false;
1340
+
1341
+ if ('TouchEvent' in window && event instanceof TouchEvent) {
1342
+ // Force "rollover"
1343
+
1344
+ scope.axis = null;
1345
+ scope.update();
1346
+ scope.dispatchEvent(changeEvent);
1347
+ } else {
1348
+ onPointerHover(event);
1349
+ }
1350
+ }
1351
+
1352
+ function intersectObjects(pointer, objects) {
1353
+ var rect = domElement.getBoundingClientRect();
1354
+ var x = (pointer.clientX - rect.left) / rect.width;
1355
+ var y = (pointer.clientY - rect.top) / rect.height;
1356
+
1357
+ pointerVector.set(x * 2 - 1, -(y * 2) + 1);
1358
+ ray.setFromCamera(pointerVector, camera);
1359
+
1360
+ var intersections = ray.intersectObjects(objects, true);
1361
+ return intersections[0] ? intersections[0] : false;
1362
+ }
1363
+ }
1364
+ };
1365
+ })();