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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
@@ -1,6 +1,11 @@
1
1
  import RemoteCalibrator from '../core'
2
2
 
3
- import { constructInstructions, shuffle, blurAll } from '../components/utils'
3
+ import {
4
+ constructInstructions,
5
+ shuffle,
6
+ blurAll,
7
+ safeExecuteFunc,
8
+ } from '../components/utils'
4
9
  import { debug } from '../debug'
5
10
  import { bindKeys, unbindKeys } from '../components/keyBinder'
6
11
  import { phrases } from '../i18n'
@@ -60,8 +65,7 @@ RemoteCalibrator.prototype.calibrateGaze = function (options = {}, callback) {
60
65
  this._removeBackground() // Remove calibration background when the calibration finished
61
66
  unbindKeys(bindKeysFunction)
62
67
 
63
- // TODO Pass timestamp into callback
64
- if (callback && typeof callback === 'function') callback()
68
+ safeExecuteFunc(callback, { timestamp: new Date() })
65
69
  })
66
70
 
67
71
  const breakFunction = () => {
@@ -73,6 +77,11 @@ RemoteCalibrator.prototype.calibrateGaze = function (options = {}, callback) {
73
77
  originalStyles.video = false
74
78
  originalStyles.gazer = false
75
79
 
80
+ if (!this._trackingSetupFinishedStatus.gaze) {
81
+ this._trackingSetupFinishedStatus.gaze = true
82
+ this.endGaze()
83
+ }
84
+
76
85
  unbindKeys(bindKeysFunction)
77
86
  }
78
87
 
@@ -206,7 +215,8 @@ class GazeCalibrationDot {
206
215
  originalStyles.video = false
207
216
  originalStyles.gazer = false
208
217
 
209
- this.endCalibrationCallback()
218
+ safeExecuteFunc(this.endCalibrationCallback)
219
+ this.RC._trackingSetupFinishedStatus.gaze = true
210
220
  }
211
221
  }
212
222
 
@@ -1,7 +1,10 @@
1
1
  import webgazer from '../WebGazer4RC/src/index.mjs'
2
2
 
3
- import { toFixedNumber } from '../components/utils'
3
+ import { safeExecuteFunc, toFixedNumber } from '../components/utils'
4
4
  import { checkWebgazerReady } from '../components/video'
5
+ import Swal from 'sweetalert2'
6
+ import { swalInfoOptions } from '../components/swalOptions'
7
+ import { phrases } from '../i18n'
5
8
 
