@zephyr3d/editor 0.3.4 → 0.3.7

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 (75) hide show
  1. package/dist/assets/{index-DzQzWsCG.js → index-ySiLtSxz.js} +3 -3
  2. package/dist/assistant/zephyr-types-index.json +14217 -7895
  3. package/dist/index.html +1 -1
  4. package/dist/modules/zephyr3d_backend-webgl.js.map +1 -1
  5. package/dist/modules/zephyr3d_backend-webgpu.js +13 -12
  6. package/dist/modules/zephyr3d_backend-webgpu.js.map +1 -1
  7. package/dist/modules/zephyr3d_device.js +15 -15
  8. package/dist/modules/zephyr3d_device.js.map +1 -1
  9. package/dist/modules/zephyr3d_imgui.js.map +1 -1
  10. package/dist/modules/zephyr3d_scene.js +3276 -1089
  11. package/dist/modules/zephyr3d_scene.js.map +1 -1
  12. package/dist/vendor/zephyr3d/backend-webgl/dist/index.js.map +1 -1
  13. package/dist/vendor/zephyr3d/backend-webgpu/dist/capabilities_webgpu.js +7 -6
  14. package/dist/vendor/zephyr3d/backend-webgpu/dist/capabilities_webgpu.js.map +1 -1
  15. package/dist/vendor/zephyr3d/backend-webgpu/dist/index.js.map +1 -1
  16. package/dist/vendor/zephyr3d/backend-webgpu/dist/renderpass_webgpu.js +6 -6
  17. package/dist/vendor/zephyr3d/backend-webgpu/dist/renderpass_webgpu.js.map +1 -1
  18. package/dist/vendor/zephyr3d/device/dist/device.js +15 -15
  19. package/dist/vendor/zephyr3d/device/dist/device.js.map +1 -1
  20. package/dist/vendor/zephyr3d/imgui/dist/index.d.ts +7 -0
  21. package/dist/vendor/zephyr3d/imgui/dist/index.js.map +1 -1
  22. package/dist/vendor/zephyr3d/scene/dist/animation/animation.js +87 -0
  23. package/dist/vendor/zephyr3d/scene/dist/animation/animation.js.map +1 -1
  24. package/dist/vendor/zephyr3d/scene/dist/animation/animationcontroller.js +503 -0
  25. package/dist/vendor/zephyr3d/scene/dist/animation/animationcontroller.js.map +1 -0
  26. package/dist/vendor/zephyr3d/scene/dist/animation/animationset.js +686 -63
  27. package/dist/vendor/zephyr3d/scene/dist/animation/animationset.js.map +1 -1
  28. package/dist/vendor/zephyr3d/scene/dist/animation/animationtimeline.js +974 -0
  29. package/dist/vendor/zephyr3d/scene/dist/animation/animationtimeline.js.map +1 -0
  30. package/dist/vendor/zephyr3d/scene/dist/animation/joint_dynamics_modifier.js +19 -19
  31. package/dist/vendor/zephyr3d/scene/dist/animation/joint_dynamics_modifier.js.map +1 -1
  32. package/dist/vendor/zephyr3d/scene/dist/app/engine.js +131 -131
  33. package/dist/vendor/zephyr3d/scene/dist/app/engine.js.map +1 -1
  34. package/dist/vendor/zephyr3d/scene/dist/app/scriptregistry.js +17 -12
  35. package/dist/vendor/zephyr3d/scene/dist/app/scriptregistry.js.map +1 -1
  36. package/dist/vendor/zephyr3d/scene/dist/asset/model.js +2 -1
  37. package/dist/vendor/zephyr3d/scene/dist/asset/model.js.map +1 -1
  38. package/dist/vendor/zephyr3d/scene/dist/avatar/wardrobe.js +13 -13
  39. package/dist/vendor/zephyr3d/scene/dist/avatar/wardrobe.js.map +1 -1
  40. package/dist/vendor/zephyr3d/scene/dist/camera/camera.js +201 -201
  41. package/dist/vendor/zephyr3d/scene/dist/camera/camera.js.map +1 -1
  42. package/dist/vendor/zephyr3d/scene/dist/index.d.ts +1271 -10
  43. package/dist/vendor/zephyr3d/scene/dist/index.js +3 -1
  44. package/dist/vendor/zephyr3d/scene/dist/index.js.map +1 -1
  45. package/dist/vendor/zephyr3d/scene/dist/material/mixins/lightmodel/pbrmetallicroughness.js +5 -5
  46. package/dist/vendor/zephyr3d/scene/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
  47. package/dist/vendor/zephyr3d/scene/dist/material/mixins/lit.js +7 -3
  48. package/dist/vendor/zephyr3d/scene/dist/material/mixins/lit.js.map +1 -1
  49. package/dist/vendor/zephyr3d/scene/dist/material/mtoon.js +4 -4
  50. package/dist/vendor/zephyr3d/scene/dist/material/mtoon.js.map +1 -1
  51. package/dist/vendor/zephyr3d/scene/dist/material/pbrblueprint.js +11 -11
  52. package/dist/vendor/zephyr3d/scene/dist/material/pbrblueprint.js.map +1 -1
  53. package/dist/vendor/zephyr3d/scene/dist/material/shader/helper.js +284 -284
  54. package/dist/vendor/zephyr3d/scene/dist/material/shader/helper.js.map +1 -1
  55. package/dist/vendor/zephyr3d/scene/dist/posteffect/ssr.js +9 -9
  56. package/dist/vendor/zephyr3d/scene/dist/posteffect/ssr.js.map +1 -1
  57. package/dist/vendor/zephyr3d/scene/dist/render/lightpass.js +5 -5
  58. package/dist/vendor/zephyr3d/scene/dist/render/lightpass.js.map +1 -1
  59. package/dist/vendor/zephyr3d/scene/dist/render/renderer.js +7 -7
  60. package/dist/vendor/zephyr3d/scene/dist/render/renderer.js.map +1 -1
  61. package/dist/vendor/zephyr3d/scene/dist/shadow/esm.js +1 -1
  62. package/dist/vendor/zephyr3d/scene/dist/shadow/esm.js.map +1 -1
  63. package/dist/vendor/zephyr3d/scene/dist/shadow/shadow_region.js +45 -45
  64. package/dist/vendor/zephyr3d/scene/dist/shadow/shadow_region.js.map +1 -1
  65. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/manager.js +276 -275
  66. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/manager.js.map +1 -1
  67. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/animation.js +4 -3
  68. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/animation.js.map +1 -1
  69. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/camera.js +1 -1
  70. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/camera.js.map +1 -1
  71. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/mesh.js.map +1 -1
  72. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/node.js +3 -2
  73. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/node.js.map +1 -1
  74. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/sprite.js.map +1 -1
  75. package/package.json +8 -8
