remote-calibrator 0.3.0-rc.3 → 0.5.0-beta.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. package/CHANGELOG.md +35 -3
  2. package/README.md +34 -49
  3. package/homepage/example.css +4 -3
  4. package/homepage/example.js +42 -22
  5. package/homepage/index.html +19 -4
  6. package/i18n/fetch-languages-sheets.js +11 -1
  7. package/lib/RemoteCalibrator.min.js +1 -1
  8. package/lib/RemoteCalibrator.min.js.LICENSE.txt +19 -2
  9. package/lib/RemoteCalibrator.min.js.map +1 -1
  10. package/netlify.toml +1 -1
  11. package/package.json +25 -24
  12. package/src/WebGazer4RC/package-lock.json +198 -143
  13. package/src/WebGazer4RC/package.json +2 -2
  14. package/src/WebGazer4RC/src/index.mjs +161 -52
  15. package/src/WebGazer4RC/test/webgazer_test.js +1 -1
  16. package/src/check/checkScreenSize.js +84 -0
  17. package/src/components/buttons.js +21 -4
  18. package/src/components/input.js +82 -0
  19. package/src/components/keyBinder.js +5 -6
  20. package/src/components/language.js +5 -0
  21. package/src/components/mediaPermission.js +21 -0
  22. package/src/components/onCanvas.js +2 -2
  23. package/src/components/sound.js +30 -2
  24. package/src/components/swalOptions.js +6 -3
  25. package/src/components/utils.js +27 -1
  26. package/src/components/video.js +9 -6
  27. package/src/const.js +15 -0
  28. package/src/core.js +103 -48
  29. package/src/css/buttons.scss +34 -7
  30. package/src/css/components.scss +57 -0
  31. package/src/css/distance.scss +71 -1
  32. package/src/css/gaze.css +9 -5
  33. package/src/css/main.css +22 -6
  34. package/src/css/panel.scss +33 -3
  35. package/src/css/screenSize.css +6 -5
  36. package/src/css/swal.css +1 -1
  37. package/src/css/video.scss +19 -0
  38. package/src/distance/distance.js +194 -41
  39. package/src/distance/distanceCheck.js +241 -0
  40. package/src/distance/distanceTrack.js +165 -68
  41. package/src/{interpupillaryDistance.js → distance/interPupillaryDistance.js} +27 -19
  42. package/src/gaze/gaze.js +4 -7
  43. package/src/gaze/gazeAccuracy.js +9 -4
  44. package/src/gaze/gazeCalibration.js +14 -4
  45. package/src/gaze/gazeTracker.js +40 -9
  46. package/src/i18n.js +1 -1
  47. package/src/index.js +7 -2
  48. package/src/media/two-side-arrow.svg +1 -0
  49. package/src/media/two-sided-horizontal.svg +1 -0
  50. package/src/media/two-sided-vertical.svg +3 -0
  51. package/src/panel.js +130 -65
  52. package/src/screenSize.js +38 -5
  53. package/webpack.config.js +7 -4
  54. package/media/measureDistance.png +0 -0
  55. package/media/panel.png +0 -0
  56. package/media/screenSize.png +0 -0
  57. package/media/trackGaze.png +0 -0
  58. package/src/displaySize.js +0 -28
@@ -6,9 +6,11 @@ import {
6
6
  constructInstructions,
7
7
  blurAll,
8
8
  sleep,
9
+ safeExecuteFunc,
9
10
  } from '../components/utils'
10
11
  import { iRepeat } from '../components/iRepeat'
11
12
  import { phrases } from '../i18n'
13
+ import { spaceForLanguage } from '../components/language'
12
14
 
