@woosh/meep-engine 2.46.29 → 2.46.30

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 (165) hide show
  1. package/editor/Editor.js +793 -0
  2. package/editor/SelectionVisualizer.js +148 -0
  3. package/editor/actions/concrete/ActionUpdateTexture.js +21 -0
  4. package/editor/actions/concrete/ArrayCopyAction.js +39 -0
  5. package/editor/actions/concrete/ComponentAddAction.js +47 -0
  6. package/editor/actions/concrete/ComponentRemoveAction.js +38 -0
  7. package/editor/actions/concrete/EntityCreateAction.js +47 -0
  8. package/editor/actions/concrete/EntityRemoveAction.js +51 -0
  9. package/editor/actions/concrete/ModifyPatchSampler2DAction.js +118 -0
  10. package/editor/actions/concrete/ModifyPatchSampler2DAction.spec.js +30 -0
  11. package/editor/actions/concrete/ModifyPatchTextureArray2DAction.js +182 -0
  12. package/editor/actions/concrete/PaintTerrainOverlayAction.js +45 -0
  13. package/editor/actions/concrete/PatchTerrainHeightAction.js +67 -0
  14. package/editor/actions/concrete/PatchTerrainTextureAction.js +152 -0
  15. package/editor/actions/concrete/SelectionAddAction.js +36 -0
  16. package/editor/actions/concrete/SelectionClearAction.js +22 -0
  17. package/editor/actions/concrete/SelectionRemoveAction.js +30 -0
  18. package/editor/actions/concrete/TransformModifyAction.js +46 -0
  19. package/editor/actions/concrete/WriteGridValueAction.js +46 -0
  20. package/editor/ecs/EditorEntity.js +12 -0
  21. package/editor/ecs/EditorEntitySystem.js +14 -0
  22. package/editor/ecs/component/FieldDescriptor.js +34 -0
  23. package/editor/ecs/component/FieldValueAdapter.js +20 -0
  24. package/editor/ecs/component/TypeEditor.js +33 -0
  25. package/editor/ecs/component/TypeSchema.d.ts +38 -0
  26. package/editor/ecs/component/createFieldEditor.js +92 -0
  27. package/editor/ecs/component/createObjectEditor.js +361 -0
  28. package/editor/ecs/component/editors/ColorEditor.js +39 -0
  29. package/editor/ecs/component/editors/HTMLElementEditor.js +17 -0
  30. package/editor/ecs/component/editors/ImagePathEditor.js +82 -0
  31. package/editor/ecs/component/editors/LargeStrongEditor.js +107 -0
  32. package/editor/ecs/component/editors/NumericIntervalEditor.js +86 -0
  33. package/editor/ecs/component/editors/ObservedBooleanEditor.js +13 -0
  34. package/editor/ecs/component/editors/ObservedEnumEditor.js +32 -0
  35. package/editor/ecs/component/editors/ObservedIntegerEditor.js +43 -0
  36. package/editor/ecs/component/editors/ObservedStringEditor.js +51 -0
  37. package/editor/ecs/component/editors/Sampler2DEditor.js +221 -0
  38. package/editor/ecs/component/editors/collection/ListEditor.js +83 -0
  39. package/editor/ecs/component/editors/common/BitFlagsEditor.js +80 -0
  40. package/editor/ecs/component/editors/common/EnumEditor.js +41 -0
  41. package/editor/ecs/component/editors/common/makeV3_editor.js +85 -0
  42. package/editor/ecs/component/editors/common/noEditor.js +9 -0
  43. package/editor/ecs/component/editors/ecs/GridObstacleEditor.js +17 -0
  44. package/editor/ecs/component/editors/ecs/MinimapMarkerEditor.js +16 -0
  45. package/editor/ecs/component/editors/ecs/ParameterLookupTableEditor.js +225 -0
  46. package/editor/ecs/component/editors/ecs/ParameterTrackEditor.js +17 -0
  47. package/editor/ecs/component/editors/ecs/ParameterTrackSetEditor.js +18 -0
  48. package/editor/ecs/component/editors/ecs/ParticleEmitterEditor.js +58 -0
  49. package/editor/ecs/component/editors/ecs/ParticleEmitterLayerEditor.js +58 -0
  50. package/editor/ecs/component/editors/ecs/SimulationStepDefinitionEditor.js +21 -0
  51. package/editor/ecs/component/editors/ecs/Trail2DEditor.js +33 -0
  52. package/editor/ecs/component/editors/ecs/TransformEditor.js +23 -0
  53. package/editor/ecs/component/editors/ecs/terrain/SplatMappingEditor.js +21 -0
  54. package/editor/ecs/component/editors/ecs/terrain/TerrainEditor.js +95 -0
  55. package/editor/ecs/component/editors/ecs/terrain/TerrainLayerEditor.js +18 -0
  56. package/editor/ecs/component/editors/ecs/terrain/TerrainLayersEditor.js +22 -0
  57. package/editor/ecs/component/editors/ecs/terrain/TerrainOverlayEditor.js +20 -0
  58. package/editor/ecs/component/editors/geom/QuaternionEditor.js +63 -0
  59. package/editor/ecs/component/editors/geom/Vector1Editor.js +57 -0
  60. package/editor/ecs/component/editors/geom/Vector2Editor.js +11 -0
  61. package/editor/ecs/component/editors/geom/Vector3Editor.js +13 -0
  62. package/editor/ecs/component/editors/geom/Vector4Editor.js +12 -0
  63. package/editor/ecs/component/editors/primitive/ArrayEditor.js +46 -0
  64. package/editor/ecs/component/editors/primitive/BooleanEditor.js +27 -0
  65. package/editor/ecs/component/editors/primitive/FunctionEditor.js +29 -0
  66. package/editor/ecs/component/editors/primitive/NumberEditor.js +60 -0
  67. package/editor/ecs/component/editors/primitive/ObjectEditor.js +12 -0
  68. package/editor/ecs/component/editors/primitive/StringEditor.js +31 -0
  69. package/editor/ecs/component/editors/three/BufferGeometryEditor.js +28 -0
  70. package/editor/ecs/component/editors/three/MaterialEditor.js +27 -0
  71. package/editor/ecs/component/editors/three/MeshEditor.js +35 -0
  72. package/editor/ecs/component/editors/three/TextureEditor.js +112 -0
  73. package/editor/ecs/component/findNearestRegisteredType.js +59 -0
  74. package/editor/ecs/component/prototypeObjectEditor.js +379 -0
  75. package/editor/enableEditor.js +85 -0
  76. package/editor/library/MeshLibrary.js +33 -0
  77. package/editor/process/DisableGameUIProcess.js +43 -0
  78. package/editor/process/EditorProcess.js +35 -0
  79. package/editor/process/ObstacleGridDisplayProcess.js +120 -0
  80. package/editor/process/ProcessEngine.js +123 -0
  81. package/editor/process/SymbolicDisplayProcess.js +132 -0
  82. package/editor/process/symbolic/ComponentSymbolicDisplay.js +34 -0
  83. package/editor/process/symbolic/SymbolicDisplayInternalAPI.js +159 -0
  84. package/editor/process/symbolic/buildThreeJSHelperEntity.js +36 -0
  85. package/editor/process/symbolic/make3DSymbolicDisplay.js +91 -0
  86. package/editor/process/symbolic/makeCameraSymbolicDisplay.js +32 -0
  87. package/editor/process/symbolic/makeGridPositionSymbolDisplay.js +176 -0
  88. package/editor/process/symbolic/makeHelperBoxGeometry.js +44 -0
  89. package/editor/process/symbolic/makeHelperSphereGeometry.js +73 -0
  90. package/editor/process/symbolic/makeLightSymbolicDisplay.js +77 -0
  91. package/editor/process/symbolic/makeParticleEmitterSymbolicDisplay.js +146 -0
  92. package/editor/process/symbolic/makePathSymbolicDisplay.js +105 -0
  93. package/editor/process/symbolic/makePositionedIconDisplaySymbol.js +74 -0
  94. package/editor/process/symbolic/makeSocketsSymbolicDisplay.js +153 -0
  95. package/editor/process/symbolic/makeSolidArrowGeometry.js +391 -0
  96. package/editor/process/symbolic/makeSoundEmitterSymbolicDisplay.js +89 -0
  97. package/editor/process/symbolic/makeStoryTriggerSetAreaDisplay.js +114 -0
  98. package/editor/process/symbolic/synchronizeTransform.js +50 -0
  99. package/editor/tools/FoliagePaintTool.js +168 -0
  100. package/editor/tools/GridPaintTool.js +247 -0
  101. package/editor/tools/SelectionTool.js +407 -0
  102. package/editor/tools/TopDownCameraControlTool.js +59 -0
  103. package/editor/tools/TransformTool.js +370 -0
  104. package/editor/tools/engine/Tool.js +121 -0
  105. package/editor/tools/engine/ToolEngine.js +193 -0
  106. package/editor/tools/engine/ToolState.js +9 -0
  107. package/editor/tools/engine/ToolStateMachine.js +53 -0
  108. package/editor/tools/paint/TerrainHeightPaintTool.js +297 -0
  109. package/editor/tools/paint/TerrainPaintTool.js +211 -0
  110. package/editor/tools/paint/TerrainTexturePaintTool.js +193 -0
  111. package/editor/tools/paint/prototypeTerrainEditor.js +135 -0
  112. package/editor/tools/v2/BlenderCameraOrientationGizmo.d.ts +50 -0
  113. package/editor/tools/v2/BlenderCameraOrientationGizmo.js +500 -0
  114. package/editor/tools/v2/TransformControls.d.ts +20 -0
  115. package/editor/tools/v2/TransformControls.js +1782 -0
  116. package/editor/tools/v2/prototypeTransformControls.js +92 -0
  117. package/editor/view/EditorView.js +462 -0
  118. package/editor/view/GridPickCoordinateView.js +88 -0
  119. package/editor/view/ecs/ComponentControlFactory.js +48 -0
  120. package/editor/view/ecs/ComponentControlView.js +214 -0
  121. package/editor/view/ecs/EntityEditor.js +258 -0
  122. package/editor/view/ecs/EntityList.js +258 -0
  123. package/editor/view/ecs/components/BlackboardController.js +50 -0
  124. package/editor/view/ecs/components/DatGuiController.js +216 -0
  125. package/editor/view/ecs/components/FogOfWarController.js +78 -0
  126. package/editor/view/ecs/components/FogOfWarRevealerController.js +44 -0
  127. package/editor/view/ecs/components/GeneratedArmyController.js +42 -0
  128. package/editor/view/ecs/components/GridObstacleController.js +72 -0
  129. package/editor/view/ecs/components/GridPositionController.js +40 -0
  130. package/editor/view/ecs/components/HeadsUpDisplayController.js +30 -0
  131. package/editor/view/ecs/components/HighlightController.js +47 -0
  132. package/editor/view/ecs/components/MeshController.js +125 -0
  133. package/editor/view/ecs/components/PathFollowerController.js +87 -0
  134. package/editor/view/ecs/components/TagController.js +80 -0
  135. package/editor/view/ecs/components/TerrainController.js +225 -0
  136. package/editor/view/ecs/components/TransformController.js +103 -0
  137. package/editor/view/ecs/components/UnitShopController.js +112 -0
  138. package/editor/view/ecs/components/army/ArmyController.js +130 -0
  139. package/editor/view/ecs/components/color/GaugeView.js +107 -0
  140. package/editor/view/ecs/components/common/AutoCanvasView.js +53 -0
  141. package/editor/view/ecs/components/common/LineView.js +17 -0
  142. package/editor/view/ecs/components/common/NumberController.js +112 -0
  143. package/editor/view/ecs/components/common/NumericIntervalController.js +64 -0
  144. package/editor/view/ecs/components/gui/GUIElementController.js +117 -0
  145. package/editor/view/ecs/components/items/ItemContainerController.js +132 -0
  146. package/editor/view/ecs/components/items/ItemContainerController.stories.js +50 -0
  147. package/editor/view/ecs/components/items/ItemController.js +52 -0
  148. package/editor/view/ecs/components/particles/ColorParameterLUTController.js +444 -0
  149. package/editor/view/ecs/components/particles/ParameterTrackController.js +51 -0
  150. package/editor/view/ecs/components/particles/ParticleEmitterController.js +213 -0
  151. package/editor/view/ecs/components/particles/ParticleLayerController.js +213 -0
  152. package/editor/view/ecs/components/particles/ScalarParameterLUTController.js +401 -0
  153. package/editor/view/ecs/components/sockets/AttachmentSocketsController.js +51 -0
  154. package/editor/view/ecs/components/sound/SoundEmitterController.js +137 -0
  155. package/editor/view/ecs/components/story/StoryTriggerSetController.js +214 -0
  156. package/editor/view/ecs/components/unit/AuraController.js +45 -0
  157. package/editor/view/library/MeshLibraryView.js +164 -0
  158. package/editor/view/node-graph/NodeGraphEditorView.js +170 -0
  159. package/editor/view/node-graph/NodeGraphView.js +453 -0
  160. package/editor/view/node-graph/NodeView.js +135 -0
  161. package/editor/view/node-graph/PortView.js +69 -0
  162. package/editor/view/process/ProcessView.js +63 -0
  163. package/editor/view/tools/ToolSettingsView.js +143 -0
  164. package/editor/view/tools/ToolView.js +58 -0
  165. package/package.json +2 -1