6
9
  /**
7
10
  * The gaze tracker object to wrap all gaze-related functions
@@ -32,7 +35,7 @@ export default class GazeTracker {
32
35
  begin({ pipWidthPx }, callback) {
33
36
  if (this.checkInitialized('gaze', true)) {
34
37
  if (!this._running.gaze) {
35
- this.webgazer.begin()
38
+ this.webgazer.begin(this.videoFailed.bind(this))
36
39
  this._running.gaze = true
37
40
  this._runningVideo = true
38
41
  }
@@ -51,7 +54,7 @@ export default class GazeTracker {
51
54
  // Begin video only
52
55
  if (this.checkInitialized('distance', true)) {
53
56
  if (!this._runningVideo) {
54
- this.webgazer.beginVideo()
57
+ this.webgazer.beginVideo(this.videoFailed.bind(this))
55
58
  this._runningVideo = true
56
59
  }
57
60
 
@@ -65,12 +68,24 @@ export default class GazeTracker {
65
68
  }
66
69
  }
67
70
 
71
+ videoFailed(videoInputs) {
72
+ Swal.fire({
73
+ ...swalInfoOptions(this.calibrator, { showIcon: true }),
74
+ icon: 'error',
75
+ iconColor: this.calibrator._CONST.COLOR.DARK_RED,
76
+ showConfirmButton: false,
77
+ html: videoInputs.length
78
+ ? phrases.RC_errorCameraUseDenied[this.calibrator.L]
79
+ : phrases.RC_errorNoCamera[this.calibrator.L],
80
+ })
81
+ }
82
+
68
83
  attachNewCallback(callback) {
69
84
  if (this.checkInitialized('gaze', true)) {
70
85
  this.webgazer.setGazeListener(d => {
71
86
  if (d) {
72
87
  const data = (this.calibrator.newGazePositionData = this.getData(d))
73
- if (callback) callback(data)
88
+ safeExecuteFunc(callback, data)
74
89
  }
75
90
  })
76
91
  }
@@ -80,7 +95,7 @@ export default class GazeTracker {
80
95
  let data = (this.calibrator.newGazePositionData = this.getData(
81
96
  await this.webgazer.getCurrentPrediction()
82
97
  ))
83
- if (callback) callback(data)
98
+ safeExecuteFunc(callback, data)
84
99
  return data
85
100
  }
86
101
 
@@ -95,10 +110,13 @@ GazeTracker.prototype._init = function (
95
110
  ) {
96
111
  if (!this.checkInitialized(task)) {
97
112
  if (task === 'gaze') {
98
- this.webgazer.clearData()
99
- this.webgazer.saveDataAcrossSessions(false)
113
+ // TODO Manually clear data
114
+ // this.webgazer.clearData()
115
+ // this.webgazer.saveDataAcrossSessions(false)
100
116
  this.webgazer.params.greedyLearner = greedyLearner
101
117
  this.webgazer.params.framerate = framerate
118
+ this.webgazer.params.getLatestVideoFrameTimestamp =
119
+ this._getLatestVideoTimestamp.bind(this)
102
120
  this.showGazer(showGazer)
103
121
  }
104
122
 
@@ -126,12 +144,15 @@ GazeTracker.prototype.checkInitialized = function (task, warning = false) {
126
144
  }
127
145
 
128
146
  GazeTracker.prototype.getData = function (d) {
147
+ let t = new Date()
129
148
  return {
130
149
  value: {
131
150
  x: toFixedNumber(d.x, this._toFixedN),
132
151
  y: toFixedNumber(d.y, this._toFixedN),
152
+ latencyMs:
153
+ t.getTime() - this.calibrator._tackingVideoFrameTimestamps.gaze, // latency
133
154
  },
134
- timestamp: new Date(),
155
+ timestamp: t,
135
156
  }
136
157
  }
137
158
 
@@ -155,6 +176,8 @@ GazeTracker.prototype.end = function (type, endAll = false) {
155
176
  this._endGaze()
156
177
  if (endEverything && this.checkInitialized('distance'))
157
178
  this.calibrator.endDistance(false, false)
179
+
180
+ this.calibrator._tackingVideoFrameTimestamps.gaze = 0
158
181
  } else {
159
182
  // Distance
160
183
  this.defaultDistanceTrackCallback = null
@@ -187,8 +210,16 @@ GazeTracker.prototype._endGaze = function () {
187
210
 
188
211
  this.webgazer.params.greedyLearner = false
189
212
  this.webgazer.params.framerate = 60
213
+
214
+ this.webgazer.params.getLatestVideoFrameTimestamp = () => {}
190
215
  }
191
216
 
217
+ GazeTracker.prototype._getLatestVideoTimestamp = function (t) {
218
+ this.calibrator._tackingVideoFrameTimestamps.gaze = t.getTime()
219
+ }
220
+
221
+ /* -------------------------------------------------------------------------- */
222
+
192
223
  GazeTracker.prototype.startStoringPoints = function () {
193
224
  this.webgazer.params.storingPoints = true
194
225
  }
@@ -218,7 +249,7 @@ GazeTracker.prototype.showGazer = function (show) {
218
249
  }
219
250
 
220
251
  GazeTracker.prototype.showVideo = function (show) {
221
- this.webgazer.showVideo(show)
252
+ this.webgazer.showVideo(show, this.calibrator._params.videoOpacity)
222
253
  }
223
254
 
224
255
  GazeTracker.prototype.showFaceOverlay = function (show) {