13
15
  const originalStyles = {
14
16
  video: false,
@@ -41,17 +43,26 @@ RemoteCalibrator.prototype.trackDistance = function (
41
43
  {
42
44
  fullscreen: false,
43
45
  repeatTesting: 2,
44
- sparkle: true,
46
+ sparkle: false,
45
47
  pipWidthPx:
46
48
  this._CONST.N.VIDEO_W[this.isMobile.value ? 'MOBILE' : 'DESKTOP'],
47
49
  showVideo: true,
48
50
  showFaceOverlay: false,
49
51
  decimalPlace: 1,
50
- framerate: 3, // track rate
51
- nearPoint: true, // New 0.0.6
52
- showNearPoint: false, // New 0.0.6
53
- headline: '🙂 ' + phrases.RC_headTrackingTitle[this.L],
54
- description: phrases.RC_headTrackingIntro[this.L],
52
+ framerate: 3, // tracking rate
53
+ desiredDistanceCm: undefined,
54
+ desiredDistanceTolerance: 1.2,
55
+ desiredDistanceMonitor: false,
56
+ desiredDistanceMonitorCancelable: false,
57
+ nearPoint: true,
58
+ showNearPoint: false,
59
+ headline: '🙂 ' + phrases.RC_distanceTrackingTitle[this.L],
60
+ description:
61
+ phrases.RC_distanceTrackingIntroStart[this.L] +
62
+ spaceForLanguage(this.L) +
63
+ phrases.RC_viewingDistanceIntro[this.L] +
64
+ spaceForLanguage(this.L) +
65
+ phrases.RC_distanceTrackingIntroEnd[this.L],
55
66
  },
56
67
  options
57
68
  )
@@ -85,9 +96,7 @@ RemoteCalibrator.prototype.trackDistance = function (
85
96
  if (this.gazeTracker.checkInitialized('gaze', false))
86
97
  this.showGazer(originalGazer)
87
98
 
88
- if (callbackStatic && typeof callbackStatic === 'function')
89
- callbackStatic(distData)
90
-
99
+ safeExecuteFunc(callbackStatic, distData)
91
100
  stdDist.current = distData
92
101
  }
93
102
 
@@ -112,6 +121,12 @@ RemoteCalibrator.prototype.trackDistance = function (
112
121
  trackingOptions.nearPoint = options.nearPoint
113
122
  trackingOptions.showNearPoint = options.showNearPoint
114
123
 
124
+ trackingOptions.desiredDistanceCm = options.desiredDistanceCm
125
+ trackingOptions.desiredDistanceTolerance = options.desiredDistanceTolerance
126
+ trackingOptions.desiredDistanceMonitor = options.desiredDistanceMonitor
127
+ trackingOptions.desiredDistanceMonitorCancelable =
128
+ options.desiredDistanceMonitorCancelable
129
+
115
130
  originalStyles.video = options.showVideo
116
131
 
117
132
  this.gazeTracker._init(
@@ -123,41 +138,52 @@ RemoteCalibrator.prototype.trackDistance = function (
123
138
  'distance'
124
139
  )
125
140
 
141
+ this._trackingSetupFinishedStatus.distance = false
142
+
143
+ const trackingConfig = {
144
+ options: options,
145
+ callbackStatic: callbackStatic,
146
+ callbackTrack: callbackTrack,
147
+ }
148
+
126
149
  if (options.nearPoint) {
127
150
  startTrackingPupils(
128
151
  this,
129
152
  () => {
130
- this.measurePD({}, _)
153
+ this._measurePD({}, _)
131
154
  },
132
- callbackTrack
155
+ callbackTrack,
156
+ trackingConfig
133
157
  )
134
158
  } else {
135
- startTrackingPupils(this, _, callbackTrack)
159
+ startTrackingPupils(this, _, callbackTrack, trackingConfig)
136
160
  }
137
161
  }
138
162
 
139
163
  /* -------------------------------------------------------------------------- */
140
164
 
141
- const startTrackingPupils = async (RC, beforeCallbackTrack, callbackTrack) => {
165
+ const startTrackingPupils = async (
166
+ RC,
167
+ beforeCallbackTrack,
168
+ callbackTrack,
169
+ trackingConfig
170
+ ) => {
142
171
  RC.gazeTracker.beginVideo({ pipWidthPx: trackingOptions.pipWidthPx }, () => {
143
172
  RC._removeFloatInstructionElement()
144
- beforeCallbackTrack()
145
- _tracking(RC, trackingOptions, callbackTrack)
173
+ safeExecuteFunc(beforeCallbackTrack)
174
+ _tracking(RC, trackingOptions, callbackTrack, trackingConfig)
146
175
  })
147
176
  }
148
177
 
149
178
  const eyeDist = (a, b) => {
150
- return Math.sqrt(
151
- Math.pow(a[0] - b[0], 2) +
152
- Math.pow(a[1] - b[1], 2) +
153
- Math.pow(a[2] - b[2], 2)
154
- )
179
+ return Math.hypot(a[0] - b[0], a[1] - b[1], a[2] - b[2])
155
180
  }
156
181
 
157
182
  const cyclopean = (video, a, b) => {
158
- let [aX, aY] = [video.videoWidth - a[0], a[1]]
159
- let [bX, bY] = [video.videoWidth - b[0], b[1]]
160
- return [(aX + bX) / 2, (aY + bY) / 2]
183
+ return [
184
+ (-a[0] - b[0] + video.videoWidth) / 2,
185
+ (-a[1] - b[1] + video.videoHeight) / 2,
186
+ ]
161
187
  }
162
188
 
163
189
  /* -------------------------------------------------------------------------- */
@@ -167,6 +193,10 @@ const trackingOptions = {
167
193
  framerate: 3,
168
194
  nearPoint: true,
169
195
  showNearPoint: false,
196
+ desiredDistanceCm: undefined,
197
+ desiredDistanceTolerance: 1.2,
198
+ desiredDistanceMonitor: false,
199
+ desiredDistanceMonitorCancelable: false,
170
200
  }
171
201
 
172
202
  const stdDist = { current: null }
@@ -177,22 +207,31 @@ let iRepeatOptions = { framerate: 20, break: true }
177
207
  let nearPointDot = null
178
208
  /* -------------------------------------------------------------------------- */
179
209
 
180
- const _tracking = async (RC, trackingOptions, callbackTrack) => {
210
+ let readyToGetFirstData = false
211
+ let averageDist = 0
212
+ let distCount = 1
213
+
214
+ const _tracking = async (
215
+ RC,
216
+ trackingOptions,
217
+ callbackTrack,
218
+ trackingConfig
219
+ ) => {
181
220
  const video = document.querySelector('#webgazerVideoFeed')
182
221
 
183
222
  const _ = async () => {
184
223
  // const canvas = RC.gazeTracker.webgazer.videoCanvas
185
224
  let model, faces
186
225
 
187
- // Get the average of 2 estimates for one measure
188
- let averageDist = 0
189
- let distCount = 1
226
+ // Get the average of 5 estimates for one measure
227
+ averageDist = 0
228
+ distCount = 1
190
229
  const targetCount = 5
191
230
 
192
231
  model = await RC.gazeTracker.webgazer.getTracker().model
193
232
 
194
233
  // Near point
195
- let ppi = RC.screenPpi ? RC.screenPpi.value : 108
234
+ let ppi = RC.screenPpi ? RC.screenPpi.value : RC._CONST.N.PPI_DONT_USE
196
235
  if (!RC.screenPpi && trackingOptions.nearPoint)
197
236
  console.error(
198
237
  'Screen size measurement is required to get accurate near point tracking.'
@@ -215,29 +254,54 @@ const _tracking = async (RC, trackingOptions, callbackTrack) => {
215
254
  })
216
255
  }
217
256
 
257
+ readyToGetFirstData = false
258
+ const {
259
+ desiredDistanceCm,
260
+ desiredDistanceTolerance,
261
+ desiredDistanceMonitor,
262
+ desiredDistanceMonitorCancelable,
263
+ } = trackingOptions
264
+
265
+ // Always enable correct on a fresh start
266
+ RC._distanceTrackNudging.distanceCorrectEnabled = true
267
+ RC._distanceTrackNudging.distanceDesired = desiredDistanceCm
268
+ RC._distanceTrackNudging.distanceAllowedRatio = desiredDistanceTolerance
269
+
218
270
  viewingDistanceTrackingFunction = async () => {
271
+ //
272
+ const videoTimestamp = new Date().getTime()
273
+ //
219
274
  faces = await model.estimateFaces(video)
220
275
  if (faces.length) {
221
276
  // There's at least one face in video
222
- const mesh = faces[0].scaledMesh
277
+ RC._tackingVideoFrameTimestamps.distance += videoTimestamp
223
278
  // https://github.com/tensorflow/tfjs-models/blob/master/facemesh/mesh_map.jpg
279
+ const mesh = faces[0].scaledMesh
280
+
224
281
  if (targetCount === distCount) {
225
282
  averageDist += eyeDist(mesh[133], mesh[362])
226
- averageDist /= 5
283
+ averageDist /= targetCount
284
+ RC._tackingVideoFrameTimestamps.distance /= targetCount
227
285
 
286
+ // TODO Add more samples for the first estimate
228
287
  if (stdDist.current !== null) {
229
288
  if (!stdFactor) {
230
289
  // ! First time estimate
231
290
  // Face_Known_Px * Distance_Known_Cm = Face_Now_Px * Distance_x_Cm
232
291
  // Get the factor to be used for future predictions
233
292
  stdFactor = averageDist * stdDist.current.value
234
- // FINISH
293
+ // ! FINISH
235
294
  RC._removeBackground()
295
+ RC._trackingSetupFinishedStatus.distance = true
296
+ readyToGetFirstData = true
236
297
  }
237
298
 
238
299
  /* -------------------------------------------------------------------------- */
239
300
 
240
301
  const timestamp = new Date()
302
+ const latency = Math.round(
303
+ timestamp.getTime() - RC._tackingVideoFrameTimestamps.distance
304
+ )
241
305
 
242
306
  const data = (RC.newViewingDistanceData = {
243
307
  value: toFixedNumber(
@@ -245,9 +309,20 @@ const _tracking = async (RC, trackingOptions, callbackTrack) => {
245
309
  trackingOptions.decimalPlace
246
310
  ),
247
311
  timestamp: timestamp,
248
- method: 'Facemesh Predict',
312
+ method: RC._CONST.VIEW_METHOD.F,
313
+ latencyMs: latency,
249
314
  })
250
315
 
316
+ if (readyToGetFirstData || desiredDistanceMonitor) {
317
+ // ! Check distance
318
+ if (desiredDistanceCm)
319
+ RC.checkDistance(
320
+ desiredDistanceMonitorCancelable,
321
+ trackingConfig
322
+ )
323
+ readyToGetFirstData = false
324
+ }
325
+
251
326
  /* -------------------------------------------------------------------------- */
252
327
 
253
328
  // Near point
@@ -260,7 +335,8 @@ const _tracking = async (RC, trackingOptions, callbackTrack) => {
260
335
  mesh,
261
336
  averageDist,
262
337
  timestamp,
263
- ppi
338
+ ppi,
339
+ latency
264
340
  )
265
341
  }
266
342
 
@@ -272,15 +348,18 @@ const _tracking = async (RC, trackingOptions, callbackTrack) => {
272
348
  value: {
273
349
  viewingDistanceCm: data.value,
274
350
  nearPointCm: nPData ? nPData.value : [null, null],
351
+ latencyMs: latency,
275
352
  },
276
353
  timestamp: timestamp,
277
- method: 'Facemesh Predict',
354
+ method: RC._CONST.VIEW_METHOD.F,
278
355
  })
279
356
  }
280
357
  }
281
358
 
282
359
  averageDist = 0
283
360
  distCount = 1
361
+
362
+ RC._tackingVideoFrameTimestamps.distance = 0
284
363
  } else {
285
364
  averageDist += eyeDist(mesh[133], mesh[362])
286
365
  ++distCount
@@ -289,11 +368,11 @@ const _tracking = async (RC, trackingOptions, callbackTrack) => {
289
368
  }
290
369
 
291
370
  iRepeatOptions.break = false
292
- iRepeatOptions.framerate = targetCount * trackingOptions.framerate // Default 3 * 5
371
+ iRepeatOptions.framerate = targetCount * trackingOptions.framerate // Default 5 * 3
293
372
  iRepeat(viewingDistanceTrackingFunction, iRepeatOptions)
294
373
  }
295
374
 
296
- sleep(500).then(_)
375
+ sleep(1000).then(_)
297
376
  }
298
377
 
299
378
  const _getNearPoint = (
@@ -303,45 +382,42 @@ const _getNearPoint = (
303
382
  mesh,
304
383
  averageDist,
305
384
  timestamp,
306
- ppi
385
+ ppi,
386
+ latency
307
387
  ) => {
308
- let m = cyclopean(video, mesh[133], mesh[362])
309
- let offsetToVideoMid = [
310
- m[0] - video.videoWidth / 2,
311
- video.videoHeight / 2 - m[1],
312
- ]
313
-
314
- const videoFactor = video.videoHeight / video.clientHeight
315
- offsetToVideoMid.forEach((e, i) => {
316
- // Average interpupillary distance - 6.4cm
317
- offsetToVideoMid[i] =
318
- ((RC.PDCm ? RC.PDCm.value : 6.4) * e) /
319
- (averageDist * (videoFactor / 2)) /* Should this be videoFactor? */
388
+ let offsetToVideoCenter = cyclopean(video, mesh[133], mesh[362])
389
+ offsetToVideoCenter.forEach((offset, i) => {
390
+ // Average inter-pupillary distance - 6.4cm
391
+ offsetToVideoCenter[i] =
392
+ ((RC.PDCm ? RC.PDCm.value : RC._CONST.N.PD_DONT_USE) * offset) /
393
+ averageDist
320
394
  })
321
395
 
322
396
  let nPData = (RC.newNearPointData = {
323
397
  value: {
324
- x: toFixedNumber(offsetToVideoMid[0], trackingOptions.decimalPlace),
398
+ x: toFixedNumber(offsetToVideoCenter[0], trackingOptions.decimalPlace),
325
399
  y: toFixedNumber(
326
- offsetToVideoMid[1] + 0.5, // Commonly the webcam is 0.5cm above the screen
400
+ offsetToVideoCenter[1] + ((screen.height / 2) * 2.54) / ppi, // Commonly the webcam is 0.5cm above the screen
327
401
  trackingOptions.decimalPlace
328
402
  ),
403
+ latencyMs: latency,
329
404
  },
330
405
  timestamp: timestamp,
331
406
  })
332
407
 
333
408
  // SHOW
409
+ const dotR = 5
334
410
  if (trackingOptions.showNearPoint) {
335
411
  let offsetX = (nPData.value.x * ppi) / 2.54
336
412
  let offsetY = (nPData.value.y * ppi) / 2.54
337
413
  Object.assign(nearPointDot.style, {
338
- left: `${screen.width / 2 - window.screenLeft - 5 + offsetX}px`,
414
+ left: `${screen.width / 2 - window.screenLeft + offsetX - dotR}px`,
339
415
  top: `${
340
416
  screen.height / 2 -
341
417
  window.screenTop -
342
- 5 -
343
- (RC.isFullscreen.value ? 0 : 50) -
344
- offsetY
418
+ (window.outerHeight - window.innerHeight) -
419
+ offsetY -
420
+ dotR
345
421
  }px`,
346
422
  })
347
423
  }
@@ -353,6 +429,7 @@ RemoteCalibrator.prototype.pauseDistance = function () {
353
429
  if (this.gazeTracker.checkInitialized('distance', true)) {
354
430
  iRepeatOptions.break = true
355
431
  if (nearPointDot) nearPointDot.style.display = 'none'
432
+ this._tackingVideoFrameTimestamps.distance = 0
356
433
  return this
357
434
  }
358
435
  return null
@@ -362,6 +439,11 @@ RemoteCalibrator.prototype.resumeDistance = function () {
362
439
  if (this.gazeTracker.checkInitialized('distance', true)) {
363
440
  iRepeatOptions.break = false
364
441
  if (nearPointDot) nearPointDot.style.display = 'block'
442
+
443
+ averageDist = 0
444
+ distCount = 1
445
+ this._tackingVideoFrameTimestamps.distance = 0
446
+
365
447
  iRepeat(viewingDistanceTrackingFunction, iRepeatOptions)
366
448
  return this
367
449
  }
@@ -379,21 +461,30 @@ RemoteCalibrator.prototype.endDistance = function (endAll = false, _r = true) {
379
461
  trackingOptions.nearPoint = true
380
462
  trackingOptions.showNearPoint = false
381
463
 
464
+ trackingOptions.desiredDistanceCm = undefined
465
+ trackingOptions.desiredDistanceTolerance = 1.2
466
+ trackingOptions.desiredDistanceMonitor = false
467
+ trackingOptions.desiredDistanceMonitorCancelable = false
468
+
382
469
  stdDist.current = null
383
470
  stdFactor = null
384
471
  viewingDistanceTrackingFunction = null
385
472
 
473
+ readyToGetFirstData = false
474
+ this._tackingVideoFrameTimestamps.distance = 0
475
+
386
476
  // Near point
387
477
  if (nearPointDot) {
388
478
  document.body.removeChild(nearPointDot)
389
479
  nearPointDot = null
390
480
  }
391
481
 
392
- if (_r) this.gazeTracker.end('distance', endAll)
482
+ // Nudger
483
+ this.endNudger()
393
484
 
485
+ if (_r) this.gazeTracker.end('distance', endAll)
394
486
  return this
395
487
  }
396
-
397
488
  return null
398
489
  }
399
490
 
@@ -409,6 +500,7 @@ RemoteCalibrator.prototype.getDistanceNow = async function (callback = null) {
409
500
 
410
501
  let v = document.querySelector('#webgazerVideoFeed')
411
502
  let m = await this.gazeTracker.webgazer.getTracker().model
503
+ const videoTimestamp = new Date().getTime()
412
504
  let f = await m.estimateFaces(v)
413
505
 
414
506
  if (f.length) {
@@ -416,11 +508,15 @@ RemoteCalibrator.prototype.getDistanceNow = async function (callback = null) {
416
508
  const dist = eyeDist(mesh[133], mesh[362])
417
509
 
418
510
  let timestamp = new Date()
511
+ //
512
+ const latency = timestamp.getTime() - videoTimestamp
513
+ //
419
514
 
420
515
  const data = (this.newViewingDistanceData = {
421
516
  value: toFixedNumber(stdFactor / dist, trackingOptions.decimalPlace),
422
517
  timestamp: timestamp,
423
- method: 'Facemesh Predict',
518
+ method: this._CONST.VIEW_METHOD.F,
519
+ latencyMs: latency,
424
520
  })
425
521
 
426
522
  let nPData
@@ -432,19 +528,20 @@ RemoteCalibrator.prototype.getDistanceNow = async function (callback = null) {
432
528
  mesh,
433
529
  dist,
434
530
  timestamp,
435
- this.screenPpi ? this.screenPpi.value : 108
531
+ this.screenPpi ? this.screenPpi.value : this._CONST.N.PPI_DONT_USE,
532
+ latency
436
533
  )
437
534
  }
438
535
 
439
- if (c)
440
- c({
441
- value: {
442
- viewingDistanceCm: data.value,
443
- nearPointCm: nPData ? nPData.value : null,
444
- },
445
- timestamp: timestamp,
446
- method: 'Facemesh Predict',
447
- })
536
+ safeExecuteFunc(c, {
537
+ value: {
538
+ viewingDistanceCm: data.value,
539
+ nearPointCm: nPData ? nPData.value : null,
540
+ latencyMs: latency,
541
+ },
542
+ timestamp: timestamp,
543
+ method: this._CONST.VIEW_METHOD.F,
544
+ })
448
545
  return data
449
546
  }
450
547
 
@@ -1,19 +1,20 @@
1
1
  import Swal from 'sweetalert2'
2
2
 
3
- import RemoteCalibrator from './core'
3
+ import RemoteCalibrator from '../core'
4
4
 
5
5
  import {
6
6
  blurAll,
7
7
  constructInstructions,
8
+ safeExecuteFunc,
8
9
  toFixedNumber,
9
- } from './components/utils'
10
- import { swalInfoOptions } from './components/swalOptions'
11
- import Arrow from './media/arrow.svg'
12
- import PD from './media/pd.png?width=480&height=240'
13
- import { bindKeys, unbindKeys } from './components/keyBinder'
14
- import { addButtons } from './components/buttons'
15
- import { setDefaultVideoPosition } from './components/video'
16
- import { phrases } from './i18n'
10
+ } from '../components/utils'
11
+ import { swalInfoOptions } from '../components/swalOptions'
12
+ import Arrow from '../media/arrow.svg'
13
+ import PD from '../media/pd.png?width=480&height=240'
14
+ import { bindKeys, unbindKeys } from '../components/keyBinder'
15
+ import { addButtons } from '../components/buttons'
16
+ import { setDefaultVideoPosition } from '../components/video'
17
+ import { phrases } from '../i18n'
17
18
 
18
19
  // let selfVideo = false // No WebGazer video available and an extra video element needs to be created
19
20
 
@@ -29,7 +30,7 @@ const originalStyles = {
29
30
  const videoWidthFactor = 0.9
30
31
  const videoHeightFactor = 0.3
31
32
 
32
- RemoteCalibrator.prototype.measurePD = function (options = {}, callback) {
33
+ RemoteCalibrator.prototype._measurePD = function (options = {}, callback) {
33
34
  ////
34
35
  if (!this.checkInitialized()) return
35
36
  blurAll()
@@ -39,7 +40,7 @@ RemoteCalibrator.prototype.measurePD = function (options = {}, callback) {
39
40
  {
40
41
  fullscreen: false,
41
42
  headline: '👁️ ' + phrases.RC_nearPointTitle[this.L],
42
- description: phrases.RC_nearPointIntroCaption[this.L],
43
+ description: phrases.RC_nearPointIntro[this.L],
43
44
  shortDescription: phrases.RC_nearPointIntro[this.L],
44
45
  },
45
46
  options
@@ -50,9 +51,11 @@ RemoteCalibrator.prototype.measurePD = function (options = {}, callback) {
50
51
  this._replaceBackground()
51
52
 
52
53
  this._replaceBackground(
53
- constructInstructions(options.headline, options.shortDescription)
54
+ constructInstructions(options.headline, options.shortDescription, true)
54
55
  )
55
- const screenPpi = this.screenPpi ? this.screenPpi.value : 108
56
+ const screenPpi = this.screenPpi
57
+ ? this.screenPpi.value
58
+ : this._CONST.N.PPI_DONT_USE
56
59
 
57
60
  let [videoWidth, videoHeight] = setupVideo(this)
58
61
  let [ruler, rulerListener] = setupRuler(
@@ -64,7 +67,7 @@ RemoteCalibrator.prototype.measurePD = function (options = {}, callback) {
64
67
 
65
68
  const RC = this
66
69
 
67
- const breakFunction = () => {
70
+ const breakFunction = (toBreak = true) => {
68
71
  ruler.removeEventListener('mousedown', rulerListener)
69
72
  this._removeBackground()
70
73
 
@@ -77,7 +80,7 @@ RemoteCalibrator.prototype.measurePD = function (options = {}, callback) {
77
80
  height: originalStyles.videoHeight,
78
81
  width: originalStyles.videoWidth,
79
82
  opacity: originalStyles.opacity,
80
- borderRadius: '0px',
83
+ borderRadius: '5px',
81
84
  })
82
85
  setDefaultVideoPosition(
83
86
  RC,
@@ -99,6 +102,11 @@ RemoteCalibrator.prototype.measurePD = function (options = {}, callback) {
99
102
  originalStyles.gaze = false
100
103
  originalStyles.faceOverlay = false
101
104
 
105
+ if (!RC._trackingSetupFinishedStatus.distance && toBreak) {
106
+ RC._trackingSetupFinishedStatus.distance = true
107
+ RC.endDistance()
108
+ }
109
+
102
110
  unbindKeys(bindKeysFunction)
103
111
  }
104
112
 
@@ -110,14 +118,14 @@ RemoteCalibrator.prototype.measurePD = function (options = {}, callback) {
110
118
  }
111
119
  this.newPDData = newPDData
112
120
 
113
- breakFunction()
114
- callback()
121
+ breakFunction(false)
122
+ safeExecuteFunc(callback, newPDData)
115
123
  }
116
124
  }
117
125
 
118
- // if (callback && typeof callback === 'function') callback()
119
126
  const bindKeysFunction = bindKeys({
120
127
  Escape: breakFunction,
128
+ Enter: finishFunction,
121
129
  ' ': finishFunction,
122
130
  })
123
131
  addButtons(
@@ -133,7 +141,7 @@ RemoteCalibrator.prototype.measurePD = function (options = {}, callback) {
133
141
  // TODO To be removed
134
142
  setTimeout(() => {
135
143
  Swal.fire({
136
- ...swalInfoOptions(this),
144
+ ...swalInfoOptions(this, { showIcon: false }),
137
145
  icon: undefined,
138
146
  imageUrl: PD,
139
147
  imageWidth: 480,
package/src/gaze/gaze.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import RemoteCalibrator from '../core'
2
2
 
3
- import { blurAll } from '../components/utils'
3
+ import { blurAll, safeExecuteFunc } from '../components/utils'
4
4
  import { gazeCalibrationPrepare } from './gazeCalibration'
5
5
  import { phrases } from '../i18n'
6
6
 
@@ -97,17 +97,14 @@ RemoteCalibrator.prototype.trackGaze = function (
97
97
  description: options.description,
98
98
  }
99
99
  this.gazeTracker.begin(gazeTrackerBeginOptions, () => {
100
+ this._trackingSetupFinishedStatus.gaze = false
100
101
  this.calibrateGaze(calibrateGazeOptions, onCalibrationEnded)
101
102
  })
102
103
 
103
104
  // Calibration
104
105
 
105
- const onCalibrationEnded = () => {
106
- if (
107
- callbackOnCalibrationEnd &&
108
- typeof callbackOnCalibrationEnd === 'function'
109
- )
110
- callbackOnCalibrationEnd()
106
+ const onCalibrationEnded = data => {
107
+ safeExecuteFunc(callbackOnCalibrationEnd, data)
111
108
 
112
109
  // ! greedyLearner
113
110
  if (!this.gazeTracker.webgazer.params.greedyLearner) {
@@ -3,7 +3,12 @@ import Swal from 'sweetalert2/dist/sweetalert2.js'
3
3
  import RemoteCalibrator from '../core'
4
4
 
5
5
  import { _cross } from '../components/onCanvas'
6
- import { blurAll, sleep, toFixedNumber } from '../components/utils'
6
+ import {
7
+ blurAll,
8
+ safeExecuteFunc,
9
+ sleep,
10
+ toFixedNumber,
11
+ } from '../components/utils'
7
12
  import { swalInfoOptions } from '../components/swalOptions'
8
13
 
9
14
  let inGetAccuracy = false
@@ -57,7 +62,7 @@ RemoteCalibrator.prototype.getGazeAccuracy = function (
57
62
  _resizeCanvas()
58
63
 
59
64
  Swal.fire({
60
- ...swalInfoOptions(this),
65
+ ...swalInfoOptions(this, { showIcon: true }),
61
66
  // title: text.getGazeAccuracy.headline,
62
67
  html: `We will measure your gaze accuracy. Please do not move the mouse and look at the fixation at the middle of the screen for the next 5 seconds.`,
63
68
  }).then(() => {
@@ -88,8 +93,8 @@ RemoteCalibrator.prototype.getGazeAccuracy = function (
88
93
 
89
94
  if (averageDegree < options.thresholdDeg)
90
95
  // Success
91
- callbackSuccess()
92
- else callbackFail()
96
+ safeExecuteFunc(callbackSuccess)
97
+ else safeExecuteFunc(callbackFail)
93
98
 
94
99
  ctx.clearRect(0, 0, canvas.width, canvas.height)
95
100
  resizeObserver.unobserve(this.background)