@benev/tact 0.2.0 → 0.3.0-1
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.
- package/README.md +48 -390
- package/package.json +25 -27
- package/s/_archive/README.md +435 -0
- package/s/_archive/deck/deck.ts +69 -0
- package/s/_archive/demo/main.bundle.ts +10 -0
- package/s/_archive/demo/main.css +85 -0
- package/s/_archive/index.html.ts +61 -0
- package/s/_archive/index.ts +8 -0
- package/s/_archive/tests.test.ts +6 -0
- package/s/_archive/utils/circular-clamp.ts +14 -0
- package/s/_archive/utils/evergreen.ts +10 -0
- package/s/_archive/utils/split-axis.ts +15 -0
- package/s/assets/b.png +0 -0
- package/s/core/atom/defaults.ts +32 -0
- package/s/core/atom/lens-algo.ts +84 -0
- package/s/core/atom/types.ts +44 -0
- package/s/core/bindings/normalize.ts +27 -0
- package/s/core/bindings/shape.ts +15 -0
- package/s/core/bindings/table.ts +22 -0
- package/s/core/intent/bucket.ts +28 -0
- package/s/core/intent/consts.ts +4 -0
- package/s/core/intent/decode.ts +23 -0
- package/s/core/intent/encode.ts +20 -0
- package/s/core/intent/merge.ts +15 -0
- package/s/core/parts/action.ts +36 -0
- package/s/core/parts/sample-map.ts +24 -0
- package/s/core/resolvers/actions.ts +30 -0
- package/s/core/resolvers/intents.ts +106 -0
- package/s/core/types.ts +40 -0
- package/s/deck/controller.ts +35 -0
- package/s/deck/deck.ts +76 -53
- package/s/deck/parts/profiles.ts +39 -0
- package/s/deck/parts/runtime.ts +11 -0
- package/s/deck/parts/settings.ts +30 -0
- package/s/deck/port.ts +35 -0
- package/s/deck/types.ts +16 -0
- package/s/demo/demo-app/element.ts +17 -0
- package/s/demo/demo-app/style.css.ts +10 -0
- package/s/demo/main.bundle.ts +67 -6
- package/s/demo/main.css +6 -8
- package/s/device/devices.ts +24 -0
- package/s/device/gamepad.ts +42 -0
- package/s/device/keyboard.ts +33 -0
- package/s/device/pad/on-pad.ts +50 -0
- package/s/device/pad/pad.ts +10 -0
- package/s/device/pointer.ts +97 -0
- package/s/device/sampler.ts +25 -0
- package/s/device/stick.ts +24 -0
- package/s/gamepad/gamepad-app/element.ts +65 -0
- package/s/gamepad/gamepad-app/style.css.ts +73 -0
- package/s/gamepad/index.html.ts +44 -0
- package/s/gamepad/main.bundle.ts +6 -0
- package/s/gamepad/main.css +60 -0
- package/s/index-ui.ts +3 -0
- package/s/index.html.ts +10 -17
- package/s/index.ts +28 -5
- package/s/test.ts +339 -0
- package/s/ui/views/desk/style.css.ts +70 -0
- package/s/ui/views/desk/view.ts +122 -0
- package/s/utils/circular-clamp.ts +2 -2
- package/s/utils/do-async.ts +5 -0
- package/s/utils/freeze-clone.ts +7 -0
- package/s/utils/identifier.ts +30 -0
- package/s/utils/insert.ts +6 -0
- package/s/utils/is-down.ts +5 -0
- package/s/utils/make-id.ts +7 -0
- package/s/utils/remap.ts +7 -0
- package/s/utils/shift-limit.ts +9 -0
- package/s/utils/sort-by-key.ts +7 -0
- package/s/utils/tmax.ts +7 -0
- package/s/utils/tmin.ts +7 -0
- package/x/_archive/demo/main.css +85 -0
- package/x/assets/b.png +0 -0
- package/x/core/{bindings/parts → atom}/defaults.d.ts +1 -1
- package/x/core/atom/defaults.js.map +1 -0
- package/x/core/{bindings/parts → atom}/lens-algo.d.ts +1 -1
- package/x/core/{bindings/parts → atom}/lens-algo.js +8 -8
- package/x/core/atom/lens-algo.js.map +1 -0
- package/x/core/{bindings → atom}/types.d.ts +1 -15
- package/x/core/{devices → atom}/types.js.map +1 -1
- package/x/core/bindings/normalize.d.ts +2 -0
- package/x/core/bindings/normalize.js +17 -0
- package/x/core/bindings/normalize.js.map +1 -0
- package/x/core/bindings/shape.d.ts +2 -0
- package/x/core/bindings/shape.js +10 -0
- package/x/core/bindings/shape.js.map +1 -0
- package/x/core/bindings/table.d.ts +2 -0
- package/x/core/bindings/table.js +15 -0
- package/x/core/bindings/table.js.map +1 -0
- package/x/core/intent/bucket.d.ts +7 -0
- package/x/core/intent/bucket.js +21 -0
- package/x/core/intent/bucket.js.map +1 -0
- package/x/core/intent/consts.d.ts +2 -0
- package/x/core/intent/consts.js +3 -0
- package/x/core/intent/consts.js.map +1 -0
- package/x/core/intent/decode.d.ts +3 -0
- package/x/core/intent/decode.js +18 -0
- package/x/core/intent/decode.js.map +1 -0
- package/x/core/intent/encode.d.ts +3 -0
- package/x/core/intent/encode.js +15 -0
- package/x/core/intent/encode.js.map +1 -0
- package/x/core/intent/merge.d.ts +3 -0
- package/x/core/intent/merge.js +10 -0
- package/x/core/intent/merge.js.map +1 -0
- package/x/core/{bindings → parts}/action.d.ts +5 -3
- package/x/core/parts/action.js +30 -0
- package/x/core/parts/action.js.map +1 -0
- package/x/core/parts/sample-map.d.ts +6 -0
- package/x/core/{bindings → parts}/sample-map.js +2 -3
- package/x/core/parts/sample-map.js.map +1 -0
- package/x/core/resolvers/actions.d.ts +2 -0
- package/x/core/resolvers/actions.js +23 -0
- package/x/core/resolvers/actions.js.map +1 -0
- package/x/core/resolvers/intents.d.ts +2 -0
- package/x/core/{bindings/resolver.js → resolvers/intents.js} +39 -43
- package/x/core/resolvers/intents.js.map +1 -0
- package/x/core/types.d.ts +43 -0
- package/x/core/types.js +2 -0
- package/x/core/types.js.map +1 -0
- package/x/deck/controller.d.ts +11 -0
- package/x/deck/controller.js +28 -0
- package/x/deck/controller.js.map +1 -0
- package/x/deck/deck.d.ts +30 -26
- package/x/deck/deck.js +64 -43
- package/x/deck/deck.js.map +1 -1
- package/x/deck/parts/profiles.d.ts +12 -0
- package/x/deck/parts/profiles.js +31 -0
- package/x/deck/parts/profiles.js.map +1 -0
- package/x/deck/parts/runtime.d.ts +8 -0
- package/x/deck/parts/runtime.js +7 -0
- package/x/deck/parts/runtime.js.map +1 -0
- package/x/deck/parts/settings.d.ts +11 -0
- package/x/deck/parts/settings.js +26 -0
- package/x/deck/parts/settings.js.map +1 -0
- package/x/deck/port.d.ts +10 -0
- package/x/deck/port.js +24 -0
- package/x/deck/port.js.map +1 -0
- package/x/deck/types.d.ts +11 -0
- package/x/deck/types.js +2 -0
- package/x/deck/types.js.map +1 -0
- package/x/demo/demo-app/element.d.ts +3 -0
- package/x/demo/demo-app/element.js +13 -0
- package/x/demo/demo-app/element.js.map +1 -0
- package/x/demo/demo-app/style.css.js +9 -0
- package/x/demo/demo-app/style.css.js.map +1 -0
- package/x/demo/main.bundle.js +53 -5
- package/x/demo/main.bundle.js.map +1 -1
- package/x/demo/main.bundle.min.js +106 -395
- package/x/demo/main.bundle.min.js.LEGAL.txt +33 -0
- package/x/demo/main.bundle.min.js.map +4 -4
- package/x/demo/main.css +6 -8
- package/x/device/devices.d.ts +7 -0
- package/x/device/devices.js +17 -0
- package/x/device/devices.js.map +1 -0
- package/x/device/gamepad.d.ts +9 -0
- package/x/device/gamepad.js +37 -0
- package/x/device/gamepad.js.map +1 -0
- package/x/{core/devices/standard → device}/keyboard.d.ts +1 -1
- package/x/{core/devices/standard → device}/keyboard.js +4 -2
- package/x/device/keyboard.js.map +1 -0
- package/x/device/pad/on-pad.d.ts +3 -0
- package/x/device/pad/on-pad.js +42 -0
- package/x/device/pad/on-pad.js.map +1 -0
- package/x/device/pad/pad.d.ts +6 -0
- package/x/device/pad/pad.js +11 -0
- package/x/device/pad/pad.js.map +1 -0
- package/x/{core/devices/standard → device}/pointer.d.ts +2 -2
- package/x/{core/devices/standard → device}/pointer.js +4 -4
- package/x/device/pointer.js.map +1 -0
- package/x/device/sampler.d.ts +9 -0
- package/x/device/sampler.js +19 -0
- package/x/device/sampler.js.map +1 -0
- package/x/{core/devices/standard → device}/stick.d.ts +2 -3
- package/x/{core/devices/standard → device}/stick.js +4 -6
- package/x/device/stick.js.map +1 -0
- package/x/gamepad/gamepad-app/element.d.ts +1 -0
- package/x/gamepad/gamepad-app/element.js +54 -0
- package/x/gamepad/gamepad-app/element.js.map +1 -0
- package/x/gamepad/gamepad-app/style.css.js +72 -0
- package/x/gamepad/gamepad-app/style.css.js.map +1 -0
- package/x/gamepad/index.html +35 -0
- package/x/gamepad/index.html.d.ts +2 -0
- package/x/gamepad/index.html.js +41 -0
- package/x/gamepad/index.html.js.map +1 -0
- package/x/gamepad/main.bundle.js +4 -0
- package/x/gamepad/main.bundle.js.map +1 -0
- package/x/gamepad/main.bundle.min.js +126 -0
- package/x/gamepad/main.bundle.min.js.LEGAL.txt +33 -0
- package/x/gamepad/main.bundle.min.js.map +7 -0
- package/x/gamepad/main.css +60 -0
- package/x/index-ui.d.ts +1 -0
- package/x/index-ui.js +2 -0
- package/x/index-ui.js.map +1 -0
- package/x/index.d.ts +27 -5
- package/x/index.html +17 -24
- package/x/index.html.js +10 -17
- package/x/index.html.js.map +1 -1
- package/x/index.js +27 -5
- package/x/index.js.map +1 -1
- package/x/test.d.ts +9 -0
- package/x/test.js +307 -0
- package/x/test.js.map +1 -0
- package/x/ui/views/desk/style.css.js +69 -0
- package/x/ui/views/desk/style.css.js.map +1 -0
- package/x/ui/views/desk/view.d.ts +7 -0
- package/x/ui/views/desk/view.js +102 -0
- package/x/ui/views/desk/view.js.map +1 -0
- package/x/utils/circular-clamp.js +2 -2
- package/x/utils/circular-clamp.js.map +1 -1
- package/x/utils/do-async.d.ts +1 -0
- package/x/utils/do-async.js +4 -0
- package/x/utils/do-async.js.map +1 -0
- package/x/utils/freeze-clone.d.ts +1 -0
- package/x/utils/freeze-clone.js +5 -0
- package/x/utils/freeze-clone.js.map +1 -0
- package/x/utils/identifier.d.ts +6 -0
- package/x/utils/identifier.js +25 -0
- package/x/utils/identifier.js.map +1 -0
- package/x/utils/insert.d.ts +1 -0
- package/x/utils/insert.js +5 -0
- package/x/utils/insert.js.map +1 -0
- package/x/utils/is-down.d.ts +1 -0
- package/x/utils/is-down.js +4 -0
- package/x/utils/is-down.js.map +1 -0
- package/x/utils/make-id.d.ts +1 -0
- package/x/utils/make-id.js +5 -0
- package/x/utils/make-id.js.map +1 -0
- package/x/utils/remap.d.ts +1 -0
- package/x/utils/remap.js +6 -0
- package/x/utils/remap.js.map +1 -0
- package/x/utils/shift-limit.d.ts +2 -0
- package/x/utils/shift-limit.js +7 -0
- package/x/utils/shift-limit.js.map +1 -0
- package/x/utils/sort-by-key.d.ts +1 -0
- package/x/utils/sort-by-key.js +6 -0
- package/x/utils/sort-by-key.js.map +1 -0
- package/x/utils/{quick-math.d.ts → tmax.d.ts} +0 -1
- package/x/utils/tmax.js +6 -0
- package/x/utils/tmax.js.map +1 -0
- package/x/utils/tmin.d.ts +1 -0
- package/x/utils/tmin.js +6 -0
- package/x/utils/tmin.js.map +1 -0
- package/s/tests.test.ts +0 -6
- package/x/core/bindings/action.js +0 -24
- package/x/core/bindings/action.js.map +0 -1
- package/x/core/bindings/parts/defaults.js.map +0 -1
- package/x/core/bindings/parts/is-pressed.d.ts +0 -1
- package/x/core/bindings/parts/is-pressed.js +0 -4
- package/x/core/bindings/parts/is-pressed.js.map +0 -1
- package/x/core/bindings/parts/lens-algo.js.map +0 -1
- package/x/core/bindings/parts/lookup-proxies.js +0 -19
- package/x/core/bindings/parts/lookup-proxies.js.map +0 -1
- package/x/core/bindings/resolver.d.ts +0 -9
- package/x/core/bindings/resolver.js.map +0 -1
- package/x/core/bindings/sample-map.d.ts +0 -7
- package/x/core/bindings/sample-map.js.map +0 -1
- package/x/core/bindings/types.js +0 -4
- package/x/core/bindings/types.js.map +0 -1
- package/x/core/core.test.d.ts +0 -13
- package/x/core/core.test.js +0 -138
- package/x/core/core.test.js.map +0 -1
- package/x/core/devices/auto-gamepads.d.ts +0 -2
- package/x/core/devices/auto-gamepads.js +0 -6
- package/x/core/devices/auto-gamepads.js.map +0 -1
- package/x/core/devices/device.d.ts +0 -5
- package/x/core/devices/device.js +0 -7
- package/x/core/devices/device.js.map +0 -1
- package/x/core/devices/infra/group.d.ts +0 -7
- package/x/core/devices/infra/group.js +0 -21
- package/x/core/devices/infra/group.js.map +0 -1
- package/x/core/devices/infra/sampler.d.ts +0 -9
- package/x/core/devices/infra/sampler.js +0 -18
- package/x/core/devices/infra/sampler.js.map +0 -1
- package/x/core/devices/standard/gamepad.d.ts +0 -11
- package/x/core/devices/standard/gamepad.js +0 -65
- package/x/core/devices/standard/gamepad.js.map +0 -1
- package/x/core/devices/standard/index.d.ts +0 -6
- package/x/core/devices/standard/index.js +0 -7
- package/x/core/devices/standard/index.js.map +0 -1
- package/x/core/devices/standard/keyboard.js.map +0 -1
- package/x/core/devices/standard/pointer.js.map +0 -1
- package/x/core/devices/standard/primary.d.ts +0 -10
- package/x/core/devices/standard/primary.js +0 -17
- package/x/core/devices/standard/primary.js.map +0 -1
- package/x/core/devices/standard/stick.js.map +0 -1
- package/x/core/devices/standard/vpad.d.ts +0 -7
- package/x/core/devices/standard/vpad.js +0 -20
- package/x/core/devices/standard/vpad.js.map +0 -1
- package/x/core/devices/types.d.ts +0 -1
- package/x/core/hub/hub.d.ts +0 -32
- package/x/core/hub/hub.js +0 -101
- package/x/core/hub/hub.js.map +0 -1
- package/x/core/hub/meta-bindings.d.ts +0 -2
- package/x/core/hub/meta-bindings.js +0 -21
- package/x/core/hub/meta-bindings.js.map +0 -1
- package/x/core/hub/parts/connected.d.ts +0 -14
- package/x/core/hub/parts/connected.js +0 -12
- package/x/core/hub/parts/connected.js.map +0 -1
- package/x/core/hub/port.d.ts +0 -9
- package/x/core/hub/port.js +0 -19
- package/x/core/hub/port.js.map +0 -1
- package/x/core/hub/types.d.ts +0 -9
- package/x/core/hub/types.js +0 -2
- package/x/core/hub/types.js.map +0 -1
- package/x/core/index.d.ts +0 -15
- package/x/core/index.js +0 -16
- package/x/core/index.js.map +0 -1
- package/x/core/testing/testing.d.ts +0 -52
- package/x/core/testing/testing.js +0 -45
- package/x/core/testing/testing.js.map +0 -1
- package/x/deck/index.d.ts +0 -9
- package/x/deck/index.js +0 -10
- package/x/deck/index.js.map +0 -1
- package/x/deck/parts/catalog.d.ts +0 -22
- package/x/deck/parts/catalog.js +0 -35
- package/x/deck/parts/catalog.js.map +0 -1
- package/x/deck/parts/db.d.ts +0 -17
- package/x/deck/parts/db.js +0 -52
- package/x/deck/parts/db.js.map +0 -1
- package/x/deck/parts/device-skins/device-icons.d.ts +0 -12
- package/x/deck/parts/device-skins/device-icons.js +0 -27
- package/x/deck/parts/device-skins/device-icons.js.map +0 -1
- package/x/deck/parts/device-skins/device-skin.d.ts +0 -14
- package/x/deck/parts/device-skins/device-skin.js +0 -22
- package/x/deck/parts/device-skins/device-skin.js.map +0 -1
- package/x/deck/parts/local-storage-kv.d.ts +0 -2
- package/x/deck/parts/local-storage-kv.js +0 -6
- package/x/deck/parts/local-storage-kv.js.map +0 -1
- package/x/deck/parts/merge-bindings.d.ts +0 -2
- package/x/deck/parts/merge-bindings.js +0 -15
- package/x/deck/parts/merge-bindings.js.map +0 -1
- package/x/deck/parts/overlay-visibility.d.ts +0 -18
- package/x/deck/parts/overlay-visibility.js +0 -35
- package/x/deck/parts/overlay-visibility.js.map +0 -1
- package/x/deck/views/bindings/style.css.js +0 -5
- package/x/deck/views/bindings/style.css.js.map +0 -1
- package/x/deck/views/bindings/view.d.ts +0 -2
- package/x/deck/views/bindings/view.js +0 -80
- package/x/deck/views/bindings/view.js.map +0 -1
- package/x/deck/views/overlay/style.css.js +0 -109
- package/x/deck/views/overlay/style.css.js.map +0 -1
- package/x/deck/views/overlay/view.d.ts +0 -2
- package/x/deck/views/overlay/view.js +0 -40
- package/x/deck/views/overlay/view.js.map +0 -1
- package/x/demo/game/game.d.ts +0 -17
- package/x/demo/game/game.js +0 -63
- package/x/demo/game/game.js.map +0 -1
- package/x/demo/game/parts/agent.d.ts +0 -7
- package/x/demo/game/parts/agent.js +0 -8
- package/x/demo/game/parts/agent.js.map +0 -1
- package/x/demo/game/parts/game-bindings.d.ts +0 -15
- package/x/demo/game/parts/game-bindings.js +0 -10
- package/x/demo/game/parts/game-bindings.js.map +0 -1
- package/x/demo/game/parts/logic.d.ts +0 -8
- package/x/demo/game/parts/logic.js +0 -21
- package/x/demo/game/parts/logic.js.map +0 -1
- package/x/demo/game/parts/player.d.ts +0 -14
- package/x/demo/game/parts/player.js +0 -26
- package/x/demo/game/parts/player.js.map +0 -1
- package/x/demo/game/parts/renderer.d.ts +0 -13
- package/x/demo/game/parts/renderer.js +0 -91
- package/x/demo/game/parts/renderer.js.map +0 -1
- package/x/demo/game/parts/state.d.ts +0 -8
- package/x/demo/game/parts/state.js +0 -20
- package/x/demo/game/parts/state.js.map +0 -1
- package/x/demo/game/parts/virtual-device.d.ts +0 -8
- package/x/demo/game/parts/virtual-device.js +0 -11
- package/x/demo/game/parts/virtual-device.js.map +0 -1
- package/x/demo/ui/theater/styles.css.d.ts +0 -1
- package/x/demo/ui/theater/styles.css.js +0 -57
- package/x/demo/ui/theater/styles.css.js.map +0 -1
- package/x/demo/ui/theater/view.d.ts +0 -2
- package/x/demo/ui/theater/view.js +0 -45
- package/x/demo/ui/theater/view.js.map +0 -1
- package/x/demo/ui/theater/virtual/style.css.js +0 -42
- package/x/demo/ui/theater/virtual/style.css.js.map +0 -1
- package/x/demo/ui/theater/virtual/view.d.ts +0 -4
- package/x/demo/ui/theater/virtual/view.js +0 -19
- package/x/demo/ui/theater/virtual/view.js.map +0 -1
- package/x/demo/ui/utils/loader.d.ts +0 -2
- package/x/demo/ui/utils/loader.js +0 -3
- package/x/demo/ui/utils/loader.js.map +0 -1
- package/x/nubs/index.d.ts +0 -3
- package/x/nubs/index.js +0 -4
- package/x/nubs/index.js.map +0 -1
- package/x/nubs/lookpad/styles.d.ts +0 -1
- package/x/nubs/lookpad/styles.js +0 -21
- package/x/nubs/lookpad/styles.js.map +0 -1
- package/x/nubs/lookpad/view.d.ts +0 -1
- package/x/nubs/lookpad/view.js +0 -33
- package/x/nubs/lookpad/view.js.map +0 -1
- package/x/nubs/stick/style.css.d.ts +0 -2
- package/x/nubs/stick/style.css.js +0 -69
- package/x/nubs/stick/style.css.js.map +0 -1
- package/x/nubs/stick/view.d.ts +0 -2
- package/x/nubs/stick/view.js +0 -95
- package/x/nubs/stick/view.js.map +0 -1
- package/x/nubs/vpad/styles.css.d.ts +0 -2
- package/x/nubs/vpad/styles.css.js +0 -133
- package/x/nubs/vpad/styles.css.js.map +0 -1
- package/x/nubs/vpad/utils/gamepad-inputs.d.ts +0 -29
- package/x/nubs/vpad/utils/gamepad-inputs.js +0 -31
- package/x/nubs/vpad/utils/gamepad-inputs.js.map +0 -1
- package/x/nubs/vpad/utils/prevent-default-touch-shenanigans.d.ts +0 -1
- package/x/nubs/vpad/utils/prevent-default-touch-shenanigans.js +0 -9
- package/x/nubs/vpad/utils/prevent-default-touch-shenanigans.js.map +0 -1
- package/x/nubs/vpad/utils/touch-tracking.d.ts +0 -6
- package/x/nubs/vpad/utils/touch-tracking.js +0 -55
- package/x/nubs/vpad/utils/touch-tracking.js.map +0 -1
- package/x/nubs/vpad/view.d.ts +0 -2
- package/x/nubs/vpad/view.js +0 -123
- package/x/nubs/vpad/view.js.map +0 -1
- package/x/tests.test.d.ts +0 -1
- package/x/tests.test.js +0 -4
- package/x/tests.test.js.map +0 -1
- package/x/utils/dispensers.d.ts +0 -7
- package/x/utils/dispensers.js +0 -16
- package/x/utils/dispensers.js.map +0 -1
- package/x/utils/gamepads.d.ts +0 -14
- package/x/utils/gamepads.js +0 -40
- package/x/utils/gamepads.js.map +0 -1
- package/x/utils/quick-math.js +0 -11
- package/x/utils/quick-math.js.map +0 -1
- /package/s/{core → _archive/core}/bindings/action.ts +0 -0
- /package/s/{core → _archive/core}/bindings/parts/defaults.ts +0 -0
- /package/s/{core → _archive/core}/bindings/parts/is-pressed.ts +0 -0
- /package/s/{core → _archive/core}/bindings/parts/lens-algo.ts +0 -0
- /package/s/{core → _archive/core}/bindings/parts/lookup-proxies.ts +0 -0
- /package/s/{core → _archive/core}/bindings/resolver.ts +0 -0
- /package/s/{core → _archive/core}/bindings/sample-map.ts +0 -0
- /package/s/{core → _archive/core}/bindings/types.ts +0 -0
- /package/s/{core → _archive/core}/core.test.ts +0 -0
- /package/s/{core → _archive/core}/devices/auto-gamepads.ts +0 -0
- /package/s/{core → _archive/core}/devices/device.ts +0 -0
- /package/s/{core → _archive/core}/devices/infra/group.ts +0 -0
- /package/s/{core → _archive/core}/devices/infra/sampler.ts +0 -0
- /package/s/{core → _archive/core}/devices/standard/gamepad.ts +0 -0
- /package/s/{core → _archive/core}/devices/standard/index.ts +0 -0
- /package/s/{core → _archive/core}/devices/standard/keyboard.ts +0 -0
- /package/s/{core → _archive/core}/devices/standard/pointer.ts +0 -0
- /package/s/{core → _archive/core}/devices/standard/primary.ts +0 -0
- /package/s/{core → _archive/core}/devices/standard/stick.ts +0 -0
- /package/s/{core → _archive/core}/devices/standard/vpad.ts +0 -0
- /package/s/{core → _archive/core}/devices/types.ts +0 -0
- /package/s/{core → _archive/core}/hub/hub.ts +0 -0
- /package/s/{core → _archive/core}/hub/meta-bindings.ts +0 -0
- /package/s/{core → _archive/core}/hub/parts/connected.ts +0 -0
- /package/s/{core → _archive/core}/hub/port.ts +0 -0
- /package/s/{core → _archive/core}/hub/types.ts +0 -0
- /package/s/{core → _archive/core}/index.ts +0 -0
- /package/s/{core → _archive/core}/testing/testing.ts +0 -0
- /package/s/{deck → _archive/deck}/index.ts +0 -0
- /package/s/{deck → _archive/deck}/parts/catalog.ts +0 -0
- /package/s/{deck → _archive/deck}/parts/db.ts +0 -0
- /package/s/{deck → _archive/deck}/parts/device-skins/device-icons.ts +0 -0
- /package/s/{deck → _archive/deck}/parts/device-skins/device-skin.ts +0 -0
- /package/s/{deck → _archive/deck}/parts/local-storage-kv.ts +0 -0
- /package/s/{deck → _archive/deck}/parts/merge-bindings.ts +0 -0
- /package/s/{deck → _archive/deck}/parts/overlay-visibility.ts +0 -0
- /package/s/{deck → _archive/deck}/views/bindings/style.css.ts +0 -0
- /package/s/{deck → _archive/deck}/views/bindings/view.ts +0 -0
- /package/s/{deck → _archive/deck}/views/overlay/style.css.ts +0 -0
- /package/s/{deck → _archive/deck}/views/overlay/view.ts +0 -0
- /package/s/{demo → _archive/demo}/game/game.ts +0 -0
- /package/s/{demo → _archive/demo}/game/parts/agent.ts +0 -0
- /package/s/{demo → _archive/demo}/game/parts/game-bindings.ts +0 -0
- /package/s/{demo → _archive/demo}/game/parts/logic.ts +0 -0
- /package/s/{demo → _archive/demo}/game/parts/player.ts +0 -0
- /package/s/{demo → _archive/demo}/game/parts/renderer.ts +0 -0
- /package/s/{demo → _archive/demo}/game/parts/state.ts +0 -0
- /package/s/{demo → _archive/demo}/game/parts/virtual-device.ts +0 -0
- /package/s/{demo → _archive/demo}/ui/theater/styles.css.ts +0 -0
- /package/s/{demo → _archive/demo}/ui/theater/view.ts +0 -0
- /package/s/{demo → _archive/demo}/ui/theater/virtual/style.css.ts +0 -0
- /package/s/{demo → _archive/demo}/ui/theater/virtual/view.ts +0 -0
- /package/s/{demo → _archive/demo}/ui/utils/loader.ts +0 -0
- /package/s/{nubs → _archive/nubs}/index.ts +0 -0
- /package/s/{nubs → _archive/nubs}/lookpad/styles.ts +0 -0
- /package/s/{nubs → _archive/nubs}/lookpad/view.ts +0 -0
- /package/s/{nubs → _archive/nubs}/stick/style.css.ts +0 -0
- /package/s/{nubs → _archive/nubs}/stick/view.ts +0 -0
- /package/s/{nubs → _archive/nubs}/vpad/styles.css.ts +0 -0
- /package/s/{nubs → _archive/nubs}/vpad/utils/gamepad-inputs.ts +0 -0
- /package/s/{nubs → _archive/nubs}/vpad/utils/prevent-default-touch-shenanigans.ts +0 -0
- /package/s/{nubs → _archive/nubs}/vpad/utils/touch-tracking.ts +0 -0
- /package/s/{nubs → _archive/nubs}/vpad/view.ts +0 -0
- /package/s/{utils → _archive/utils}/dispensers.ts +0 -0
- /package/s/{utils → _archive/utils}/gamepads.ts +0 -0
- /package/s/{utils → _archive/utils}/quick-math.ts +0 -0
- /package/x/core/{bindings/parts → atom}/defaults.js +0 -0
- /package/x/core/{devices → atom}/types.js +0 -0
- /package/x/{deck/views/bindings → demo/demo-app}/style.css.d.ts +0 -0
- /package/x/{deck/views/overlay → gamepad/gamepad-app}/style.css.d.ts +0 -0
- /package/x/{core/bindings/parts/lookup-proxies.d.ts → gamepad/main.bundle.d.ts} +0 -0
- /package/x/{demo/ui/theater/virtual → ui/views/desk}/style.css.d.ts +0 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
import {Xy} from "@benev/math"
|
|
3
|
+
|
|
4
|
+
export function splitAxis(n: number) {
|
|
5
|
+
return (n >= 0)
|
|
6
|
+
? [n, 0]
|
|
7
|
+
: [0, Math.abs(n)]
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function splitVector(vector: Xy) {
|
|
11
|
+
const [right, left] = splitAxis(vector.x)
|
|
12
|
+
const [down, up] = splitAxis(vector.y)
|
|
13
|
+
return {up, down, left, right}
|
|
14
|
+
}
|
|
15
|
+
|
package/s/assets/b.png
ADDED
|
Binary file
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
|
|
2
|
+
import {Code, CodeSettings, CodeState} from "./types.js"
|
|
3
|
+
|
|
4
|
+
export const defaultHoldTime = 250
|
|
5
|
+
|
|
6
|
+
export function defaultCodeState([,,settings]: Code, now: number): CodeState {
|
|
7
|
+
return {
|
|
8
|
+
lastValue: 0,
|
|
9
|
+
holdStart: now,
|
|
10
|
+
settings: defaultifyCodeSettings(settings),
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function defaultCodeSettings(): CodeSettings {
|
|
15
|
+
return {
|
|
16
|
+
scale: 1,
|
|
17
|
+
invert: false,
|
|
18
|
+
clamp: null,
|
|
19
|
+
range: null,
|
|
20
|
+
bottom: null,
|
|
21
|
+
top: null,
|
|
22
|
+
timing: ["direct"],
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function defaultifyCodeSettings(partial: Partial<CodeSettings> = {}): CodeSettings {
|
|
27
|
+
return {
|
|
28
|
+
...defaultCodeSettings(),
|
|
29
|
+
...partial,
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
|
|
2
|
+
import {pipe} from "@e280/stz"
|
|
3
|
+
import {CodeState} from "./types.js"
|
|
4
|
+
import {defaultHoldTime} from "./defaults.js"
|
|
5
|
+
import {isDown} from "../../utils/is-down.js"
|
|
6
|
+
import {between, clamp, remap} from "@benev/math"
|
|
7
|
+
|
|
8
|
+
export const lensAlgo = (
|
|
9
|
+
now: number,
|
|
10
|
+
state: CodeState,
|
|
11
|
+
v: number,
|
|
12
|
+
) => pipe(v).line(
|
|
13
|
+
|
|
14
|
+
function clippings(value) {
|
|
15
|
+
const {settings} = state
|
|
16
|
+
if (settings.clamp) {
|
|
17
|
+
const [bottom, top] = settings.clamp
|
|
18
|
+
value = clamp(value, bottom, top)
|
|
19
|
+
}
|
|
20
|
+
if (settings.range) {
|
|
21
|
+
const [bottom, top] = settings.range
|
|
22
|
+
value = between(value, bottom, top)
|
|
23
|
+
? remap(
|
|
24
|
+
value,
|
|
25
|
+
bottom, top,
|
|
26
|
+
0, 1,
|
|
27
|
+
true,
|
|
28
|
+
)
|
|
29
|
+
: 0
|
|
30
|
+
}
|
|
31
|
+
if (settings.bottom) value = (value < settings.bottom) ? 0 : value
|
|
32
|
+
if (settings.top) value = Math.min(settings.top, value)
|
|
33
|
+
return value
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
function inversion(value) {
|
|
37
|
+
return state.settings.invert
|
|
38
|
+
? 1 - value
|
|
39
|
+
: value
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
function scaling(value) {
|
|
43
|
+
return state.settings.scale * value
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
function timing(value) {
|
|
47
|
+
const {settings} = state
|
|
48
|
+
|
|
49
|
+
const holdTime = (
|
|
50
|
+
settings.timing[0] === "direct"
|
|
51
|
+
? undefined
|
|
52
|
+
: settings.timing[1]
|
|
53
|
+
) ?? defaultHoldTime
|
|
54
|
+
|
|
55
|
+
const isFreshlyPressed = !isDown(state.lastValue) && isDown(value)
|
|
56
|
+
const isFreshlyReleased = isDown(state.lastValue) && !isDown(value)
|
|
57
|
+
|
|
58
|
+
if (isFreshlyPressed)
|
|
59
|
+
state.holdStart = now
|
|
60
|
+
|
|
61
|
+
const isHolding = (now - state.holdStart) >= holdTime
|
|
62
|
+
|
|
63
|
+
state.lastValue = value
|
|
64
|
+
|
|
65
|
+
switch (settings.timing[0]) {
|
|
66
|
+
case "direct":
|
|
67
|
+
return value
|
|
68
|
+
|
|
69
|
+
case "tap":
|
|
70
|
+
return (isFreshlyReleased && !isHolding)
|
|
71
|
+
? 1
|
|
72
|
+
: 0
|
|
73
|
+
|
|
74
|
+
case "hold":
|
|
75
|
+
return (isDown(value) && isHolding)
|
|
76
|
+
? value
|
|
77
|
+
: 0
|
|
78
|
+
|
|
79
|
+
default:
|
|
80
|
+
throw new Error(`unknown bindings timing`)
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
)
|
|
84
|
+
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
|
|
2
|
+
export type Atom = string | (
|
|
3
|
+
| Code
|
|
4
|
+
| And
|
|
5
|
+
| Or
|
|
6
|
+
| Not
|
|
7
|
+
| Cond
|
|
8
|
+
| Mods
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
export type Code = ["code", string, settings?: Partial<CodeSettings>]
|
|
12
|
+
export type And = ["and", ...Atom[]]
|
|
13
|
+
export type Or = ["or", ...Atom[]]
|
|
14
|
+
export type Not = ["not", Atom]
|
|
15
|
+
export type Cond = ["cond", Atom, guard: Atom]
|
|
16
|
+
export type Mods = ["mods", Atom, modifiers: Partial<Modifiers>]
|
|
17
|
+
|
|
18
|
+
export type CodeSettings = {
|
|
19
|
+
scale: number
|
|
20
|
+
invert: boolean
|
|
21
|
+
clamp: null | [number, number]
|
|
22
|
+
range: null | [number, number]
|
|
23
|
+
bottom: null | number
|
|
24
|
+
top: null | number
|
|
25
|
+
timing: (
|
|
26
|
+
| ["direct"]
|
|
27
|
+
| ["tap", holdTime?: number]
|
|
28
|
+
| ["hold", holdTime?: number]
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type CodeState = {
|
|
33
|
+
settings: CodeSettings
|
|
34
|
+
lastValue: number
|
|
35
|
+
holdStart: number
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type Modifiers = {
|
|
39
|
+
ctrl: boolean
|
|
40
|
+
alt: boolean
|
|
41
|
+
shift: boolean
|
|
42
|
+
meta: boolean
|
|
43
|
+
}
|
|
44
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
|
|
2
|
+
import {deep, is} from "@e280/stz"
|
|
3
|
+
import {Bindings} from "../types.js"
|
|
4
|
+
|
|
5
|
+
export function normalizeBindings<B extends Bindings>(
|
|
6
|
+
standard: B,
|
|
7
|
+
suspect: any,
|
|
8
|
+
): B {
|
|
9
|
+
|
|
10
|
+
const fresh = deep.clone(standard)
|
|
11
|
+
|
|
12
|
+
if (!is.object(suspect))
|
|
13
|
+
return fresh
|
|
14
|
+
|
|
15
|
+
for (const [modeName, freshBracket] of Object.entries(fresh)) {
|
|
16
|
+
const suspectBracket = suspect[modeName]
|
|
17
|
+
if (!is.object(suspectBracket)) continue
|
|
18
|
+
|
|
19
|
+
for (const [actionName, freshAtom] of Object.entries(freshBracket)) {
|
|
20
|
+
const suspectAtom = suspectBracket[actionName]
|
|
21
|
+
freshBracket[actionName] = suspectAtom ?? freshAtom
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return fresh
|
|
26
|
+
}
|
|
27
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
import {obMap} from "@e280/stz"
|
|
3
|
+
import {bindingsTable} from "./table.js"
|
|
4
|
+
import {Bindings, BindingsShape} from "../types.js"
|
|
5
|
+
|
|
6
|
+
export function bindingsShape<B extends Bindings>(data: B) {
|
|
7
|
+
const table = bindingsTable(data)
|
|
8
|
+
const shape = obMap(data, bracket => obMap(bracket, () => 0)) as any
|
|
9
|
+
|
|
10
|
+
for (const [id, {mode, action}] of table)
|
|
11
|
+
shape[mode][action] = id
|
|
12
|
+
|
|
13
|
+
return shape as BindingsShape<B>
|
|
14
|
+
}
|
|
15
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
|
|
2
|
+
import {Bindings, BindingsRow} from "../types.js"
|
|
3
|
+
import {sortByKey} from "../../utils/sort-by-key.js"
|
|
4
|
+
|
|
5
|
+
export function bindingsTable<B extends Bindings>(data: B) {
|
|
6
|
+
data = structuredClone(data)
|
|
7
|
+
const table = new Map<number, BindingsRow<B>>()
|
|
8
|
+
|
|
9
|
+
Object.entries(data)
|
|
10
|
+
.sort(sortByKey)
|
|
11
|
+
.flatMap(([mode, bracket]) =>
|
|
12
|
+
Object.entries(bracket)
|
|
13
|
+
.sort(sortByKey)
|
|
14
|
+
.map(([action, atom]) => ({mode, action, atom}))
|
|
15
|
+
)
|
|
16
|
+
.forEach((bind, id) => {
|
|
17
|
+
table.set(id, {...bind, id})
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
return table
|
|
21
|
+
}
|
|
22
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
|
|
2
|
+
import {Intent} from "../types.js"
|
|
3
|
+
|
|
4
|
+
/** merge/accumulate intents together */
|
|
5
|
+
export class IntentBucket {
|
|
6
|
+
#state = new Map<number, number>()
|
|
7
|
+
#changes = new Map<number, number>()
|
|
8
|
+
|
|
9
|
+
accumulate(intents: Intent[]) {
|
|
10
|
+
for (const [id, value] of intents) {
|
|
11
|
+
const previous = this.#state.get(id)
|
|
12
|
+
|
|
13
|
+
if (previous !== value) {
|
|
14
|
+
this.#state.set(id, value)
|
|
15
|
+
this.#changes.set(id, value)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return this
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
take() {
|
|
23
|
+
const intents = [...this.#changes.entries()]
|
|
24
|
+
this.#changes.clear()
|
|
25
|
+
return intents
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
|
|
2
|
+
import {dataViewFrom} from "@e280/stz"
|
|
3
|
+
import {Intent} from "../types.js"
|
|
4
|
+
import {littleEndian, size} from "./consts.js"
|
|
5
|
+
|
|
6
|
+
/** decode intents from compact binary format */
|
|
7
|
+
export function decodeIntents(bytes: Uint8Array) {
|
|
8
|
+
const n = bytes.byteLength / size
|
|
9
|
+
if (!Number.isInteger(n)) throw new Error("invalid bytes length")
|
|
10
|
+
|
|
11
|
+
const data = dataViewFrom(bytes)
|
|
12
|
+
const intents: Intent[] = new Array<Intent>(n)
|
|
13
|
+
|
|
14
|
+
for (let i = 0; i < n; i++) {
|
|
15
|
+
const offset = i * size
|
|
16
|
+
const index = data.getUint16(offset, littleEndian)
|
|
17
|
+
const value = data.getFloat32(offset + 2, littleEndian)
|
|
18
|
+
intents[i] = [index, value]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return intents
|
|
22
|
+
}
|
|
23
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
|
|
2
|
+
import {Intent} from "../types.js"
|
|
3
|
+
import {littleEndian, size} from "./consts.js"
|
|
4
|
+
|
|
5
|
+
/** encode intents into compact binary format (good for networking) */
|
|
6
|
+
export function encodeIntents(intents: Intent[]) {
|
|
7
|
+
const length = intents.length * size
|
|
8
|
+
const buffer = new ArrayBuffer(length)
|
|
9
|
+
const view = new DataView(buffer)
|
|
10
|
+
|
|
11
|
+
for (let i = 0; i < intents.length; i++) {
|
|
12
|
+
const [index, value] = intents[i]
|
|
13
|
+
const offset = i * size
|
|
14
|
+
view.setUint16(offset, index, littleEndian)
|
|
15
|
+
view.setFloat32(offset + 2, value, littleEndian)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return new Uint8Array(buffer)
|
|
19
|
+
}
|
|
20
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
import {Intent} from "../types.js"
|
|
3
|
+
|
|
4
|
+
/** merge multiple sources of intents together */
|
|
5
|
+
export function mergeIntents(intents: Intent[]): Intent[] {
|
|
6
|
+
const map = new Map<number, number>()
|
|
7
|
+
|
|
8
|
+
for (const [id, value] of intents) {
|
|
9
|
+
const previous = map.get(id) ?? 0
|
|
10
|
+
map.set(id, Math.max(previous, value))
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return [...map.entries()]
|
|
14
|
+
}
|
|
15
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
|
|
2
|
+
import {sub} from "@e280/stz"
|
|
3
|
+
import {isDown} from "../../utils/is-down.js"
|
|
4
|
+
|
|
5
|
+
export class Action {
|
|
6
|
+
on = sub<[Action]>()
|
|
7
|
+
onUp = sub<[Action]>()
|
|
8
|
+
onDown = sub<[Action]>()
|
|
9
|
+
|
|
10
|
+
#value = 0
|
|
11
|
+
#previous = 0
|
|
12
|
+
|
|
13
|
+
changed = false
|
|
14
|
+
|
|
15
|
+
get value() {
|
|
16
|
+
return this.#value
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
set value(v: number) {
|
|
20
|
+
this.#previous = this.#value
|
|
21
|
+
this.#value = v
|
|
22
|
+
|
|
23
|
+
if (this.changed) {
|
|
24
|
+
this.on.publish(this)
|
|
25
|
+
if (this.up) this.onUp.publish(this)
|
|
26
|
+
else this.onDown.publish(this)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
get previous() { return this.#previous }
|
|
31
|
+
get up() { return !isDown(this.#value) }
|
|
32
|
+
get down() { return isDown(this.#value) }
|
|
33
|
+
get changedUp() { return this.changed && this.up }
|
|
34
|
+
get changedDown() { return this.changed && this.down }
|
|
35
|
+
}
|
|
36
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
|
|
2
|
+
import {Sample} from "../types.js"
|
|
3
|
+
|
|
4
|
+
export class SampleMap extends Map<string, number> {
|
|
5
|
+
constructor(samples?: Iterable<Sample>) {
|
|
6
|
+
super()
|
|
7
|
+
if (samples) {
|
|
8
|
+
for (const [code, value] of samples)
|
|
9
|
+
this.set(code, value)
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
zero() {
|
|
14
|
+
for (const code of this.keys()) this.set(code, 0)
|
|
15
|
+
return this
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
merge([code, value]: Sample) {
|
|
19
|
+
const previous = this.get(code) ?? 0
|
|
20
|
+
if (value > previous) this.set(code, value)
|
|
21
|
+
return this
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
|
|
2
|
+
import {need, obMap} from "@e280/stz"
|
|
3
|
+
import {Action} from "../parts/action.js"
|
|
4
|
+
import {bindingsShape} from "../bindings/shape.js"
|
|
5
|
+
import {Actions, Bindings, Intent} from "../types.js"
|
|
6
|
+
|
|
7
|
+
export function makeActionsResolver<B extends Bindings>(bindings: B) {
|
|
8
|
+
const shape = bindingsShape(bindings)
|
|
9
|
+
const map = new Map<number, Action>()
|
|
10
|
+
|
|
11
|
+
const actions = obMap(shape, bracket => obMap(bracket, id => {
|
|
12
|
+
const action = new Action()
|
|
13
|
+
map.set(id, action)
|
|
14
|
+
return action
|
|
15
|
+
})) as Actions<B>
|
|
16
|
+
|
|
17
|
+
return (intents: Intent[]) => {
|
|
18
|
+
for (const action of map.values())
|
|
19
|
+
action.changed = false
|
|
20
|
+
|
|
21
|
+
for (const [id, value] of intents) {
|
|
22
|
+
const action = need(map, id)
|
|
23
|
+
action.changed = action.value !== value
|
|
24
|
+
action.value = value
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return actions
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
|
|
2
|
+
import {guarantee} from "@e280/stz"
|
|
3
|
+
import {tmax} from "../../utils/tmax.js"
|
|
4
|
+
import {tmin} from "../../utils/tmin.js"
|
|
5
|
+
import {lensAlgo} from "../atom/lens-algo.js"
|
|
6
|
+
import {SampleMap} from "../parts/sample-map.js"
|
|
7
|
+
import {bindingsTable} from "../bindings/table.js"
|
|
8
|
+
import {defaultCodeState} from "../atom/defaults.js"
|
|
9
|
+
import {Bindings, Sample, Intent} from "../types.js"
|
|
10
|
+
import {Atom, CodeSettings, CodeState} from "../atom/types.js"
|
|
11
|
+
|
|
12
|
+
export function makeIntentsResolver<B extends Bindings>(bindings: B) {
|
|
13
|
+
const table = bindingsTable(bindings)
|
|
14
|
+
const sampleMap = new SampleMap()
|
|
15
|
+
const codeStates = new Map<string, CodeState>()
|
|
16
|
+
const intentMap = new Map<number, number>()
|
|
17
|
+
|
|
18
|
+
for (const bind of table.values())
|
|
19
|
+
intentMap.set(bind.id, 0)
|
|
20
|
+
|
|
21
|
+
const resolveCode = (now: number, path: string[], code: string, settings?: Partial<CodeSettings>) => {
|
|
22
|
+
const state = guarantee(
|
|
23
|
+
codeStates,
|
|
24
|
+
path.join("/"),
|
|
25
|
+
() => defaultCodeState(["code", code, settings], now),
|
|
26
|
+
)
|
|
27
|
+
const value = sampleMap.get(code) ?? 0
|
|
28
|
+
return lensAlgo(now, state, value)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const resolveAtomForPath = (now: number, path: string[]) => (atom: Atom, zone: string | number): number => {
|
|
32
|
+
const nextPath = [
|
|
33
|
+
...path,
|
|
34
|
+
String(zone),
|
|
35
|
+
typeof atom === "string" ? atom : atom[0],
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
const resolveAtom = resolveAtomForPath(now, nextPath)
|
|
39
|
+
|
|
40
|
+
if (typeof atom === "string")
|
|
41
|
+
return resolveCode(now, nextPath, atom)
|
|
42
|
+
|
|
43
|
+
else switch (atom[0]) {
|
|
44
|
+
case "code": {
|
|
45
|
+
const [, code, settings] = atom
|
|
46
|
+
return resolveCode(now, nextPath, code, settings)
|
|
47
|
+
}
|
|
48
|
+
case "and": {
|
|
49
|
+
const [,...atoms] = atom
|
|
50
|
+
const values = atoms.map(resolveAtom)
|
|
51
|
+
return tmin(values)
|
|
52
|
+
}
|
|
53
|
+
case "or": {
|
|
54
|
+
const [,...atoms] = atom
|
|
55
|
+
const values = atoms.map(resolveAtom)
|
|
56
|
+
return tmax(values)
|
|
57
|
+
}
|
|
58
|
+
case "not": {
|
|
59
|
+
const [, subject] = atom
|
|
60
|
+
const value = resolveAtom(subject, "subject")
|
|
61
|
+
return (value > 0) ? 0 : 1
|
|
62
|
+
}
|
|
63
|
+
case "cond": {
|
|
64
|
+
const [, subject, guard] = atom
|
|
65
|
+
return (resolveAtom(guard, "guard") > 0)
|
|
66
|
+
? resolveAtom(subject, "subject")
|
|
67
|
+
: 0
|
|
68
|
+
}
|
|
69
|
+
case "mods": {
|
|
70
|
+
const [, subject, modifiers] = atom
|
|
71
|
+
const maybe = (x: boolean, ...codes: Atom[]): Atom => x
|
|
72
|
+
? ["or", ...codes]
|
|
73
|
+
: ["not", ["or", ...codes]]
|
|
74
|
+
const guard = resolveAtom(["cond", subject, ["and",
|
|
75
|
+
maybe(modifiers.ctrl ?? false, "ControlLeft", "ControlRight"),
|
|
76
|
+
maybe(modifiers.alt ?? false, "AltLeft", "AltRight"),
|
|
77
|
+
maybe(modifiers.meta ?? false, "MetaLeft", "MetaRight"),
|
|
78
|
+
maybe(modifiers.shift ?? false, "ShiftLeft", "ShiftRight"),
|
|
79
|
+
]], "guard")
|
|
80
|
+
return (guard > 0)
|
|
81
|
+
? resolveAtom(subject, "subject")
|
|
82
|
+
: 0
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return (now: number, samples: Iterable<Sample>) => {
|
|
88
|
+
sampleMap.zero()
|
|
89
|
+
const intents: Intent[] = []
|
|
90
|
+
|
|
91
|
+
for (const sample of samples)
|
|
92
|
+
sampleMap.merge(sample)
|
|
93
|
+
|
|
94
|
+
for (const bind of table.values()) {
|
|
95
|
+
const value = resolveAtomForPath(now, [])(bind.atom, bind.mode as string)
|
|
96
|
+
const previous = intentMap.get(bind.id)
|
|
97
|
+
if (value !== previous) {
|
|
98
|
+
intentMap.set(bind.id, value)
|
|
99
|
+
intents.push([bind.id, value])
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return intents
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
package/s/core/types.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
|
|
2
|
+
import {Atom} from "./atom/types.js"
|
|
3
|
+
import {Action} from "./parts/action.js"
|
|
4
|
+
|
|
5
|
+
/** json-friendly description of how samples are interpreted */
|
|
6
|
+
export type Bindings = {[mode: string]: {[action: string]: Atom}}
|
|
7
|
+
|
|
8
|
+
/** describes the shape of how bindings relate to the binds index (useful on serverside) */
|
|
9
|
+
export type BindingsShape<B extends Bindings> = {[MK in keyof B]: {[AK in keyof B[MK]]: number}}
|
|
10
|
+
|
|
11
|
+
/** integer-indexed flat map of bindings info (for efficient networking) */
|
|
12
|
+
export type BindingsTable<B extends Bindings> = Map<number, BindingsRow<B>>
|
|
13
|
+
|
|
14
|
+
/** the binding for a single action */
|
|
15
|
+
export type BindingsRow<B extends Bindings> = {
|
|
16
|
+
id: number
|
|
17
|
+
mode: keyof B
|
|
18
|
+
action: keyof B[keyof B]
|
|
19
|
+
atom: Atom
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** produces user input samples (eg, a keyboard produces samples) */
|
|
23
|
+
export type Device = {samples(): Iterable<Sample>}
|
|
24
|
+
|
|
25
|
+
/** raw user input, eg, `["KeyW", 1]` */
|
|
26
|
+
export type Sample = [code: string, value: number]
|
|
27
|
+
|
|
28
|
+
/** efficiently express resolved values */
|
|
29
|
+
export type Intent = [id: number, value: number]
|
|
30
|
+
|
|
31
|
+
/** ergonomic access to user inputs (your app logic should read from this) */
|
|
32
|
+
export type Actions<B extends Bindings> = {
|
|
33
|
+
[M in keyof B]: {
|
|
34
|
+
[A in keyof B[M]]: Action
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type AsBindings<B extends Bindings> = {[MK in keyof B]: {[AK in keyof B[MK]]: Atom}}
|
|
39
|
+
export const asBindings = <B extends Bindings>(b: B) => (b as AsBindings<B>)
|
|
40
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
|
|
2
|
+
import {deep} from "@e280/stz"
|
|
3
|
+
import {Bindings, Device} from "../core/types.js"
|
|
4
|
+
import {makeIntentsResolver} from "../core/resolvers/intents.js"
|
|
5
|
+
|
|
6
|
+
/** associate a device with particular bindings */
|
|
7
|
+
export class Controller<B extends Bindings = Bindings, D extends Device = Device> {
|
|
8
|
+
#bindings: B
|
|
9
|
+
#resolveIntents
|
|
10
|
+
|
|
11
|
+
constructor(
|
|
12
|
+
readonly handle: string,
|
|
13
|
+
bindings: B,
|
|
14
|
+
public device: D,
|
|
15
|
+
) {
|
|
16
|
+
this.#bindings = bindings
|
|
17
|
+
this.#resolveIntents = makeIntentsResolver(bindings)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
get bindings() {
|
|
21
|
+
return this.#bindings
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
set bindings(bindings: B) {
|
|
25
|
+
if (!deep.equal(this.#bindings, bindings)) {
|
|
26
|
+
this.#bindings = bindings
|
|
27
|
+
this.#resolveIntents = makeIntentsResolver(bindings)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
resolveIntents(now: number) {
|
|
32
|
+
return this.#resolveIntents(now, this.device.samples())
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|