@lovelace_lol/polymer 0.0.7 → 0.0.9

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 (95) hide show
  1. package/README.md +434 -12
  2. package/dist/index.d.ts +1945 -244
  3. package/dist/index.js +1686 -1017
  4. package/dist/vision/face-worker.js +296 -0
  5. package/dist/vision/face_landmarker.task +0 -0
  6. package/dist/vision/manifest.edn +1 -0
  7. package/dist/vision/vision_bundle.js +2 -0
  8. package/dist/vision/wasm/vision_wasm_internal.js +8841 -0
  9. package/dist/vision/wasm/vision_wasm_internal.wasm +0 -0
  10. package/dist/vision/wasm/vision_wasm_module_internal.js +8837 -0
  11. package/dist/vision/wasm/vision_wasm_module_internal.wasm +0 -0
  12. package/dist/vision/wasm/vision_wasm_nosimd_internal.js +8832 -0
  13. package/dist/vision/wasm/vision_wasm_nosimd_internal.wasm +0 -0
  14. package/dist/worker/agency-worker.js +1276 -962
  15. package/dist/worker/manifest.edn +1 -1
  16. package/package.json +33 -20
  17. package/dist/test.cjs +0 -1519
  18. package/shadow-cljs.edn +0 -173
  19. package/src/polymer/animation/agency.cljs +0 -84
  20. package/src/polymer/animation/domain.cljs +0 -110
  21. package/src/polymer/animation/planner.cljs +0 -88
  22. package/src/polymer/animation/runtime.cljs +0 -137
  23. package/src/polymer/animation/scheduler.cljs +0 -178
  24. package/src/polymer/animation/service.cljs +0 -981
  25. package/src/polymer/animation/state.cljs +0 -112
  26. package/src/polymer/blink/agency.cljs +0 -131
  27. package/src/polymer/blink/planner.cljs +0 -115
  28. package/src/polymer/blink/scheduler.cljs +0 -90
  29. package/src/polymer/blink/snippet.cljs +0 -50
  30. package/src/polymer/blink/state.cljs +0 -102
  31. package/src/polymer/camera_context/agency.cljs +0 -132
  32. package/src/polymer/camera_context/domain.cljs +0 -186
  33. package/src/polymer/camera_context/planner.cljs +0 -50
  34. package/src/polymer/camera_context/scheduler.cljs +0 -113
  35. package/src/polymer/camera_context/state.cljs +0 -121
  36. package/src/polymer/character.cljs +0 -403
  37. package/src/polymer/conversation/agency.cljs +0 -83
  38. package/src/polymer/conversation/domain.cljs +0 -35
  39. package/src/polymer/conversation/effector.cljs +0 -130
  40. package/src/polymer/conversation/planner.cljs +0 -178
  41. package/src/polymer/conversation/scheduler.cljs +0 -202
  42. package/src/polymer/conversation/service.cljs +0 -329
  43. package/src/polymer/conversation/state.cljs +0 -186
  44. package/src/polymer/core.cljs +0 -172
  45. package/src/polymer/eye_head/agency.cljs +0 -75
  46. package/src/polymer/eye_head/domain.cljs +0 -133
  47. package/src/polymer/eye_head/goap.cljs +0 -106
  48. package/src/polymer/eye_head/scheduler.cljs +0 -176
  49. package/src/polymer/eye_head/service.cljs +0 -259
  50. package/src/polymer/eye_head/snippet.cljs +0 -92
  51. package/src/polymer/eye_head/state.cljs +0 -167
  52. package/src/polymer/gaze/agency.cljs +0 -85
  53. package/src/polymer/gaze/domain.cljs +0 -211
  54. package/src/polymer/gaze/goap.cljs +0 -208
  55. package/src/polymer/gaze/scheduler.cljs +0 -184
  56. package/src/polymer/gaze/state.cljs +0 -202
  57. package/src/polymer/gesture/agency.cljs +0 -185
  58. package/src/polymer/gesture/goap.cljs +0 -461
  59. package/src/polymer/gesture/scheduler.cljs +0 -122
  60. package/src/polymer/gesture/snippet.cljs +0 -198
  61. package/src/polymer/gesture/state.cljs +0 -273
  62. package/src/polymer/lipsync/agency.cljs +0 -593
  63. package/src/polymer/lipsync/articulation/jaw.cljs +0 -258
  64. package/src/polymer/lipsync/articulation/snippet.cljs +0 -605
  65. package/src/polymer/lipsync/articulation/tongue.cljs +0 -418
  66. package/src/polymer/lipsync/articulation/visemes.cljs +0 -429
  67. package/src/polymer/lipsync/goap.cljs +0 -132
  68. package/src/polymer/lipsync/pronunciation/effector.cljs +0 -51
  69. package/src/polymer/lipsync/scheduler.cljs +0 -302
  70. package/src/polymer/lipsync/state.cljs +0 -202
  71. package/src/polymer/nlp/phonemes.cljs +0 -164
  72. package/src/polymer/prosodic/agency.cljs +0 -196
  73. package/src/polymer/prosodic/goap.cljs +0 -122
  74. package/src/polymer/prosodic/scheduler.cljs +0 -99
  75. package/src/polymer/prosodic/snippet.cljs +0 -106
  76. package/src/polymer/prosodic/state.cljs +0 -139
  77. package/src/polymer/runtime/embody.cljs +0 -117
  78. package/src/polymer/runtime/embody_wasm.cljs +0 -177
  79. package/src/polymer/runtime/rust_embody_host.cljs +0 -647
  80. package/src/polymer/society.cljs +0 -253
  81. package/src/polymer/stream.cljs +0 -130
  82. package/src/polymer/transcription/agency.cljs +0 -69
  83. package/src/polymer/transcription/domain.cljs +0 -68
  84. package/src/polymer/transcription/effector.cljs +0 -611
  85. package/src/polymer/transcription/planner.cljs +0 -203
  86. package/src/polymer/transcription/scheduler.cljs +0 -225
  87. package/src/polymer/transcription/service.cljs +0 -209
  88. package/src/polymer/transcription/state.cljs +0 -239
  89. package/src/polymer/tts/agency.cljs +0 -503
  90. package/src/polymer/tts/azure.cljs +0 -290
  91. package/src/polymer/tts/planner.cljs +0 -178
  92. package/src/polymer/tts/runtime.cljs +0 -624
  93. package/src/polymer/tts/scheduler.cljs +0 -162
  94. package/src/polymer/tts/state.cljs +0 -191
  95. package/src/polymer/worker.cljs +0 -81
