@sapui5/sap.ui.vbm 1.103.0 → 1.104.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/sap/ui/vbm/.library +1 -1
- package/src/sap/ui/vbm/Adapter.js +1 -1
- package/src/sap/ui/vbm/Adapter3D.js +45 -11
- package/src/sap/ui/vbm/ClusterBase.js +2 -2
- package/src/sap/ui/vbm/Viewport.js +8 -3
- package/src/sap/ui/vbm/adapter3d/DragDropHandler.js +972 -0
- package/src/sap/ui/vbm/adapter3d/ModelHandler.js +25 -14
- package/src/sap/ui/vbm/adapter3d/ObjectFactory.js +1 -1
- package/src/sap/ui/vbm/adapter3d/PolygonHandler.js +31 -25
- package/src/sap/ui/vbm/adapter3d/SceneBuilder.js +78 -34
- package/src/sap/ui/vbm/adapter3d/Utilities.js +15 -4
- package/src/sap/ui/vbm/adapter3d/VBIJSONParser.js +58 -3
- package/src/sap/ui/vbm/adapter3d/thirdparty/OrbitControls.js +15 -0
- package/src/sap/ui/vbm/lib/sapscene.js +17 -11
- package/src/sap/ui/vbm/lib/sapvobase.js +1 -1
- package/src/sap/ui/vbm/library.js +2 -2
- package/src/sap/ui/vbm/themes/sap_belize_hcb/AnalyticMap.less +4 -0
- package/src/sap/ui/vbm/themes/sap_belize_hcb/VBI.less +96 -0
- package/src/sap/ui/vbm/themes/sap_belize_hcb/library.source.less +4 -1
|
@@ -0,0 +1,972 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* ! SAP UI development toolkit for HTML5 (SAPUI5) (c) Copyright 2009-2012 SAP AG. All rights reserved
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// Provides class sap.ui.vbm.adapter3d.DragDropHandler
|
|
6
|
+
sap.ui.define([
|
|
7
|
+
"sap/ui/base/Object",
|
|
8
|
+
"./Utilities",
|
|
9
|
+
"./thirdparty/three",
|
|
10
|
+
"sap/base/Log"
|
|
11
|
+
], function(BaseObject, Utilities, THREE, Log) {
|
|
12
|
+
"use strict";
|
|
13
|
+
|
|
14
|
+
// Aliases
|
|
15
|
+
var Color = THREE.Color;
|
|
16
|
+
var Vector2 = THREE.Vector2;
|
|
17
|
+
var Vector3 = THREE.Vector3;
|
|
18
|
+
var Matrix4 = THREE.Matrix4;
|
|
19
|
+
var toColor = Utilities.toColor;
|
|
20
|
+
var toBoolean = Utilities.toBoolean;
|
|
21
|
+
var vbToThreeJs = Utilities.vbToThreeJs;
|
|
22
|
+
var threeJsToVb = Utilities.threeJsToVb;
|
|
23
|
+
var thisModule = "sap.ui.vbm.DragDropHandler";
|
|
24
|
+
|
|
25
|
+
// Constants
|
|
26
|
+
var RED = new Color(1,0,0);
|
|
27
|
+
var GREEN = new Color(0,1,0);
|
|
28
|
+
var BLUE = new Color(0,0,1);
|
|
29
|
+
var BLACK = new Color(0,0,0);
|
|
30
|
+
var CYAN = new Color(0,1,1);
|
|
31
|
+
|
|
32
|
+
var X_DIR = new Vector3(1,0,0);
|
|
33
|
+
var Y_DIR = new Vector3(0,1,0);
|
|
34
|
+
var Z_DIR = new Vector3(0,0,1);
|
|
35
|
+
|
|
36
|
+
var CONFIG_SNAP_X_COLOR = "SNAP_X_COLOR";
|
|
37
|
+
var CONFIG_SNAP_Y_COLOR = "SNAP_Y_COLOR";
|
|
38
|
+
var CONFIG_SNAP_Z_COLOR = "SNAP_Z_COLOR";
|
|
39
|
+
|
|
40
|
+
var CONFIG_SNAP_COLOR = "SNAP_COLOR";
|
|
41
|
+
var CONFIG_SNAP_HIGHLIGHT_COLOR = "SNAP_HIGHLIGHT_COLOR";
|
|
42
|
+
|
|
43
|
+
var DIR_LENGTH = 10000.0;
|
|
44
|
+
var COLLISION_DISTANCE = 0.01;
|
|
45
|
+
var AXIS_SNAP_DISTANCE = 0.04;
|
|
46
|
+
|
|
47
|
+
var SNAP_POINTS_COUNT = 8; // max amount of snapping points
|
|
48
|
+
|
|
49
|
+
// To avoid allocation with every function call
|
|
50
|
+
var _p1 = new Vector3();
|
|
51
|
+
var _p2 = new Vector3();
|
|
52
|
+
var _p3 = new Vector3();
|
|
53
|
+
var _p4 = new Vector3();
|
|
54
|
+
var _p5 = new Vector3();
|
|
55
|
+
var _matrix = new Matrix4();
|
|
56
|
+
var _pointer = new Vector2();
|
|
57
|
+
var _box = new THREE.Box3();
|
|
58
|
+
var _ray = new THREE.Ray();
|
|
59
|
+
var _line = new THREE.Line3();
|
|
60
|
+
var _raycaster = new THREE.Raycaster();
|
|
61
|
+
var _quaternion = new THREE.Quaternion();
|
|
62
|
+
|
|
63
|
+
var STATE = {
|
|
64
|
+
PICK: 0,
|
|
65
|
+
DRAG: 1
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// Viewport event delegate. 'this' object in all methods is DragDropHandler instance
|
|
69
|
+
var viewportEventDelegate = {
|
|
70
|
+
onBeforeRendering: function(event) {
|
|
71
|
+
this._unsubscribe();
|
|
72
|
+
},
|
|
73
|
+
onAfterRendering: function(event) {
|
|
74
|
+
this._subscribe();
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Constructor for a new drag and drop handler.
|
|
80
|
+
*
|
|
81
|
+
* @class
|
|
82
|
+
* Provides a class for handling drag and drop operation.
|
|
83
|
+
*
|
|
84
|
+
* @private
|
|
85
|
+
* @author SAP SE
|
|
86
|
+
* @version 1.104.0
|
|
87
|
+
* @alias sap.ui.vbm.adapter3d.DragDropHandler
|
|
88
|
+
*/
|
|
89
|
+
var DragDropHandler = BaseObject.extend("sap.ui.vbm.adapter3d.DragDropHandler", /** @lends sap.ui.vbm.adapter3d.DragDropHandler.prototype */ {
|
|
90
|
+
|
|
91
|
+
constructor: function(adapter) {
|
|
92
|
+
BaseObject.call(this);
|
|
93
|
+
|
|
94
|
+
this._adapter = adapter; // fire submit event
|
|
95
|
+
this._context = adapter._context; // access evaluated data
|
|
96
|
+
this._viewport = adapter._viewport; // events
|
|
97
|
+
this._root = this._viewport._root;
|
|
98
|
+
this._scene = this._viewport._scene;
|
|
99
|
+
this._camera = this._viewport._camera;
|
|
100
|
+
this._cameraControls = this._viewport._cameraController;
|
|
101
|
+
|
|
102
|
+
// current action state
|
|
103
|
+
this._state = STATE.PICK;
|
|
104
|
+
|
|
105
|
+
// indicate whether snapping enabled during drag and drop
|
|
106
|
+
this._snapping = false;
|
|
107
|
+
|
|
108
|
+
// flag indicates movement is done by X, Y, Z axes only i.e always snapping
|
|
109
|
+
this._snapAlways = false;
|
|
110
|
+
|
|
111
|
+
// flag indicates whether movement is locked to axis or not
|
|
112
|
+
this._lockToAxis = false;
|
|
113
|
+
|
|
114
|
+
// snapped axis (Vector3) and Color or null if it's not snapped to axis
|
|
115
|
+
this._snapAxis = null;
|
|
116
|
+
|
|
117
|
+
// set of instances which marked as changeable and which may participate in drag and drop action, updated with every payload
|
|
118
|
+
this._changeables = new Set();
|
|
119
|
+
|
|
120
|
+
// array of changeable 3d objects for hit test, updated with every payload and with every drag and drop action
|
|
121
|
+
this._changeables3d = [];
|
|
122
|
+
|
|
123
|
+
// Instances participating in drag and drop action, updated with every drag and drop action
|
|
124
|
+
this._instances = [];
|
|
125
|
+
|
|
126
|
+
// drag and drop origin instance
|
|
127
|
+
this._origin = null;
|
|
128
|
+
|
|
129
|
+
// hovered instance
|
|
130
|
+
this._hovered = null;
|
|
131
|
+
|
|
132
|
+
// touch point where Drag and Drop started (world CRD)
|
|
133
|
+
this._touch = null;
|
|
134
|
+
|
|
135
|
+
// offset between touch point and touch object origin
|
|
136
|
+
this._offset = new Vector3();
|
|
137
|
+
|
|
138
|
+
// movement plane
|
|
139
|
+
this._plane = new THREE.Plane();
|
|
140
|
+
|
|
141
|
+
// drag and drop origin object's parent world inverse
|
|
142
|
+
this._inverseMatrix = new Matrix4();
|
|
143
|
+
|
|
144
|
+
// evaluated colors for axes
|
|
145
|
+
this._xAxisColor = RED;
|
|
146
|
+
this._yAxisColor = BLUE;
|
|
147
|
+
this._zAxisColor = GREEN;
|
|
148
|
+
|
|
149
|
+
// Snap line object & materials
|
|
150
|
+
this._lineMaterialSolid = new THREE.LineBasicMaterial({
|
|
151
|
+
depthTest: false,
|
|
152
|
+
depthWrite: false,
|
|
153
|
+
color: 0x000000,
|
|
154
|
+
linewidth: 1,
|
|
155
|
+
transparent: true,
|
|
156
|
+
opacity: 0.99
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
this._lineMaterialDashed = new THREE.LineDashedMaterial({
|
|
160
|
+
depthTest: false,
|
|
161
|
+
depthWrite: false,
|
|
162
|
+
color: 0x000000,
|
|
163
|
+
linewidth: 1,
|
|
164
|
+
scale: 1,
|
|
165
|
+
dashSize: 0.1,
|
|
166
|
+
gapSize: 0.06,
|
|
167
|
+
transparent: true,
|
|
168
|
+
opacity: 0.99
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
this._snapLine = new THREE.Line(
|
|
172
|
+
new THREE.BufferGeometry().setFromPoints([new Vector3(), new Vector3()]),
|
|
173
|
+
this._lineMaterialDashed
|
|
174
|
+
);
|
|
175
|
+
// invisible, layer #1 (disable hit test), render order #1000 (always on top)
|
|
176
|
+
this._addToScene(this._snapLine, this._root, false, 1, 1000);
|
|
177
|
+
|
|
178
|
+
// position and scale for snap points to update when necessary (to avoid matrix decomposition)
|
|
179
|
+
this._snapPointsData = [];
|
|
180
|
+
|
|
181
|
+
for (var i = 0; i < SNAP_POINTS_COUNT; ++i) {
|
|
182
|
+
this._snapPointsData.push({
|
|
183
|
+
pos: new Vector3(),
|
|
184
|
+
scale: new Vector3()
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
this._snapPoints = new THREE.InstancedMesh(
|
|
189
|
+
new THREE.SphereGeometry(1, 16, 16),
|
|
190
|
+
new THREE.MeshBasicMaterial({
|
|
191
|
+
depthTest: false,
|
|
192
|
+
depthWrite: false,
|
|
193
|
+
color: 0x00ffff,
|
|
194
|
+
transparent: true,
|
|
195
|
+
opacity: 0.99
|
|
196
|
+
}),
|
|
197
|
+
SNAP_POINTS_COUNT
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
// invisible, layer #1 (disable hit test), render order #1010 (always on top)
|
|
201
|
+
this._addToScene(this._snapPoints, this._scene, false, 1, 1010);
|
|
202
|
+
|
|
203
|
+
this._snapHighlightPoint = new THREE.Mesh(
|
|
204
|
+
new THREE.SphereGeometry(1, 16, 16),
|
|
205
|
+
new THREE.MeshBasicMaterial({
|
|
206
|
+
depthTest: false,
|
|
207
|
+
depthWrite: true,
|
|
208
|
+
color: 0xff0000,
|
|
209
|
+
transparent: true,
|
|
210
|
+
opacity: 0.99
|
|
211
|
+
})
|
|
212
|
+
);
|
|
213
|
+
// invisible, layer #1 (disable hit test), render order #1020 (always on top)
|
|
214
|
+
this._addToScene(this._snapHighlightPoint, this._scene, false, 1, 1020);
|
|
215
|
+
|
|
216
|
+
this._snapBox = new THREE.BoxHelper(undefined, 0x00ffff);
|
|
217
|
+
// invisible, layer #1 (disable hit test)
|
|
218
|
+
this._addToScene(this._snapBox, this._scene, false, 1);
|
|
219
|
+
|
|
220
|
+
this._viewport.addEventDelegate(viewportEventDelegate, this);
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Destroys drag and drop handler object.
|
|
226
|
+
* @public
|
|
227
|
+
*/
|
|
228
|
+
DragDropHandler.prototype.destroy = function() {
|
|
229
|
+
this._unsubscribe();
|
|
230
|
+
this._viewport.removeEventDelegate(viewportEventDelegate);
|
|
231
|
+
|
|
232
|
+
this._snapBox.geometry.dispose();
|
|
233
|
+
this._snapBox.material.dispose();
|
|
234
|
+
|
|
235
|
+
this._snapPoints.geometry.dispose();
|
|
236
|
+
this._snapPoints.material.dispose();
|
|
237
|
+
|
|
238
|
+
this._snapHighlightPoint.geometry.dispose();
|
|
239
|
+
this._snapHighlightPoint.material.dispose();
|
|
240
|
+
|
|
241
|
+
this._snapLine.geometry.dispose();
|
|
242
|
+
this._lineMaterialSolid.dispose();
|
|
243
|
+
this._lineMaterialDashed.dispose();
|
|
244
|
+
|
|
245
|
+
this._root.remove(this._snapLine);
|
|
246
|
+
this._scene.remove(this._snapBox, this._snapPoints, this._snapHighlightPoint);
|
|
247
|
+
|
|
248
|
+
// reset all
|
|
249
|
+
this._adapter = null;
|
|
250
|
+
this._context = null;
|
|
251
|
+
this._viewport = null;
|
|
252
|
+
this._root = null;
|
|
253
|
+
this._scene = null;
|
|
254
|
+
this._camera = null;
|
|
255
|
+
this._cameraControls = null;
|
|
256
|
+
this._lineMaterialSolid = null;
|
|
257
|
+
this._lineMaterialDashed = null;
|
|
258
|
+
this._snapBox = null;
|
|
259
|
+
this._snapLine = null;
|
|
260
|
+
this._snapPoints = null;
|
|
261
|
+
this._snapHighlightPoint = null;
|
|
262
|
+
|
|
263
|
+
BaseObject.prototype.destroy.call(this);
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Updates list of changeable instances.
|
|
268
|
+
* @public
|
|
269
|
+
*/
|
|
270
|
+
DragDropHandler.prototype.update = function() {
|
|
271
|
+
|
|
272
|
+
this._cancel(); // cancel active drag and drop action if any
|
|
273
|
+
|
|
274
|
+
var scene = this._context.scene;
|
|
275
|
+
var queues = this._context.voQueues;
|
|
276
|
+
|
|
277
|
+
// Visual object instances split by types of changes
|
|
278
|
+
(queues.toAdd.get(scene) || []).forEach(function(instance) {
|
|
279
|
+
if (instance["VB:c"] && (instance.isBox || instance.isCylinder) && toBoolean(instance["VB:c"])) {
|
|
280
|
+
this._changeables.add(instance);
|
|
281
|
+
}
|
|
282
|
+
}, this);
|
|
283
|
+
|
|
284
|
+
(queues.toRemove.get(scene) || []).forEach(function(instance) {
|
|
285
|
+
this._changeables.delete(instance);
|
|
286
|
+
}, this);
|
|
287
|
+
|
|
288
|
+
(queues.toUpdate.get(scene) || []).forEach(function(instance) {
|
|
289
|
+
if (instance["VB:c"] && (instance.isBox || instance.isCylinder) && Utilities.propertyChanged(instance, "VB:c")) {
|
|
290
|
+
if (toBoolean(instance["VB:c"])) {
|
|
291
|
+
this._changeables.add(instance)
|
|
292
|
+
} else {
|
|
293
|
+
this._changeables.delete(instance);
|
|
294
|
+
}
|
|
295
|
+
Utilities.updateProperty(instance, "VB:c");
|
|
296
|
+
}
|
|
297
|
+
}, this);
|
|
298
|
+
|
|
299
|
+
// make array of 3d objects
|
|
300
|
+
this._changeables3d = Array.from(this._changeables, function(instance) {
|
|
301
|
+
return instance.object3D;
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
var cfg = this._context.config;
|
|
305
|
+
|
|
306
|
+
this._xAxisColor = cfg.has(CONFIG_SNAP_X_COLOR) ? toColor(cfg.get(CONFIG_SNAP_X_COLOR)).rgb : RED;
|
|
307
|
+
this._yAxisColor = cfg.has(CONFIG_SNAP_Y_COLOR) ? toColor(cfg.get(CONFIG_SNAP_Y_COLOR)).rgb : BLUE;
|
|
308
|
+
this._zAxisColor = cfg.has(CONFIG_SNAP_Z_COLOR) ? toColor(cfg.get(CONFIG_SNAP_Z_COLOR)).rgb : GREEN;
|
|
309
|
+
|
|
310
|
+
var snapColor = cfg.has(CONFIG_SNAP_COLOR) ? toColor(cfg.get(CONFIG_SNAP_COLOR)).rgb : CYAN;
|
|
311
|
+
var snapHighlightColor = cfg.has(CONFIG_SNAP_HIGHLIGHT_COLOR) ? toColor(cfg.get(CONFIG_SNAP_HIGHLIGHT_COLOR)).rgb : RED;
|
|
312
|
+
|
|
313
|
+
this._snapBox.material.color.copy(snapColor);
|
|
314
|
+
this._snapBox.material.needsUpdate = true;
|
|
315
|
+
|
|
316
|
+
this._snapPoints.material.color.copy(snapColor);
|
|
317
|
+
this._snapPoints.material.needsUpdate = true;
|
|
318
|
+
|
|
319
|
+
this._snapHighlightPoint.material.color.copy(snapHighlightColor);
|
|
320
|
+
this._snapHighlightPoint.material.needsUpdate = true;
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
DragDropHandler.prototype._onKeyUp = function(event) {
|
|
324
|
+
if (!event.repeat) {
|
|
325
|
+
this._handleKeyPress(event, false);
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
DragDropHandler.prototype._onKeyDown = function(event) {
|
|
330
|
+
if (!event.repeat) {
|
|
331
|
+
this._handleKeyPress(event, true);
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
DragDropHandler.prototype._onPointerDown = function(event) {
|
|
336
|
+
this._mouseDown = true;
|
|
337
|
+
|
|
338
|
+
if (this._hovered) {
|
|
339
|
+
var point;
|
|
340
|
+
|
|
341
|
+
if (this._snapHighlightPoint.visible) {
|
|
342
|
+
this._snapping = true; // drag and drop starts from snapping point -> snapping enabled
|
|
343
|
+
point = this._snapHighlightPoint.position;
|
|
344
|
+
} else {
|
|
345
|
+
_raycaster.layers.set(0);
|
|
346
|
+
_raycaster.setFromCamera(this._updatePointer(event, _pointer), this._camera);
|
|
347
|
+
var intersections = _raycaster.intersectObject(this._hovered, false);
|
|
348
|
+
|
|
349
|
+
if (intersections.length > 0) {
|
|
350
|
+
point = intersections[0].point;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
if (point) {
|
|
355
|
+
this._dom.style.cursor = "move";
|
|
356
|
+
this._dragStart(point);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
DragDropHandler.prototype._onPointerMove = function(event) {
|
|
362
|
+
// nothing to do as camera is operating
|
|
363
|
+
if (this._mouseDown && this._cameraControls.enabled) {
|
|
364
|
+
this._snapBox.visible = false;
|
|
365
|
+
this._snapLine.visible = false;
|
|
366
|
+
this._snapPoints.visible = false;
|
|
367
|
+
this._snapHighlightPoint.visible = false;
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
this._updatePointer(event, _pointer);
|
|
372
|
+
|
|
373
|
+
// if drag started
|
|
374
|
+
if (this._state === STATE.DRAG) {
|
|
375
|
+
_raycaster.layers.set(0);
|
|
376
|
+
_raycaster.setFromCamera(_pointer, this._camera);
|
|
377
|
+
if (_raycaster.ray.intersectPlane(this._plane, _p1)) {
|
|
378
|
+
this._drag(_p1.sub(this._offset).applyMatrix4(this._inverseMatrix), _pointer, event.ctrlKey, event.shiftKey);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// hover support for PICK state or DRAG with snapping enabled
|
|
383
|
+
if (this._state === STATE.PICK || this._snapping) {
|
|
384
|
+
this._handleHover(_pointer);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// handle snapping highlight point only in PICK state
|
|
388
|
+
if (this._state === STATE.PICK && this._snapPoints.visible) {
|
|
389
|
+
_raycaster.layers.set(1);
|
|
390
|
+
var intersections = _raycaster.intersectObject(this._snapPoints, false);
|
|
391
|
+
|
|
392
|
+
if (intersections.length > 0) {
|
|
393
|
+
var instanceId = intersections[0].instanceId;
|
|
394
|
+
this._snapHighlightPoint.scale.copy(this._snapPointsData[instanceId].scale);
|
|
395
|
+
this._snapHighlightPoint.position.copy(this._snapPointsData[instanceId].pos);
|
|
396
|
+
this._snapHighlightPoint.updateMatrix();
|
|
397
|
+
this._snapHighlightPoint.visible = true;
|
|
398
|
+
} else {
|
|
399
|
+
this._snapHighlightPoint.visible = false;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
DragDropHandler.prototype._onPointerCancel = function(event) {
|
|
405
|
+
this._mouseDown = false;
|
|
406
|
+
this._dom.style.cursor = this._hovered ? "pointer" : "auto";
|
|
407
|
+
this._dragEnd();
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
DragDropHandler.prototype._handleHover = function(pointer) {
|
|
411
|
+
var intersections = [], bbox = false;
|
|
412
|
+
|
|
413
|
+
_raycaster.layers.set(0);
|
|
414
|
+
_raycaster.setFromCamera(pointer, this._camera);
|
|
415
|
+
_raycaster.intersectObjects(this._changeables3d, false, intersections);
|
|
416
|
+
|
|
417
|
+
if (this._hovered !== null) {
|
|
418
|
+
if (!this._hovered.geometry.boundingBox) {
|
|
419
|
+
this._hovered.geometry.computeBoundingBox();
|
|
420
|
+
}
|
|
421
|
+
_box.copy(this._hovered.geometry.boundingBox);
|
|
422
|
+
_box.applyMatrix4(this._hovered.matrixWorld);
|
|
423
|
+
|
|
424
|
+
if (_raycaster.ray.intersectBox(_box, _p1)) {
|
|
425
|
+
bbox = true;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
if (!bbox) {
|
|
430
|
+
if (intersections.length > 0) {
|
|
431
|
+
var object = intersections[0].object;
|
|
432
|
+
|
|
433
|
+
if (this._hovered !== object && this._hovered !== null) {
|
|
434
|
+
this._hovered = null;
|
|
435
|
+
this._dom.style.cursor = "auto";
|
|
436
|
+
this._hoverOff();
|
|
437
|
+
}
|
|
438
|
+
if (this._hovered !== object) {
|
|
439
|
+
this._hovered = object;
|
|
440
|
+
this._dom.style.cursor = "pointer";
|
|
441
|
+
this._hoverOn(this._hovered);
|
|
442
|
+
}
|
|
443
|
+
} else if (this._hovered !== null) {
|
|
444
|
+
this._hovered = null;
|
|
445
|
+
this._dom.style.cursor = "auto";
|
|
446
|
+
this._hoverOff();
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
DragDropHandler.prototype._handleKeyPress = function(event, down) {
|
|
452
|
+
if (event.keyCode === 16) { // Shift
|
|
453
|
+
this._lockToAxis = down;
|
|
454
|
+
this._updateSnapLine();
|
|
455
|
+
} else if (event.keyCode === 20) { // Caps Lock
|
|
456
|
+
this._snapAlways = event.getModifierState("CapsLock");
|
|
457
|
+
this._updateSnapLine();
|
|
458
|
+
} else if (event.keyCode === 27 && down) { // Esc
|
|
459
|
+
this._cancel();
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
DragDropHandler.prototype._dragStart = function(intersection) {
|
|
464
|
+
this._plane.setFromNormalAndCoplanarPoint(this._camera.getWorldDirection(this._plane.normal), intersection);
|
|
465
|
+
this._inverseMatrix.copy(this._hovered.parent.matrixWorld).invert();
|
|
466
|
+
this._offset.copy(intersection).sub(_p1.setFromMatrixPosition(this._hovered.matrixWorld));
|
|
467
|
+
this._touch = Utilities.threeJsToVb(intersection);
|
|
468
|
+
|
|
469
|
+
this._instances.length = 0;
|
|
470
|
+
// if drag and drop starts from selected instance then all selected and changeable instances participate in drag and drop
|
|
471
|
+
// otherwise only that instance participate in drag and drop
|
|
472
|
+
var hoveredSelected = toBoolean(this._hovered._sapInstance["VB:s"]);
|
|
473
|
+
this._changeables.forEach(function(instance) {
|
|
474
|
+
if (instance === this._hovered._sapInstance || (hoveredSelected && toBoolean(instance["VB:s"]))) {
|
|
475
|
+
this._instances.push(instance);
|
|
476
|
+
instance._last.dragStart = instance.object3D.position.clone();
|
|
477
|
+
// check if instance has Decals on it -> prepare them as well
|
|
478
|
+
var decals = this._adapter._sceneBuilder._instanceDecals.get(instance);
|
|
479
|
+
if (decals) {
|
|
480
|
+
decals.forEach(function(decal) {
|
|
481
|
+
decal._last.dragStart = decal.object3D.position.clone();
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
// remove drag and drop participating object from the list of changeable objects for hit test
|
|
485
|
+
this._changeables3d.splice(this._changeables3d.indexOf(instance.object3D), 1);
|
|
486
|
+
}
|
|
487
|
+
}, this);
|
|
488
|
+
|
|
489
|
+
this._origin = this._hovered;
|
|
490
|
+
this._hovered = null;
|
|
491
|
+
this._state = STATE.DRAG;
|
|
492
|
+
|
|
493
|
+
this._snapBox.visible = false;
|
|
494
|
+
this._snapPoints.visible = false;
|
|
495
|
+
this._snapHighlightPoint.visible = false;
|
|
496
|
+
|
|
497
|
+
this._cameraControls.setEnabled(false);
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
DragDropHandler.prototype._drag = function(position, pointer, ctrl, shift) {
|
|
501
|
+
var i, proceed = true, snapped = false, distance, minDistance = Number.MAX_VALUE;
|
|
502
|
+
var delta = position.clone().sub(this._origin._sapInstance._last.dragStart);
|
|
503
|
+
|
|
504
|
+
// if drag with snapping initiated then try to snap to closest snapping point
|
|
505
|
+
_p1.set(pointer.x, pointer.y, 0);
|
|
506
|
+
|
|
507
|
+
if (this._snapping && this._snapPoints.visible) {
|
|
508
|
+
for (i = 0; i < SNAP_POINTS_COUNT; ++i) {
|
|
509
|
+
_p2.copy(this._snapPointsData[i].pos);
|
|
510
|
+
_p3.copy(_p2);
|
|
511
|
+
_p2.project(this._camera);
|
|
512
|
+
_p2.z = 0;
|
|
513
|
+
distance = _p1.distanceTo(_p2);
|
|
514
|
+
if (distance < AXIS_SNAP_DISTANCE && distance < minDistance) {
|
|
515
|
+
snapped = true;
|
|
516
|
+
minDistance = distance;
|
|
517
|
+
threeJsToVb(_p3, _p3);
|
|
518
|
+
threeJsToVb(this._offset, _p4);
|
|
519
|
+
_p5.copy(_p3.sub(this._origin._sapInstance._last.dragStart));
|
|
520
|
+
_p5.sub(_p4);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
if (snapped) {
|
|
526
|
+
delta.copy(_p5);
|
|
527
|
+
} else {
|
|
528
|
+
var snapAxis = [
|
|
529
|
+
{dir: X_DIR, color: this._xAxisColor},
|
|
530
|
+
{dir: Y_DIR, color: this._yAxisColor},
|
|
531
|
+
{dir: Z_DIR, color: this._zAxisColor}
|
|
532
|
+
];
|
|
533
|
+
|
|
534
|
+
if (!this._lockToAxis) {
|
|
535
|
+
// calc snapping distance for each axis
|
|
536
|
+
snapAxis.forEach(function(item) {
|
|
537
|
+
item.distance = this._getAxisSnapDistance(this._touch, delta, item.dir);
|
|
538
|
+
}, this);
|
|
539
|
+
|
|
540
|
+
// find min distance
|
|
541
|
+
snapAxis.sort(function(a, b) {
|
|
542
|
+
return a.distance < b.distance ? -1 : 1;
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
// correct delta if snapping threshold reached
|
|
546
|
+
if (snapAxis[0].distance < AXIS_SNAP_DISTANCE || this._snapAlways) {
|
|
547
|
+
this._snapAxis = snapAxis[0];
|
|
548
|
+
} else {
|
|
549
|
+
this._snapAxis = null;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
this._updateSnapLine(); // update type & color
|
|
554
|
+
|
|
555
|
+
if (this._snapAxis) {
|
|
556
|
+
this._getAxisSnapPosition(this._touch, delta, this._snapAxis.dir, delta);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// if collision detection enabled
|
|
561
|
+
if (ctrl) {
|
|
562
|
+
for (i = 0; i < this._instances.length; ++i) {
|
|
563
|
+
var instance = this._instances[i];
|
|
564
|
+
var pos = instance._last.dragStart.clone().add(delta);
|
|
565
|
+
var world = new Matrix4().compose(pos, instance.object3D.quaternion, instance.object3D.scale);
|
|
566
|
+
world.multiplyMatrices(instance.object3D.parent.matrixWorld, world);
|
|
567
|
+
|
|
568
|
+
if (!instance.object3D.geometry.boundingBox) {
|
|
569
|
+
instance.object3D.geometry.computeBoundingBox();
|
|
570
|
+
}
|
|
571
|
+
var box = new THREE.Box3().copy(instance.object3D.geometry.boundingBox);
|
|
572
|
+
box.applyMatrix4(world);
|
|
573
|
+
|
|
574
|
+
if (this._isCollide(this._scene, box)) {
|
|
575
|
+
proceed = false;
|
|
576
|
+
break;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
if (proceed) {
|
|
582
|
+
this._updateSnapLineGeometry(this._touch, delta);
|
|
583
|
+
|
|
584
|
+
for (i = 0; i < this._instances.length; ++i) {
|
|
585
|
+
this._instances[i].object3D.position.copy(this._instances[i]._last.dragStart).add(delta);
|
|
586
|
+
this._instances[i].object3D.updateMatrix();
|
|
587
|
+
|
|
588
|
+
var decals = this._adapter._sceneBuilder._instanceDecals.get(this._instances[i]);
|
|
589
|
+
if (decals) {
|
|
590
|
+
vbToThreeJs(delta, _p1); // convert delta from VB to ThreeJs as Decals are not in VB CRS
|
|
591
|
+
decals.forEach(function(decal) {
|
|
592
|
+
decal.object3D.position.copy(decal._last.dragStart).add(_p1);
|
|
593
|
+
decal.object3D.updateMatrix();
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
// objects have moved -> adjust camera clipping planes
|
|
598
|
+
this._viewport._resetBBox();
|
|
599
|
+
this._viewport._updateCamera();
|
|
600
|
+
}
|
|
601
|
+
this._snapLine.visible = true;
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
DragDropHandler.prototype._dragEnd = function() {
|
|
605
|
+
if (this._state !== STATE.DRAG) {
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
// generate submit event
|
|
610
|
+
var dataMap = new Map();
|
|
611
|
+
|
|
612
|
+
var payload = {
|
|
613
|
+
version : "2.0",
|
|
614
|
+
"xmlns:VB" : "VB",
|
|
615
|
+
Data: {
|
|
616
|
+
Merge: {
|
|
617
|
+
N: []
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
};
|
|
621
|
+
|
|
622
|
+
this._instances.forEach(function(instance) {
|
|
623
|
+
if (instance.id) {
|
|
624
|
+
if (instance.voGroup.isDataBound) {
|
|
625
|
+
var dataType = instance.voGroup.datasource; // VO group data source linked to a DataType by name
|
|
626
|
+
var data = dataMap.get(dataType);
|
|
627
|
+
|
|
628
|
+
if (!data) {
|
|
629
|
+
data = {
|
|
630
|
+
name: dataType,
|
|
631
|
+
E: []
|
|
632
|
+
};
|
|
633
|
+
dataMap.set(dataType, data);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
var attr = instance.voGroup.template.pos;
|
|
637
|
+
var posAttr = attr.path[attr.path.length - 1]; // last entry on path is attribute name
|
|
638
|
+
var posAlias = this._adapter._parser.getAttributeAlias(dataType, posAttr);
|
|
639
|
+
var keyAlias = this._adapter._parser.getAttributeAlias(dataType, instance.voGroup.keyAttributeName);
|
|
640
|
+
var pos = instance.object3D.position;
|
|
641
|
+
var value = pos.x.toFixed(5) + ";" + pos.y.toFixed(5) + ";" + pos.z.toFixed(5);
|
|
642
|
+
|
|
643
|
+
// make sure position is updated in all 3 places:
|
|
644
|
+
// evaluated instance
|
|
645
|
+
// instance last changed values
|
|
646
|
+
// and in instance's data instance
|
|
647
|
+
instance.dataInstance[posAttr] = instance._last.pos = instance.pos = value;
|
|
648
|
+
|
|
649
|
+
var obj = {};
|
|
650
|
+
obj[keyAlias] = instance.id;
|
|
651
|
+
obj[posAlias] = value;
|
|
652
|
+
|
|
653
|
+
data.E.push(obj);
|
|
654
|
+
} else {
|
|
655
|
+
Log.error("Only data bound instance can be included in Data.Merge section", instance.id, thisModule);
|
|
656
|
+
}
|
|
657
|
+
} else {
|
|
658
|
+
Log.error("Cannot process instance without id", instance, thisModule);
|
|
659
|
+
}
|
|
660
|
+
}, this);
|
|
661
|
+
|
|
662
|
+
// don't fire empty events
|
|
663
|
+
if (dataMap.size > 0) {
|
|
664
|
+
dataMap.forEach(function(item) {
|
|
665
|
+
payload.Data.Merge.N.push(item);
|
|
666
|
+
});
|
|
667
|
+
|
|
668
|
+
this._adapter.fireSubmit({
|
|
669
|
+
data: JSON.stringify(payload)
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
this._state = STATE.PICK;
|
|
674
|
+
this._hovered = null;
|
|
675
|
+
this._origin = null;
|
|
676
|
+
this._touch = null;
|
|
677
|
+
this._snapping = false;
|
|
678
|
+
this._snapLine.visible = false;
|
|
679
|
+
this._instances.length = 0;
|
|
680
|
+
this._changeables3d = Array.from(this._changeables, function(instance) {
|
|
681
|
+
return instance.object3D;
|
|
682
|
+
});
|
|
683
|
+
this._cameraControls.setEnabled(true);
|
|
684
|
+
};
|
|
685
|
+
|
|
686
|
+
DragDropHandler.prototype._hoverOn = function(obj) {
|
|
687
|
+
var that = this;
|
|
688
|
+
|
|
689
|
+
if (!obj.geometry.boundingBox) {
|
|
690
|
+
obj.geometry.computeBoundingBox();
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
_box.copy(obj.geometry.boundingBox);
|
|
694
|
+
_box.applyMatrix4(obj.matrixWorld);
|
|
695
|
+
|
|
696
|
+
function pos(index, x, y, z) {
|
|
697
|
+
that._snapPointsData[index].pos.set(x, y, z);
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
pos(0, _box.min.x, _box.min.y, _box.min.z);
|
|
701
|
+
pos(1, _box.min.x, _box.min.y, _box.max.z);
|
|
702
|
+
pos(2, _box.min.x, _box.max.y, _box.min.z);
|
|
703
|
+
pos(3, _box.min.x, _box.max.y, _box.max.z);
|
|
704
|
+
pos(4, _box.max.x, _box.min.y, _box.min.z);
|
|
705
|
+
pos(5, _box.max.x, _box.min.y, _box.max.z);
|
|
706
|
+
pos(6, _box.max.x, _box.max.y, _box.min.z);
|
|
707
|
+
pos(7, _box.max.x, _box.max.y, _box.max.z);
|
|
708
|
+
|
|
709
|
+
this._snapPoints.visible = true;
|
|
710
|
+
this._updateSnapPoints();
|
|
711
|
+
|
|
712
|
+
this._snapBox.visible = true;
|
|
713
|
+
this._snapBox.setFromObject(obj);
|
|
714
|
+
};
|
|
715
|
+
|
|
716
|
+
DragDropHandler.prototype._hoverOff = function() {
|
|
717
|
+
this._snapBox.visible = false;
|
|
718
|
+
this._snapPoints.visible = false;
|
|
719
|
+
this._snapHighlightPoint.visible = false;
|
|
720
|
+
};
|
|
721
|
+
|
|
722
|
+
DragDropHandler.prototype._isCollide = function(object, box) {
|
|
723
|
+
var i;
|
|
724
|
+
if (object.visible && object.geometry && Utilities.layersEnabled(object.layers, 0) && this._instances.indexOf(object._sapInstance) < 0) {
|
|
725
|
+
object.updateWorldMatrix(false, false);
|
|
726
|
+
if (!object.geometry.boundingBox) {
|
|
727
|
+
object.geometry.computeBoundingBox();
|
|
728
|
+
}
|
|
729
|
+
if (object.isInstancedMesh) {
|
|
730
|
+
for (i = 0; i < object.count; ++i) {
|
|
731
|
+
object.getMatrixAt(i, _matrix);
|
|
732
|
+
_box.copy(object.geometry.boundingBox);
|
|
733
|
+
_box.applyMatrix4(_matrix);
|
|
734
|
+
|
|
735
|
+
if (_box.intersectsBox(box)) {
|
|
736
|
+
return true;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
} else {
|
|
740
|
+
_box.copy(object.geometry.boundingBox);
|
|
741
|
+
_box.applyMatrix4(object.matrixWorld);
|
|
742
|
+
|
|
743
|
+
if (_box.intersectsBox(box)) {
|
|
744
|
+
return true;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
var children = object.children;
|
|
750
|
+
for (i = 0; i < children.length; ++i) {
|
|
751
|
+
if (this._isCollide(children[i], box)) {
|
|
752
|
+
return true;
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
return false;
|
|
756
|
+
};
|
|
757
|
+
|
|
758
|
+
DragDropHandler.prototype._updateSnapLineGeometry = function(from, delta) {
|
|
759
|
+
var pos = this._snapLine.geometry.attributes.position;
|
|
760
|
+
pos.needsUpdate = true;
|
|
761
|
+
|
|
762
|
+
pos.array[0] = from.x;
|
|
763
|
+
pos.array[1] = from.y;
|
|
764
|
+
pos.array[2] = from.z;
|
|
765
|
+
pos.array[3] = from.x + delta.x;
|
|
766
|
+
pos.array[4] = from.y + delta.y;
|
|
767
|
+
pos.array[5] = from.z + delta.z;
|
|
768
|
+
|
|
769
|
+
this._snapLine.geometry.computeBoundingBox();
|
|
770
|
+
this._snapLine.geometry.computeBoundingSphere();
|
|
771
|
+
|
|
772
|
+
if (this._snapLine.material === this._lineMaterialDashed) {
|
|
773
|
+
this._snapLine.computeLineDistances();
|
|
774
|
+
}
|
|
775
|
+
};
|
|
776
|
+
|
|
777
|
+
DragDropHandler.prototype._updateSnapLine = function() {
|
|
778
|
+
this._updateSnapLineColor(this._snapAxis ? this._snapAxis.color : BLACK);
|
|
779
|
+
this._updateSnapLineType((this._snapAxis && this._lockToAxis) || this._snapAlways);
|
|
780
|
+
};
|
|
781
|
+
|
|
782
|
+
DragDropHandler.prototype._updateSnapLineColor = function(color) {
|
|
783
|
+
if (!this._snapLine.material.color.equals(color)) {
|
|
784
|
+
this._snapLine.material.color.copy(color);
|
|
785
|
+
this._snapLine.material.needsUpdate = true;
|
|
786
|
+
}
|
|
787
|
+
};
|
|
788
|
+
|
|
789
|
+
DragDropHandler.prototype._updateSnapLineType = function(solid) {
|
|
790
|
+
var old = this._snapLine.material;
|
|
791
|
+
this._snapLine.material = solid ? this._lineMaterialSolid : this._lineMaterialDashed;
|
|
792
|
+
|
|
793
|
+
if (old !== this._snapLine.material) {
|
|
794
|
+
this._snapLine.material.color.copy(old.color);
|
|
795
|
+
this._snapLine.material.needsUpdate = true;
|
|
796
|
+
|
|
797
|
+
if (this._snapLine.material === this._lineMaterialDashed) {
|
|
798
|
+
this._snapLine.computeLineDistances();
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
};
|
|
802
|
+
|
|
803
|
+
DragDropHandler.prototype._getAxisSnapDistance = function(org, delta, dir) {
|
|
804
|
+
vbToThreeJs(org, _p1); // origin of the movement (world CRD)
|
|
805
|
+
vbToThreeJs(_p2.copy(org).add(delta), _p2); // current position of the movement (world CRD)
|
|
806
|
+
_p3.copy(_p1).add(dir); // offset position to form a line in "dir" direction (world CRD)
|
|
807
|
+
|
|
808
|
+
var camera = this._viewport._camera;
|
|
809
|
+
|
|
810
|
+
// to device normalized CRD
|
|
811
|
+
_p1.project(camera);
|
|
812
|
+
_p2.project(camera);
|
|
813
|
+
_p3.project(camera);
|
|
814
|
+
|
|
815
|
+
_p1.z = _p2.z = _p3.z = 0; // reset depth to calculate closest point on a plane not within frustrum
|
|
816
|
+
|
|
817
|
+
_line.start.copy(_p1);
|
|
818
|
+
_line.end.copy(_p3);
|
|
819
|
+
_line.closestPointToPoint(_p2, false, _p1);
|
|
820
|
+
|
|
821
|
+
return _p2.distanceTo(_p1);
|
|
822
|
+
};
|
|
823
|
+
|
|
824
|
+
DragDropHandler.prototype._getAxisSnapPosition = function(org, delta, dir, out) {
|
|
825
|
+
vbToThreeJs(org, _p1); // origin of the movement (world CRD)
|
|
826
|
+
vbToThreeJs(_p2.copy(org).add(delta), _p2); // current position of the movement (world CRD)
|
|
827
|
+
_p3.copy(dir).multiplyScalar(DIR_LENGTH); // magnified direction (world CRD)
|
|
828
|
+
_p4.copy(_p1).sub(_p3); // offset position in -"dir" direction to form a line
|
|
829
|
+
_p5.copy(_p1).add(_p3); // offset position in +"dir" direction to form a line
|
|
830
|
+
|
|
831
|
+
var camera = this._viewport._camera;
|
|
832
|
+
|
|
833
|
+
// to normalized device CRD
|
|
834
|
+
_p2.project(camera);
|
|
835
|
+
_p1.copy(_p4).project(camera);
|
|
836
|
+
_p3.copy(_p5).project(camera);
|
|
837
|
+
|
|
838
|
+
_p1.z = _p2.z = _p3.z = 0; // reset depth to calculate closest point on a plane not within frustrum
|
|
839
|
+
|
|
840
|
+
_line.start.copy(_p1);
|
|
841
|
+
_line.end.copy(_p3);
|
|
842
|
+
_line.closestPointToPoint(_p2, false, _p1);
|
|
843
|
+
|
|
844
|
+
// "project" back to find snapping point in world CRD
|
|
845
|
+
_ray.origin.setFromMatrixPosition(camera.matrixWorld);
|
|
846
|
+
_ray.direction.set(_p1.x, _p1.y, 0.5).unproject(camera).sub(_ray.origin).normalize();
|
|
847
|
+
|
|
848
|
+
if (_ray.distanceSqToSegment(_p4, _p5, _p1, _p2) < COLLISION_DISTANCE) {
|
|
849
|
+
threeJsToVb(_p2, _p2); // back to VB CRD
|
|
850
|
+
out.copy(_p2.sub(org)); // output is delta to final position
|
|
851
|
+
} else {
|
|
852
|
+
Log.error("failed to calculate snapping point", "", thisModule);
|
|
853
|
+
}
|
|
854
|
+
};
|
|
855
|
+
|
|
856
|
+
DragDropHandler.prototype._cancel = function() {
|
|
857
|
+
if (this._touch) {
|
|
858
|
+
// move objects back to original position
|
|
859
|
+
for (var i = 0; i < this._instances.length; ++i) {
|
|
860
|
+
this._instances[i].object3D.position.copy(this._instances[i]._last.dragStart);
|
|
861
|
+
this._instances[i].object3D.updateMatrix();
|
|
862
|
+
|
|
863
|
+
// move Decals back if any
|
|
864
|
+
var decals = this._adapter._sceneBuilder._instanceDecals.get(this._instances[i]);
|
|
865
|
+
if (decals) {
|
|
866
|
+
decals.forEach(function(decal) {
|
|
867
|
+
decal.object3D.position.copy(decal._last.dragStart);
|
|
868
|
+
decal.object3D.updateMatrix();
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
this._touch = null; // reset touch point to indicate there is no active drag and drop
|
|
874
|
+
this._hovered = null; // reset hovered instance
|
|
875
|
+
this._snapLine.visible = false; // hide guide line
|
|
876
|
+
this._instances.length = 0; // clear to indicate current action has been cancelled
|
|
877
|
+
this._cameraControls.setEnabled(true); // enable camera controls
|
|
878
|
+
this._dom.style.cursor = "auto";
|
|
879
|
+
|
|
880
|
+
// objects have moved -> adjust camera clipping planes
|
|
881
|
+
this._viewport._resetBBox();
|
|
882
|
+
this._viewport._updateCamera();
|
|
883
|
+
}
|
|
884
|
+
};
|
|
885
|
+
|
|
886
|
+
DragDropHandler.prototype._addToScene = function(obj, parent, visible, layer, order) {
|
|
887
|
+
if (visible !== undefined) {
|
|
888
|
+
obj.visible = visible;
|
|
889
|
+
}
|
|
890
|
+
if (layer !== undefined) {
|
|
891
|
+
obj.layers.set(layer);
|
|
892
|
+
}
|
|
893
|
+
if (order !== undefined) {
|
|
894
|
+
obj.renderOrder = order;
|
|
895
|
+
}
|
|
896
|
+
parent.add(obj);
|
|
897
|
+
obj.matrixAutoUpdate = false;
|
|
898
|
+
};
|
|
899
|
+
|
|
900
|
+
DragDropHandler.prototype._addListener = function(source, event, handler) {
|
|
901
|
+
var proxy = handler.bind(this);
|
|
902
|
+
this[event + "Proxy"] = proxy;
|
|
903
|
+
source.addEventListener(event, proxy);
|
|
904
|
+
};
|
|
905
|
+
|
|
906
|
+
DragDropHandler.prototype._removeListener = function(source, event) {
|
|
907
|
+
source.removeEventListener(event, this[event + "Proxy"]);
|
|
908
|
+
delete this[event + "Proxy"];
|
|
909
|
+
};
|
|
910
|
+
|
|
911
|
+
DragDropHandler.prototype._subscribe = function() {
|
|
912
|
+
var ref = this._viewport.getDomRef();
|
|
913
|
+
if (ref) {
|
|
914
|
+
this._dom = ref;
|
|
915
|
+
this._addListener(ref, "keyup", this._onKeyUp);
|
|
916
|
+
this._addListener(ref, "keydown", this._onKeyDown);
|
|
917
|
+
this._addListener(ref, "wheel", this._onPointerMove);
|
|
918
|
+
this._addListener(ref, "pointerup", this._onPointerCancel);
|
|
919
|
+
this._addListener(ref, "pointerdown", this._onPointerDown);
|
|
920
|
+
this._addListener(ref, "pointermove", this._onPointerMove);
|
|
921
|
+
this._addListener(ref, "pointerleave", this._onPointerCancel);
|
|
922
|
+
}
|
|
923
|
+
this._addListener(this._cameraControls, "change", this._onCameraChange);
|
|
924
|
+
};
|
|
925
|
+
|
|
926
|
+
DragDropHandler.prototype._unsubscribe = function() {
|
|
927
|
+
var ref = this._viewport.getDomRef();
|
|
928
|
+
if (ref) {
|
|
929
|
+
this._dom = null;
|
|
930
|
+
this._removeListener(ref, "wheel");
|
|
931
|
+
this._removeListener(ref, "keyup");
|
|
932
|
+
this._removeListener(ref, "keydown");
|
|
933
|
+
this._removeListener(ref, "pointerup");
|
|
934
|
+
this._removeListener(ref, "pointerdown");
|
|
935
|
+
this._removeListener(ref, "pointermove");
|
|
936
|
+
this._removeListener(ref, "pointerleave");
|
|
937
|
+
}
|
|
938
|
+
this._removeListener(this._cameraControls, "change");
|
|
939
|
+
};
|
|
940
|
+
|
|
941
|
+
DragDropHandler.prototype._updatePointer = function(event, out) {
|
|
942
|
+
var rect = this._viewport.getDomRef().getBoundingClientRect();
|
|
943
|
+
out.x = (event.cursor ? event.cursor.x : event.pageX - window.pageXOffset - rect.left) / rect.width * 2 - 1;
|
|
944
|
+
out.y = -(event.cursor ? event.cursor.y : event.pageY - window.pageYOffset - rect.top) / rect.height * 2 + 1;
|
|
945
|
+
|
|
946
|
+
return out;
|
|
947
|
+
};
|
|
948
|
+
|
|
949
|
+
DragDropHandler.prototype._updateSnapPoints = function() {
|
|
950
|
+
// calc bbox center of all snapping points
|
|
951
|
+
_p1.copy(this._snapPointsData[0].pos).add(this._snapPointsData[SNAP_POINTS_COUNT-1].pos).multiplyScalar(0.5);
|
|
952
|
+
var factor = _p1.distanceTo(this._camera.position) * Math.min(1.9 * Math.tan(Math.PI * this._camera.fov / 360) / this._camera.zoom, 10);
|
|
953
|
+
|
|
954
|
+
for (var i = 0; i < SNAP_POINTS_COUNT; ++i) {
|
|
955
|
+
this._snapPointsData[i].scale.set(1,1,1).multiplyScalar(factor / 170);
|
|
956
|
+
_matrix.compose(this._snapPointsData[i].pos, _quaternion, this._snapPointsData[i].scale);
|
|
957
|
+
this._snapPoints.setMatrixAt(i, _matrix);
|
|
958
|
+
}
|
|
959
|
+
this._snapPoints.instanceMatrix.needsUpdate = true;
|
|
960
|
+
// update highlight snapping points as well
|
|
961
|
+
this._snapHighlightPoint.scale.copy(this._snapPointsData[0].scale);
|
|
962
|
+
this._snapHighlightPoint.updateMatrix();
|
|
963
|
+
};
|
|
964
|
+
|
|
965
|
+
DragDropHandler.prototype._onCameraChange = function(event) {
|
|
966
|
+
if (this._snapPoints.visible) {
|
|
967
|
+
this._updateSnapPoints();
|
|
968
|
+
}
|
|
969
|
+
};
|
|
970
|
+
|
|
971
|
+
return DragDropHandler;
|
|
972
|
+
});
|