@@ -0,0 +1,503 @@
1
+ import { Observable } from '@zephyr3d/base';
2
+ import { AnimationTimeline } from './animationtimeline.js';
3
+
4
+ /**
5
+ * Event-driven animation state controller.
6
+ *
7
+ * Each state owns one serializable timeline. External gameplay events are dispatched to the
8
+ * current timeline first, then to the current state's response table, so different states can
9
+ * respond to the same event differently.
10
+ * @public
11
+ */ class AnimationController extends Observable {
12
+ /**
13
+ * Animation set used to create playbacks for all state timelines.
14
+ */ animationSet;
15
+ _states;
16
+ _currentState;
17
+ _runner;
18
+ _onRunnerComplete;
19
+ _onRunnerEmit;
20
+ /**
21
+ * Create a controller for an animation set.
22
+ *
23
+ * @param animationSet - Animation set that owns the clips and active playbacks.
24
+ */ constructor(animationSet){
25
+ super();
26
+ this.animationSet = animationSet;
27
+ this._states = new Map();
28
+ this._currentState = null;
29
+ this._runner = null;
30
+ this._onRunnerComplete = null;
31
+ this._onRunnerEmit = null;
32
+ }
33
+ /**
34
+ * Current state name.
35
+ *
36
+ * @returns The active state name, or null when the controller is stopped or has not entered a state.
37
+ */ get currentState() {
38
+ return this._currentState;
39
+ }
40
+ /**
41
+ * Current timeline runner.
42
+ *
43
+ * @returns The active timeline runner, or null when no state is running.
44
+ */ get runner() {
45
+ return this._runner;
46
+ }
47
+ /**
48
+ * Register or replace a named state definition.
49
+ *
50
+ * @param name - Unique state name.
51
+ * @param definition - Timeline and event response configuration for the state.
52
+ * @returns This controller for chaining.
53
+ */ addState(name, definition) {
54
+ if (this._states.has(name)) {
55
+ console.warn(`AnimationController state ${name} already exists; overwriting`);
56
+ }
57
+ this._states.set(name, definition);
58
+ return this;
59
+ }
60
+ /**
61
+ * Test whether a state has been registered.
62
+ *
63
+ * @param name - State name to look up.
64
+ * @returns True if the controller contains a state with the given name; otherwise false.
65
+ */ hasState(name) {
66
+ return this._states.has(name);
67
+ }
68
+ /**
69
+ * Enter a registered state.
70
+ *
71
+ * If the requested state is already current and `options.force` is not set, this returns the
72
+ * existing runner without restarting the timeline. When a transition duration is provided, the
73
+ * previous runner fades out while the entry plays of the new state fade in.
74
+ *
75
+ * @param name - State name to enter.
76
+ * @param options - Optional transition, re-entry, and stop behavior.
77
+ * @returns The active runner for the entered state, or null if the state does not exist.
78
+ */ setState(name, options) {
79
+ const definition = this._states.get(name);
80
+ if (!definition) {
81
+ console.error(`AnimationController state ${name} not exists`);
82
+ return null;
83
+ }
84
+ if (!options?.force && this._currentState === name) {
85
+ return this._runner;
86
+ }
87
+ const previousState = this._currentState;
88
+ const transition = Math.max(options?.transition ?? definition.transition ?? 0, 0);
89
+ const returnTarget = this.resolveReturnTarget(options?.returnTo, previousState, options?.returnTransition);
90
+ this.detachRunner();
91
+ if (transition > 0) {
92
+ this._runner?.stop({
93
+ fadeOut: transition,
94
+ reason: 'interrupted'
95
+ });
96
+ } else {
97
+ this._runner?.stop(options?.stop ?? {
98
+ reason: 'interrupted'
99
+ });
100
+ }
101
+ const timeline = new AnimationTimeline(prepareTimelineForTransition(definition.timeline, transition, returnTarget?.transition, options?.sync));
102
+ this._runner = timeline.createRunner(this.animationSet);
103
+ const runner = this._runner;
104
+ this.attachRunner(runner, name, returnTarget);
105
+ // Enter the new state *before* starting the runner: start() flushes synchronously, so any
106
+ // initial `emit`/`statecomplete` must observe the controller already in `name`. Otherwise a
107
+ // listener calling dispatch() would route against the previous state.
108
+ this._currentState = name;
109
+ this.dispatchEvent('statechange', name, previousState);
110
+ // The statechange listener may have re-entered (stop() or another setState()), swapping out or
111
+ // clearing `_runner`. Only start the runner we created if it is still the active one.
112
+ if (this._runner === runner && this._currentState === name) {
113
+ runner.start();
114
+ }
115
+ // If a reentrant listener superseded us, `_runner` is the now-active runner (or null after a
116
+ // reentrant stop()); return that rather than a runner we never started.
117
+ return this._runner;
118
+ }
119
+ /**
120
+ * Dispatch a gameplay event to the active state.
121
+ *
122
+ * The active timeline receives the event first. If it does not handle the event, the current
123
+ * state's response table may consume it, enqueue or run steps, or transition to another state.
124
+ *
125
+ * @param event - Event name to dispatch.
126
+ * @param payload - Optional event payload passed through result notifications.
127
+ * @returns The resolved handling result for the event.
128
+ */ dispatch(event, payload) {
129
+ if (!this._currentState || !this._runner) {
130
+ return this.emitResult({
131
+ handled: false,
132
+ policy: 'none',
133
+ event,
134
+ payload
135
+ });
136
+ }
137
+ const timelineResult = this._runner.dispatch(event, payload);
138
+ if (timelineResult.handled) {
139
+ return this.emitResult(timelineResult);
140
+ }
141
+ const response = this._states.get(this._currentState)?.responses?.find((item)=>item.event === event);
142
+ if (!response || response.target.ignore) {
143
+ return this.emitResult({
144
+ handled: false,
145
+ policy: response ? 'ignore' : 'none',
146
+ event,
147
+ payload
148
+ });
149
+ }
150
+ if (response.target.consume) {
151
+ return this.emitResult({
152
+ handled: true,
153
+ policy: 'consume',
154
+ event,
155
+ payload
156
+ });
157
+ }
158
+ if (response.target.targetState !== undefined) {
159
+ const transition = typeof response.onActive === 'object' ? response.onActive.fadeOut : undefined;
160
+ const runner = this.setState(response.target.targetState, {
161
+ transition,
162
+ returnTo: response.target.returnTo,
163
+ returnTransition: response.target.returnTransition
164
+ });
165
+ // setState returns null when the target state is not registered: a config error must not be
166
+ // reported as a successfully handled transition.
167
+ if (!runner) {
168
+ return this.emitResult({
169
+ handled: false,
170
+ policy: 'transition',
171
+ event,
172
+ payload
173
+ });
174
+ }
175
+ return this.emitResult({
176
+ handled: true,
177
+ policy: 'transition',
178
+ event,
179
+ payload
180
+ });
181
+ }
182
+ const steps = response.target.steps;
183
+ if (!steps?.length) {
184
+ return this.emitResult({
185
+ handled: false,
186
+ policy: 'none',
187
+ event,
188
+ payload
189
+ });
190
+ }
191
+ if (response.enqueue) {
192
+ this._runner.enqueue(steps);
193
+ return this.emitResult({
194
+ handled: true,
195
+ policy: 'enqueue',
196
+ event,
197
+ payload
198
+ });
199
+ }
200
+ const disposition = response.onActive ?? 'stop';
201
+ if (disposition === 'keep') {
202
+ this._runner.runConcurrent(steps);
203
+ } else {
204
+ const stopOptions = typeof disposition === 'object' ? {
205
+ ...disposition,
206
+ reason: 'interrupted'
207
+ } : undefined;
208
+ this.detachRunner();
209
+ this._runner.stop(stopOptions);
210
+ this._runner = new AnimationTimeline(steps).createRunner(this.animationSet);
211
+ this.attachRunner(this._runner, this._currentState);
212
+ this._runner.start();
213
+ }
214
+ return this.emitResult({
215
+ handled: true,
216
+ policy: 'steps',
217
+ event,
218
+ payload
219
+ });
220
+ }
221
+ /**
222
+ * Stop the active state and clear the current state.
223
+ *
224
+ * @param options - Optional stop behavior applied to playbacks owned by the active runner.
225
+ * @returns void
226
+ */ stop(options) {
227
+ const previousState = this._currentState;
228
+ this.detachRunner();
229
+ this._runner?.stop(options);
230
+ this._runner = null;
231
+ this._currentState = null;
232
+ if (previousState !== null) {
233
+ this.dispatchEvent('statechange', null, previousState);
234
+ }
235
+ }
236
+ /**
237
+ * Stop playback and remove all registered states.
238
+ *
239
+ * @returns void
240
+ */ dispose() {
241
+ this.stop();
242
+ this._states.clear();
243
+ }
244
+ emitResult(result) {
245
+ this.dispatchEvent('event', result.event, result.payload, result);
246
+ return result;
247
+ }
248
+ resolveReturnTarget(returnTo, previousState, returnTransition) {
249
+ if (returnTo === undefined) {
250
+ return null;
251
+ }
252
+ const state = returnTo === true ? previousState : returnTo;
253
+ if (!state) {
254
+ return null;
255
+ }
256
+ const definition = this._states.get(state);
257
+ if (!definition) {
258
+ console.error(`AnimationController return state ${state} not exists`);
259
+ return null;
260
+ }
261
+ return {
262
+ state,
263
+ transition: returnTransition ?? definition.transition
264
+ };
265
+ }
266
+ attachRunner(runner, state, returnTarget) {
267
+ this._onRunnerComplete = ()=>{
268
+ this.dispatchEvent('statecomplete', state);
269
+ if (returnTarget && this._runner === runner && this._currentState === state) {
270
+ const sync = returnTarget.transition && runner.lastCompletedPlaybackId ? {
271
+ target: runner.lastCompletedPlaybackId,
272
+ mode: 'normalized'
273
+ } : undefined;
274
+ this.setState(returnTarget.state, {
275
+ transition: returnTarget.transition,
276
+ sync
277
+ });
278
+ }
279
+ };
280
+ this._onRunnerEmit = (event, payload)=>{
281
+ this.dispatchEvent('emit', event, payload);
282
+ };
283
+ runner.on('complete', this._onRunnerComplete);
284
+ runner.on('emit', this._onRunnerEmit);
285
+ }
286
+ detachRunner() {
287
+ if (this._runner) {
288
+ if (this._onRunnerComplete) {
289
+ this._runner.off('complete', this._onRunnerComplete);
290
+ }
291
+ if (this._onRunnerEmit) {
292
+ this._runner.off('emit', this._onRunnerEmit);
293
+ }
294
+ }
295
+ this._onRunnerComplete = null;
296
+ this._onRunnerEmit = null;
297
+ }
298
+ }
299
+ function prepareTimelineForTransition(definition, entryTransition, returnTransition, entrySync) {
300
+ let timeline = definition;
301
+ if (entrySync) {
302
+ timeline = withEntrySync(timeline, entrySync);
303
+ }
304
+ const completionFadeOut = Math.max(returnTransition ?? 0, 0);
305
+ if (completionFadeOut > 0) {
306
+ timeline = withCompletionFadeOut(timeline, completionFadeOut);
307
+ }
308
+ return entryTransition > 0 ? withFadeIn(timeline, entryTransition) : timeline;
309
+ }
310
+ /**
311
+ * Return a copy of the timeline definition whose entry plays use `sync` unless they already
312
+ * declare a more specific synchronization source.
313
+ */ function withEntrySync(definition, sync) {
314
+ const def = Array.isArray(definition) ? {
315
+ steps: definition
316
+ } : definition;
317
+ return {
318
+ steps: injectEntrySync(def.steps, sync).steps,
319
+ responses: def.responses
320
+ };
321
+ }
322
+ function injectEntrySync(steps, sync) {
323
+ let blocked = false;
324
+ const out = steps.map((step)=>{
325
+ if (blocked) {
326
+ return step;
327
+ }
328
+ switch(step.type){
329
+ case 'play':
330
+ if (step.wait === 'complete') {
331
+ blocked = true;
332
+ }
333
+ return {
334
+ ...step,
335
+ options: {
336
+ ...step.options,
337
+ sync: step.options?.sync ?? sync
338
+ }
339
+ };
340
+ case 'sequence':
341
+ {
342
+ const result = injectEntrySync(step.steps, sync);
343
+ blocked = result.blocked;
344
+ return {
345
+ ...step,
346
+ steps: result.steps
347
+ };
348
+ }
349
+ case 'parallel':
350
+ {
351
+ let anyBranchBlocked = false;
352
+ const branches = step.steps.map((branch)=>{
353
+ const result = injectEntrySync([
354
+ branch
355
+ ], sync);
356
+ anyBranchBlocked = anyBranchBlocked || result.blocked;
357
+ return result.steps[0];
358
+ });
359
+ blocked = anyBranchBlocked;
360
+ return {
361
+ ...step,
362
+ steps: branches
363
+ };
364
+ }
365
+ case 'wait':
366
+ case 'waitEvent':
367
+ case 'waitMarker':
368
+ case 'waitFrame':
369
+ blocked = true;
370
+ return step;
371
+ default:
372
+ return step;
373
+ }
374
+ });
375
+ return {
376
+ steps: out,
377
+ blocked
378
+ };
379
+ }
380
+ /**
381
+ * Return a copy of the timeline definition whose entry plays fade in over `duration`, so a state
382
+ * transition cross-fades against the previous state's fade-out.
383
+ *
384
+ * "Entry plays" are every `play` that starts before the control flow first blocks: plays before a
385
+ * `wait`/`waitEvent`/`waitMarker`/`waitFrame`, before a blocking `play` (`wait: 'complete'`), and
386
+ * every branch of a leading `parallel` (all branches start simultaneously). This covers parallel
387
+ * states whose branches would otherwise snap in at full weight while only the first faded.
388
+ */ function withFadeIn(definition, duration) {
389
+ const def = Array.isArray(definition) ? {
390
+ steps: definition
391
+ } : definition;
392
+ return {
393
+ steps: injectEntryFadeIn(def.steps, duration).steps,
394
+ responses: def.responses
395
+ };
396
+ }
397
+ /**
398
+ * Inject `fadeIn` into every entry play in `steps`. Returns the rewritten steps and whether the
399
+ * flow blocks before reaching the end (so callers stop injecting into later, non-entry steps).
400
+ */ function injectEntryFadeIn(steps, duration) {
401
+ let blocked = false;
402
+ const out = steps.map((step)=>{
403
+ if (blocked) {
404
+ return step;
405
+ }
406
+ switch(step.type){
407
+ case 'play':
408
+ if (step.wait === 'complete') {
409
+ blocked = true;
410
+ }
411
+ return {
412
+ ...step,
413
+ options: {
414
+ ...step.options,
415
+ fadeIn: duration
416
+ }
417
+ };
418
+ case 'sequence':
419
+ {
420
+ const result = injectEntryFadeIn(step.steps, duration);
421
+ blocked = result.blocked;
422
+ return {
423
+ ...step,
424
+ steps: result.steps
425
+ };
426
+ }
427
+ case 'parallel':
428
+ {
429
+ // Every branch starts simultaneously, so inject into all of them. The parallel join only
430
+ // blocks the steps that follow it if at least one branch blocks; if all branches are
431
+ // non-blocking they drain in the same flush, so the following steps are still entry plays.
432
+ let anyBranchBlocked = false;
433
+ const branches = step.steps.map((branch)=>{
434
+ const result = injectEntryFadeIn([
435
+ branch
436
+ ], duration);
437
+ anyBranchBlocked = anyBranchBlocked || result.blocked;
438
+ return result.steps[0];
439
+ });
440
+ blocked = anyBranchBlocked;
441
+ return {
442
+ ...step,
443
+ steps: branches
444
+ };
445
+ }
446
+ case 'wait':
447
+ case 'waitEvent':
448
+ case 'waitMarker':
449
+ case 'waitFrame':
450
+ blocked = true;
451
+ return step;
452
+ default:
453
+ return step;
454
+ }
455
+ });
456
+ return {
457
+ steps: out,
458
+ blocked
459
+ };
460
+ }
461
+ /**
462
+ * Return a copy of the timeline definition whose play steps keep completed playbacks alive long
463
+ * enough to cross-fade into the automatic return state.
464
+ */ function withCompletionFadeOut(definition, duration) {
465
+ const def = Array.isArray(definition) ? {
466
+ steps: definition
467
+ } : definition;
468
+ return {
469
+ steps: injectCompletionFadeOut(def.steps, duration),
470
+ responses: def.responses
471
+ };
472
+ }
473
+ function injectCompletionFadeOut(steps, duration) {
474
+ return steps.map((step)=>{
475
+ switch(step.type){
476
+ case 'play':
477
+ return {
478
+ ...step,
479
+ options: {
480
+ ...step.options,
481
+ completionFadeOut: step.options?.completionFadeOut ?? duration
482
+ }
483
+ };
484
+ case 'sequence':
485
+ return {
486
+ ...step,
487
+ steps: injectCompletionFadeOut(step.steps, duration)
488
+ };
489
+ case 'parallel':
490
+ return {
491
+ ...step,
492
+ steps: step.steps.map((branch)=>injectCompletionFadeOut([
493
+ branch
494
+ ], duration)[0])
495
+ };
496
+ default:
497
+ return step;
498
+ }
499
+ });
500
+ }
501
+
502
+ export { AnimationController };
503
+ //# sourceMappingURL=animationcontroller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"animationcontroller.js","sources":["../../src/animation/animationcontroller.ts"],"sourcesContent":["import { Observable } from '@zephyr3d/base';\r\nimport type { AnimationPlaybackSyncOptions, AnimationSet, StopAnimationOptions } from './animationset';\r\nimport type {\r\n AnimationTimelineEventResponse,\r\n AnimationTimelineEventResult,\r\n AnimationTimelineRunner,\r\n AnimationTimelineStateReturnTarget,\r\n AnimationTimelineStep\r\n} from './animationtimeline';\r\nimport { AnimationTimeline, type AnimationTimelineDefinition } from './animationtimeline';\r\n\r\ntype AnimationControllerReturnTarget = {\r\n state: string;\r\n transition?: number;\r\n};\r\n\r\n/**\r\n * Definition of a named animation controller state.\r\n * @public\r\n */\r\nexport type AnimationControllerStateDefinition = {\r\n /**\r\n * Timeline executed when the controller enters this state.\r\n */\r\n timeline: AnimationTimelineDefinition;\r\n /**\r\n * Optional state-local responses evaluated after the active timeline does not handle a\r\n * dispatched event.\r\n */\r\n responses?: AnimationTimelineEventResponse[];\r\n /**\r\n * Default cross-fade duration (seconds) applied when transitioning *into* this state.\r\n * The outgoing state fades out and this state's first `play` step fades in over this time.\r\n */\r\n transition?: number;\r\n};\r\n\r\n/**\r\n * Options used when switching the controller to another state.\r\n * @public\r\n */\r\nexport type AnimationControllerSetStateOptions = {\r\n /** Cross-fade duration (seconds). Overrides the target state's own `transition`. */\r\n transition?: number;\r\n /**\r\n * Optional phase synchronization source applied to entry play steps that do not already define\r\n * their own `options.sync`.\r\n */\r\n sync?: AnimationPlaybackSyncOptions;\r\n /** Re-enter the state even if it is already current. Defaults to false (no-op on same state). */\r\n force?: boolean;\r\n /** Stop options for the outgoing state when no cross-fade is used. */\r\n stop?: StopAnimationOptions;\r\n /**\r\n * Optional state to enter when the target state completes.\r\n *\r\n * Use `true` to return to the state active before this transition, or a string to return to a\r\n * specific named state.\r\n */\r\n returnTo?: AnimationTimelineStateReturnTarget;\r\n /**\r\n * Optional transition duration used when returning from the target state.\r\n *\r\n * If omitted, the return state's own transition setting is used.\r\n */\r\n returnTransition?: number;\r\n};\r\n\r\n/**\r\n * Event map emitted by {@link AnimationController}.\r\n * @public\r\n */\r\nexport type AnimationControllerEventMap = {\r\n /**\r\n * Emitted after the current state changes.\r\n *\r\n * The first argument is the new state name, or null when stopped. The second argument is the\r\n * previous state name, or null when there was no previous state.\r\n */\r\n statechange: [state: string | null, previousState: string | null];\r\n /**\r\n * Emitted when the active state's timeline runner drains all main, concurrent, and queued work.\r\n */\r\n statecomplete: [state: string];\r\n /** Forwarded from the active state's timeline runner, so listeners need not rebind per state. */\r\n emit: [event: string, payload: unknown];\r\n /**\r\n * Emitted for every call to {@link AnimationController.dispatch} with the resolved event result.\r\n */\r\n event: [event: string, payload: unknown, result: AnimationTimelineEventResult];\r\n};\r\n\r\n/**\r\n * Event-driven animation state controller.\r\n *\r\n * Each state owns one serializable timeline. External gameplay events are dispatched to the\r\n * current timeline first, then to the current state's response table, so different states can\r\n * respond to the same event differently.\r\n * @public\r\n */\r\nexport class AnimationController extends Observable<AnimationControllerEventMap> {\r\n /**\r\n * Animation set used to create playbacks for all state timelines.\r\n */\r\n readonly animationSet: AnimationSet;\r\n private readonly _states: Map<string, AnimationControllerStateDefinition>;\r\n private _currentState: string | null;\r\n private _runner: AnimationTimelineRunner | null;\r\n private _onRunnerComplete: (() => void) | null;\r\n private _onRunnerEmit: ((event: string, payload: unknown) => void) | null;\r\n\r\n /**\r\n * Create a controller for an animation set.\r\n *\r\n * @param animationSet - Animation set that owns the clips and active playbacks.\r\n */\r\n constructor(animationSet: AnimationSet) {\r\n super();\r\n this.animationSet = animationSet;\r\n this._states = new Map();\r\n this._currentState = null;\r\n this._runner = null;\r\n this._onRunnerComplete = null;\r\n this._onRunnerEmit = null;\r\n }\r\n\r\n /**\r\n * Current state name.\r\n *\r\n * @returns The active state name, or null when the controller is stopped or has not entered a state.\r\n */\r\n get currentState() {\r\n return this._currentState;\r\n }\r\n\r\n /**\r\n * Current timeline runner.\r\n *\r\n * @returns The active timeline runner, or null when no state is running.\r\n */\r\n get runner() {\r\n return this._runner;\r\n }\r\n\r\n /**\r\n * Register or replace a named state definition.\r\n *\r\n * @param name - Unique state name.\r\n * @param definition - Timeline and event response configuration for the state.\r\n * @returns This controller for chaining.\r\n */\r\n addState(name: string, definition: AnimationControllerStateDefinition) {\r\n if (this._states.has(name)) {\r\n console.warn(`AnimationController state ${name} already exists; overwriting`);\r\n }\r\n this._states.set(name, definition);\r\n return this;\r\n }\r\n\r\n /**\r\n * Test whether a state has been registered.\r\n *\r\n * @param name - State name to look up.\r\n * @returns True if the controller contains a state with the given name; otherwise false.\r\n */\r\n hasState(name: string) {\r\n return this._states.has(name);\r\n }\r\n\r\n /**\r\n * Enter a registered state.\r\n *\r\n * If the requested state is already current and `options.force` is not set, this returns the\r\n * existing runner without restarting the timeline. When a transition duration is provided, the\r\n * previous runner fades out while the entry plays of the new state fade in.\r\n *\r\n * @param name - State name to enter.\r\n * @param options - Optional transition, re-entry, and stop behavior.\r\n * @returns The active runner for the entered state, or null if the state does not exist.\r\n */\r\n setState(name: string, options?: AnimationControllerSetStateOptions) {\r\n const definition = this._states.get(name);\r\n if (!definition) {\r\n console.error(`AnimationController state ${name} not exists`);\r\n return null;\r\n }\r\n if (!options?.force && this._currentState === name) {\r\n return this._runner;\r\n }\r\n const previousState = this._currentState;\r\n const transition = Math.max(options?.transition ?? definition.transition ?? 0, 0);\r\n const returnTarget = this.resolveReturnTarget(\r\n options?.returnTo,\r\n previousState,\r\n options?.returnTransition\r\n );\r\n this.detachRunner();\r\n if (transition > 0) {\r\n this._runner?.stop({ fadeOut: transition, reason: 'interrupted' });\r\n } else {\r\n this._runner?.stop(options?.stop ?? { reason: 'interrupted' });\r\n }\r\n const timeline = new AnimationTimeline(\r\n prepareTimelineForTransition(definition.timeline, transition, returnTarget?.transition, options?.sync)\r\n );\r\n this._runner = timeline.createRunner(this.animationSet);\r\n const runner = this._runner;\r\n this.attachRunner(runner, name, returnTarget);\r\n // Enter the new state *before* starting the runner: start() flushes synchronously, so any\r\n // initial `emit`/`statecomplete` must observe the controller already in `name`. Otherwise a\r\n // listener calling dispatch() would route against the previous state.\r\n this._currentState = name;\r\n this.dispatchEvent('statechange', name, previousState);\r\n // The statechange listener may have re-entered (stop() or another setState()), swapping out or\r\n // clearing `_runner`. Only start the runner we created if it is still the active one.\r\n if (this._runner === runner && this._currentState === name) {\r\n runner.start();\r\n }\r\n // If a reentrant listener superseded us, `_runner` is the now-active runner (or null after a\r\n // reentrant stop()); return that rather than a runner we never started.\r\n return this._runner;\r\n }\r\n\r\n /**\r\n * Dispatch a gameplay event to the active state.\r\n *\r\n * The active timeline receives the event first. If it does not handle the event, the current\r\n * state's response table may consume it, enqueue or run steps, or transition to another state.\r\n *\r\n * @param event - Event name to dispatch.\r\n * @param payload - Optional event payload passed through result notifications.\r\n * @returns The resolved handling result for the event.\r\n */\r\n dispatch(event: string, payload?: unknown): AnimationTimelineEventResult {\r\n if (!this._currentState || !this._runner) {\r\n return this.emitResult({ handled: false, policy: 'none', event, payload });\r\n }\r\n const timelineResult = this._runner.dispatch(event, payload);\r\n if (timelineResult.handled) {\r\n return this.emitResult(timelineResult);\r\n }\r\n const response = this._states.get(this._currentState)?.responses?.find((item) => item.event === event);\r\n if (!response || response.target.ignore) {\r\n return this.emitResult({ handled: false, policy: response ? 'ignore' : 'none', event, payload });\r\n }\r\n if (response.target.consume) {\r\n return this.emitResult({ handled: true, policy: 'consume', event, payload });\r\n }\r\n if (response.target.targetState !== undefined) {\r\n const transition = typeof response.onActive === 'object' ? response.onActive.fadeOut : undefined;\r\n const runner = this.setState(response.target.targetState, {\r\n transition,\r\n returnTo: response.target.returnTo,\r\n returnTransition: response.target.returnTransition\r\n });\r\n // setState returns null when the target state is not registered: a config error must not be\r\n // reported as a successfully handled transition.\r\n if (!runner) {\r\n return this.emitResult({ handled: false, policy: 'transition', event, payload });\r\n }\r\n return this.emitResult({ handled: true, policy: 'transition', event, payload });\r\n }\r\n const steps = response.target.steps;\r\n if (!steps?.length) {\r\n return this.emitResult({ handled: false, policy: 'none', event, payload });\r\n }\r\n if (response.enqueue) {\r\n this._runner.enqueue(steps);\r\n return this.emitResult({ handled: true, policy: 'enqueue', event, payload });\r\n }\r\n const disposition = response.onActive ?? 'stop';\r\n if (disposition === 'keep') {\r\n this._runner.runConcurrent(steps);\r\n } else {\r\n const stopOptions =\r\n typeof disposition === 'object' ? { ...disposition, reason: 'interrupted' as const } : undefined;\r\n this.detachRunner();\r\n this._runner.stop(stopOptions);\r\n this._runner = new AnimationTimeline(steps).createRunner(this.animationSet);\r\n this.attachRunner(this._runner, this._currentState);\r\n this._runner.start();\r\n }\r\n return this.emitResult({ handled: true, policy: 'steps', event, payload });\r\n }\r\n\r\n /**\r\n * Stop the active state and clear the current state.\r\n *\r\n * @param options - Optional stop behavior applied to playbacks owned by the active runner.\r\n * @returns void\r\n */\r\n stop(options?: StopAnimationOptions) {\r\n const previousState = this._currentState;\r\n this.detachRunner();\r\n this._runner?.stop(options);\r\n this._runner = null;\r\n this._currentState = null;\r\n if (previousState !== null) {\r\n this.dispatchEvent('statechange', null, previousState);\r\n }\r\n }\r\n\r\n /**\r\n * Stop playback and remove all registered states.\r\n *\r\n * @returns void\r\n */\r\n dispose() {\r\n this.stop();\r\n this._states.clear();\r\n }\r\n\r\n private emitResult(result: AnimationTimelineEventResult): AnimationTimelineEventResult {\r\n this.dispatchEvent('event', result.event, result.payload, result);\r\n return result;\r\n }\r\n\r\n private resolveReturnTarget(\r\n returnTo: AnimationTimelineStateReturnTarget | undefined,\r\n previousState: string | null,\r\n returnTransition: number | undefined\r\n ): AnimationControllerReturnTarget | null {\r\n if (returnTo === undefined) {\r\n return null;\r\n }\r\n const state = returnTo === true ? previousState : returnTo;\r\n if (!state) {\r\n return null;\r\n }\r\n const definition = this._states.get(state);\r\n if (!definition) {\r\n console.error(`AnimationController return state ${state} not exists`);\r\n return null;\r\n }\r\n return { state, transition: returnTransition ?? definition.transition };\r\n }\r\n\r\n private attachRunner(\r\n runner: AnimationTimelineRunner,\r\n state: string,\r\n returnTarget?: AnimationControllerReturnTarget | null\r\n ) {\r\n this._onRunnerComplete = () => {\r\n this.dispatchEvent('statecomplete', state);\r\n if (returnTarget && this._runner === runner && this._currentState === state) {\r\n const sync =\r\n returnTarget.transition && runner.lastCompletedPlaybackId\r\n ? { target: runner.lastCompletedPlaybackId, mode: 'normalized' as const }\r\n : undefined;\r\n this.setState(returnTarget.state, { transition: returnTarget.transition, sync });\r\n }\r\n };\r\n this._onRunnerEmit = (event, payload) => {\r\n this.dispatchEvent('emit', event, payload);\r\n };\r\n runner.on('complete', this._onRunnerComplete);\r\n runner.on('emit', this._onRunnerEmit);\r\n }\r\n\r\n private detachRunner() {\r\n if (this._runner) {\r\n if (this._onRunnerComplete) {\r\n this._runner.off('complete', this._onRunnerComplete);\r\n }\r\n if (this._onRunnerEmit) {\r\n this._runner.off('emit', this._onRunnerEmit);\r\n }\r\n }\r\n this._onRunnerComplete = null;\r\n this._onRunnerEmit = null;\r\n }\r\n}\r\n\r\nfunction prepareTimelineForTransition(\r\n definition: AnimationTimelineDefinition | AnimationTimelineStep[],\r\n entryTransition: number,\r\n returnTransition: number | undefined,\r\n entrySync: AnimationPlaybackSyncOptions | undefined\r\n): AnimationTimelineDefinition | AnimationTimelineStep[] {\r\n let timeline: AnimationTimelineDefinition | AnimationTimelineStep[] = definition;\r\n if (entrySync) {\r\n timeline = withEntrySync(timeline, entrySync);\r\n }\r\n const completionFadeOut = Math.max(returnTransition ?? 0, 0);\r\n if (completionFadeOut > 0) {\r\n timeline = withCompletionFadeOut(timeline, completionFadeOut);\r\n }\r\n return entryTransition > 0 ? withFadeIn(timeline, entryTransition) : timeline;\r\n}\r\n\r\n/**\r\n * Return a copy of the timeline definition whose entry plays use `sync` unless they already\r\n * declare a more specific synchronization source.\r\n */\r\nfunction withEntrySync(\r\n definition: AnimationTimelineDefinition | AnimationTimelineStep[],\r\n sync: AnimationPlaybackSyncOptions\r\n): AnimationTimelineDefinition {\r\n const def: AnimationTimelineDefinition = Array.isArray(definition) ? { steps: definition } : definition;\r\n return { steps: injectEntrySync(def.steps, sync).steps, responses: def.responses };\r\n}\r\n\r\nfunction injectEntrySync(\r\n steps: AnimationTimelineStep[],\r\n sync: AnimationPlaybackSyncOptions\r\n): { steps: AnimationTimelineStep[]; blocked: boolean } {\r\n let blocked = false;\r\n const out = steps.map((step) => {\r\n if (blocked) {\r\n return step;\r\n }\r\n switch (step.type) {\r\n case 'play':\r\n if (step.wait === 'complete') {\r\n blocked = true;\r\n }\r\n return { ...step, options: { ...step.options, sync: step.options?.sync ?? sync } };\r\n case 'sequence': {\r\n const result = injectEntrySync(step.steps, sync);\r\n blocked = result.blocked;\r\n return { ...step, steps: result.steps };\r\n }\r\n case 'parallel': {\r\n let anyBranchBlocked = false;\r\n const branches = step.steps.map((branch) => {\r\n const result = injectEntrySync([branch], sync);\r\n anyBranchBlocked = anyBranchBlocked || result.blocked;\r\n return result.steps[0];\r\n });\r\n blocked = anyBranchBlocked;\r\n return { ...step, steps: branches };\r\n }\r\n case 'wait':\r\n case 'waitEvent':\r\n case 'waitMarker':\r\n case 'waitFrame':\r\n blocked = true;\r\n return step;\r\n default:\r\n return step;\r\n }\r\n });\r\n return { steps: out, blocked };\r\n}\r\n\r\n/**\r\n * Return a copy of the timeline definition whose entry plays fade in over `duration`, so a state\r\n * transition cross-fades against the previous state's fade-out.\r\n *\r\n * \"Entry plays\" are every `play` that starts before the control flow first blocks: plays before a\r\n * `wait`/`waitEvent`/`waitMarker`/`waitFrame`, before a blocking `play` (`wait: 'complete'`), and\r\n * every branch of a leading `parallel` (all branches start simultaneously). This covers parallel\r\n * states whose branches would otherwise snap in at full weight while only the first faded.\r\n */\r\nfunction withFadeIn(\r\n definition: AnimationTimelineDefinition | AnimationTimelineStep[],\r\n duration: number\r\n): AnimationTimelineDefinition {\r\n const def: AnimationTimelineDefinition = Array.isArray(definition) ? { steps: definition } : definition;\r\n return { steps: injectEntryFadeIn(def.steps, duration).steps, responses: def.responses };\r\n}\r\n\r\n/**\r\n * Inject `fadeIn` into every entry play in `steps`. Returns the rewritten steps and whether the\r\n * flow blocks before reaching the end (so callers stop injecting into later, non-entry steps).\r\n */\r\nfunction injectEntryFadeIn(\r\n steps: AnimationTimelineStep[],\r\n duration: number\r\n): { steps: AnimationTimelineStep[]; blocked: boolean } {\r\n let blocked = false;\r\n const out = steps.map((step) => {\r\n if (blocked) {\r\n return step;\r\n }\r\n switch (step.type) {\r\n case 'play':\r\n if (step.wait === 'complete') {\r\n blocked = true;\r\n }\r\n return { ...step, options: { ...step.options, fadeIn: duration } };\r\n case 'sequence': {\r\n const result = injectEntryFadeIn(step.steps, duration);\r\n blocked = result.blocked;\r\n return { ...step, steps: result.steps };\r\n }\r\n case 'parallel': {\r\n // Every branch starts simultaneously, so inject into all of them. The parallel join only\r\n // blocks the steps that follow it if at least one branch blocks; if all branches are\r\n // non-blocking they drain in the same flush, so the following steps are still entry plays.\r\n let anyBranchBlocked = false;\r\n const branches = step.steps.map((branch) => {\r\n const result = injectEntryFadeIn([branch], duration);\r\n anyBranchBlocked = anyBranchBlocked || result.blocked;\r\n return result.steps[0];\r\n });\r\n blocked = anyBranchBlocked;\r\n return { ...step, steps: branches };\r\n }\r\n case 'wait':\r\n case 'waitEvent':\r\n case 'waitMarker':\r\n case 'waitFrame':\r\n blocked = true;\r\n return step;\r\n default:\r\n return step;\r\n }\r\n });\r\n return { steps: out, blocked };\r\n}\r\n\r\n/**\r\n * Return a copy of the timeline definition whose play steps keep completed playbacks alive long\r\n * enough to cross-fade into the automatic return state.\r\n */\r\nfunction withCompletionFadeOut(\r\n definition: AnimationTimelineDefinition | AnimationTimelineStep[],\r\n duration: number\r\n): AnimationTimelineDefinition {\r\n const def: AnimationTimelineDefinition = Array.isArray(definition) ? { steps: definition } : definition;\r\n return { steps: injectCompletionFadeOut(def.steps, duration), responses: def.responses };\r\n}\r\n\r\nfunction injectCompletionFadeOut(steps: AnimationTimelineStep[], duration: number): AnimationTimelineStep[] {\r\n return steps.map((step) => {\r\n switch (step.type) {\r\n case 'play':\r\n return {\r\n ...step,\r\n options: {\r\n ...step.options,\r\n completionFadeOut: step.options?.completionFadeOut ?? duration\r\n }\r\n };\r\n case 'sequence':\r\n return { ...step, steps: injectCompletionFadeOut(step.steps, duration) };\r\n case 'parallel':\r\n return { ...step, steps: step.steps.map((branch) => injectCompletionFadeOut([branch], duration)[0]) };\r\n default:\r\n return step;\r\n }\r\n });\r\n}\r\n"],"names":["AnimationController","Observable","_states","_currentState","_runner","_onRunnerComplete","_onRunnerEmit","animationSet","Map","currentState","runner","addState","name","definition","has","console","warn","set","hasState","setState","options","get","error","force","previousState","transition","Math","max","returnTarget","resolveReturnTarget","returnTo","returnTransition","detachRunner","stop","fadeOut","reason","timeline","AnimationTimeline","prepareTimelineForTransition","sync","createRunner","attachRunner","dispatchEvent","start","dispatch","event","payload","emitResult","handled","policy","timelineResult","response","responses","find","item","target","ignore","consume","targetState","undefined","onActive","steps","length","enqueue","disposition","runConcurrent","stopOptions","dispose","clear","result","state","lastCompletedPlaybackId","mode","on","off","entryTransition","entrySync","withEntrySync","completionFadeOut","withCompletionFadeOut","withFadeIn","def","Array","isArray","injectEntrySync","blocked","out","map","step","type","wait","anyBranchBlocked","branches","branch","duration","injectEntryFadeIn","fadeIn","injectCompletionFadeOut"],"mappings":";;;AA4FA;;;;;;;IAQO,MAAMA,mBAA4BC,SAAAA,UAAAA,CAAAA;AACvC;;AAEC,MACD,YAAoC;IACnBC,OAAyD;IAClEC,aAA6B;IAC7BC,OAAwC;IACxCC,iBAAuC;IACvCC,aAAkE;AAE1E;;;;MAKA,WAAA,CAAYC,YAA0B,CAAE;QACtC,KAAK,EAAA;QACL,IAAI,CAACA,YAAY,GAAGA,YAAAA;QACpB,IAAI,CAACL,OAAO,GAAG,IAAIM,GAAAA,EAAAA;QACnB,IAAI,CAACL,aAAa,GAAG,IAAA;QACrB,IAAI,CAACC,OAAO,GAAG,IAAA;QACf,IAAI,CAACC,iBAAiB,GAAG,IAAA;QACzB,IAAI,CAACC,aAAa,GAAG,IAAA;AACvB;AAEA;;;;AAIC,MACD,IAAIG,YAAe,GAAA;QACjB,OAAO,IAAI,CAACN,aAAa;AAC3B;AAEA;;;;AAIC,MACD,IAAIO,MAAS,GAAA;QACX,OAAO,IAAI,CAACN,OAAO;AACrB;AAEA;;;;;;AAMC,MACDO,QAASC,CAAAA,IAAY,EAAEC,UAA8C,EAAE;AACrE,QAAA,IAAI,IAAI,CAACX,OAAO,CAACY,GAAG,CAACF,IAAO,CAAA,EAAA;AAC1BG,YAAAA,OAAAA,CAAQC,IAAI,CAAC,CAAC,0BAA0B,EAAEJ,IAAAA,CAAK,4BAA4B,CAAC,CAAA;AAC9E;AACA,QAAA,IAAI,CAACV,OAAO,CAACe,GAAG,CAACL,IAAMC,EAAAA,UAAAA,CAAAA;AACvB,QAAA,OAAO,IAAI;AACb;AAEA;;;;;MAMAK,QAAAA,CAASN,IAAY,EAAE;AACrB,QAAA,OAAO,IAAI,CAACV,OAAO,CAACY,GAAG,CAACF,IAAAA,CAAAA;AAC1B;AAEA;;;;;;;;;;AAUC,MACDO,QAASP,CAAAA,IAAY,EAAEQ,OAA4C,EAAE;AACnE,QAAA,MAAMP,aAAa,IAAI,CAACX,OAAO,CAACmB,GAAG,CAACT,IAAAA,CAAAA;AACpC,QAAA,IAAI,CAACC,UAAY,EAAA;AACfE,YAAAA,OAAAA,CAAQO,KAAK,CAAC,CAAC,0BAA0B,EAAEV,IAAAA,CAAK,WAAW,CAAC,CAAA;YAC5D,OAAO,IAAA;AACT;AACA,QAAA,IAAI,CAACQ,OAASG,EAAAA,KAAAA,IAAS,IAAI,CAACpB,aAAa,KAAKS,IAAM,EAAA;YAClD,OAAO,IAAI,CAACR,OAAO;AACrB;QACA,MAAMoB,aAAAA,GAAgB,IAAI,CAACrB,aAAa;QACxC,MAAMsB,UAAAA,GAAaC,KAAKC,GAAG,CAACP,SAASK,UAAcZ,IAAAA,UAAAA,CAAWY,UAAU,IAAI,CAAG,EAAA,CAAA,CAAA;QAC/E,MAAMG,YAAAA,GAAe,IAAI,CAACC,mBAAmB,CAC3CT,OAASU,EAAAA,QAAAA,EACTN,eACAJ,OAASW,EAAAA,gBAAAA,CAAAA;AAEX,QAAA,IAAI,CAACC,YAAY,EAAA;AACjB,QAAA,IAAIP,aAAa,CAAG,EAAA;YAClB,IAAI,CAACrB,OAAO,EAAE6B,IAAK,CAAA;gBAAEC,OAAST,EAAAA,UAAAA;gBAAYU,MAAQ,EAAA;AAAc,aAAA,CAAA;SAC3D,MAAA;AACL,YAAA,IAAI,CAAC/B,OAAO,EAAE6B,IAAAA,CAAKb,SAASa,IAAQ,IAAA;gBAAEE,MAAQ,EAAA;AAAc,aAAA,CAAA;AAC9D;QACA,MAAMC,QAAAA,GAAW,IAAIC,iBAAAA,CACnBC,4BAA6BzB,CAAAA,UAAAA,CAAWuB,QAAQ,EAAEX,UAAAA,EAAYG,YAAcH,EAAAA,UAAAA,EAAYL,OAASmB,EAAAA,IAAAA,CAAAA,CAAAA;QAEnG,IAAI,CAACnC,OAAO,GAAGgC,QAAAA,CAASI,YAAY,CAAC,IAAI,CAACjC,YAAY,CAAA;QACtD,MAAMG,MAAAA,GAAS,IAAI,CAACN,OAAO;AAC3B,QAAA,IAAI,CAACqC,YAAY,CAAC/B,MAAAA,EAAQE,IAAMgB,EAAAA,YAAAA,CAAAA;;;;QAIhC,IAAI,CAACzB,aAAa,GAAGS,IAAAA;AACrB,QAAA,IAAI,CAAC8B,aAAa,CAAC,aAAA,EAAe9B,IAAMY,EAAAA,aAAAA,CAAAA;;;QAGxC,IAAI,IAAI,CAACpB,OAAO,KAAKM,UAAU,IAAI,CAACP,aAAa,KAAKS,IAAM,EAAA;AAC1DF,YAAAA,MAAAA,CAAOiC,KAAK,EAAA;AACd;;;QAGA,OAAO,IAAI,CAACvC,OAAO;AACrB;AAEA;;;;;;;;;AASC,MACDwC,QAASC,CAAAA,KAAa,EAAEC,OAAiB,EAAgC;QACvE,IAAI,CAAC,IAAI,CAAC3C,aAAa,IAAI,CAAC,IAAI,CAACC,OAAO,EAAE;YACxC,OAAO,IAAI,CAAC2C,UAAU,CAAC;gBAAEC,OAAS,EAAA,KAAA;gBAAOC,MAAQ,EAAA,MAAA;AAAQJ,gBAAAA,KAAAA;AAAOC,gBAAAA;AAAQ,aAAA,CAAA;AAC1E;AACA,QAAA,MAAMI,iBAAiB,IAAI,CAAC9C,OAAO,CAACwC,QAAQ,CAACC,KAAOC,EAAAA,OAAAA,CAAAA;QACpD,IAAII,cAAAA,CAAeF,OAAO,EAAE;YAC1B,OAAO,IAAI,CAACD,UAAU,CAACG,cAAAA,CAAAA;AACzB;AACA,QAAA,MAAMC,WAAW,IAAI,CAACjD,OAAO,CAACmB,GAAG,CAAC,IAAI,CAAClB,aAAa,GAAGiD,SAAWC,EAAAA,IAAAA,CAAK,CAACC,IAASA,GAAAA,IAAAA,CAAKT,KAAK,KAAKA,KAAAA,CAAAA;AAChG,QAAA,IAAI,CAACM,QAAYA,IAAAA,QAAAA,CAASI,MAAM,CAACC,MAAM,EAAE;YACvC,OAAO,IAAI,CAACT,UAAU,CAAC;gBAAEC,OAAS,EAAA,KAAA;AAAOC,gBAAAA,MAAAA,EAAQE,WAAW,QAAW,GAAA,MAAA;AAAQN,gBAAAA,KAAAA;AAAOC,gBAAAA;AAAQ,aAAA,CAAA;AAChG;AACA,QAAA,IAAIK,QAASI,CAAAA,MAAM,CAACE,OAAO,EAAE;YAC3B,OAAO,IAAI,CAACV,UAAU,CAAC;gBAAEC,OAAS,EAAA,IAAA;gBAAMC,MAAQ,EAAA,SAAA;AAAWJ,gBAAAA,KAAAA;AAAOC,gBAAAA;AAAQ,aAAA,CAAA;AAC5E;AACA,QAAA,IAAIK,QAASI,CAAAA,MAAM,CAACG,WAAW,KAAKC,SAAW,EAAA;YAC7C,MAAMlC,UAAAA,GAAa,OAAO0B,QAAAA,CAASS,QAAQ,KAAK,WAAWT,QAASS,CAAAA,QAAQ,CAAC1B,OAAO,GAAGyB,SAAAA;YACvF,MAAMjD,MAAAA,GAAS,IAAI,CAACS,QAAQ,CAACgC,QAASI,CAAAA,MAAM,CAACG,WAAW,EAAE;AACxDjC,gBAAAA,UAAAA;gBACAK,QAAUqB,EAAAA,QAAAA,CAASI,MAAM,CAACzB,QAAQ;gBAClCC,gBAAkBoB,EAAAA,QAAAA,CAASI,MAAM,CAACxB;AACpC,aAAA,CAAA;;;AAGA,YAAA,IAAI,CAACrB,MAAQ,EAAA;gBACX,OAAO,IAAI,CAACqC,UAAU,CAAC;oBAAEC,OAAS,EAAA,KAAA;oBAAOC,MAAQ,EAAA,YAAA;AAAcJ,oBAAAA,KAAAA;AAAOC,oBAAAA;AAAQ,iBAAA,CAAA;AAChF;YACA,OAAO,IAAI,CAACC,UAAU,CAAC;gBAAEC,OAAS,EAAA,IAAA;gBAAMC,MAAQ,EAAA,YAAA;AAAcJ,gBAAAA,KAAAA;AAAOC,gBAAAA;AAAQ,aAAA,CAAA;AAC/E;AACA,QAAA,MAAMe,KAAQV,GAAAA,QAAAA,CAASI,MAAM,CAACM,KAAK;QACnC,IAAI,CAACA,OAAOC,MAAQ,EAAA;YAClB,OAAO,IAAI,CAACf,UAAU,CAAC;gBAAEC,OAAS,EAAA,KAAA;gBAAOC,MAAQ,EAAA,MAAA;AAAQJ,gBAAAA,KAAAA;AAAOC,gBAAAA;AAAQ,aAAA,CAAA;AAC1E;QACA,IAAIK,QAAAA,CAASY,OAAO,EAAE;AACpB,YAAA,IAAI,CAAC3D,OAAO,CAAC2D,OAAO,CAACF,KAAAA,CAAAA;YACrB,OAAO,IAAI,CAACd,UAAU,CAAC;gBAAEC,OAAS,EAAA,IAAA;gBAAMC,MAAQ,EAAA,SAAA;AAAWJ,gBAAAA,KAAAA;AAAOC,gBAAAA;AAAQ,aAAA,CAAA;AAC5E;QACA,MAAMkB,WAAAA,GAAcb,QAASS,CAAAA,QAAQ,IAAI,MAAA;AACzC,QAAA,IAAII,gBAAgB,MAAQ,EAAA;AAC1B,YAAA,IAAI,CAAC5D,OAAO,CAAC6D,aAAa,CAACJ,KAAAA,CAAAA;SACtB,MAAA;YACL,MAAMK,WAAAA,GACJ,OAAOF,WAAAA,KAAgB,QAAW,GAAA;AAAE,gBAAA,GAAGA,WAAW;gBAAE7B,MAAQ,EAAA;aAA2BwB,GAAAA,SAAAA;AACzF,YAAA,IAAI,CAAC3B,YAAY,EAAA;AACjB,YAAA,IAAI,CAAC5B,OAAO,CAAC6B,IAAI,CAACiC,WAAAA,CAAAA;YAClB,IAAI,CAAC9D,OAAO,GAAG,IAAIiC,iBAAAA,CAAkBwB,OAAOrB,YAAY,CAAC,IAAI,CAACjC,YAAY,CAAA;YAC1E,IAAI,CAACkC,YAAY,CAAC,IAAI,CAACrC,OAAO,EAAE,IAAI,CAACD,aAAa,CAAA;YAClD,IAAI,CAACC,OAAO,CAACuC,KAAK,EAAA;AACpB;QACA,OAAO,IAAI,CAACI,UAAU,CAAC;YAAEC,OAAS,EAAA,IAAA;YAAMC,MAAQ,EAAA,OAAA;AAASJ,YAAAA,KAAAA;AAAOC,YAAAA;AAAQ,SAAA,CAAA;AAC1E;AAEA;;;;;MAMAb,IAAAA,CAAKb,OAA8B,EAAE;QACnC,MAAMI,aAAAA,GAAgB,IAAI,CAACrB,aAAa;AACxC,QAAA,IAAI,CAAC6B,YAAY,EAAA;QACjB,IAAI,CAAC5B,OAAO,EAAE6B,IAAKb,CAAAA,OAAAA,CAAAA;QACnB,IAAI,CAAChB,OAAO,GAAG,IAAA;QACf,IAAI,CAACD,aAAa,GAAG,IAAA;AACrB,QAAA,IAAIqB,kBAAkB,IAAM,EAAA;AAC1B,YAAA,IAAI,CAACkB,aAAa,CAAC,aAAA,EAAe,IAAMlB,EAAAA,aAAAA,CAAAA;AAC1C;AACF;AAEA;;;;AAIC,MACD2C,OAAU,GAAA;AACR,QAAA,IAAI,CAAClC,IAAI,EAAA;QACT,IAAI,CAAC/B,OAAO,CAACkE,KAAK,EAAA;AACpB;AAEQrB,IAAAA,UAAAA,CAAWsB,MAAoC,EAAgC;QACrF,IAAI,CAAC3B,aAAa,CAAC,OAAA,EAAS2B,OAAOxB,KAAK,EAAEwB,MAAOvB,CAAAA,OAAO,EAAEuB,MAAAA,CAAAA;QAC1D,OAAOA,MAAAA;AACT;AAEQxC,IAAAA,mBAAAA,CACNC,QAAwD,EACxDN,aAA4B,EAC5BO,gBAAoC,EACI;AACxC,QAAA,IAAID,aAAa6B,SAAW,EAAA;YAC1B,OAAO,IAAA;AACT;QACA,MAAMW,KAAAA,GAAQxC,QAAa,KAAA,IAAA,GAAON,aAAgBM,GAAAA,QAAAA;AAClD,QAAA,IAAI,CAACwC,KAAO,EAAA;YACV,OAAO,IAAA;AACT;AACA,QAAA,MAAMzD,aAAa,IAAI,CAACX,OAAO,CAACmB,GAAG,CAACiD,KAAAA,CAAAA;AACpC,QAAA,IAAI,CAACzD,UAAY,EAAA;AACfE,YAAAA,OAAAA,CAAQO,KAAK,CAAC,CAAC,iCAAiC,EAAEgD,KAAAA,CAAM,WAAW,CAAC,CAAA;YACpE,OAAO,IAAA;AACT;QACA,OAAO;AAAEA,YAAAA,KAAAA;YAAO7C,UAAYM,EAAAA,gBAAAA,IAAoBlB,WAAWY;AAAW,SAAA;AACxE;AAEQgB,IAAAA,YAAAA,CACN/B,MAA+B,EAC/B4D,KAAa,EACb1C,YAAqD,EACrD;QACA,IAAI,CAACvB,iBAAiB,GAAG,IAAA;YACvB,IAAI,CAACqC,aAAa,CAAC,eAAiB4B,EAAAA,KAAAA,CAAAA;YACpC,IAAI1C,YAAAA,IAAgB,IAAI,CAACxB,OAAO,KAAKM,UAAU,IAAI,CAACP,aAAa,KAAKmE,KAAO,EAAA;AAC3E,gBAAA,MAAM/B,OACJX,YAAaH,CAAAA,UAAU,IAAIf,MAAAA,CAAO6D,uBAAuB,GACrD;AAAEhB,oBAAAA,MAAAA,EAAQ7C,OAAO6D,uBAAuB;oBAAEC,IAAM,EAAA;iBAChDb,GAAAA,SAAAA;AACN,gBAAA,IAAI,CAACxC,QAAQ,CAACS,YAAAA,CAAa0C,KAAK,EAAE;AAAE7C,oBAAAA,UAAAA,EAAYG,aAAaH,UAAU;AAAEc,oBAAAA;AAAK,iBAAA,CAAA;AAChF;AACF,SAAA;AACA,QAAA,IAAI,CAACjC,aAAa,GAAG,CAACuC,KAAOC,EAAAA,OAAAA,GAAAA;AAC3B,YAAA,IAAI,CAACJ,aAAa,CAAC,MAAA,EAAQG,KAAOC,EAAAA,OAAAA,CAAAA;AACpC,SAAA;AACApC,QAAAA,MAAAA,CAAO+D,EAAE,CAAC,UAAY,EAAA,IAAI,CAACpE,iBAAiB,CAAA;AAC5CK,QAAAA,MAAAA,CAAO+D,EAAE,CAAC,MAAQ,EAAA,IAAI,CAACnE,aAAa,CAAA;AACtC;IAEQ0B,YAAe,GAAA;QACrB,IAAI,IAAI,CAAC5B,OAAO,EAAE;YAChB,IAAI,IAAI,CAACC,iBAAiB,EAAE;gBAC1B,IAAI,CAACD,OAAO,CAACsE,GAAG,CAAC,UAAY,EAAA,IAAI,CAACrE,iBAAiB,CAAA;AACrD;YACA,IAAI,IAAI,CAACC,aAAa,EAAE;gBACtB,IAAI,CAACF,OAAO,CAACsE,GAAG,CAAC,MAAQ,EAAA,IAAI,CAACpE,aAAa,CAAA;AAC7C;AACF;QACA,IAAI,CAACD,iBAAiB,GAAG,IAAA;QACzB,IAAI,CAACC,aAAa,GAAG,IAAA;AACvB;AACF;AAEA,SAASgC,6BACPzB,UAAiE,EACjE8D,eAAuB,EACvB5C,gBAAoC,EACpC6C,SAAmD,EAAA;AAEnD,IAAA,IAAIxC,QAAkEvB,GAAAA,UAAAA;AACtE,IAAA,IAAI+D,SAAW,EAAA;AACbxC,QAAAA,QAAAA,GAAWyC,cAAczC,QAAUwC,EAAAA,SAAAA,CAAAA;AACrC;AACA,IAAA,MAAME,iBAAoBpD,GAAAA,IAAAA,CAAKC,GAAG,CAACI,oBAAoB,CAAG,EAAA,CAAA,CAAA;AAC1D,IAAA,IAAI+C,oBAAoB,CAAG,EAAA;AACzB1C,QAAAA,QAAAA,GAAW2C,sBAAsB3C,QAAU0C,EAAAA,iBAAAA,CAAAA;AAC7C;AACA,IAAA,OAAOH,eAAkB,GAAA,CAAA,GAAIK,UAAW5C,CAAAA,QAAAA,EAAUuC,eAAmBvC,CAAAA,GAAAA,QAAAA;AACvE;AAEA;;;AAGC,IACD,SAASyC,aAAAA,CACPhE,UAAiE,EACjE0B,IAAkC,EAAA;AAElC,IAAA,MAAM0C,GAAmCC,GAAAA,KAAAA,CAAMC,OAAO,CAACtE,UAAc,CAAA,GAAA;QAAEgD,KAAOhD,EAAAA;KAAeA,GAAAA,UAAAA;IAC7F,OAAO;AAAEgD,QAAAA,KAAAA,EAAOuB,eAAgBH,CAAAA,GAAAA,CAAIpB,KAAK,EAAEtB,MAAMsB,KAAK;AAAET,QAAAA,SAAAA,EAAW6B,IAAI7B;AAAU,KAAA;AACnF;AAEA,SAASgC,eAAAA,CACPvB,KAA8B,EAC9BtB,IAAkC,EAAA;AAElC,IAAA,IAAI8C,OAAU,GAAA,KAAA;AACd,IAAA,MAAMC,GAAMzB,GAAAA,KAAAA,CAAM0B,GAAG,CAAC,CAACC,IAAAA,GAAAA;AACrB,QAAA,IAAIH,OAAS,EAAA;YACX,OAAOG,IAAAA;AACT;AACA,QAAA,OAAQA,KAAKC,IAAI;YACf,KAAK,MAAA;gBACH,IAAID,IAAAA,CAAKE,IAAI,KAAK,UAAY,EAAA;oBAC5BL,OAAU,GAAA,IAAA;AACZ;gBACA,OAAO;AAAE,oBAAA,GAAGG,IAAI;oBAAEpE,OAAS,EAAA;AAAE,wBAAA,GAAGoE,KAAKpE,OAAO;wBAAEmB,IAAMiD,EAAAA,IAAAA,CAAKpE,OAAO,EAAEmB,IAAQA,IAAAA;AAAK;AAAE,iBAAA;YACnF,KAAK,UAAA;AAAY,gBAAA;AACf,oBAAA,MAAM8B,MAASe,GAAAA,eAAAA,CAAgBI,IAAK3B,CAAAA,KAAK,EAAEtB,IAAAA,CAAAA;AAC3C8C,oBAAAA,OAAAA,GAAUhB,OAAOgB,OAAO;oBACxB,OAAO;AAAE,wBAAA,GAAGG,IAAI;AAAE3B,wBAAAA,KAAAA,EAAOQ,OAAOR;AAAM,qBAAA;AACxC;YACA,KAAK,UAAA;AAAY,gBAAA;AACf,oBAAA,IAAI8B,gBAAmB,GAAA,KAAA;AACvB,oBAAA,MAAMC,WAAWJ,IAAK3B,CAAAA,KAAK,CAAC0B,GAAG,CAAC,CAACM,MAAAA,GAAAA;AAC/B,wBAAA,MAAMxB,SAASe,eAAgB,CAAA;AAACS,4BAAAA;yBAAO,EAAEtD,IAAAA,CAAAA;wBACzCoD,gBAAmBA,GAAAA,gBAAAA,IAAoBtB,OAAOgB,OAAO;wBACrD,OAAOhB,MAAAA,CAAOR,KAAK,CAAC,CAAE,CAAA;AACxB,qBAAA,CAAA;oBACAwB,OAAUM,GAAAA,gBAAAA;oBACV,OAAO;AAAE,wBAAA,GAAGH,IAAI;wBAAE3B,KAAO+B,EAAAA;AAAS,qBAAA;AACpC;YACA,KAAK,MAAA;YACL,KAAK,WAAA;YACL,KAAK,YAAA;YACL,KAAK,WAAA;gBACHP,OAAU,GAAA,IAAA;gBACV,OAAOG,IAAAA;AACT,YAAA;gBACE,OAAOA,IAAAA;AACX;AACF,KAAA,CAAA;IACA,OAAO;QAAE3B,KAAOyB,EAAAA,GAAAA;AAAKD,QAAAA;AAAQ,KAAA;AAC/B;AAEA;;;;;;;;AAQC,IACD,SAASL,UAAAA,CACPnE,UAAiE,EACjEiF,QAAgB,EAAA;AAEhB,IAAA,MAAMb,GAAmCC,GAAAA,KAAAA,CAAMC,OAAO,CAACtE,UAAc,CAAA,GAAA;QAAEgD,KAAOhD,EAAAA;KAAeA,GAAAA,UAAAA;IAC7F,OAAO;AAAEgD,QAAAA,KAAAA,EAAOkC,iBAAkBd,CAAAA,GAAAA,CAAIpB,KAAK,EAAEiC,UAAUjC,KAAK;AAAET,QAAAA,SAAAA,EAAW6B,IAAI7B;AAAU,KAAA;AACzF;AAEA;;;AAGC,IACD,SAAS2C,iBAAAA,CACPlC,KAA8B,EAC9BiC,QAAgB,EAAA;AAEhB,IAAA,IAAIT,OAAU,GAAA,KAAA;AACd,IAAA,MAAMC,GAAMzB,GAAAA,KAAAA,CAAM0B,GAAG,CAAC,CAACC,IAAAA,GAAAA;AACrB,QAAA,IAAIH,OAAS,EAAA;YACX,OAAOG,IAAAA;AACT;AACA,QAAA,OAAQA,KAAKC,IAAI;YACf,KAAK,MAAA;gBACH,IAAID,IAAAA,CAAKE,IAAI,KAAK,UAAY,EAAA;oBAC5BL,OAAU,GAAA,IAAA;AACZ;gBACA,OAAO;AAAE,oBAAA,GAAGG,IAAI;oBAAEpE,OAAS,EAAA;AAAE,wBAAA,GAAGoE,KAAKpE,OAAO;wBAAE4E,MAAQF,EAAAA;AAAS;AAAE,iBAAA;YACnE,KAAK,UAAA;AAAY,gBAAA;AACf,oBAAA,MAAMzB,MAAS0B,GAAAA,iBAAAA,CAAkBP,IAAK3B,CAAAA,KAAK,EAAEiC,QAAAA,CAAAA;AAC7CT,oBAAAA,OAAAA,GAAUhB,OAAOgB,OAAO;oBACxB,OAAO;AAAE,wBAAA,GAAGG,IAAI;AAAE3B,wBAAAA,KAAAA,EAAOQ,OAAOR;AAAM,qBAAA;AACxC;YACA,KAAK,UAAA;AAAY,gBAAA;;;;AAIf,oBAAA,IAAI8B,gBAAmB,GAAA,KAAA;AACvB,oBAAA,MAAMC,WAAWJ,IAAK3B,CAAAA,KAAK,CAAC0B,GAAG,CAAC,CAACM,MAAAA,GAAAA;AAC/B,wBAAA,MAAMxB,SAAS0B,iBAAkB,CAAA;AAACF,4BAAAA;yBAAO,EAAEC,QAAAA,CAAAA;wBAC3CH,gBAAmBA,GAAAA,gBAAAA,IAAoBtB,OAAOgB,OAAO;wBACrD,OAAOhB,MAAAA,CAAOR,KAAK,CAAC,CAAE,CAAA;AACxB,qBAAA,CAAA;oBACAwB,OAAUM,GAAAA,gBAAAA;oBACV,OAAO;AAAE,wBAAA,GAAGH,IAAI;wBAAE3B,KAAO+B,EAAAA;AAAS,qBAAA;AACpC;YACA,KAAK,MAAA;YACL,KAAK,WAAA;YACL,KAAK,YAAA;YACL,KAAK,WAAA;gBACHP,OAAU,GAAA,IAAA;gBACV,OAAOG,IAAAA;AACT,YAAA;gBACE,OAAOA,IAAAA;AACX;AACF,KAAA,CAAA;IACA,OAAO;QAAE3B,KAAOyB,EAAAA,GAAAA;AAAKD,QAAAA;AAAQ,KAAA;AAC/B;AAEA;;;AAGC,IACD,SAASN,qBAAAA,CACPlE,UAAiE,EACjEiF,QAAgB,EAAA;AAEhB,IAAA,MAAMb,GAAmCC,GAAAA,KAAAA,CAAMC,OAAO,CAACtE,UAAc,CAAA,GAAA;QAAEgD,KAAOhD,EAAAA;KAAeA,GAAAA,UAAAA;IAC7F,OAAO;QAAEgD,KAAOoC,EAAAA,uBAAAA,CAAwBhB,GAAIpB,CAAAA,KAAK,EAAEiC,QAAAA,CAAAA;AAAW1C,QAAAA,SAAAA,EAAW6B,IAAI7B;AAAU,KAAA;AACzF;AAEA,SAAS6C,uBAAAA,CAAwBpC,KAA8B,EAAEiC,QAAgB,EAAA;IAC/E,OAAOjC,KAAAA,CAAM0B,GAAG,CAAC,CAACC,IAAAA,GAAAA;AAChB,QAAA,OAAQA,KAAKC,IAAI;YACf,KAAK,MAAA;gBACH,OAAO;AACL,oBAAA,GAAGD,IAAI;oBACPpE,OAAS,EAAA;AACP,wBAAA,GAAGoE,KAAKpE,OAAO;wBACf0D,iBAAmBU,EAAAA,IAAAA,CAAKpE,OAAO,EAAE0D,iBAAqBgB,IAAAA;AACxD;AACF,iBAAA;YACF,KAAK,UAAA;gBACH,OAAO;AAAE,oBAAA,GAAGN,IAAI;oBAAE3B,KAAOoC,EAAAA,uBAAAA,CAAwBT,IAAK3B,CAAAA,KAAK,EAAEiC,QAAAA;AAAU,iBAAA;YACzE,KAAK,UAAA;gBACH,OAAO;AAAE,oBAAA,GAAGN,IAAI;AAAE3B,oBAAAA,KAAAA,EAAO2B,KAAK3B,KAAK,CAAC0B,GAAG,CAAC,CAACM,SAAWI,uBAAwB,CAAA;AAACJ,4BAAAA;yBAAO,EAAEC,QAAAA,CAAS,CAAC,CAAE,CAAA;AAAE,iBAAA;AACtG,YAAA;gBACE,OAAON,IAAAA;AACX;AACF,KAAA,CAAA;AACF;;;;"}