@@ -1,259 +0,0 @@
1
- (ns polymer.eye-head.service
2
- (:require [polymer.animation.service :as animation-service]
3
- [polymer.eye-head.agency :as eye-head-agency]))
4
-
5
- ;; Compatibility adapter for the JavaScript service API LoomLarge already uses.
6
- ;; This is not the Eye/Head agency implementation. Movement work enters
7
- ;; Polymer's Eye/Head agency first; this adapter only preserves the historical
8
- ;; API while routing accepted animation requests into Polymer Animation.
9
-
10
- (def EYE_AUS
11
- #js {:BOTH_LOOK_LEFT 61
12
- :BOTH_LOOK_RIGHT 62
13
- :BOTH_LOOK_UP 63
14
- :BOTH_LOOK_DOWN 64
15
- :BLINK 43
16
- :WIDE 5
17
- :SQUINT 7})
18
-
19
- (def HEAD_AUS
20
- #js {:TURN_LEFT 51
21
- :TURN_RIGHT 52
22
- :TURN_UP 53
23
- :TURN_DOWN 54
24
- :TILT_LEFT 55
25
- :TILT_RIGHT 56})
26
-
27
- (def DEFAULT_EYE_HEAD_CONFIG
28
- #js {:gazeMode "engine"
29
- :eyeTrackingEnabled false
30
- :headTrackingEnabled false
31
- :headFollowEyes true
32
- :eyeIntensity 1.0
33
- :headIntensity 0.5
34
- :returnToNeutralEnabled false
35
- :returnToNeutralDelay 3000
36
- :returnToNeutralDuration 800
37
- :useAnimationAgency true})
38
-
39
- (def DEFAULT_ANIMATION_KEYS
40
- #js {:EYE_LOOK_LEFT "eyeHeadTracking/eyeLookLeft"
41
- :EYE_LOOK_RIGHT "eyeHeadTracking/eyeLookRight"
42
- :EYE_LOOK_UP "eyeHeadTracking/eyeLookUp"
43
- :EYE_LOOK_DOWN "eyeHeadTracking/eyeLookDown"
44
- :EYE_BLINK "eyeHeadTracking/eyeBlink"
45
- :HEAD_TURN_LEFT "eyeHeadTracking/headTurnLeft"
46
- :HEAD_TURN_RIGHT "eyeHeadTracking/headTurnRight"
47
- :HEAD_TURN_UP "eyeHeadTracking/headTurnUp"
48
- :HEAD_TURN_DOWN "eyeHeadTracking/headTurnDown"
49
- :HEAD_TILT_LEFT "eyeHeadTracking/headTiltLeft"
50
- :HEAD_TILT_RIGHT "eyeHeadTracking/headTiltRight"})
51
-
52
- (defn data-map [value]
53
- (cond
54
- (map? value) value
55
- value (js->clj value :keywordize-keys true)
56
- :else {}))
57
-
58
- (defn finite-number? [value]
59
- (and (number? value) (js/isFinite value)))
60
-
61
- (defn number-or [value fallback]
62
- (if (finite-number? value) value fallback))
63
-
64
- (defn js-call [target method-name & args]
65
- (when target
66
- (when-let [method (aget target method-name)]
67
- (when (fn? method)
68
- (.apply method target (to-array args))))))
69
-
70
- (defn runtime-prop [value property-name]
71
- (cond
72
- (map? value) (get value (keyword property-name))
73
- value (aget value property-name)
74
- :else nil))
75
-
76
- (defn normalize-target [target fallback]
77
- (let [input (merge {:x 0 :y 0 :z 0} fallback (data-map target))]
78
- {:x (max -1 (min 1 (number-or (:x input) 0)))
79
- :y (max -1 (min 1 (number-or (:y input) 0)))
80
- :z (number-or (:z input) 0)}))
81
-
82
- (defn service-config [config]
83
- (let [input (data-map config)
84
- transition (number-or (:agencyTransitionDuration input)
85
- (number-or (:transitionDurationMs input) 240))
86
- neutral-duration (number-or (:returnToNeutralDuration input)
87
- (number-or (:returnToCenterDurationMs input) 300))]
88
- {:enabled true
89
- :eyeTrackingEnabled (boolean (:eyeTrackingEnabled input))
90
- :headTrackingEnabled (boolean (:headTrackingEnabled input))
91
- :headFollowEyes (if (contains? input :headFollowEyes)
92
- (boolean (:headFollowEyes input))
93
- true)
94
- :eyeIntensity (number-or (:eyeIntensity input) 1.0)
95
- :headIntensity (number-or (:headIntensity input) 0.5)
96
- :transitionDurationMs transition
97
- :returnToCenterDurationMs neutral-duration
98
- :coalesceMs (number-or (:coalesceMs input) 0)
99
- :replaceExisting true}))
100
-
101
- (defn service-state [state-atom mode-atom]
102
- (let [snapshot @state-atom
103
- agency-state (data-map snapshot)
104
- config (or (:config agency-state) {})
105
- current-target (or (:currentTarget agency-state) {:x 0 :y 0 :z 0})]
106
- #js {:eyeStatus (if (get config :eyeTrackingEnabled) "tracking" "idle")
107
- :headStatus (if (get config :headTrackingEnabled) "tracking" "idle")
108
- :currentGaze (clj->js current-target)
109
- :targetGaze (clj->js current-target)
110
- :eyeIntensity (number-or (:eyeIntensity config) 1.0)
111
- :lastBlinkTime (:lastBlinkTime agency-state)
112
- :headIntensity (number-or (:headIntensity config) 0.5)
113
- :headFollowTimer nil
114
- :isSpeaking (boolean (:isSpeaking agency-state))
115
- :isListening (boolean (:isListening agency-state))
116
- :returnToNeutralTimer nil
117
- :lastGazeUpdateTime (or (:lastGazeUpdateTime agency-state) 0)
118
- :mode @mode-atom}))
119
-
120
- (defn create-blink-snippet []
121
- (let [name (str "eyeHeadTracking:blink:" (.now js/Date))]
122
- {:name name
123
- :curves {"43" [{:time 0.0 :intensity 0.0 :inherit true}
124
- {:time 0.045 :intensity 1.0}
125
- {:time 0.13 :intensity 0.0}]}
126
- :channels [{:target {:type "au" :id 43}
127
- :keyframes [{:time 0.0 :intensity 0.0 :inherit true}
128
- {:time 0.045 :intensity 1.0}
129
- {:time 0.13 :intensity 0.0}]}]
130
- :maxTime 0.13
131
- :loop false
132
- :snippetCategory "eyeHeadTracking"
133
- :snippetPriority 25
134
- :snippetBlendMode "additive"
135
- :snippetPlaybackRate 1.0
136
- :snippetIntensityScale 1.0}))
137
-
138
- (defn animation-target [config]
139
- (or (runtime-prop config "animationAgency")
140
- (when-let [engine (runtime-prop config "engine")]
141
- (animation-service/createAnimationService engine))))
142
-
143
- (defn schedule-animation! [anim snippet options]
144
- (or (js-call anim "schedule" (clj->js snippet) (clj->js options))
145
- (js-call anim "scheduleSnippet" (clj->js snippet) (clj->js options))))
146
-
147
- (defn remove-animation! [anim name]
148
- (or (js-call anim "remove" name)
149
- (js-call anim "removeSnippet" name)))
150
-
151
- (defn createEyeHeadTrackingService
152
- ([]
153
- (createEyeHeadTrackingService nil nil))
154
- ([config]
155
- (createEyeHeadTrackingService config nil))
156
- ([config callbacks]
157
- (let [config-atom (atom (service-config config))
158
- mode-atom (atom (or (:gazeMode (data-map config)) "manual"))
159
- state-atom (atom (merge {:isSpeaking false
160
- :isListening false
161
- :lastBlinkTime nil
162
- :lastGazeUpdateTime 0}
163
- {:config @config-atom
164
- :currentTarget {:x 0 :y 0 :z 0}}))
165
- agency (eye-head-agency/create-eye-head-tracking-agency (clj->js @config-atom))
166
- anim (animation-target config)
167
- started? (atom false)
168
- disposed? (atom false)
169
- unsubscribers (atom [])]
170
- (letfn [(dispatch! [command]
171
- (when-not @disposed?
172
- (js-call agency "dispatch" (clj->js command))))
173
- (configure! [next-config]
174
- (swap! config-atom merge (service-config next-config))
175
- (swap! state-atom assoc :config @config-atom)
176
- (dispatch! {:type "configure" :config @config-atom}))
177
- (route-event! [event]
178
- (let [payload (data-map event)]
179
- (case (:type payload)
180
- "animation.requestScheduleSnippet"
181
- (schedule-animation! anim (:snippet payload) (or (:options payload) {:autoPlay true}))
182
-
183
- "animation.requestRemoveSnippet"
184
- (remove-animation! anim (:name payload))
185
-
186
- "error"
187
- (js-call callbacks "onError" (js/Error. (or (:message payload)
188
- "Eye/head tracking error")))
189
-
190
- nil)
191
- (when (= "animation.requestScheduleSnippet" (:type payload))
192
- (swap! state-atom assoc
193
- :currentTarget (get-in payload [:snippet :metadata :target] (:currentTarget @state-atom))
194
- :lastGazeUpdateTime (.now js/Date)))))
195
- (teardown! []
196
- (doseq [unsubscribe @unsubscribers]
197
- (unsubscribe))
198
- (reset! unsubscribers []))]
199
- (swap! unsubscribers conj (js-call agency "subscribeEvents" route-event!))
200
- #js {:start (fn []
201
- (when-not @disposed?
202
- (reset! started? true)
203
- (dispatch! {:type "enable"})))
204
- :stop (fn []
205
- (when-not @disposed?
206
- (reset! started? false)
207
- (dispatch! {:type "cancel" :reason "stopped"})))
208
- :setGazeTarget (fn [target]
209
- (let [normalized (normalize-target target nil)]
210
- (swap! state-atom assoc
211
- :currentTarget normalized
212
- :lastGazeUpdateTime (.now js/Date))
213
- (dispatch! {:type "setTarget"
214
- :target normalized
215
- :mode @mode-atom})))
216
- :resetToNeutral (fn
217
- ([] (dispatch! {:type "reset"}))
218
- ([duration-ms]
219
- (dispatch! {:type "reset" :durationMs duration-ms})))
220
- :blink (fn []
221
- (when-not @disposed?
222
- (let [snippet (create-blink-snippet)]
223
- (swap! state-atom assoc :lastBlinkTime (.now js/Date))
224
- (schedule-animation! anim snippet {:autoPlay true
225
- :sourceAgency "eyeHeadTracking"}))))
226
- :setSpeaking (fn [is-speaking]
227
- (swap! state-atom assoc :isSpeaking (boolean is-speaking))
228
- (if is-speaking
229
- (js-call callbacks "onHeadStart")
230
- (js-call callbacks "onHeadStop")))
231
- :setListening (fn [is-listening]
232
- (swap! state-atom assoc :isListening (boolean is-listening))
233
- (if is-listening
234
- (js-call callbacks "onEyeStart")
235
- (js-call callbacks "onEyeStop")))
236
- :setEyeBlendWeight (fn [_value] nil)
237
- :setHeadBlendWeight (fn [_value] nil)
238
- :updateConfig configure!
239
- :getState (fn [] (service-state state-atom mode-atom))
240
- :getMachineContext (fn []
241
- #js {:config (clj->js @config-atom)
242
- :mode @mode-atom
243
- :target (clj->js (:currentTarget @state-atom))
244
- :lastApplied (clj->js (:currentTarget @state-atom))
245
- :status #js {:eye (if (:eyeTrackingEnabled @config-atom) "tracking" "idle")
246
- :head (if (:headTrackingEnabled @config-atom) "tracking" "idle")}})
247
- :getSnippets (fn [] #js {:eye (js/Map.) :head (js/Map.)})
248
- :setMode (fn [mode]
249
- (reset! mode-atom mode)
250
- (dispatch! {:type "configure" :config {:mode mode}}))
251
- :getMode (fn [] @mode-atom)
252
- :subscribeToWebcam (fn [_callback] (fn [] nil))
253
- :getWebcamVideoElement (fn [] nil)
254
- :isWebcamActive (fn [] false)
255
- :dispose (fn []
256
- (when-not @disposed?
257
- (reset! disposed? true)
258
- (teardown!)
259
- (js-call agency "dispose")))}))))
@@ -1,92 +0,0 @@
1
- (ns polymer.eye-head.snippet)
2
-
3
- ;; Eye/Head snippets use typed AU channels. Numeric curve keys remain for
4
- ;; compatibility with older animation builds, while typed channels are the
5
- ;; canonical contract for the current Animation agency.
6
-
7
- (def eye-yaw-left 61)
8
- (def eye-yaw-right 62)
9
- (def eye-pitch-up 63)
10
- (def eye-pitch-down 64)
11
- (def head-yaw-left 51)
12
- (def head-yaw-right 52)
13
- (def head-pitch-up 53)
14
- (def head-pitch-down 54)
15
- (def head-roll-left 55)
16
- (def head-roll-right 56)
17
-
18
- (defn seconds
19
- [duration-ms]
20
- (/ (max 1 duration-ms) 1000))
21
-
22
- (defn axis-curves
23
- [negative-au positive-au value duration-sec]
24
- (let [value (max -1 (min 1 value))
25
- negative-value (if (neg? value) (js/Math.abs value) 0)
26
- positive-value (if (pos? value) value 0)]
27
- {(str negative-au) [{:time 0 :intensity 0 :inherit true}
28
- {:time duration-sec :intensity negative-value}]
29
- (str positive-au) [{:time 0 :intensity 0 :inherit true}
30
- {:time duration-sec :intensity positive-value}]}))
31
-
32
- (defn au-channel
33
- [au-id curve]
34
- {:target {:type "au" :id au-id}
35
- :keyframes curve})
36
-
37
- (defn curves->channels
38
- [curves]
39
- (into []
40
- (map (fn [[au-id curve]]
41
- (au-channel (js/parseInt au-id 10) curve)))
42
- curves))
43
-
44
- (defn merge-curves
45
- [& curve-maps]
46
- (apply merge curve-maps))
47
-
48
- (defn build-eye-curves
49
- [request]
50
- (let [target (:target request)
51
- duration-sec (seconds (:eyeDurationMs request))
52
- yaw (* (:x target) (:eyeIntensity request))
53
- pitch (* (:y target) (:eyeIntensity request))]
54
- (merge-curves
55
- (axis-curves eye-yaw-left eye-yaw-right yaw duration-sec)
56
- (axis-curves eye-pitch-down eye-pitch-up pitch duration-sec))))
57
-
58
- (defn build-head-curves
59
- [request]
60
- (let [target (:target request)
61
- duration-sec (seconds (:headDurationMs request))
62
- yaw (* (:x target) (:headIntensity request))
63
- pitch (* (:y target) (:headIntensity request))
64
- roll (* (:headRoll request) (:headIntensity request))]
65
- (merge-curves
66
- (axis-curves head-yaw-left head-yaw-right yaw duration-sec)
67
- (axis-curves head-pitch-down head-pitch-up pitch duration-sec)
68
- (axis-curves head-roll-left head-roll-right roll duration-sec))))
69
-
70
- (defn build-gaze-snippet
71
- [request config]
72
- (let [eye-curves (when (:eyeEnabled request) (build-eye-curves request))
73
- head-curves (when (and (:headEnabled request) (:headFollowEyes request))
74
- (build-head-curves request))
75
- curves (merge-curves (or eye-curves {}) (or head-curves {}))
76
- channels (curves->channels curves)
77
- max-time (max (seconds (:eyeDurationMs request))
78
- (seconds (:headDurationMs request)))]
79
- {:name (str "eyeHeadTracking:gaze:" (:requestId request))
80
- :curves curves
81
- :channels channels
82
- :maxTime max-time
83
- :loop false
84
- :mixerClampWhenFinished true
85
- :snippetPriority (:snippetPriority config)
86
- :snippetPlaybackRate 1.0
87
- :snippetIntensityScale 1.0
88
- :metadata {:agency "eyeHeadTracking"
89
- :sourceAgency (:sourceAgency request)
90
- :requestId (:requestId request)
91
- :mode (:mode request)
92
- :target (:target request)}}))
@@ -1,167 +0,0 @@
1
- (ns polymer.eye-head.state
2
- (:require [polymer.eye-head.domain :as domain]))
3
-
4
- ;; Eye/Head state tracks the local movement schedule. Runtime handles remain
5
- ;; private to the Animation agency; this agency only records plain request and
6
- ;; snippet metadata.
7
-
8
- (def default-config
9
- {:enabled true
10
- :eyeTrackingEnabled true
11
- :headTrackingEnabled true
12
- :headFollowEyes true
13
- :eyeIntensity 1.0
14
- :headIntensity 0.5
15
- :headRoll 0
16
- :eyePriority 20
17
- :headPriority 15
18
- :snippetPriority 20
19
- :transitionDurationMs 240
20
- :returnToCenterDurationMs 300
21
- :coalesceMs 0
22
- :replaceExisting true})
23
-
24
- (defn input-value
25
- [input camel-key kebab-key fallback]
26
- (let [camel (get input camel-key ::missing)
27
- kebab (get input kebab-key ::missing)]
28
- (cond
29
- (not= camel ::missing) camel
30
- (not= kebab ::missing) kebab
31
- :else fallback)))
32
-
33
- (defn normalize-config
34
- [config]
35
- (let [input (merge default-config (domain/data-map config))]
36
- {:enabled (boolean (input-value input :enabled :enabled (:enabled default-config)))
37
- :eyeTrackingEnabled (boolean (input-value input :eyeTrackingEnabled :eye-tracking-enabled (:eyeTrackingEnabled default-config)))
38
- :headTrackingEnabled (boolean (input-value input :headTrackingEnabled :head-tracking-enabled (:headTrackingEnabled default-config)))
39
- :headFollowEyes (boolean (input-value input :headFollowEyes :head-follow-eyes (:headFollowEyes default-config)))
40
- :eyeIntensity (domain/clamp 0 2
41
- (domain/number-or (input-value input :eyeIntensity :eye-intensity nil)
42
- (:eyeIntensity default-config)))
43
- :headIntensity (domain/clamp 0 2
44
- (domain/number-or (input-value input :headIntensity :head-intensity nil)
45
- (:headIntensity default-config)))
46
- :headRoll (domain/clamp -1 1
47
- (domain/number-or (input-value input :headRoll :head-roll nil)
48
- (:headRoll default-config)))
49
- :eyePriority (int (domain/clamp 0 100
50
- (domain/number-or (input-value input :eyePriority :eye-priority nil)
51
- (:eyePriority default-config))))
52
- :headPriority (int (domain/clamp 0 100
53
- (domain/number-or (input-value input :headPriority :head-priority nil)
54
- (:headPriority default-config))))
55
- :snippetPriority (int (domain/clamp 0 100
56
- (domain/number-or (input-value input :snippetPriority :snippet-priority nil)
57
- (:snippetPriority default-config))))
58
- :transitionDurationMs (int (domain/clamp 50 3000
59
- (domain/number-or
60
- (input-value input :transitionDurationMs :transition-duration-ms nil)
61
- (:transitionDurationMs default-config))))
62
- :returnToCenterDurationMs (int (domain/clamp 50 3000
63
- (domain/number-or
64
- (input-value input :returnToCenterDurationMs :return-to-center-duration-ms nil)
65
- (:returnToCenterDurationMs default-config))))
66
- :coalesceMs (int (domain/clamp 0 1000
67
- (domain/number-or (input-value input :coalesceMs :coalesce-ms nil)
68
- (:coalesceMs default-config))))
69
- :replaceExisting (boolean (input-value input :replaceExisting :replace-existing (:replaceExisting default-config)))}))
70
-
71
- (defn default-state
72
- [config]
73
- {:agency "eyeHeadTracking"
74
- :status "idle"
75
- :mode "manual"
76
- :currentTarget domain/zero-target
77
- :pendingRequest nil
78
- :lastRequest nil
79
- :lastSnippet nil
80
- :activeSnippetNames []
81
- :lastIgnored nil
82
- :lastPlan nil
83
- :scheduledCount 0
84
- :removedCount 0
85
- :resetCount 0
86
- :cancelCount 0
87
- :ignoredCount 0
88
- :config (normalize-config config)})
89
-
90
- (defn config->state
91
- [config]
92
- (default-state config))
93
-
94
- (defn visible-state
95
- [state]
96
- (clj->js state))
97
-
98
- (defn configure
99
- [state config]
100
- (assoc state :config (normalize-config (merge (:config state)
101
- (domain/data-map config)))))
102
-
103
- (defn set-enabled
104
- [state enabled]
105
- (assoc-in state [:config :enabled] (boolean enabled)))
106
-
107
- (defn record-plan
108
- [state plan]
109
- (assoc state :lastPlan plan))
110
-
111
- (defn record-pending
112
- [state request]
113
- (assoc state
114
- :status "pending"
115
- :pendingRequest request))
116
-
117
- (defn record-scheduled
118
- [state request snippet published-at]
119
- (-> state
120
- (assoc :status "tracking"
121
- :mode (:mode request)
122
- :currentTarget (:target request)
123
- :pendingRequest nil
124
- :lastRequest request
125
- :lastSnippet snippet
126
- :activeSnippetNames [(:name snippet)]
127
- :lastPlan nil
128
- :lastEvent {:type "animation.requestScheduleSnippet"
129
- :name (:name snippet)
130
- :requestId (:requestId request)
131
- :at published-at})
132
- (update :scheduledCount inc)))
133
-
134
- (defn record-removed
135
- [state name reason removed-at]
136
- (-> state
137
- (assoc :activeSnippetNames []
138
- :lastEvent {:type "animation.requestRemoveSnippet"
139
- :name name
140
- :reason reason
141
- :at removed-at})
142
- (update :removedCount inc)))
143
-
144
- (defn record-ignored
145
- [state ignored]
146
- (-> state
147
- (assoc :status "ignored"
148
- :lastIgnored ignored
149
- :pendingRequest nil
150
- :lastEvent ignored)
151
- (update :ignoredCount inc)))
152
-
153
- (defn record-reset
154
- [state request snippet published-at]
155
- (-> (record-scheduled state request snippet published-at)
156
- (assoc :status "reset"
157
- :currentTarget domain/zero-target)
158
- (update :resetCount inc)))
159
-
160
- (defn record-cancel
161
- [state request]
162
- (-> state
163
- (assoc :status "cancelled"
164
- :pendingRequest nil
165
- :activeSnippetNames []
166
- :lastEvent request)
167
- (update :cancelCount inc)))
@@ -1,85 +0,0 @@
1
- (ns polymer.gaze.agency
2
- (:require [polymer.gaze.domain :as domain]
3
- [polymer.gaze.goap :as goap]
4
- [polymer.gaze.scheduler :as scheduler]
5
- [polymer.gaze.state :as state]
6
- [polymer.stream :as stream]))
7
-
8
- ;; Gaze converts attention and camera-relative facts into look-intent requests.
9
- ;; It does not move eyes or head directly. The downstream movement agency owns
10
- ;; the runtime side effects after accepting these request messages.
11
-
12
- (defn now-ms
13
- []
14
- (.now js/Date))
15
-
16
- (defn create-gaze-agency
17
- [config]
18
- (let [input-stream (stream/create-stream)
19
- event-stream (stream/create-stream)
20
- state-atom (atom (state/config->state config))
21
- disposed? (atom false)
22
- emit-input (:emit input-stream)
23
- emit-event (:emit event-stream)
24
- scheduler-atom (atom nil)]
25
- (letfn [(dispatch! [command]
26
- (when-not @disposed?
27
- (let [payload (domain/data-map command)
28
- plan (goap/plan-command payload @state-atom (now-ms))]
29
- (emit-input {:type "command"
30
- :agency "gaze"
31
- :command payload})
32
- (swap! state-atom assoc :lastPlan plan)
33
- (when-let [agency-scheduler @scheduler-atom]
34
- ((:schedule agency-scheduler) plan)))))
35
-
36
- (dispatch-type! [type]
37
- (dispatch! #js {:type type}))]
38
- (let [agency-scheduler (scheduler/create-scheduler
39
- {:state-atom state-atom
40
- :emit-event emit-event})]
41
- (reset! scheduler-atom agency-scheduler)
42
- #js {:dispatch dispatch!
43
- :snapshot (fn [] (state/visible-state @state-atom))
44
- :input (stream/writable-port input-stream dispatch!)
45
- :events (stream/readable-port event-stream)
46
- :subscribeInput (fn [listener] ((:subscribe input-stream) listener))
47
- :subscribeEvents (fn [listener] ((:subscribe event-stream) listener))
48
- :subscribe (fn [listener] ((:subscribe event-stream) listener))
49
- :subscribeStatus (fn [listener] ((:subscribe event-stream) listener))
50
- :setTarget (fn
51
- ([target] (dispatch! #js {:type "setTarget"
52
- :target target}))
53
- ([target options] (dispatch! #js {:type "setTarget"
54
- :target target
55
- :options options})))
56
- :focusTarget (fn [target] (dispatch! #js {:type "focusTarget"
57
- :target target}))
58
- :configure (fn [config] (dispatch! #js {:type "configure"
59
- :config config}))
60
- :setMode (fn [mode] (dispatch! #js {:type "setMode"
61
- :mode mode}))
62
- :setActive (fn [active] (dispatch! #js {:type "setActive"
63
- :active active}))
64
- :enable (fn [] (dispatch-type! "enable"))
65
- :disable (fn [] (dispatch-type! "disable"))
66
- :reset (fn
67
- ([] (dispatch-type! "reset"))
68
- ([duration-ms] (dispatch! #js {:type "reset"
69
- :durationMs duration-ms})))
70
- :cancel (fn
71
- ([] (dispatch-type! "cancel"))
72
- ([reason] (dispatch! #js {:type "cancel"
73
- :reason reason})))
74
- :flush (fn []
75
- (when-let [agency-scheduler @scheduler-atom]
76
- ((:flush agency-scheduler))))
77
- :queue (fn []
78
- (when-let [agency-scheduler @scheduler-atom]
79
- (clj->js ((:queue agency-scheduler)))))
80
- :dispose (fn []
81
- (when-not @disposed?
82
- (reset! disposed? true)
83
- ((:dispose agency-scheduler))
84
- ((:dispose input-stream))
85
- ((:dispose event-stream))))}))))