@xeokit/xeokit-sdk 2.6.23 → 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.
@@ -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);
@@ -11,7 +11,82 @@ export function transformToNode(from, to, vec) {
11
11
  vec[1] += fromRec.top - toRec.top;
12
12
  };
13
13
 
14
- export function createDraggableDot3D(cfg) {
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) {
15
90
  const extractCFG = function(propName, defaultValue) {
16
91
  if (propName in cfg) {
17
92
  return cfg[propName];
@@ -23,8 +98,6 @@ export function createDraggableDot3D(cfg) {
23
98
  };
24
99
 
25
100
  const viewer = extractCFG("viewer");
26
- const worldPos = extractCFG("worldPos");
27
- const color = extractCFG("color");
28
101
  const ray2WorldPos = extractCFG("ray2WorldPos");
29
102
  const handleMouseEvents = extractCFG("handleMouseEvents", false);
30
103
  const handleTouchEvents = extractCFG("handleTouchEvents", false);
@@ -35,8 +108,6 @@ export function createDraggableDot3D(cfg) {
35
108
  const scene = viewer.scene;
36
109
  const canvas = scene.canvas.canvas;
37
110
 
38
- const marker = new Marker(scene, {});
39
-
40
111
  const pickWorldPos = canvasPos => {
41
112
  const origin = math.vec3();
42
113
  const direction = math.vec3();
@@ -47,11 +118,7 @@ export function createDraggableDot3D(cfg) {
47
118
  const onChange = event => {
48
119
  const canvasPos = math.vec2([ event.clientX, event.clientY ]);
49
120
  transformToNode(canvas.ownerDocument.body, canvas, canvasPos);
50
-
51
- const worldPos = pickWorldPos(canvasPos);
52
- marker.worldPos = worldPos;
53
- updateDotPos();
54
- onMove(canvasPos, worldPos);
121
+ onMove(canvasPos, pickWorldPos(canvasPos));
55
122
  };
56
123
 
57
124
  let currentDrag = null;
@@ -97,13 +164,17 @@ export function createDraggableDot3D(cfg) {
97
164
  onStart();
98
165
  };
99
166
 
100
- const dotCfg = { fillColor: color };
167
+ const cleanupDotHandlers = [ ];
168
+ const dot_on = function(event, callback) {
169
+ const id = dot.on(event, callback);
170
+ cleanupDotHandlers.push(() => dot.off(id));
171
+ };
101
172
 
102
173
  if (handleMouseEvents)
103
174
  {
104
- dotCfg.onMouseOver = () => (! currentDrag) && dot.setOpacity(1.0);
105
- dotCfg.onMouseLeave = () => (! currentDrag) && dot.setOpacity(idleOpacity);
106
- dotCfg.onMouseDown = event => {
175
+ dot_on("mouseover", () => (! currentDrag) && dot.setOpacity(1.0));
176
+ dot_on("mouseleave", () => (! currentDrag) && dot.setOpacity(idleOpacity));
177
+ dot_on("mousedown", event => {
107
178
  if (event.which === 1)
108
179
  {
109
180
  canvas.addEventListener("mousemove", onDragMove);
@@ -115,13 +186,13 @@ export function createDraggableDot3D(cfg) {
115
186
  canvas.removeEventListener("mouseup", onDragEnd);
116
187
  });
117
188
  }
118
- };
189
+ });
119
190
  }
120
191
 
121
192
  if (handleTouchEvents)
122
193
  {
123
194
  let touchStartId;
124
- dotCfg.onTouchstart = event => {
195
+ dot_on("touchstart", event => {
125
196
  event.preventDefault();
126
197
  if (event.touches.length === 1)
127
198
  {
@@ -130,46 +201,24 @@ export function createDraggableDot3D(cfg) {
130
201
  event => [...event.changedTouches].find(e => e.identifier === touchStartId),
131
202
  () => { touchStartId = null; });
132
203
  }
133
- };
134
- dotCfg.onTouchmove = event => {
204
+ });
205
+ dot_on("touchmove", event => {
135
206
  event.preventDefault();
136
207
  onDragMove(event);
137
- };
138
- dotCfg.onTouchend = event => {
208
+ });
209
+ dot_on("touchend", event => {
139
210
  event.preventDefault();
140
211
  onDragEnd(event);
141
- };
212
+ });
142
213
  }
143
214
 
144
- const dotParent = canvas.ownerDocument.body;
145
- const dot = new Dot(dotParent, dotCfg);
146
-
147
- const idleOpacity = 0.5;
215
+ const idleOpacity = 0.8;
148
216
  dot.setOpacity(idleOpacity);
149
217
 
150
- const updateDotPos = function() {
151
- const pos = marker.canvasPos.slice();
152
- transformToNode(canvas, dotParent, pos);
153
- dot.setPos(pos[0], pos[1]);
154
- };
155
-
156
- marker.worldPos = worldPos;
157
- updateDotPos();
158
-
159
- const onViewMatrix = scene.camera.on("viewMatrix", updateDotPos);
160
- const onProjMatrix = scene.camera.on("projMatrix", updateDotPos);
161
-
162
- return {
163
- setActive: value => dot.setClickable(value),
164
- getWorldPos: () => marker.worldPos,
165
- setWorldPos: pos => { marker.worldPos = pos; updateDotPos(); },
166
- destroy: function() {
167
- currentDrag && currentDrag.cleanup();
168
- scene.camera.off(onViewMatrix);
169
- scene.camera.off(onProjMatrix);
170
- marker.destroy();
171
- dot.destroy();
172
- }
218
+ return function() {
219
+ currentDrag && currentDrag.cleanup();
220
+ cleanupDotHandlers.forEach(c => c());
221
+ dot.setOpacity(1.0);
173
222
  };
174
223
  };
175
224
 
@@ -187,11 +236,10 @@ export function activateDraggableDots(cfg) {
187
236
  const viewer = extractCFG("viewer");
188
237
  const handleMouseEvents = extractCFG("handleMouseEvents", false);
189
238
  const handleTouchEvents = extractCFG("handleTouchEvents", false);
190
- const snapping = extractCFG("snapping");
191
239
  const pointerLens = extractCFG("pointerLens", null);
192
- const color = extractCFG("color");
193
- const markers = extractCFG("markers");
194
- const onEdit = extractCFG("onEdit", nop);
240
+ const dots = extractCFG("dots");
241
+ const ray2WorldPos = extractCFG("ray2WorldPos");
242
+ const onEnd = extractCFG("onEnd", nop);
195
243
 
196
244
  const updatePointerLens = (pointerLens
197
245
  ? function(canvasPos) {
@@ -203,62 +251,36 @@ export function activateDraggableDots(cfg) {
203
251
  }
204
252
  : () => { });
205
253
 
206
- const dots = markers.map(marker => {
207
- let initDotPos, initMarkerPos;
208
- const setCoord = coord => marker.worldPos = coord;
209
-
210
- const dot = createDraggableDot3D({
254
+ const cleanups = dots.map(dot => {
255
+ let initPos;
256
+ return activateDraggableDot(dot, {
211
257
  handleMouseEvents: handleMouseEvents,
212
258
  handleTouchEvents: handleTouchEvents,
213
259
  viewer: viewer,
214
- worldPos: marker.worldPos,
215
- color: color,
216
- ray2WorldPos: (orig, dir, canvasPos) => {
217
- const tryPickWorldPos = snap => {
218
- const pickResult = viewer.scene.pick({
219
- canvasPos: canvasPos,
220
- snapToEdge: snap,
221
- snapToVertex: snap,
222
- pickSurface: true // <<------ This causes picking to find the intersection point on the entity
223
- });
224
-
225
- // If - when snapping - no pick found, then try w/o snapping
226
- return (pickResult && pickResult.worldPos) ? pickResult.worldPos : (snap && tryPickWorldPos(false));
227
- };
228
-
229
- return tryPickWorldPos(!!snapping) || initDotPos;
230
- },
260
+ ray2WorldPos: (orig, dir, canvasPos) => (ray2WorldPos(orig, dir, canvasPos) || initPos),
231
261
  onStart: () => {
232
- initDotPos = dot.getWorldPos().slice();
233
- initMarkerPos = marker.worldPos.slice();
262
+ initPos = dot.worldPos.slice();
234
263
  setOtherDotsActive(false, dot);
235
264
  },
236
265
  onMove: (canvasPos, worldPos) => {
237
266
  updatePointerLens(canvasPos);
238
- setCoord(worldPos);
267
+ dot.worldPos = worldPos;
239
268
  },
240
269
  onEnd: () => {
241
- if (! math.compareVec3(initMarkerPos, marker.worldPos))
242
- {
243
- onEdit();
244
- }
245
- else
246
- {
247
- dot.setWorldPos(initDotPos);
248
- setCoord(initMarkerPos);
270
+ if (! onEnd(initPos, dot)) {
271
+ dot.worldPos = initPos;
249
272
  }
250
273
  updatePointerLens(null);
251
274
  setOtherDotsActive(true, dot);
252
275
  }
253
276
  });
254
- return dot;
255
277
  });
256
278
 
257
- const setOtherDotsActive = (active, dot) => dots.forEach(d => (d !== dot) && d.setActive(active));
279
+ const setOtherDotsActive = (active, dot) => dots.forEach(d => (d !== dot) && d.setClickable(active));
258
280
  setOtherDotsActive(true);
259
281
 
260
282
  return function() {
261
- dots.forEach(m => m.destroy());
283
+ cleanups.forEach(c => c());
262
284
  updatePointerLens(null);
263
285
  };
264
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.off(this._onEntityDestroyed);
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.off(this._onEntityModelDestroyed);
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.model.on("destroyed", () => {
221
+ this._onEntityDestroyed = this._entity.on("destroyed", () => {
216
222
  this._entity = null;
217
223
  this._onEntityDestroyed = null;
218
224
  });