@xeokit/xeokit-sdk 2.6.22 → 2.6.25
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/dist/xeokit-sdk.cjs.js +1046 -512
- package/dist/xeokit-sdk.es.js +1042 -513
- package/dist/xeokit-sdk.es5.js +957 -742
- package/dist/xeokit-sdk.min.cjs.js +5 -5
- package/dist/xeokit-sdk.min.es.js +5 -5
- package/dist/xeokit-sdk.min.es5.js +4 -4
- package/package.json +1 -1
- package/src/plugins/AngleMeasurementsPlugin/AngleMeasurement.js +25 -34
- package/src/plugins/AngleMeasurementsPlugin/AngleMeasurementsMouseControl.js +2 -2
- package/src/plugins/AngleMeasurementsPlugin/index.js +79 -1
- package/src/plugins/AnnotationsPlugin/Annotation.js +31 -0
- package/src/plugins/AnnotationsPlugin/AnnotationsPlugin.js +9 -24
- package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurement.js +17 -23
- package/src/plugins/DistanceMeasurementsPlugin/index.js +79 -1
- package/src/plugins/XKTLoaderPlugin/XKTDefaultDataSource.js +0 -1
- package/src/plugins/ZonesPlugin/index.js +29 -200
- package/src/plugins/lib/html/Dot.js +18 -18
- package/src/plugins/lib/ui/index.js +286 -0
- package/src/viewer/scene/geometry/builders/index.js +2 -1
- package/src/viewer/scene/marker/Marker.js +9 -3
|
@@ -7,19 +7,13 @@ import {PhongMaterial} from "../../viewer/scene/materials/PhongMaterial.js";
|
|
|
7
7
|
import {math} from "../../viewer/scene/math/math.js";
|
|
8
8
|
import {Mesh} from "../../viewer/scene/mesh/Mesh.js";
|
|
9
9
|
import {Dot} from "../lib/html/Dot.js";
|
|
10
|
+
import {activateDraggableDots, Dot3D, transformToNode} from "../../../src/plugins/lib/ui/index.js";
|
|
10
11
|
|
|
11
12
|
const hex2rgb = function(color) {
|
|
12
13
|
const rgb = idx => parseInt(color.substr(idx + 1, 2), 16) / 255;
|
|
13
14
|
return [ rgb(0), rgb(2), rgb(4) ];
|
|
14
15
|
};
|
|
15
16
|
|
|
16
|
-
const transformToNode = function(from, to, vec) {
|
|
17
|
-
const fromRec = from.getBoundingClientRect();
|
|
18
|
-
const toRec = to.getBoundingClientRect();
|
|
19
|
-
vec[0] += fromRec.left - toRec.left;
|
|
20
|
-
vec[1] += fromRec.top - toRec.top;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
17
|
const triangulateEarClipping = function(planeCoords) {
|
|
24
18
|
|
|
25
19
|
const polygonVertices = [ ];
|
|
@@ -123,148 +117,6 @@ const triangulateEarClipping = function(planeCoords) {
|
|
|
123
117
|
return [ planeCoords, baseTriangles ];
|
|
124
118
|
};
|
|
125
119
|
|
|
126
|
-
const draggableDot3D = function(handleMouseEvents, handleTouchEvents, viewer, worldPos, color, ray2WorldPos, onStart, onMove, onEnd) {
|
|
127
|
-
const scene = viewer.scene;
|
|
128
|
-
const canvas = scene.canvas.canvas;
|
|
129
|
-
|
|
130
|
-
const marker = new Marker(scene, {});
|
|
131
|
-
|
|
132
|
-
const pickWorldPos = canvasPos => {
|
|
133
|
-
const origin = math.vec3();
|
|
134
|
-
const direction = math.vec3();
|
|
135
|
-
math.canvasPosToWorldRay(canvas, scene.camera.viewMatrix, scene.camera.projMatrix, canvasPos, origin, direction);
|
|
136
|
-
return ray2WorldPos(origin, direction);
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
const onChange = event => {
|
|
140
|
-
const canvasPos = math.vec2([ event.clientX, event.clientY ]);
|
|
141
|
-
transformToNode(canvas.ownerDocument.body, canvas, canvasPos);
|
|
142
|
-
|
|
143
|
-
const worldPos = pickWorldPos(canvasPos);
|
|
144
|
-
marker.worldPos = worldPos;
|
|
145
|
-
updateDotPos();
|
|
146
|
-
onMove(canvasPos, worldPos);
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
let currentDrag = null;
|
|
150
|
-
|
|
151
|
-
const onDragMove = function(event) {
|
|
152
|
-
const e = currentDrag.matchesEvent(event);
|
|
153
|
-
if (e)
|
|
154
|
-
{
|
|
155
|
-
onChange(e);
|
|
156
|
-
}
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
const onDragEnd = function(event) {
|
|
160
|
-
const e = currentDrag.matchesEvent(event);
|
|
161
|
-
if (e)
|
|
162
|
-
{
|
|
163
|
-
dot.setOpacity(idleOpacity);
|
|
164
|
-
currentDrag.cleanup();
|
|
165
|
-
onChange(e);
|
|
166
|
-
onEnd();
|
|
167
|
-
}
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
const startDrag = function(matchesEvent, cleanupHandlers) {
|
|
171
|
-
if (currentDrag) {
|
|
172
|
-
currentDrag.cleanup();
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
dot.setOpacity(1.0);
|
|
176
|
-
dot.setClickable(false);
|
|
177
|
-
viewer.cameraControl.active = false;
|
|
178
|
-
|
|
179
|
-
currentDrag = {
|
|
180
|
-
matchesEvent: matchesEvent,
|
|
181
|
-
cleanup: function() {
|
|
182
|
-
currentDrag = null;
|
|
183
|
-
dot.setClickable(true);
|
|
184
|
-
viewer.cameraControl.active = true;
|
|
185
|
-
cleanupHandlers();
|
|
186
|
-
}
|
|
187
|
-
};
|
|
188
|
-
|
|
189
|
-
onStart();
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
const dotCfg = { fillColor: color };
|
|
193
|
-
|
|
194
|
-
if (handleMouseEvents)
|
|
195
|
-
{
|
|
196
|
-
dotCfg.onMouseOver = () => (! currentDrag) && dot.setOpacity(1.0);
|
|
197
|
-
dotCfg.onMouseLeave = () => (! currentDrag) && dot.setOpacity(idleOpacity);
|
|
198
|
-
dotCfg.onMouseDown = event => {
|
|
199
|
-
if (event.which === 1)
|
|
200
|
-
{
|
|
201
|
-
canvas.addEventListener("mousemove", onDragMove);
|
|
202
|
-
canvas.addEventListener("mouseup", onDragEnd);
|
|
203
|
-
startDrag(
|
|
204
|
-
event => (event.which === 1) && event,
|
|
205
|
-
() => {
|
|
206
|
-
canvas.removeEventListener("mousemove", onDragMove);
|
|
207
|
-
canvas.removeEventListener("mouseup", onDragEnd);
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
if (handleTouchEvents)
|
|
214
|
-
{
|
|
215
|
-
let touchStartId;
|
|
216
|
-
dotCfg.onTouchstart = event => {
|
|
217
|
-
event.preventDefault();
|
|
218
|
-
if (event.touches.length === 1)
|
|
219
|
-
{
|
|
220
|
-
touchStartId = event.touches[0].identifier;
|
|
221
|
-
startDrag(
|
|
222
|
-
event => [...event.changedTouches].find(e => e.identifier === touchStartId),
|
|
223
|
-
() => { touchStartId = null; });
|
|
224
|
-
}
|
|
225
|
-
};
|
|
226
|
-
dotCfg.onTouchmove = event => {
|
|
227
|
-
event.preventDefault();
|
|
228
|
-
onDragMove(event);
|
|
229
|
-
};
|
|
230
|
-
dotCfg.onTouchend = event => {
|
|
231
|
-
event.preventDefault();
|
|
232
|
-
onDragEnd(event);
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
const dotParent = canvas.ownerDocument.body;
|
|
237
|
-
const dot = new Dot(dotParent, dotCfg);
|
|
238
|
-
|
|
239
|
-
const idleOpacity = 0.5;
|
|
240
|
-
dot.setOpacity(idleOpacity);
|
|
241
|
-
|
|
242
|
-
const updateDotPos = function() {
|
|
243
|
-
const pos = marker.canvasPos.slice();
|
|
244
|
-
transformToNode(canvas, dotParent, pos);
|
|
245
|
-
dot.setPos(pos[0], pos[1]);
|
|
246
|
-
};
|
|
247
|
-
|
|
248
|
-
marker.worldPos = worldPos;
|
|
249
|
-
updateDotPos();
|
|
250
|
-
|
|
251
|
-
const onViewMatrix = scene.camera.on("viewMatrix", updateDotPos);
|
|
252
|
-
const onProjMatrix = scene.camera.on("projMatrix", updateDotPos);
|
|
253
|
-
|
|
254
|
-
return {
|
|
255
|
-
setActive: value => dot.setClickable(value),
|
|
256
|
-
getWorldPos: () => marker.worldPos,
|
|
257
|
-
setWorldPos: pos => { marker.worldPos = pos; updateDotPos(); },
|
|
258
|
-
destroy: function() {
|
|
259
|
-
currentDrag && currentDrag.cleanup();
|
|
260
|
-
scene.camera.off(onViewMatrix);
|
|
261
|
-
scene.camera.off(onProjMatrix);
|
|
262
|
-
marker.destroy();
|
|
263
|
-
dot.destroy();
|
|
264
|
-
}
|
|
265
|
-
};
|
|
266
|
-
};
|
|
267
|
-
|
|
268
120
|
const marker3D = function(scene, color) {
|
|
269
121
|
const canvas = scene.canvas.canvas;
|
|
270
122
|
|
|
@@ -1760,26 +1612,19 @@ export class ZonesPolysurfaceTouchControl extends Component {
|
|
|
1760
1612
|
|
|
1761
1613
|
export class ZoneEditControl extends Component {
|
|
1762
1614
|
constructor(zone, cfg, handleMouseEvents, handleTouchEvents) {
|
|
1763
|
-
|
|
1764
|
-
const
|
|
1615
|
+
const viewer = zone.plugin.viewer;
|
|
1616
|
+
const scene = viewer.scene;
|
|
1617
|
+
super(scene);
|
|
1765
1618
|
|
|
1766
1619
|
const altitude = zone._geometry.altitude;
|
|
1767
|
-
const pointerLens = cfg && cfg.pointerLens;
|
|
1768
|
-
const updatePointerLens = (pointerLens
|
|
1769
|
-
? function(canvasPos) {
|
|
1770
|
-
pointerLens.visible = !! canvasPos;
|
|
1771
|
-
if (canvasPos)
|
|
1772
|
-
{
|
|
1773
|
-
pointerLens.canvasPos = canvasPos;
|
|
1774
|
-
}
|
|
1775
|
-
}
|
|
1776
|
-
: () => { });
|
|
1777
1620
|
|
|
1778
1621
|
const dots = zone._geometry.planeCoordinates.map(planeCoord => {
|
|
1779
|
-
|
|
1780
|
-
const
|
|
1781
|
-
|
|
1782
|
-
|
|
1622
|
+
const dotParent = scene.canvas.canvas.ownerDocument.body;
|
|
1623
|
+
const dot = new Dot3D(scene, {}, dotParent, { fillColor: zone._color });
|
|
1624
|
+
dot.worldPos = math.vec3([ planeCoord[0], altitude, planeCoord[1] ]);
|
|
1625
|
+
dot.on("worldPos", function() {
|
|
1626
|
+
planeCoord[0] = dot.worldPos[0];
|
|
1627
|
+
planeCoord[1] = dot.worldPos[2];
|
|
1783
1628
|
try {
|
|
1784
1629
|
zone._rebuildMesh();
|
|
1785
1630
|
} catch (e) {
|
|
@@ -1788,45 +1633,29 @@ export class ZoneEditControl extends Component {
|
|
|
1788
1633
|
zone._zoneMesh = null;
|
|
1789
1634
|
}
|
|
1790
1635
|
}
|
|
1791
|
-
};
|
|
1792
|
-
|
|
1793
|
-
const dot = draggableDot3D(
|
|
1794
|
-
handleMouseEvents,
|
|
1795
|
-
handleTouchEvents,
|
|
1796
|
-
zone.plugin.viewer,
|
|
1797
|
-
math.vec3([ planeCoord[0], altitude, planeCoord[1] ]),
|
|
1798
|
-
zone._color,
|
|
1799
|
-
(orig, dir) => planeIntersect(altitude, math.vec3([ 0, 1, 0 ]), orig, dir),
|
|
1800
|
-
() => {
|
|
1801
|
-
initWorldPos = dot.getWorldPos().slice();
|
|
1802
|
-
initPlaneCoord = planeCoord.slice();
|
|
1803
|
-
set_other_dots_active(false, dot);
|
|
1804
|
-
},
|
|
1805
|
-
(canvasPos, worldPos) => {
|
|
1806
|
-
updatePointerLens(canvasPos);
|
|
1807
|
-
setPlaneCoord([ worldPos[0], worldPos[2] ]);
|
|
1808
|
-
},
|
|
1809
|
-
() => {
|
|
1810
|
-
if (zone._zoneMesh)
|
|
1811
|
-
{
|
|
1812
|
-
self.fire("edited");
|
|
1813
|
-
}
|
|
1814
|
-
else
|
|
1815
|
-
{
|
|
1816
|
-
dot.setWorldPos(initWorldPos);
|
|
1817
|
-
setPlaneCoord(initPlaneCoord);
|
|
1818
|
-
}
|
|
1819
|
-
updatePointerLens(null);
|
|
1820
|
-
set_other_dots_active(true, dot);
|
|
1821
|
-
});
|
|
1636
|
+
});
|
|
1822
1637
|
return dot;
|
|
1823
1638
|
});
|
|
1824
|
-
|
|
1825
|
-
|
|
1639
|
+
|
|
1640
|
+
const cleanupDrag = activateDraggableDots({
|
|
1641
|
+
viewer: viewer,
|
|
1642
|
+
handleMouseEvents: handleMouseEvents,
|
|
1643
|
+
handleTouchEvents: handleTouchEvents,
|
|
1644
|
+
pointerLens: cfg && cfg.pointerLens,
|
|
1645
|
+
dots: dots,
|
|
1646
|
+
ray2WorldPos: (orig, dir) => planeIntersect(altitude, math.vec3([ 0, 1, 0 ]), orig, dir),
|
|
1647
|
+
onEnd: (initPos, dot) => {
|
|
1648
|
+
if (zone._zoneMesh)
|
|
1649
|
+
{
|
|
1650
|
+
this.fire("edited");
|
|
1651
|
+
}
|
|
1652
|
+
return !! zone._zoneMesh;
|
|
1653
|
+
}
|
|
1654
|
+
});
|
|
1826
1655
|
|
|
1827
1656
|
const cleanup = function() {
|
|
1828
|
-
|
|
1829
|
-
|
|
1657
|
+
cleanupDrag();
|
|
1658
|
+
dots.forEach(d => d.destroy());
|
|
1830
1659
|
};
|
|
1831
1660
|
|
|
1832
1661
|
const destroyCb = zone.on("destroyed", cleanup);
|
|
@@ -97,6 +97,24 @@ class Dot {
|
|
|
97
97
|
});
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
if (cfg.onTouchstart) {
|
|
101
|
+
dotClickable.addEventListener('touchstart', (event) => {
|
|
102
|
+
cfg.onTouchstart(event, this);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (cfg.onTouchmove) {
|
|
107
|
+
dotClickable.addEventListener('touchmove', (event) => {
|
|
108
|
+
cfg.onTouchmove(event, this);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (cfg.onTouchend) {
|
|
113
|
+
dotClickable.addEventListener('touchend', (event) => {
|
|
114
|
+
cfg.onTouchend(event, this);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
100
118
|
if (cfg.onContextMenu) {
|
|
101
119
|
if(os.isIphoneSafari()){
|
|
102
120
|
dotClickable.addEventListener('touchstart', (event) => {
|
|
@@ -136,24 +154,6 @@ class Dot {
|
|
|
136
154
|
|
|
137
155
|
}
|
|
138
156
|
|
|
139
|
-
if (cfg.onTouchstart) {
|
|
140
|
-
dotClickable.addEventListener('touchstart', (event) => {
|
|
141
|
-
cfg.onTouchstart(event, this);
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
if (cfg.onTouchmove) {
|
|
146
|
-
dotClickable.addEventListener('touchmove', (event) => {
|
|
147
|
-
cfg.onTouchmove(event, this);
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (cfg.onTouchend) {
|
|
152
|
-
dotClickable.addEventListener('touchend', (event) => {
|
|
153
|
-
cfg.onTouchend(event, this);
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
|
|
157
157
|
this.setPos(cfg.x || 0, cfg.y || 0);
|
|
158
158
|
this.setFillColor(cfg.fillColor);
|
|
159
159
|
this.setBorderColor(cfg.borderColor);
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import {Dot} from "../html/Dot.js";
|
|
2
|
+
import {math} from "../../../viewer/scene/math/math.js";
|
|
3
|
+
import {Marker} from "../../../viewer/scene/marker/Marker.js";
|
|
4
|
+
|
|
5
|
+
const nop = () => { };
|
|
6
|
+
|
|
7
|
+
export function transformToNode(from, to, vec) {
|
|
8
|
+
const fromRec = from.getBoundingClientRect();
|
|
9
|
+
const toRec = to.getBoundingClientRect();
|
|
10
|
+
vec[0] += fromRec.left - toRec.left;
|
|
11
|
+
vec[1] += fromRec.top - toRec.top;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export class Dot3D extends Marker {
|
|
15
|
+
constructor(scene, markerCfg, parentElement, cfg = {}) {
|
|
16
|
+
super(scene, markerCfg);
|
|
17
|
+
|
|
18
|
+
const handler = (cfgEvent, componentEvent) => {
|
|
19
|
+
return event => {
|
|
20
|
+
if (cfgEvent) {
|
|
21
|
+
cfgEvent(event);
|
|
22
|
+
}
|
|
23
|
+
this.fire(componentEvent, event, true);
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
this._dot = new Dot(parentElement, {
|
|
27
|
+
fillColor: cfg.fillColor,
|
|
28
|
+
zIndex: cfg.zIndex,
|
|
29
|
+
onMouseOver: handler(cfg.onMouseOver, "mouseover"),
|
|
30
|
+
onMouseLeave: handler(cfg.onMouseLeave, "mouseleave"),
|
|
31
|
+
onMouseWheel: handler(cfg.onMouseWheel, "wheel"),
|
|
32
|
+
onMouseDown: handler(cfg.onMouseDown, "mousedown"),
|
|
33
|
+
onMouseUp: handler(cfg.onMouseUp, "mouseup"),
|
|
34
|
+
onMouseMove: handler(cfg.onMouseMove, "mousemove"),
|
|
35
|
+
onTouchstart: handler(cfg.onTouchstart, "touchstart"),
|
|
36
|
+
onTouchmove: handler(cfg.onTouchmove, "touchmove"),
|
|
37
|
+
onTouchend: handler(cfg.onTouchend, "touchend"),
|
|
38
|
+
onContextMenu: handler(cfg.onContextMenu, "contextmenu")
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const updateDotPos = () => {
|
|
42
|
+
const pos = this.canvasPos.slice();
|
|
43
|
+
transformToNode(scene.canvas.canvas, parentElement, pos);
|
|
44
|
+
this._dot.setPos(pos[0], pos[1]);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
this.on("worldPos", updateDotPos);
|
|
48
|
+
|
|
49
|
+
const onViewMatrix = scene.camera.on("viewMatrix", updateDotPos);
|
|
50
|
+
const onProjMatrix = scene.camera.on("projMatrix", updateDotPos);
|
|
51
|
+
this._cleanup = () => {
|
|
52
|
+
scene.camera.off(onViewMatrix);
|
|
53
|
+
scene.camera.off(onProjMatrix);
|
|
54
|
+
this._dot.destroy();
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
setClickable(value) {
|
|
59
|
+
this._dot.setClickable(value);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
setCulled(value) {
|
|
63
|
+
this._dot.setCulled(value);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
setFillColor(value) {
|
|
67
|
+
this._dot.setFillColor(value);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
setHighlighted(value) {
|
|
71
|
+
this._dot.setHighlighted(value);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
setOpacity(value) {
|
|
75
|
+
this._dot.setOpacity(value);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
setVisible(value) {
|
|
79
|
+
this._dot.setVisible(value);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
destroy() {
|
|
83
|
+
this._cleanup();
|
|
84
|
+
super.destroy();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function activateDraggableDot(dot, cfg) {
|
|
90
|
+
const extractCFG = function(propName, defaultValue) {
|
|
91
|
+
if (propName in cfg) {
|
|
92
|
+
return cfg[propName];
|
|
93
|
+
} else if (defaultValue !== undefined) {
|
|
94
|
+
return defaultValue;
|
|
95
|
+
} else {
|
|
96
|
+
throw "config missing: " + propName;
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const viewer = extractCFG("viewer");
|
|
101
|
+
const ray2WorldPos = extractCFG("ray2WorldPos");
|
|
102
|
+
const handleMouseEvents = extractCFG("handleMouseEvents", false);
|
|
103
|
+
const handleTouchEvents = extractCFG("handleTouchEvents", false);
|
|
104
|
+
const onStart = extractCFG("onStart", nop);
|
|
105
|
+
const onMove = extractCFG("onMove", nop);
|
|
106
|
+
const onEnd = extractCFG("onEnd", nop);
|
|
107
|
+
|
|
108
|
+
const scene = viewer.scene;
|
|
109
|
+
const canvas = scene.canvas.canvas;
|
|
110
|
+
|
|
111
|
+
const pickWorldPos = canvasPos => {
|
|
112
|
+
const origin = math.vec3();
|
|
113
|
+
const direction = math.vec3();
|
|
114
|
+
math.canvasPosToWorldRay(canvas, scene.camera.viewMatrix, scene.camera.projMatrix, canvasPos, origin, direction);
|
|
115
|
+
return ray2WorldPos(origin, direction, canvasPos);
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const onChange = event => {
|
|
119
|
+
const canvasPos = math.vec2([ event.clientX, event.clientY ]);
|
|
120
|
+
transformToNode(canvas.ownerDocument.body, canvas, canvasPos);
|
|
121
|
+
onMove(canvasPos, pickWorldPos(canvasPos));
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
let currentDrag = null;
|
|
125
|
+
|
|
126
|
+
const onDragMove = function(event) {
|
|
127
|
+
const e = currentDrag.matchesEvent(event);
|
|
128
|
+
if (e)
|
|
129
|
+
{
|
|
130
|
+
onChange(e);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const onDragEnd = function(event) {
|
|
135
|
+
const e = currentDrag.matchesEvent(event);
|
|
136
|
+
if (e)
|
|
137
|
+
{
|
|
138
|
+
dot.setOpacity(idleOpacity);
|
|
139
|
+
currentDrag.cleanup();
|
|
140
|
+
onChange(e);
|
|
141
|
+
onEnd();
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const startDrag = function(matchesEvent, cleanupHandlers) {
|
|
146
|
+
if (currentDrag) {
|
|
147
|
+
currentDrag.cleanup();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
dot.setOpacity(1.0);
|
|
151
|
+
dot.setClickable(false);
|
|
152
|
+
viewer.cameraControl.active = false;
|
|
153
|
+
|
|
154
|
+
currentDrag = {
|
|
155
|
+
matchesEvent: matchesEvent,
|
|
156
|
+
cleanup: function() {
|
|
157
|
+
currentDrag = null;
|
|
158
|
+
dot.setClickable(true);
|
|
159
|
+
viewer.cameraControl.active = true;
|
|
160
|
+
cleanupHandlers();
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
onStart();
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const cleanupDotHandlers = [ ];
|
|
168
|
+
const dot_on = function(event, callback) {
|
|
169
|
+
const id = dot.on(event, callback);
|
|
170
|
+
cleanupDotHandlers.push(() => dot.off(id));
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
if (handleMouseEvents)
|
|
174
|
+
{
|
|
175
|
+
dot_on("mouseover", () => (! currentDrag) && dot.setOpacity(1.0));
|
|
176
|
+
dot_on("mouseleave", () => (! currentDrag) && dot.setOpacity(idleOpacity));
|
|
177
|
+
dot_on("mousedown", event => {
|
|
178
|
+
if (event.which === 1)
|
|
179
|
+
{
|
|
180
|
+
canvas.addEventListener("mousemove", onDragMove);
|
|
181
|
+
canvas.addEventListener("mouseup", onDragEnd);
|
|
182
|
+
startDrag(
|
|
183
|
+
event => (event.which === 1) && event,
|
|
184
|
+
() => {
|
|
185
|
+
canvas.removeEventListener("mousemove", onDragMove);
|
|
186
|
+
canvas.removeEventListener("mouseup", onDragEnd);
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (handleTouchEvents)
|
|
193
|
+
{
|
|
194
|
+
let touchStartId;
|
|
195
|
+
dot_on("touchstart", event => {
|
|
196
|
+
event.preventDefault();
|
|
197
|
+
if (event.touches.length === 1)
|
|
198
|
+
{
|
|
199
|
+
touchStartId = event.touches[0].identifier;
|
|
200
|
+
startDrag(
|
|
201
|
+
event => [...event.changedTouches].find(e => e.identifier === touchStartId),
|
|
202
|
+
() => { touchStartId = null; });
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
dot_on("touchmove", event => {
|
|
206
|
+
event.preventDefault();
|
|
207
|
+
onDragMove(event);
|
|
208
|
+
});
|
|
209
|
+
dot_on("touchend", event => {
|
|
210
|
+
event.preventDefault();
|
|
211
|
+
onDragEnd(event);
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const idleOpacity = 0.8;
|
|
216
|
+
dot.setOpacity(idleOpacity);
|
|
217
|
+
|
|
218
|
+
return function() {
|
|
219
|
+
currentDrag && currentDrag.cleanup();
|
|
220
|
+
cleanupDotHandlers.forEach(c => c());
|
|
221
|
+
dot.setOpacity(1.0);
|
|
222
|
+
};
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
export function activateDraggableDots(cfg) {
|
|
226
|
+
const extractCFG = function(propName, defaultValue) {
|
|
227
|
+
if (propName in cfg) {
|
|
228
|
+
return cfg[propName];
|
|
229
|
+
} else if (defaultValue !== undefined) {
|
|
230
|
+
return defaultValue;
|
|
231
|
+
} else {
|
|
232
|
+
throw "config missing: " + propName;
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
const viewer = extractCFG("viewer");
|
|
237
|
+
const handleMouseEvents = extractCFG("handleMouseEvents", false);
|
|
238
|
+
const handleTouchEvents = extractCFG("handleTouchEvents", false);
|
|
239
|
+
const pointerLens = extractCFG("pointerLens", null);
|
|
240
|
+
const dots = extractCFG("dots");
|
|
241
|
+
const ray2WorldPos = extractCFG("ray2WorldPos");
|
|
242
|
+
const onEnd = extractCFG("onEnd", nop);
|
|
243
|
+
|
|
244
|
+
const updatePointerLens = (pointerLens
|
|
245
|
+
? function(canvasPos) {
|
|
246
|
+
pointerLens.visible = !! canvasPos;
|
|
247
|
+
if (canvasPos)
|
|
248
|
+
{
|
|
249
|
+
pointerLens.canvasPos = canvasPos;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
: () => { });
|
|
253
|
+
|
|
254
|
+
const cleanups = dots.map(dot => {
|
|
255
|
+
let initPos;
|
|
256
|
+
return activateDraggableDot(dot, {
|
|
257
|
+
handleMouseEvents: handleMouseEvents,
|
|
258
|
+
handleTouchEvents: handleTouchEvents,
|
|
259
|
+
viewer: viewer,
|
|
260
|
+
ray2WorldPos: (orig, dir, canvasPos) => (ray2WorldPos(orig, dir, canvasPos) || initPos),
|
|
261
|
+
onStart: () => {
|
|
262
|
+
initPos = dot.worldPos.slice();
|
|
263
|
+
setOtherDotsActive(false, dot);
|
|
264
|
+
},
|
|
265
|
+
onMove: (canvasPos, worldPos) => {
|
|
266
|
+
updatePointerLens(canvasPos);
|
|
267
|
+
dot.worldPos = worldPos;
|
|
268
|
+
},
|
|
269
|
+
onEnd: () => {
|
|
270
|
+
if (! onEnd(initPos, dot)) {
|
|
271
|
+
dot.worldPos = initPos;
|
|
272
|
+
}
|
|
273
|
+
updatePointerLens(null);
|
|
274
|
+
setOtherDotsActive(true, dot);
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
const setOtherDotsActive = (active, dot) => dots.forEach(d => (d !== dot) && d.setClickable(active));
|
|
280
|
+
setOtherDotsActive(true);
|
|
281
|
+
|
|
282
|
+
return function() {
|
|
283
|
+
cleanups.forEach(c => c());
|
|
284
|
+
updatePointerLens(null);
|
|
285
|
+
};
|
|
286
|
+
}
|
|
@@ -6,4 +6,5 @@ export * from "./buildPlaneGeometry.js";
|
|
|
6
6
|
export * from "./buildSphereGeometry.js";
|
|
7
7
|
export * from "./buildTorusGeometry.js";
|
|
8
8
|
export * from "./buildVectorTextGeometry.js";
|
|
9
|
-
export * from "./buildPolylineGeometry.js";
|
|
9
|
+
export * from "./buildPolylineGeometry.js";
|
|
10
|
+
export * from "./buildLineGeometry.js";
|
|
@@ -196,11 +196,17 @@ class Marker extends Component {
|
|
|
196
196
|
return;
|
|
197
197
|
}
|
|
198
198
|
if (this._onEntityDestroyed !== null) {
|
|
199
|
-
this._entity.model
|
|
199
|
+
if (this._entity.model) {
|
|
200
|
+
this._entity.model.off(this._onEntityDestroyed);
|
|
201
|
+
} else {
|
|
202
|
+
this._entity.off(this._onEntityDestroyed);
|
|
203
|
+
}
|
|
200
204
|
this._onEntityDestroyed = null;
|
|
201
205
|
}
|
|
202
206
|
if (this._onEntityModelDestroyed !== null) {
|
|
203
|
-
this._entity.model
|
|
207
|
+
if (this._entity.model) {
|
|
208
|
+
this._entity.model.off(this._onEntityModelDestroyed);
|
|
209
|
+
}
|
|
204
210
|
this._onEntityModelDestroyed = null;
|
|
205
211
|
}
|
|
206
212
|
}
|
|
@@ -212,7 +218,7 @@ class Marker extends Component {
|
|
|
212
218
|
this._onEntityModelDestroyed = null;
|
|
213
219
|
});
|
|
214
220
|
} else {
|
|
215
|
-
this._onEntityDestroyed = this._entity.
|
|
221
|
+
this._onEntityDestroyed = this._entity.on("destroyed", () => {
|
|
216
222
|
this._entity = null;
|
|
217
223
|
this._onEntityDestroyed = null;
|
|
218
224
|
});
|