@@ -0,0 +1,1782 @@
1
+ import {
2
+ BoxGeometry,
3
+ BufferGeometry,
4
+ CylinderGeometry,
5
+ DoubleSide,
6
+ Euler,
7
+ Float32BufferAttribute,
8
+ LineBasicMaterial,
9
+ Matrix4,
10
+ MeshBasicMaterial,
11
+ OctahedronGeometry,
12
+ PlaneGeometry,
13
+ Quaternion,
14
+ Raycaster,
15
+ SphereGeometry,
16
+ TorusGeometry,
17
+ Vector3
18
+ } from 'three';
19
+ import { ShadedGeometry } from "../../../src/engine/graphics/ecs/mesh-v2/ShadedGeometry.js";
20
+ import { DrawMode } from "../../../src/engine/graphics/ecs/mesh-v2/DrawMode.js";
21
+ import { EntityNode } from "../../../src/engine/ecs/parent/EntityNode.js";
22
+ import { Transform } from "../../../src/engine/ecs/transform/Transform.js";
23
+ import { ShadedGeometryFlags } from "../../../src/engine/graphics/ecs/mesh-v2/ShadedGeometryFlags.js";
24
+ import { SurfacePoint3 } from "../../../src/core/geom/3d/SurfacePoint3.js";
25
+ import { FrameRunner } from "../../../src/engine/graphics/FrameRunner.js";
26
+ import { assert } from "../../../src/core/assert.js";
27
+
28
+ const _raycaster = new Raycaster();
29
+
30
+ const _tempVector = new Vector3();
31
+ const _tempVector2 = new Vector3();
32
+ const _tempQuaternion = new Quaternion();
33
+ const _unit = {
34
+ X: new Vector3(1, 0, 0),
35
+ Y: new Vector3(0, 1, 0),
36
+ Z: new Vector3(0, 0, 1)
37
+ };
38
+
39
+ const _changeEvent = { type: 'change' };
40
+ const _mouseDownEvent = { type: 'mouseDown' };
41
+ const _mouseUpEvent = { type: 'mouseUp', mode: null };
42
+ const _objectChangeEvent = { type: 'objectChange' };
43
+
44
+ /**
45
+ * @readonly
46
+ * @type {Transform}
47
+ */
48
+ const _tempTransform = new Transform();
49
+
50
+ class GizmoNode extends EntityNode {
51
+ constructor() {
52
+ super();
53
+
54
+ /**
55
+ *
56
+ * @type {boolean}
57
+ * @private
58
+ */
59
+ this._visible = true;
60
+ /**
61
+ *
62
+ * @type {EntityComponentDataset|null}
63
+ * @private
64
+ */
65
+ this.__ecd = null;
66
+
67
+ this.entity.add(new Transform());
68
+ }
69
+
70
+ build(ecd) {
71
+ this.__ecd = ecd;
72
+
73
+ if (this._visible) {
74
+ super.build(ecd);
75
+ }
76
+ }
77
+
78
+ set visible(v) {
79
+ if (this._visible === v) {
80
+ return;
81
+ }
82
+
83
+ this._visible = v;
84
+
85
+ if (this.__ecd !== null) {
86
+
87
+ if (v) {
88
+ super.build(this.__ecd);
89
+ } else {
90
+ this.destroy();
91
+ }
92
+
93
+ }
94
+ }
95
+
96
+ get visible() {
97
+ return this._visible;
98
+ }
99
+
100
+ update() {
101
+ // do nothing
102
+ const children = this.children;
103
+ const n = children.length;
104
+ for (let i = 0; i < n; i++) {
105
+ const child = children[i];
106
+ if (!(child instanceof GizmoNode)) {
107
+ continue;
108
+ }
109
+
110
+ if (!child.isBuilt) {
111
+ continue;
112
+ }
113
+
114
+ child.update();
115
+ }
116
+ }
117
+ }
118
+
119
+ class TransformControls extends GizmoNode {
120
+
121
+ /**
122
+ *
123
+ * @param {THREE.Camera} camera
124
+ * @param {HTMLElement} domElement
125
+ * @param {boolean} [autoUpdate] Will attempt to update automatically, unnecessary computation can be avoided by manually invoking "update" function each frame instead
126
+ */
127
+ constructor(camera, domElement, autoUpdate = true) {
128
+
129
+ super();
130
+
131
+ if (domElement === undefined) {
132
+
133
+ console.warn('THREE.TransformControls: The second parameter "domElement" is now mandatory.');
134
+ domElement = document;
135
+
136
+ }
137
+
138
+ this.isTransformControls = true;
139
+ this.visible = false;
140
+
141
+ this.domElement = domElement;
142
+
143
+ try {
144
+ this.domElement.style.touchAction = 'none'; // disable touch scroll
145
+ } catch (e) {
146
+ //
147
+ console.error("Failed to disable touch scroll on domElement:", e);
148
+ }
149
+
150
+ const _gizmo = new TransformControlsGizmo();
151
+ this._gizmo = _gizmo;
152
+ this.addChild(_gizmo);
153
+
154
+ const _plane = new TransformControlsPlane();
155
+ this._plane = _plane;
156
+ this.addChild(_plane);
157
+
158
+ const scope = this;
159
+
160
+ // Defined getter, setter and store for a property
161
+ function defineProperty(propName, defaultValue) {
162
+
163
+ let propValue = defaultValue;
164
+
165
+ Object.defineProperty(scope, propName, {
166
+
167
+ get: function () {
168
+
169
+ return propValue !== undefined ? propValue : defaultValue;
170
+
171
+ },
172
+
173
+ set: function (value) {
174
+
175
+ if (propValue !== value) {
176
+
177
+ propValue = value;
178
+ _plane[propName] = value;
179
+ _gizmo[propName] = value;
180
+
181
+ scope.entity.sendEvent(propName + '-changed', value);
182
+
183
+ }
184
+
185
+ }
186
+
187
+ });
188
+
189
+ scope[propName] = defaultValue;
190
+ _plane[propName] = defaultValue;
191
+ _gizmo[propName] = defaultValue;
192
+
193
+ }
194
+
195
+ // Define properties with getters/setter
196
+ // Setting the defined property will automatically trigger change event
197
+ // Defined properties are passed down to gizmo and plane
198
+
199
+ defineProperty('camera', camera);
200
+ defineProperty('object', undefined);
201
+ defineProperty('enabled', true);
202
+ defineProperty('axis', null);
203
+ defineProperty('mode', 'translate');
204
+ defineProperty('translationSnap', null);
205
+ defineProperty('rotationSnap', null);
206
+ defineProperty('scaleSnap', null);
207
+ defineProperty('space', 'world');
208
+ defineProperty('size', 1);
209
+ defineProperty('dragging', false);
210
+ defineProperty('showX', true);
211
+ defineProperty('showY', true);
212
+ defineProperty('showZ', true);
213
+
214
+ // Reusable utility variables
215
+
216
+ const worldPosition = new Vector3();
217
+ const worldPositionStart = new Vector3();
218
+ const worldQuaternion = new Quaternion();
219
+ const worldQuaternionStart = new Quaternion();
220
+ const cameraPosition = new Vector3();
221
+ const cameraQuaternion = new Quaternion();
222
+ const pointStart = new Vector3();
223
+ const pointEnd = new Vector3();
224
+ const rotationAxis = new Vector3();
225
+ const rotationAngle = 0;
226
+ const eye = new Vector3();
227
+
228
+ // TODO: remove properties unused in plane and gizmo
229
+
230
+ defineProperty('worldPosition', worldPosition);
231
+ defineProperty('worldPositionStart', worldPositionStart);
232
+ defineProperty('worldQuaternion', worldQuaternion);
233
+ defineProperty('worldQuaternionStart', worldQuaternionStart);
234
+ defineProperty('cameraPosition', cameraPosition);
235
+ defineProperty('cameraQuaternion', cameraQuaternion);
236
+ defineProperty('pointStart', pointStart);
237
+ defineProperty('pointEnd', pointEnd);
238
+ defineProperty('rotationAxis', rotationAxis);
239
+ defineProperty('rotationAngle', rotationAngle);
240
+ defineProperty('eye', eye);
241
+
242
+ this._offset = new Vector3();
243
+ this._startNorm = new Vector3();
244
+ this._endNorm = new Vector3();
245
+ this._cameraScale = new Vector3(1, 1, 1);
246
+
247
+ this._parentPosition = new Vector3();
248
+ this._parentQuaternion = new Quaternion();
249
+ this._parentQuaternionInv = new Quaternion();
250
+ this._parentScale = new Vector3(1, 1, 1);
251
+
252
+ this._worldScaleStart = new Vector3(1, 1, 1);
253
+ this._worldQuaternionInv = new Quaternion();
254
+ this._worldScale = new Vector3(1, 1, 1);
255
+
256
+ this._positionStart = new Vector3();
257
+ this._quaternionStart = new Quaternion();
258
+ this._scaleStart = new Vector3(1, 1, 1);
259
+
260
+ this._getPointer = getPointer.bind(this);
261
+ this._onPointerDown = onPointerDown.bind(this);
262
+ this._onPointerHover = onPointerHover.bind(this);
263
+ this._onPointerMove = onPointerMove.bind(this);
264
+ this._onPointerUp = onPointerUp.bind(this);
265
+
266
+ this.domElement.addEventListener('pointerdown', this._onPointerDown);
267
+ this.domElement.addEventListener('pointermove', this._onPointerHover);
268
+ this.domElement.addEventListener('pointerup', this._onPointerUp);
269
+
270
+ if (autoUpdate) {
271
+ const fr = new FrameRunner(this.update.bind(this));
272
+ this.on.built.add(fr.startup, fr);
273
+ this.on.destroyed.add(fr.shutdown, fr);
274
+ }
275
+ }
276
+
277
+
278
+ // updateMatrixWorld updates key transformation variables
279
+ update() {
280
+
281
+ if (this.object !== undefined) {
282
+
283
+ this._parentPosition.set(0, 0, 0);
284
+ this._parentScale.set(1, 1, 1);
285
+ this._parentQuaternion.set(0, 0, 0, 1);
286
+
287
+ this.worldPosition.copy(this.object_transform.position);
288
+ this.worldQuaternion.copy(this.object_transform.rotation);
289
+ this._worldScale.copy(this.object_transform.scale);
290
+
291
+ this._parentQuaternionInv.copy(this._parentQuaternion).invert();
292
+ this._worldQuaternionInv.copy(this.worldQuaternion).invert();
293
+
294
+ }
295
+
296
+ this.camera.updateMatrixWorld();
297
+ this.camera.matrixWorld.decompose(this.cameraPosition, this.cameraQuaternion, this._cameraScale);
298
+
299
+ this.eye.copy(this.cameraPosition).sub(this.worldPosition).normalize();
300
+
301
+ super.update();
302
+ }
303
+
304
+ pointerHover(pointer) {
305
+
306
+ if (this.object === undefined || this.dragging === true) return;
307
+
308
+ _raycaster.setFromCamera(pointer, this.camera);
309
+
310
+ const intersect = intersectObjectWithRay(this._gizmo.picker[this.mode], _raycaster);
311
+
312
+ if (intersect) {
313
+
314
+ this.axis = intersect.node.name;
315
+
316
+ } else {
317
+
318
+ this.axis = null;
319
+
320
+ }
321
+
322
+ }
323
+
324
+ pointerDown(pointer) {
325
+
326
+ if (this.object === undefined || this.dragging === true || pointer.button !== 0) return;
327
+
328
+ const ot = this.object_transform;
329
+
330
+ if (this.axis !== null) {
331
+
332
+ _raycaster.setFromCamera(pointer, this.camera);
333
+
334
+ const planeIntersect = intersectObjectWithRay(this._plane, _raycaster, true);
335
+
336
+ if (planeIntersect) {
337
+
338
+ this._positionStart.copy(ot.position);
339
+ this._quaternionStart.copy(ot.rotation);
340
+ this._scaleStart.copy(ot.scale);
341
+
342
+ this.worldPositionStart.copy(ot.position);
343
+ this.worldQuaternionStart.copy(ot.rotation);
344
+ this._worldScaleStart.copy(ot.scale);
345
+
346
+ this.pointStart.copy(planeIntersect.contact.position).sub(this.worldPositionStart);
347
+
348
+ }
349
+
350
+ this.dragging = true;
351
+ _mouseDownEvent.mode = this.mode;
352
+ this.dispatchEvent(_mouseDownEvent);
353
+
354
+ }
355
+
356
+ }
357
+
358
+ /**
359
+ *
360
+ * @param {{type:string}} event
361
+ */
362
+ dispatchEvent(event) {
363
+ this.entity.sendEvent(event.type, event);
364
+ }
365
+
366
+ pointerMove(pointer) {
367
+
368
+ const axis = this.axis;
369
+ const mode = this.mode;
370
+ const object = this.object;
371
+
372
+
373
+ let space = this.space;
374
+
375
+ if (mode === 'scale') {
376
+
377
+ space = 'local';
378
+
379
+ } else if (axis === 'E' || axis === 'XYZE' || axis === 'XYZ') {
380
+
381
+ space = 'world';
382
+
383
+ }
384
+
385
+ if (object === undefined || axis === null || this.dragging === false || pointer.button !== -1) return;
386
+
387
+ const object_transform = this.object_transform;
388
+
389
+ _raycaster.setFromCamera(pointer, this.camera);
390
+
391
+ const planeIntersect = intersectObjectWithRay(this._plane, _raycaster, true);
392
+
393
+ if (!planeIntersect) return;
394
+
395
+ this.pointEnd.copy(planeIntersect.contact.position).sub(this.worldPositionStart);
396
+
397
+ if (mode === 'translate') {
398
+
399
+ // Apply translate
400
+
401
+ this._offset.copy(this.pointEnd).sub(this.pointStart);
402
+
403
+ if (space === 'local' && axis !== 'XYZ') {
404
+
405
+ this._offset.applyQuaternion(this._worldQuaternionInv);
406
+
407
+ }
408
+
409
+ if (axis.indexOf('X') === -1) this._offset.x = 0;
410
+ if (axis.indexOf('Y') === -1) this._offset.y = 0;
411
+ if (axis.indexOf('Z') === -1) this._offset.z = 0;
412
+
413
+ if (space === 'local' && axis !== 'XYZ') {
414
+
415
+ this._offset.applyQuaternion(this._quaternionStart).divide(this._parentScale);
416
+
417
+ } else {
418
+
419
+ this._offset.applyQuaternion(this._parentQuaternionInv).divide(this._parentScale);
420
+
421
+ }
422
+
423
+
424
+ _tempTransform.position.copy(this._offset);
425
+ _tempTransform.position.add(this._positionStart);
426
+
427
+ // Apply translation snap
428
+
429
+ if (this.translationSnap) {
430
+
431
+ if (space === 'local') {
432
+
433
+ _tempTransform.position.applyQuaternion(_tempQuaternion.copy(this._quaternionStart).invert());
434
+
435
+ if (axis.search('X') !== -1) {
436
+
437
+ _tempTransform.position.setX(Math.round(object.position.x / this.translationSnap) * this.translationSnap);
438
+
439
+ }
440
+
441
+ if (axis.search('Y') !== -1) {
442
+
443
+ _tempTransform.position.setY(Math.round(object.position.y / this.translationSnap) * this.translationSnap);
444
+
445
+ }
446
+
447
+ if (axis.search('Z') !== -1) {
448
+
449
+ _tempTransform.position.setZ(Math.round(object.position.z / this.translationSnap) * this.translationSnap);
450
+
451
+ }
452
+
453
+ _tempTransform.position.applyQuaternion(this._quaternionStart);
454
+
455
+ }
456
+
457
+ if (space === 'world') {
458
+
459
+ if (object.parent) {
460
+
461
+ _tempTransform.position.add(_tempVector.setFromMatrixPosition(object.parent.matrixWorld));
462
+
463
+ }
464
+
465
+ if (axis.search('X') !== -1) {
466
+
467
+ _tempTransform.position.setX(Math.round(object.position.x / this.translationSnap) * this.translationSnap);
468
+
469
+ }
470
+
471
+ if (axis.search('Y') !== -1) {
472
+
473
+ _tempTransform.position.setY(Math.round(object.position.y / this.translationSnap) * this.translationSnap);
474
+
475
+ }
476
+
477
+ if (axis.search('Z') !== -1) {
478
+
479
+ _tempTransform.position.setZ(Math.round(object.position.z / this.translationSnap) * this.translationSnap);
480
+
481
+ }
482
+
483
+ if (object.parent) {
484
+
485
+ _tempTransform.position.sub(_tempVector.setFromMatrixPosition(object.parent.matrixWorld));
486
+
487
+ }
488
+
489
+ }
490
+
491
+ }
492
+ // write
493
+ object_transform.position.copy(_tempTransform.position);
494
+
495
+ } else if (mode === 'scale') {
496
+
497
+ if (axis.search('XYZ') !== -1) {
498
+
499
+ let d = this.pointEnd.length() / this.pointStart.length();
500
+
501
+ if (this.pointEnd.dot(this.pointStart) < 0) d *= -1;
502
+
503
+ _tempVector2.set(d, d, d);
504
+
505
+ } else {
506
+
507
+ _tempVector.copy(this.pointStart);
508
+ _tempVector2.copy(this.pointEnd);
509
+
510
+ _tempVector.applyQuaternion(this._worldQuaternionInv);
511
+ _tempVector2.applyQuaternion(this._worldQuaternionInv);
512
+
513
+ _tempVector2.divide(_tempVector);
514
+
515
+ if (axis.search('X') === -1) {
516
+
517
+ _tempVector2.x = 1;
518
+
519
+ }
520
+
521
+ if (axis.search('Y') === -1) {
522
+
523
+ _tempVector2.y = 1;
524
+
525
+ }
526
+
527
+ if (axis.search('Z') === -1) {
528
+
529
+ _tempVector2.z = 1;
530
+
531
+ }
532
+
533
+ }
534
+
535
+ // Apply scale
536
+
537
+ _tempTransform.scale.copy(this._scaleStart);
538
+ _tempTransform.scale.multiply(_tempVector2);
539
+
540
+ // console.log(this._scaleStart,_tempVector2,_tempVector);
541
+
542
+ if (this.scaleSnap) {
543
+
544
+ if (axis.search('X') !== -1) {
545
+
546
+ _tempTransform.scale.setX(Math.round(_tempTransform.scale.x / this.scaleSnap) * this.scaleSnap || this.scaleSnap);
547
+
548
+ }
549
+
550
+ if (axis.search('Y') !== -1) {
551
+
552
+ _tempTransform.scale.setY(Math.round(_tempTransform.scale.y / this.scaleSnap) * this.scaleSnap || this.scaleSnap);
553
+
554
+ }
555
+
556
+ if (axis.search('Z') !== -1) {
557
+
558
+ _tempTransform.scale.setZ(Math.round(_tempTransform.scale.z / this.scaleSnap) * this.scaleSnap || this.scaleSnap);
559
+
560
+ }
561
+
562
+ }
563
+
564
+ object_transform.scale.copy(_tempTransform.scale);
565
+
566
+ } else if (mode === 'rotate') {
567
+
568
+ this._offset.copy(this.pointEnd).sub(this.pointStart);
569
+
570
+ const ROTATION_SPEED = 20 / this.worldPosition.distanceTo(_tempVector.setFromMatrixPosition(this.camera.matrixWorld));
571
+
572
+ if (axis === 'E') {
573
+
574
+ this.rotationAxis.copy(this.eye);
575
+ this.rotationAngle = this.pointEnd.angleTo(this.pointStart);
576
+
577
+ this._startNorm.copy(this.pointStart).normalize();
578
+ this._endNorm.copy(this.pointEnd).normalize();
579
+
580
+ this.rotationAngle *= (this._endNorm.cross(this._startNorm).dot(this.eye) < 0 ? 1 : -1);
581
+
582
+ } else if (axis === 'XYZE') {
583
+
584
+ this.rotationAxis.copy(this._offset).cross(this.eye).normalize();
585
+ this.rotationAngle = this._offset.dot(_tempVector.copy(this.rotationAxis).cross(this.eye)) * ROTATION_SPEED;
586
+
587
+ } else if (axis === 'X' || axis === 'Y' || axis === 'Z') {
588
+
589
+ this.rotationAxis.copy(_unit[axis]);
590
+
591
+ _tempVector.copy(_unit[axis]);
592
+
593
+ if (space === 'local') {
594
+
595
+ _tempVector.applyQuaternion(this.worldQuaternion);
596
+
597
+ }
598
+
599
+ this.rotationAngle = this._offset.dot(_tempVector.cross(this.eye).normalize()) * ROTATION_SPEED;
600
+
601
+ }
602
+
603
+ // Apply rotation snap
604
+
605
+ if (this.rotationSnap) this.rotationAngle = Math.round(this.rotationAngle / this.rotationSnap) * this.rotationSnap;
606
+
607
+ // Apply rotate
608
+ if (space === 'local' && axis !== 'E' && axis !== 'XYZE') {
609
+
610
+ _tempTransform.rotation.copy(this._quaternionStart);
611
+ _tempTransform.rotation.multiply(_tempQuaternion.setFromAxisAngle(this.rotationAxis, this.rotationAngle)).normalize();
612
+
613
+ } else {
614
+
615
+ this.rotationAxis.applyQuaternion(this._parentQuaternionInv);
616
+ _tempTransform.rotation.copy(_tempQuaternion.setFromAxisAngle(this.rotationAxis, this.rotationAngle));
617
+ _tempTransform.rotation.multiply(this._quaternionStart);
618
+ _tempTransform.rotation.normalize();
619
+
620
+ }
621
+
622
+ object_transform.rotation.copy(_tempTransform.rotation);
623
+ }
624
+
625
+
626
+ this.dispatchEvent(_changeEvent);
627
+ this.dispatchEvent(_objectChangeEvent);
628
+
629
+ }
630
+
631
+ pointerUp(pointer) {
632
+
633
+ if (pointer.button !== 0) return;
634
+
635
+ if (this.dragging && (this.axis !== null)) {
636
+
637
+ _mouseUpEvent.mode = this.mode;
638
+ this.dispatchEvent(_mouseUpEvent);
639
+
640
+ }
641
+
642
+ this.dragging = false;
643
+ this.axis = null;
644
+
645
+ }
646
+
647
+ dispose() {
648
+
649
+ this.domElement.removeEventListener('pointerdown', this._onPointerDown);
650
+ this.domElement.removeEventListener('pointermove', this._onPointerHover);
651
+ this.domElement.removeEventListener('pointermove', this._onPointerMove);
652
+ this.domElement.removeEventListener('pointerup', this._onPointerUp);
653
+
654
+ }
655
+
656
+ /**
657
+ * Set current object
658
+ * @param {number} entity
659
+ * @returns {TransformControls}
660
+ */
661
+ attach(entity) {
662
+ assert.isNonNegativeInteger(entity, 'entity');
663
+
664
+ this.object = entity;
665
+
666
+ this.visible = true;
667
+
668
+ return this;
669
+
670
+ }
671
+
672
+ /**
673
+ *
674
+ * @returns {Transform|undefined}
675
+ */
676
+ get object_transform() {
677
+ const ecd = this.entity.dataset;
678
+
679
+ return ecd.getComponent(this.object, Transform);
680
+ }
681
+
682
+ // Detatch from object
683
+ detach() {
684
+
685
+ this.object = undefined;
686
+
687
+ this.visible = false;
688
+ this.axis = null;
689
+
690
+ return this;
691
+
692
+ }
693
+
694
+ reset() {
695
+
696
+ if (!this.enabled) return;
697
+
698
+ if (this.dragging) {
699
+
700
+ this.object_transform.position.copy(this._positionStart);
701
+ this.object_transform.rotation.copy(this._quaternionStart);
702
+ this.object_transform.scale.copy(this._scaleStart);
703
+
704
+ this.dispatchEvent(_changeEvent);
705
+ this.dispatchEvent(_objectChangeEvent);
706
+
707
+ this.pointStart.copy(this.pointEnd);
708
+
709
+ }
710
+
711
+ }
712
+
713
+ getRaycaster() {
714
+
715
+ return _raycaster;
716
+
717
+ }
718
+
719
+ // TODO: deprecate
720
+
721
+ getMode() {
722
+
723
+ return this.mode;
724
+
725
+ }
726
+
727
+ setMode(mode) {
728
+
729
+ this.mode = mode;
730
+
731
+ }
732
+
733
+ setTranslationSnap(translationSnap) {
734
+
735
+ this.translationSnap = translationSnap;
736
+
737
+ }
738
+
739
+ setRotationSnap(rotationSnap) {
740
+
741
+ this.rotationSnap = rotationSnap;
742
+
743
+ }
744
+
745
+ setScaleSnap(scaleSnap) {
746
+
747
+ this.scaleSnap = scaleSnap;
748
+
749
+ }
750
+
751
+ setSize(size) {
752
+
753
+ this.size = size;
754
+
755
+ }
756
+
757
+ setSpace(space) {
758
+
759
+ this.space = space;
760
+
761
+ }
762
+
763
+ }
764
+
765
+ // mouse / touch event handlers
766
+
767
+ function getPointer(event) {
768
+
769
+ if (this.domElement.ownerDocument.pointerLockElement) {
770
+
771
+ return {
772
+ x: 0,
773
+ y: 0,
774
+ button: event.button
775
+ };
776
+
777
+ } else {
778
+
779
+ const rect = this.domElement.getBoundingClientRect();
780
+
781
+ return {
782
+ x: (event.clientX - rect.left) / rect.width * 2 - 1,
783
+ y: -(event.clientY - rect.top) / rect.height * 2 + 1,
784
+ button: event.button
785
+ };
786
+
787
+ }
788
+
789
+ }
790
+
791
+ function onPointerHover(event) {
792
+
793
+ if (!this.enabled) return;
794
+
795
+ switch (event.pointerType) {
796
+
797
+ case 'mouse':
798
+ case 'pen':
799
+ this.pointerHover(this._getPointer(event));
800
+ break;
801
+
802
+ }
803
+
804
+ }
805
+
806
+ function onPointerDown(event) {
807
+
808
+ if (!this.enabled) return;
809
+
810
+ if (!document.pointerLockElement) {
811
+
812
+ this.domElement.setPointerCapture(event.pointerId);
813
+
814
+ }
815
+
816
+ this.domElement.addEventListener('pointermove', this._onPointerMove);
817
+
818
+ this.pointerHover(this._getPointer(event));
819
+ this.pointerDown(this._getPointer(event));
820
+
821
+ }
822
+
823
+ function onPointerMove(event) {
824
+
825
+ if (!this.enabled) return;
826
+
827
+ this.pointerMove(this._getPointer(event));
828
+
829
+ }
830
+
831
+ function onPointerUp(event) {
832
+
833
+ if (!this.enabled) return;
834
+
835
+ this.domElement.releasePointerCapture(event.pointerId);
836
+
837
+ this.domElement.removeEventListener('pointermove', this._onPointerMove);
838
+
839
+ this.pointerUp(this._getPointer(event));
840
+
841
+ }
842
+
843
+ /**
844
+ *
845
+ * @param {EntityNode} object
846
+ * @param {Raycaster} raycaster
847
+ * @param {boolean} [includeInvisible]
848
+ * @returns {boolean|{contact:SurfacePoint3,entity:number, node:EntityNode}}
849
+ */
850
+ function intersectObjectWithRay(object, raycaster, includeInvisible = false) {
851
+ /**
852
+ *
853
+ * @type {{contact:SurfacePoint3,entity:number, node:EntityNode}[]}
854
+ */
855
+ const contacts = [];
856
+
857
+ const ray = raycaster.ray;
858
+ const ray_array = [
859
+ ray.origin.x, ray.origin.y, ray.origin.z, ray.direction.x, ray.direction.y, ray.direction.z
860
+ ];
861
+
862
+ object.traverse(node => {
863
+
864
+ const sg = node.entity.getComponent(ShadedGeometry);
865
+
866
+ const transform = node.transform;
867
+
868
+ if (!sg) {
869
+ return;
870
+ }
871
+
872
+ if (!sg.getFlag(ShadedGeometryFlags.Visible) && !includeInvisible) {
873
+ return;
874
+ }
875
+
876
+
877
+ const contact = new SurfacePoint3();
878
+ if (sg.query_raycast_nearest(contact, ray_array, transform.matrix)) {
879
+
880
+ contacts.push({
881
+ contact,
882
+ entity: node.entity.entity,
883
+ node
884
+ });
885
+ }
886
+ });
887
+
888
+ if (contacts.length <= 0) {
889
+ return false;
890
+ }
891
+
892
+ // sort contacts by distance
893
+ contacts.sort((a, b) => {
894
+ return a.contact.position.distanceSqrTo(ray.origin) - b.contact.position.distanceSqrTo(ray.origin);
895
+ });
896
+
897
+ return contacts[0];
898
+ }
899
+
900
+ //
901
+
902
+ // Reusable utility variables
903
+
904
+ const _tempEuler = new Euler();
905
+ const _alignVector = new Vector3(0, 1, 0);
906
+ const _zeroVector = new Vector3(0, 0, 0);
907
+ const _lookAtMatrix = new Matrix4();
908
+ const _tempQuaternion2 = new Quaternion();
909
+ const _identityQuaternion = new Quaternion();
910
+ const _dirVector = new Vector3();
911
+ const _tempMatrix = new Matrix4();
912
+
913
+ const _unitX = new Vector3(1, 0, 0);
914
+ const _unitY = new Vector3(0, 1, 0);
915
+ const _unitZ = new Vector3(0, 0, 1);
916
+
917
+ const _v1 = new Vector3();
918
+ const _v2 = new Vector3();
919
+ const _v3 = new Vector3();
920
+
921
+ class TransformControlsGizmo extends GizmoNode {
922
+
923
+ constructor() {
924
+
925
+ super();
926
+
927
+ this.isTransformControlsGizmo = true;
928
+
929
+ this.type = 'TransformControlsGizmo';
930
+
931
+ // shared materials
932
+
933
+ const gizmoMaterial = new MeshBasicMaterial({
934
+ depthTest: false,
935
+ depthWrite: false,
936
+ fog: false,
937
+ toneMapped: false,
938
+ transparent: true
939
+ });
940
+
941
+ const gizmoLineMaterial = new LineBasicMaterial({
942
+ depthTest: false,
943
+ depthWrite: false,
944
+ fog: false,
945
+ toneMapped: false,
946
+ transparent: true
947
+ });
948
+
949
+ // Make unique material for each axis/color
950
+
951
+ const matInvisible = gizmoMaterial.clone();
952
+ matInvisible.opacity = 0.15;
953
+
954
+ const matHelper = gizmoLineMaterial.clone();
955
+ matHelper.opacity = 0.5;
956
+
957
+ const matRed = gizmoMaterial.clone();
958
+ matRed.color.setHex(0xff0000);
959
+
960
+ const matGreen = gizmoMaterial.clone();
961
+ matGreen.color.setHex(0x00ff00);
962
+
963
+ const matBlue = gizmoMaterial.clone();
964
+ matBlue.color.setHex(0x0000ff);
965
+
966
+ const matRedTransparent = gizmoMaterial.clone();
967
+ matRedTransparent.color.setHex(0xff0000);
968
+ matRedTransparent.opacity = 0.5;
969
+
970
+ const matGreenTransparent = gizmoMaterial.clone();
971
+ matGreenTransparent.color.setHex(0x00ff00);
972
+ matGreenTransparent.opacity = 0.5;
973
+
974
+ const matBlueTransparent = gizmoMaterial.clone();
975
+ matBlueTransparent.color.setHex(0x0000ff);
976
+ matBlueTransparent.opacity = 0.5;
977
+
978
+ const matWhiteTransparent = gizmoMaterial.clone();
979
+ matWhiteTransparent.opacity = 0.25;
980
+
981
+ const matYellowTransparent = gizmoMaterial.clone();
982
+ matYellowTransparent.color.setHex(0xffff00);
983
+ matYellowTransparent.opacity = 0.25;
984
+
985
+ const matYellow = gizmoMaterial.clone();
986
+ matYellow.color.setHex(0xffff00);
987
+
988
+ const matGray = gizmoMaterial.clone();
989
+ matGray.color.setHex(0x787878);
990
+
991
+ // reusable geometry
992
+
993
+ const arrowGeometry = new CylinderGeometry(0, 0.04, 0.1, 12);
994
+ arrowGeometry.translate(0, 0.05, 0);
995
+
996
+ const scaleHandleGeometry = new BoxGeometry(0.08, 0.08, 0.08);
997
+ scaleHandleGeometry.translate(0, 0.04, 0);
998
+
999
+ const lineGeometry = new BufferGeometry();
1000
+ lineGeometry.setAttribute('position', new Float32BufferAttribute([0, 0, 0, 1, 0, 0], 3));
1001
+
1002
+ const lineGeometry2 = new CylinderGeometry(0.0075, 0.0075, 0.5, 3);
1003
+ lineGeometry2.translate(0, 0.25, 0);
1004
+
1005
+ function CircleGeometry(radius, arc) {
1006
+
1007
+ const geometry = new TorusGeometry(radius, 0.0075, 3, 64, arc * Math.PI * 2);
1008
+ geometry.rotateY(Math.PI / 2);
1009
+ geometry.rotateX(Math.PI / 2);
1010
+ return geometry;
1011
+
1012
+ }
1013
+
1014
+ // Special geometry for transform helper. If scaled with position vector it spans from [0,0,0] to position
1015
+
1016
+ function TranslateHelperGeometry() {
1017
+
1018
+ const geometry = new BufferGeometry();
1019
+
1020
+ geometry.setAttribute('position', new Float32BufferAttribute([0, 0, 0, 1, 1, 1], 3));
1021
+
1022
+ return geometry;
1023
+
1024
+ }
1025
+
1026
+ // Gizmo definitions - custom hierarchy definitions for setupGizmo() function
1027
+
1028
+ const gizmoTranslate = {
1029
+ X: [
1030
+ [ShadedGeometry.from(arrowGeometry, matRed, DrawMode.Triangles), [0.5, 0, 0], [0, 0, -Math.PI / 2]],
1031
+ [ShadedGeometry.from(arrowGeometry, matRed, DrawMode.Triangles), [-0.5, 0, 0], [0, 0, Math.PI / 2]],
1032
+ [ShadedGeometry.from(lineGeometry2, matRed, DrawMode.Triangles), [0, 0, 0], [0, 0, -Math.PI / 2]]
1033
+ ],
1034
+ Y: [
1035
+ [ShadedGeometry.from(arrowGeometry, matGreen, DrawMode.Triangles), [0, 0.5, 0]],
1036
+ [ShadedGeometry.from(arrowGeometry, matGreen, DrawMode.Triangles), [0, -0.5, 0], [Math.PI, 0, 0]],
1037
+ [ShadedGeometry.from(lineGeometry2, matGreen, DrawMode.Triangles)]
1038
+ ],
1039
+ Z: [
1040
+ [ShadedGeometry.from(arrowGeometry, matBlue, DrawMode.Triangles), [0, 0, 0.5], [Math.PI / 2, 0, 0]],
1041
+ [ShadedGeometry.from(arrowGeometry, matBlue, DrawMode.Triangles), [0, 0, -0.5], [-Math.PI / 2, 0, 0]],
1042
+ [ShadedGeometry.from(lineGeometry2, matBlue, DrawMode.Triangles), null, [Math.PI / 2, 0, 0]]
1043
+ ],
1044
+ XYZ: [
1045
+ [ShadedGeometry.from(new OctahedronGeometry(0.1, 0), matWhiteTransparent.clone(), DrawMode.Triangles), [0, 0, 0]]
1046
+ ],
1047
+ XY: [
1048
+ [ShadedGeometry.from(new BoxGeometry(0.15, 0.15, 0.01), matBlueTransparent.clone(), DrawMode.Triangles), [0.15, 0.15, 0]]
1049
+ ],
1050
+ YZ: [
1051
+ [ShadedGeometry.from(new BoxGeometry(0.15, 0.15, 0.01), matRedTransparent.clone(), DrawMode.Triangles), [0, 0.15, 0.15], [0, Math.PI / 2, 0]]
1052
+ ],
1053
+ XZ: [
1054
+ [ShadedGeometry.from(new BoxGeometry(0.15, 0.15, 0.01), matGreenTransparent.clone(), DrawMode.Triangles), [0.15, 0, 0.15], [-Math.PI / 2, 0, 0]]
1055
+ ]
1056
+ };
1057
+
1058
+ const pickerTranslate = {
1059
+ X: [
1060
+ [ShadedGeometry.from(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible, DrawMode.Triangles), [0.3, 0, 0], [0, 0, -Math.PI / 2]],
1061
+ [ShadedGeometry.from(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible, DrawMode.Triangles), [-0.3, 0, 0], [0, 0, Math.PI / 2]]
1062
+ ],
1063
+ Y: [
1064
+ [ShadedGeometry.from(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible, DrawMode.Triangles), [0, 0.3, 0]],
1065
+ [ShadedGeometry.from(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible, DrawMode.Triangles), [0, -0.3, 0], [0, 0, Math.PI]]
1066
+ ],
1067
+ Z: [
1068
+ [ShadedGeometry.from(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible, DrawMode.Triangles), [0, 0, 0.3], [Math.PI / 2, 0, 0]],
1069
+ [ShadedGeometry.from(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible, DrawMode.Triangles), [0, 0, -0.3], [-Math.PI / 2, 0, 0]]
1070
+ ],
1071
+ XYZ: [
1072
+ [ShadedGeometry.from(new OctahedronGeometry(0.2, 0), matInvisible, DrawMode.Triangles)]
1073
+ ],
1074
+ XY: [
1075
+ [ShadedGeometry.from(new BoxGeometry(0.2, 0.2, 0.01), matInvisible, DrawMode.Triangles), [0.15, 0.15, 0]]
1076
+ ],
1077
+ YZ: [
1078
+ [ShadedGeometry.from(new BoxGeometry(0.2, 0.2, 0.01), matInvisible, DrawMode.Triangles), [0, 0.15, 0.15], [0, Math.PI / 2, 0]]
1079
+ ],
1080
+ XZ: [
1081
+ [ShadedGeometry.from(new BoxGeometry(0.2, 0.2, 0.01), matInvisible, DrawMode.Triangles), [0.15, 0, 0.15], [-Math.PI / 2, 0, 0]]
1082
+ ]
1083
+ };
1084
+
1085
+ const helperTranslate = {
1086
+ START: [
1087
+ [ShadedGeometry.from(new OctahedronGeometry(0.01, 2), matHelper, DrawMode.Triangles), null, null, null, 'helper']
1088
+ ],
1089
+ END: [
1090
+ [ShadedGeometry.from(new OctahedronGeometry(0.01, 2), matHelper, DrawMode.Triangles), null, null, null, 'helper']
1091
+ ],
1092
+ DELTA: [
1093
+ [ShadedGeometry.from(TranslateHelperGeometry(), matHelper, DrawMode.Lines), null, null, null, 'helper']
1094
+ ],
1095
+ X: [
1096
+ [ShadedGeometry.from(lineGeometry, matHelper.clone(), DrawMode.Lines), [-1e3, 0, 0], null, [1e6, 1, 1], 'helper']
1097
+ ],
1098
+ Y: [
1099
+ [ShadedGeometry.from(lineGeometry, matHelper.clone(), DrawMode.Lines), [0, -1e3, 0], [0, 0, Math.PI / 2], [1e6, 1, 1], 'helper']
1100
+ ],
1101
+ Z: [
1102
+ [ShadedGeometry.from(lineGeometry, matHelper.clone(), DrawMode.Lines), [0, 0, -1e3], [0, -Math.PI / 2, 0], [1e6, 1, 1], 'helper']
1103
+ ]
1104
+ };
1105
+
1106
+ const gizmoRotate = {
1107
+ XYZE: [
1108
+ [ShadedGeometry.from(CircleGeometry(0.5, 1), matGray, DrawMode.Triangles), null, [0, Math.PI / 2, 0]]
1109
+ ],
1110
+ X: [
1111
+ [ShadedGeometry.from(CircleGeometry(0.5, 0.5), matRed, DrawMode.Triangles)]
1112
+ ],
1113
+ Y: [
1114
+ [ShadedGeometry.from(CircleGeometry(0.5, 0.5), matGreen, DrawMode.Triangles), null, [0, 0, -Math.PI / 2]]
1115
+ ],
1116
+ Z: [
1117
+ [ShadedGeometry.from(CircleGeometry(0.5, 0.5), matBlue, DrawMode.Triangles), null, [0, Math.PI / 2, 0]]
1118
+ ],
1119
+ E: [
1120
+ [ShadedGeometry.from(CircleGeometry(0.75, 1), matYellowTransparent, DrawMode.Triangles), null, [0, Math.PI / 2, 0]]
1121
+ ]
1122
+ };
1123
+
1124
+ const helperRotate = {
1125
+ AXIS: [
1126
+ [ShadedGeometry.from(lineGeometry, matHelper.clone(), DrawMode.Lines), [-1e3, 0, 0], null, [1e6, 1, 1], 'helper']
1127
+ ]
1128
+ };
1129
+
1130
+ const pickerRotate = {
1131
+ XYZE: [
1132
+ [ShadedGeometry.from(new SphereGeometry(0.25, 10, 8), matInvisible, DrawMode.Triangles)]
1133
+ ],
1134
+ X: [
1135
+ [ShadedGeometry.from(new TorusGeometry(0.5, 0.1, 4, 24), matInvisible, DrawMode.Triangles), [0, 0, 0], [0, -Math.PI / 2, -Math.PI / 2]],
1136
+ ],
1137
+ Y: [
1138
+ [ShadedGeometry.from(new TorusGeometry(0.5, 0.1, 4, 24), matInvisible, DrawMode.Triangles), [0, 0, 0], [Math.PI / 2, 0, 0]],
1139
+ ],
1140
+ Z: [
1141
+ [ShadedGeometry.from(new TorusGeometry(0.5, 0.1, 4, 24), matInvisible, DrawMode.Triangles), [0, 0, 0], [0, 0, -Math.PI / 2]],
1142
+ ],
1143
+ E: [
1144
+ [ShadedGeometry.from(new TorusGeometry(0.75, 0.1, 2, 24), matInvisible, DrawMode.Triangles)]
1145
+ ]
1146
+ };
1147
+
1148
+ const gizmoScale = {
1149
+ X: [
1150
+ [ShadedGeometry.from(scaleHandleGeometry, matRed), [0.5, 0, 0], [0, 0, -Math.PI / 2]],
1151
+ [ShadedGeometry.from(lineGeometry2, matRed), [0, 0, 0], [0, 0, -Math.PI / 2]],
1152
+ [ShadedGeometry.from(scaleHandleGeometry, matRed), [-0.5, 0, 0], [0, 0, Math.PI / 2]],
1153
+ ],
1154
+ Y: [
1155
+ [ShadedGeometry.from(scaleHandleGeometry, matGreen), [0, 0.5, 0]],
1156
+ [ShadedGeometry.from(lineGeometry2, matGreen)],
1157
+ [ShadedGeometry.from(scaleHandleGeometry, matGreen), [0, -0.5, 0], [0, 0, Math.PI]],
1158
+ ],
1159
+ Z: [
1160
+ [ShadedGeometry.from(scaleHandleGeometry, matBlue), [0, 0, 0.5], [Math.PI / 2, 0, 0]],
1161
+ [ShadedGeometry.from(lineGeometry2, matBlue), [0, 0, 0], [Math.PI / 2, 0, 0]],
1162
+ [ShadedGeometry.from(scaleHandleGeometry, matBlue), [0, 0, -0.5], [-Math.PI / 2, 0, 0]]
1163
+ ],
1164
+ XY: [
1165
+ [ShadedGeometry.from(new BoxGeometry(0.15, 0.15, 0.01), matBlueTransparent), [0.15, 0.15, 0]]
1166
+ ],
1167
+ YZ: [
1168
+ [ShadedGeometry.from(new BoxGeometry(0.15, 0.15, 0.01), matRedTransparent), [0, 0.15, 0.15], [0, Math.PI / 2, 0]]
1169
+ ],
1170
+ XZ: [
1171
+ [ShadedGeometry.from(new BoxGeometry(0.15, 0.15, 0.01), matGreenTransparent), [0.15, 0, 0.15], [-Math.PI / 2, 0, 0]]
1172
+ ],
1173
+ XYZ: [
1174
+ [ShadedGeometry.from(new BoxGeometry(0.1, 0.1, 0.1), matWhiteTransparent.clone())],
1175
+ ]
1176
+ };
1177
+
1178
+ const pickerScale = {
1179
+ X: [
1180
+ [ShadedGeometry.from(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible), [0.3, 0, 0], [0, 0, -Math.PI / 2]],
1181
+ [ShadedGeometry.from(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible), [-0.3, 0, 0], [0, 0, Math.PI / 2]]
1182
+ ],
1183
+ Y: [
1184
+ [ShadedGeometry.from(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible), [0, 0.3, 0]],
1185
+ [ShadedGeometry.from(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible), [0, -0.3, 0], [0, 0, Math.PI]]
1186
+ ],
1187
+ Z: [
1188
+ [ShadedGeometry.from(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible), [0, 0, 0.3], [Math.PI / 2, 0, 0]],
1189
+ [ShadedGeometry.from(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible), [0, 0, -0.3], [-Math.PI / 2, 0, 0]]
1190
+ ],
1191
+ XY: [
1192
+ [ShadedGeometry.from(new BoxGeometry(0.2, 0.2, 0.01), matInvisible), [0.15, 0.15, 0]],
1193
+ ],
1194
+ YZ: [
1195
+ [ShadedGeometry.from(new BoxGeometry(0.2, 0.2, 0.01), matInvisible), [0, 0.15, 0.15], [0, Math.PI / 2, 0]],
1196
+ ],
1197
+ XZ: [
1198
+ [ShadedGeometry.from(new BoxGeometry(0.2, 0.2, 0.01), matInvisible), [0.15, 0, 0.15], [-Math.PI / 2, 0, 0]],
1199
+ ],
1200
+ XYZ: [
1201
+ [ShadedGeometry.from(new BoxGeometry(0.2, 0.2, 0.2), matInvisible), [0, 0, 0]],
1202
+ ]
1203
+ };
1204
+
1205
+ const helperScale = {
1206
+ X: [
1207
+ [ShadedGeometry.from(lineGeometry, matHelper.clone(), DrawMode.Lines), [-1e3, 0, 0], null, [1e6, 1, 1], 'helper']
1208
+ ],
1209
+ Y: [
1210
+ [ShadedGeometry.from(lineGeometry, matHelper.clone(), DrawMode.Lines), [0, -1e3, 0], [0, 0, Math.PI / 2], [1e6, 1, 1], 'helper']
1211
+ ],
1212
+ Z: [
1213
+ [ShadedGeometry.from(lineGeometry, matHelper.clone(), DrawMode.Lines), [0, 0, -1e3], [0, -Math.PI / 2, 0], [1e6, 1, 1], 'helper']
1214
+ ]
1215
+ };
1216
+
1217
+ // Creates an Object3D with gizmos described in custom hierarchy definition.
1218
+
1219
+ /**
1220
+ *
1221
+ * @returns {EntityNode}
1222
+ */
1223
+ function setupGizmo(gizmoMap) {
1224
+
1225
+ const gizmo = new GizmoNode();
1226
+
1227
+ for (const name in gizmoMap) {
1228
+
1229
+ const gizmo_elements = gizmoMap[name];
1230
+
1231
+ for (let i = gizmo_elements.length; i--;) {
1232
+ const gizmo_element = gizmo_elements[i];
1233
+
1234
+ /**
1235
+ * @type {ShadedGeometry}
1236
+ */
1237
+ const shaded_geometry = gizmo_element[0].clone();
1238
+
1239
+ // disable shadows
1240
+ shaded_geometry.clearFlag(ShadedGeometryFlags.CastShadow | ShadedGeometryFlags.ReceiveShadow);
1241
+
1242
+ // make it so that gizmo is always drawn using direct mode
1243
+ shaded_geometry.draw_method = 0;
1244
+ shaded_geometry.setFlag(ShadedGeometryFlags.DrawMethodLocked);
1245
+
1246
+ const node = new GizmoNode();
1247
+ const transform = node.entity.getComponent(Transform);
1248
+ node.entity.add(shaded_geometry);
1249
+
1250
+ /**
1251
+ * @type {number[]|undefined}
1252
+ */
1253
+ const position = gizmo_element[1];
1254
+
1255
+ /**
1256
+ * @type {number[]|undefined}
1257
+ */
1258
+ const rotation = gizmo_element[2];
1259
+
1260
+ /**
1261
+ * @type {number[]|undefined}
1262
+ */
1263
+ const scale = gizmo_element[3];
1264
+
1265
+ /**
1266
+ * @type {string|undefined}
1267
+ */
1268
+ const tag = gizmo_element[4];
1269
+
1270
+ // name and tag properties are essential for picking and updating logic.
1271
+ node.name = name;
1272
+ node.tag = tag;
1273
+
1274
+ if (position) {
1275
+
1276
+ transform.position.set(position[0], position[1], position[2]);
1277
+
1278
+ }
1279
+
1280
+ if (rotation) {
1281
+
1282
+ transform.rotation.fromEulerAnglesXYZ(rotation[0], rotation[1], rotation[2]);
1283
+
1284
+ }
1285
+
1286
+ if (scale) {
1287
+
1288
+ transform.scale.set(scale[0], scale[1], scale[2]);
1289
+
1290
+ }
1291
+
1292
+ const tempGeometry = shaded_geometry.geometry.clone();
1293
+ const m4 = new Matrix4();
1294
+ transform.toMatrix4(m4.elements);
1295
+ tempGeometry.applyMatrix4(m4);
1296
+
1297
+ shaded_geometry.geometry = tempGeometry;
1298
+ // TODO add support for render order to ShadedGeometry
1299
+ shaded_geometry.renderOrder = Infinity;
1300
+
1301
+ transform.makeIdentity();
1302
+
1303
+ gizmo.addChild(node);
1304
+
1305
+ }
1306
+
1307
+ }
1308
+
1309
+ return gizmo;
1310
+
1311
+ }
1312
+
1313
+ // Gizmo creation
1314
+
1315
+ /**
1316
+ *
1317
+ * @type {Object<EntityNode>}
1318
+ */
1319
+ this.gizmo = {};
1320
+ /**
1321
+ *
1322
+ * @type {Object<EntityNode>}
1323
+ */
1324
+ this.picker = {};
1325
+ /**
1326
+ *
1327
+ * @type {Object<EntityNode>}
1328
+ */
1329
+ this.helper = {};
1330
+
1331
+ this.addChild(this.gizmo['translate'] = setupGizmo(gizmoTranslate));
1332
+ this.addChild(this.gizmo['rotate'] = setupGizmo(gizmoRotate));
1333
+ this.addChild(this.gizmo['scale'] = setupGizmo(gizmoScale));
1334
+ this.addChild(this.picker['translate'] = setupGizmo(pickerTranslate));
1335
+ this.addChild(this.picker['rotate'] = setupGizmo(pickerRotate));
1336
+ this.addChild(this.picker['scale'] = setupGizmo(pickerScale));
1337
+ this.addChild(this.helper['translate'] = setupGizmo(helperTranslate));
1338
+ this.addChild(this.helper['rotate'] = setupGizmo(helperRotate));
1339
+ this.addChild(this.helper['scale'] = setupGizmo(helperScale));
1340
+
1341
+ // Pickers should be hidden always
1342
+
1343
+ this.picker['translate'].visible = false;
1344
+ this.picker['rotate'].visible = false;
1345
+ this.picker['scale'].visible = false;
1346
+ }
1347
+
1348
+ // updateMatrixWorld will update transformations and appearance of individual handles
1349
+
1350
+ update(force) {
1351
+
1352
+ const space = (this.mode === 'scale') ? 'local' : this.space; // scale always oriented to local rotation
1353
+
1354
+ const quaternion = (space === 'local') ? this.worldQuaternion : _identityQuaternion;
1355
+
1356
+ // Show only gizmos for current transform mode
1357
+
1358
+ this.gizmo['translate'].visible = this.mode === 'translate';
1359
+ this.gizmo['rotate'].visible = this.mode === 'rotate';
1360
+ this.gizmo['scale'].visible = this.mode === 'scale';
1361
+
1362
+ this.helper['translate'].visible = this.mode === 'translate';
1363
+ this.helper['rotate'].visible = this.mode === 'rotate';
1364
+ this.helper['scale'].visible = this.mode === 'scale';
1365
+
1366
+ /**
1367
+ *
1368
+ * @type {(GizmoNode|{name:string,tag:string})[]}
1369
+ */
1370
+ let handles = [];
1371
+ handles = handles.concat(this.picker[this.mode].children);
1372
+ handles = handles.concat(this.gizmo[this.mode].children);
1373
+ handles = handles.concat(this.helper[this.mode].children);
1374
+
1375
+ for (let i = 0; i < handles.length; i++) {
1376
+
1377
+ const handle = handles[i];
1378
+
1379
+ // hide aligned to camera
1380
+
1381
+ handle.visible = true;
1382
+ handle.transform.rotation.fromEulerAnglesXYZ(0, 0, 0);
1383
+ handle.transform.position.copy(this.worldPosition);
1384
+
1385
+ let factor;
1386
+
1387
+ if (this.camera.isOrthographicCamera) {
1388
+
1389
+ factor = (this.camera.top - this.camera.bottom) / this.camera.zoom;
1390
+
1391
+ } else {
1392
+
1393
+ factor = this.worldPosition.distanceTo(this.cameraPosition) * Math.min(1.9 * Math.tan(Math.PI * this.camera.fov / 360) / this.camera.zoom, 7);
1394
+
1395
+ }
1396
+
1397
+ if (factor === 0) {
1398
+ // prevent 0 size
1399
+ factor = 1e-10;
1400
+ }
1401
+
1402
+ handle.transform.scale.setScalar(factor * this.size / 4);
1403
+
1404
+ // TODO: simplify helpers and consider decoupling from gizmo
1405
+
1406
+ if (handle.tag === 'helper') {
1407
+ handle.visible = false;
1408
+
1409
+ if (handle.name === 'AXIS') {
1410
+
1411
+ handle.transform.position.copy(this.worldPositionStart);
1412
+ handle.visible = !!this.axis;
1413
+
1414
+ if (this.axis === 'X') {
1415
+
1416
+ _tempQuaternion.setFromEuler(_tempEuler.set(0, 0, 0));
1417
+ handle.transform.rotation.copy(quaternion);
1418
+ handle.transform.rotation.multiply(_tempQuaternion);
1419
+
1420
+ if (Math.abs(_alignVector.copy(_unitX).applyQuaternion(quaternion).dot(this.eye)) > 0.9) {
1421
+
1422
+ handle.visible = false;
1423
+
1424
+ }
1425
+
1426
+ }
1427
+
1428
+ if (this.axis === 'Y') {
1429
+
1430
+ _tempQuaternion.setFromEuler(_tempEuler.set(0, 0, Math.PI / 2));
1431
+ handle.transform.rotation.copy(quaternion);
1432
+ handle.transform.rotation.multiply(_tempQuaternion);
1433
+
1434
+ if (Math.abs(_alignVector.copy(_unitY).applyQuaternion(quaternion).dot(this.eye)) > 0.9) {
1435
+
1436
+ handle.visible = false;
1437
+
1438
+ }
1439
+
1440
+ }
1441
+
1442
+ if (this.axis === 'Z') {
1443
+
1444
+ _tempQuaternion.setFromEuler(_tempEuler.set(0, Math.PI / 2, 0));
1445
+ handle.transform.rotation.copy(quaternion);
1446
+ handle.transform.rotation.multiply(_tempQuaternion);
1447
+
1448
+ if (Math.abs(_alignVector.copy(_unitZ).applyQuaternion(quaternion).dot(this.eye)) > 0.9) {
1449
+
1450
+ handle.visible = false;
1451
+
1452
+ }
1453
+
1454
+ }
1455
+
1456
+ if (this.axis === 'XYZE') {
1457
+
1458
+ _tempQuaternion.setFromEuler(_tempEuler.set(0, Math.PI / 2, 0));
1459
+ _alignVector.copy(this.rotationAxis);
1460
+ handle.transform.rotation.setFromRotationMatrix(_lookAtMatrix.lookAt(_zeroVector, _alignVector, _unitY));
1461
+ handle.transform.rotation.multiply(_tempQuaternion);
1462
+ handle.visible = this.dragging;
1463
+
1464
+ }
1465
+
1466
+ if (this.axis === 'E') {
1467
+
1468
+ handle.visible = false;
1469
+
1470
+ }
1471
+
1472
+
1473
+ } else if (handle.name === 'START') {
1474
+
1475
+ handle.transform.position.copy(this.worldPositionStart);
1476
+ handle.visible = this.dragging;
1477
+
1478
+ } else if (handle.name === 'END') {
1479
+
1480
+ handle.transform.position.copy(this.worldPosition);
1481
+ handle.visible = this.dragging;
1482
+
1483
+ } else if (handle.name === 'DELTA') {
1484
+
1485
+ handle.transform.position.copy(this.worldPositionStart);
1486
+ handle.transform.rotation.copy(this.worldQuaternionStart);
1487
+ _tempVector.set(1e-10, 1e-10, 1e-10).add(this.worldPositionStart).sub(this.worldPosition).multiplyScalar(-1);
1488
+ _tempVector.applyQuaternion(this.worldQuaternionStart.clone().invert());
1489
+ handle.transform.scale.copy(_tempVector);
1490
+ handle.visible = this.dragging;
1491
+
1492
+ } else {
1493
+
1494
+ handle.transform.rotation.copy(quaternion);
1495
+
1496
+ if (this.dragging) {
1497
+
1498
+ handle.transform.position.copy(this.worldPositionStart);
1499
+
1500
+ } else {
1501
+
1502
+ handle.transform.position.copy(this.worldPosition);
1503
+
1504
+ }
1505
+
1506
+ if (this.axis) {
1507
+
1508
+ handle.visible = this.axis.search(handle.name) !== -1;
1509
+
1510
+ }
1511
+
1512
+ }
1513
+
1514
+ // If updating helper, skip rest of the loop
1515
+ continue;
1516
+
1517
+ }
1518
+
1519
+ // Align handles to current local or world rotation
1520
+
1521
+ handle.transform.rotation.copy(quaternion);
1522
+
1523
+ if (this.mode === 'translate' || this.mode === 'scale') {
1524
+
1525
+ // Hide translate and scale axis facing the camera
1526
+
1527
+ const AXIS_HIDE_TRESHOLD = 0.99;
1528
+ const PLANE_HIDE_TRESHOLD = 0.2;
1529
+
1530
+ if (handle.name === 'X') {
1531
+
1532
+ if (Math.abs(_alignVector.copy(_unitX).applyQuaternion(quaternion).dot(this.eye)) > AXIS_HIDE_TRESHOLD) {
1533
+
1534
+ handle.transform.scale.set(1e-10, 1e-10, 1e-10);
1535
+ handle.visible = false;
1536
+
1537
+ }
1538
+
1539
+ }
1540
+
1541
+ if (handle.name === 'Y') {
1542
+
1543
+ if (Math.abs(_alignVector.copy(_unitY).applyQuaternion(quaternion).dot(this.eye)) > AXIS_HIDE_TRESHOLD) {
1544
+
1545
+ handle.transform.scale.set(1e-10, 1e-10, 1e-10);
1546
+ handle.visible = false;
1547
+
1548
+ }
1549
+
1550
+ }
1551
+
1552
+ if (handle.name === 'Z') {
1553
+
1554
+ if (Math.abs(_alignVector.copy(_unitZ).applyQuaternion(quaternion).dot(this.eye)) > AXIS_HIDE_TRESHOLD) {
1555
+
1556
+ handle.transform.scale.set(1e-10, 1e-10, 1e-10);
1557
+ handle.visible = false;
1558
+
1559
+ }
1560
+
1561
+ }
1562
+
1563
+ if (handle.name === 'XY') {
1564
+
1565
+ if (Math.abs(_alignVector.copy(_unitZ).applyQuaternion(quaternion).dot(this.eye)) < PLANE_HIDE_TRESHOLD) {
1566
+
1567
+ handle.transform.scale.set(1e-10, 1e-10, 1e-10);
1568
+ handle.visible = false;
1569
+
1570
+ }
1571
+
1572
+ }
1573
+
1574
+ if (handle.name === 'YZ') {
1575
+
1576
+ if (Math.abs(_alignVector.copy(_unitX).applyQuaternion(quaternion).dot(this.eye)) < PLANE_HIDE_TRESHOLD) {
1577
+
1578
+ handle.transform.scale.set(1e-10, 1e-10, 1e-10);
1579
+ handle.visible = false;
1580
+
1581
+ }
1582
+
1583
+ }
1584
+
1585
+ if (handle.name === 'XZ') {
1586
+
1587
+ if (Math.abs(_alignVector.copy(_unitY).applyQuaternion(quaternion).dot(this.eye)) < PLANE_HIDE_TRESHOLD) {
1588
+
1589
+ handle.transform.scale.set(1e-10, 1e-10, 1e-10);
1590
+ handle.visible = false;
1591
+
1592
+ }
1593
+
1594
+ }
1595
+
1596
+ } else if (this.mode === 'rotate') {
1597
+
1598
+ // Align handles to current local or world rotation
1599
+
1600
+ _tempQuaternion2.copy(quaternion);
1601
+ _alignVector.copy(this.eye).applyQuaternion(_tempQuaternion.copy(quaternion).invert());
1602
+
1603
+ if (handle.name.search('E') !== -1) {
1604
+
1605
+ handle.transform.rotation.setFromRotationMatrix(_lookAtMatrix.lookAt(this.eye, _zeroVector, _unitY));
1606
+
1607
+ }
1608
+
1609
+ if (handle.name === 'X') {
1610
+
1611
+ _tempQuaternion.setFromAxisAngle(_unitX, Math.atan2(-_alignVector.y, _alignVector.z));
1612
+ _tempQuaternion.multiplyQuaternions(_tempQuaternion2, _tempQuaternion);
1613
+ handle.transform.rotation.copy(_tempQuaternion);
1614
+
1615
+ }
1616
+
1617
+ if (handle.name === 'Y') {
1618
+
1619
+ _tempQuaternion.setFromAxisAngle(_unitY, Math.atan2(_alignVector.x, _alignVector.z));
1620
+ _tempQuaternion.multiplyQuaternions(_tempQuaternion2, _tempQuaternion);
1621
+ handle.transform.rotation.copy(_tempQuaternion);
1622
+
1623
+ }
1624
+
1625
+ if (handle.name === 'Z') {
1626
+
1627
+ _tempQuaternion.setFromAxisAngle(_unitZ, Math.atan2(_alignVector.y, _alignVector.x));
1628
+ _tempQuaternion.multiplyQuaternions(_tempQuaternion2, _tempQuaternion);
1629
+ handle.transform.rotation.copy(_tempQuaternion);
1630
+
1631
+ }
1632
+
1633
+ }
1634
+
1635
+ // Hide disabled axes
1636
+ handle.visible = handle.visible && (handle.name.indexOf('X') === -1 || this.showX);
1637
+ handle.visible = handle.visible && (handle.name.indexOf('Y') === -1 || this.showY);
1638
+ handle.visible = handle.visible && (handle.name.indexOf('Z') === -1 || this.showZ);
1639
+ handle.visible = handle.visible && (handle.name.indexOf('E') === -1 || (this.showX && this.showY && this.showZ));
1640
+
1641
+ // highlight selected axis
1642
+ const sg = handle.entity.getComponent(ShadedGeometry);
1643
+
1644
+ sg.material._color = sg.material._color || sg.material.color.clone();
1645
+ sg.material._opacity = sg.material._opacity || sg.material.opacity;
1646
+
1647
+ sg.material.color.copy(sg.material._color);
1648
+ sg.material.opacity = sg.material._opacity;
1649
+
1650
+ if (this.enabled && this.axis) {
1651
+
1652
+ if (handle.name === this.axis) {
1653
+
1654
+ sg.material.color.setHex(0xffff00);
1655
+ sg.material.opacity = 1.0;
1656
+
1657
+ } else if (this.axis.split('').some(function (a) {
1658
+
1659
+ return handle.name === a;
1660
+
1661
+ })) {
1662
+
1663
+ sg.material.color.setHex(0xffff00);
1664
+ sg.material.opacity = 1.0;
1665
+
1666
+ }
1667
+
1668
+ }
1669
+
1670
+ }
1671
+
1672
+ super.update();
1673
+ }
1674
+
1675
+ }
1676
+
1677
+ //
1678
+
1679
+ class TransformControlsPlane extends GizmoNode {
1680
+
1681
+ constructor() {
1682
+
1683
+ super();
1684
+
1685
+ this.entity.add(ShadedGeometry.from(new PlaneGeometry(100000, 100000, 2, 2),
1686
+ new MeshBasicMaterial({
1687
+ visible: false,
1688
+ wireframe: true,
1689
+ side: DoubleSide,
1690
+ transparent: true,
1691
+ opacity: 0.1,
1692
+ toneMapped: false
1693
+ })));
1694
+
1695
+ this.isTransformControlsPlane = true;
1696
+
1697
+ this.type = 'TransformControlsPlane';
1698
+
1699
+
1700
+ this.transform.rotation.onChanged.add(console.warn);
1701
+ }
1702
+
1703
+ update() {
1704
+
1705
+ let space = this.space;
1706
+
1707
+ const transform = this.transform;
1708
+
1709
+ transform.position.copy(this.worldPosition);
1710
+
1711
+ if (this.mode === 'scale') space = 'local'; // scale always oriented to local rotation
1712
+
1713
+ _v1.copy(_unitX).applyQuaternion(space === 'local' ? this.worldQuaternion : _identityQuaternion);
1714
+ _v2.copy(_unitY).applyQuaternion(space === 'local' ? this.worldQuaternion : _identityQuaternion);
1715
+ _v3.copy(_unitZ).applyQuaternion(space === 'local' ? this.worldQuaternion : _identityQuaternion);
1716
+
1717
+ // Align the plane for current transform mode, axis and space.
1718
+
1719
+ _alignVector.copy(_v2);
1720
+
1721
+ switch (this.mode) {
1722
+
1723
+ case 'translate':
1724
+ case 'scale':
1725
+ switch (this.axis) {
1726
+
1727
+ case 'X':
1728
+ _alignVector.copy(this.eye).cross(_v1);
1729
+ _dirVector.copy(_v1).cross(_alignVector);
1730
+ break;
1731
+ case 'Y':
1732
+ _alignVector.copy(this.eye).cross(_v2);
1733
+ _dirVector.copy(_v2).cross(_alignVector);
1734
+ break;
1735
+ case 'Z':
1736
+ _alignVector.copy(this.eye).cross(_v3);
1737
+ _dirVector.copy(_v3).cross(_alignVector);
1738
+ break;
1739
+ case 'XY':
1740
+ _dirVector.copy(_v3);
1741
+ break;
1742
+ case 'YZ':
1743
+ _dirVector.copy(_v1);
1744
+ break;
1745
+ case 'XZ':
1746
+ _alignVector.copy(_v3);
1747
+ _dirVector.copy(_v2);
1748
+ break;
1749
+ case 'XYZ':
1750
+ case 'E':
1751
+ _dirVector.set(0, 0, 0);
1752
+ break;
1753
+
1754
+ }
1755
+
1756
+ break;
1757
+ case 'rotate':
1758
+ default:
1759
+ // special case for rotate
1760
+ _dirVector.set(0, 0, 0);
1761
+
1762
+ }
1763
+
1764
+ if (_dirVector.length() === 0) {
1765
+
1766
+ // If in rotate mode, make the plane parallel to camera
1767
+ transform.rotation.copy(this.cameraQuaternion);
1768
+
1769
+ } else {
1770
+
1771
+ _tempMatrix.lookAt(_tempVector.set(0, 0, 0), _dirVector, _alignVector);
1772
+
1773
+ transform.rotation.setFromRotationMatrix(_tempMatrix);
1774
+
1775
+ }
1776
+
1777
+ super.update();
1778
+ }
1779
+
1780
+ }
1781
+
1782
+ export { TransformControls, TransformControlsGizmo, TransformControlsPlane };