@benev/tact 0.2.0 → 0.3.0-2
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,435 @@
|
|
|
1
|
+
|
|
2
|
+
# 🎮 @benev/tact
|
|
3
|
+
> *web game input library, from keypress to couch co-op*
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
npm install @benev/tact
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
tact is a toolkit for handling user inputs on the web.
|
|
10
|
+
it's good at user-customizable keybindings, multiple gamepad support, and mobile ui.
|
|
11
|
+
|
|
12
|
+
- 🛹 **[#deck](#deck)** full setup with localstorage persistence
|
|
13
|
+
- 🎮 **[#devices](#devices)** produce user input samples
|
|
14
|
+
- 🧩 **[#bindings](#bindings)** describe how actions interpret samples
|
|
15
|
+
- 🔌 **[#port](#port)** updates actions by interpreting samples
|
|
16
|
+
- 🛞 **[#hub](#hub)** plugs devices into ports (multi-gamepad couch co-op!)
|
|
17
|
+
- 📱 **[#nubs](#nubs)** is mobile ui virtual gamepad stuff
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
<br/><br/>
|
|
21
|
+
<a id="deck"></a>
|
|
22
|
+
|
|
23
|
+
## 🍋 tact deck
|
|
24
|
+
> *full setup with ui, batteries included*
|
|
25
|
+
|
|
26
|
+
the deck ties together all the important pieces of tact into a single user experience, complete with ui views.
|
|
27
|
+
|
|
28
|
+
tact's ui is built with [`@e280/sly` shadow views](https://github.com/e280/sly).
|
|
29
|
+
|
|
30
|
+
### 🛹 deck setup
|
|
31
|
+
- **import stuff from tact**
|
|
32
|
+
```ts
|
|
33
|
+
import * as tact from "@benev/tact"
|
|
34
|
+
```
|
|
35
|
+
- **setup your deck, and your game's bindings**
|
|
36
|
+
```ts
|
|
37
|
+
const deck = await tact.Deck.load({
|
|
38
|
+
|
|
39
|
+
// how many player ports are possible? 1 is fine..
|
|
40
|
+
portCount: 4,
|
|
41
|
+
|
|
42
|
+
// where to store the user-customized bindings
|
|
43
|
+
kv: tact.localStorageKv(),
|
|
44
|
+
|
|
45
|
+
// default archetypal bindings for your game
|
|
46
|
+
bindings: {
|
|
47
|
+
walking: {forward: "KeyW", jump: "Space"},
|
|
48
|
+
gunning: {
|
|
49
|
+
shoot: ["or", "pointer.button.left", "gamepad.trigger.right"],
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
})
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### 🛹 plug devices into the hub
|
|
56
|
+
- **plug a keyboard/mouse player into the hub**
|
|
57
|
+
```ts
|
|
58
|
+
deck.hub.plug(new tact.PrimaryDevice())
|
|
59
|
+
```
|
|
60
|
+
- **automatically detect and plug gamepads**
|
|
61
|
+
```ts
|
|
62
|
+
tact.autoGamepads(deck.hub.plug)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 🛹 do your gameplay
|
|
66
|
+
- **poll the deck, interrogate actions**
|
|
67
|
+
```ts
|
|
68
|
+
myGameLoop(() => {
|
|
69
|
+
|
|
70
|
+
// do your polling
|
|
71
|
+
const [p1, p2, p3, p4] = deck.hub.poll()
|
|
72
|
+
|
|
73
|
+
// check if the first player is pressing "forward" action
|
|
74
|
+
p1.actions.walking.forward.pressed // true
|
|
75
|
+
|
|
76
|
+
// check how hard the second player is pulling that trigger
|
|
77
|
+
p2.actions.gunning.shoot.value // 0.123
|
|
78
|
+
})
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### 🛹 deck ui: the overlay
|
|
82
|
+
- **render the deck overlay with sly**
|
|
83
|
+
```ts
|
|
84
|
+
import {dom} from "@e280/sly"
|
|
85
|
+
|
|
86
|
+
dom.render(
|
|
87
|
+
dom("#game-ui"),
|
|
88
|
+
tact.DeckOverlay(deck),
|
|
89
|
+
)
|
|
90
|
+
```
|
|
91
|
+
- **place the ui on top of your game canvas**
|
|
92
|
+
```html
|
|
93
|
+
<div id="game-ui"></div>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
<br/><br/>
|
|
99
|
+
<a id="devices"></a>
|
|
100
|
+
|
|
101
|
+
## 🍋 tact devices
|
|
102
|
+
> *sources of user input "samples"*
|
|
103
|
+
|
|
104
|
+
### 🎮 polling is good, actually
|
|
105
|
+
- tact operates on the basis of *polling*
|
|
106
|
+
- *"but polling is bad"* says you — but no — you're wrong — polling is unironically *based,* and you *should* do it
|
|
107
|
+
- the gift of polling is total control over *when* inputs are processed, this is good for games
|
|
108
|
+
- i will elaborate no further 🗿
|
|
109
|
+
|
|
110
|
+
### 🎮 basically how a device works
|
|
111
|
+
- make a device
|
|
112
|
+
```ts
|
|
113
|
+
const keyboard = new tact.KeyboardDevice()
|
|
114
|
+
```
|
|
115
|
+
- reading samples looks like this
|
|
116
|
+
```ts
|
|
117
|
+
for (const sample of keyboard.samples())
|
|
118
|
+
console.log(sample) // ["KeyA", 1]
|
|
119
|
+
```
|
|
120
|
+
- some devices have disposers to call when you're done with them
|
|
121
|
+
```ts
|
|
122
|
+
keyboard.dispose()
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### 🎮 samples explained
|
|
126
|
+
- a sample is a raw input tuple of type `[code: string, value: number]`
|
|
127
|
+
- a sample has a `code` string
|
|
128
|
+
- it's either a [standard keycode](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_code_values), like `KeyA`
|
|
129
|
+
- or it's something we made up, like `pointer.button.left` or `gamepad.trigger.right`
|
|
130
|
+
- a sample has a `value` number
|
|
131
|
+
- `0` means *"nothing is going on"*
|
|
132
|
+
- `1` means *"pressed"*
|
|
133
|
+
- we don't like negative numbers
|
|
134
|
+
- values between `0` and `1`, like `0.123`, are how triggers and thumbsticks express themselves
|
|
135
|
+
- sometimes we use numbers greater then `1`, like for dots of pointer movement like in `pointer.move.up`
|
|
136
|
+
- don't worry about sensitivity, deadzones, values like `0.00001` — actions will account for all that using bindings later on
|
|
137
|
+
|
|
138
|
+
### 🎮 sample code reference
|
|
139
|
+
- **KeyboardDevice**
|
|
140
|
+
- any [standard keycode](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_code_values)
|
|
141
|
+
- `KeyA`
|
|
142
|
+
- `Space`
|
|
143
|
+
- `Digit2`
|
|
144
|
+
- etc
|
|
145
|
+
- **PointerDevice**
|
|
146
|
+
- mouse buttons
|
|
147
|
+
- `pointer.button.left`
|
|
148
|
+
- `pointer.button.right`
|
|
149
|
+
- `pointer.button.middle`
|
|
150
|
+
- `pointer.button.4`
|
|
151
|
+
- `pointer.button.5`
|
|
152
|
+
- mouse wheel
|
|
153
|
+
- `pointer.wheel.up`
|
|
154
|
+
- `pointer.wheel.down`
|
|
155
|
+
- `pointer.wheel.left`
|
|
156
|
+
- `pointer.wheel.right`
|
|
157
|
+
- mouse movements
|
|
158
|
+
- `pointer.move.up`
|
|
159
|
+
- `pointer.move.down`
|
|
160
|
+
- `pointer.move.left`
|
|
161
|
+
- `pointer.move.right`
|
|
162
|
+
- **GamepadDevice**
|
|
163
|
+
- gamepad buttons
|
|
164
|
+
- `gamepad.a`
|
|
165
|
+
- `gamepad.b`
|
|
166
|
+
- `gamepad.x`
|
|
167
|
+
- `gamepad.y`
|
|
168
|
+
- `gamepad.bumper.left`
|
|
169
|
+
- `gamepad.bumper.right`
|
|
170
|
+
- `gamepad.trigger.left`
|
|
171
|
+
- `gamepad.trigger.right`
|
|
172
|
+
- `gamepad.alpha`
|
|
173
|
+
- `gamepad.beta`
|
|
174
|
+
- `gamepad.stick.left.click`
|
|
175
|
+
- `gamepad.stick.right.click`
|
|
176
|
+
- `gamepad.up`
|
|
177
|
+
- `gamepad.down`
|
|
178
|
+
- `gamepad.left`
|
|
179
|
+
- `gamepad.right`
|
|
180
|
+
- `gamepad.gamma`
|
|
181
|
+
- gamepad sticks
|
|
182
|
+
- `gamepad.stick.left.up`
|
|
183
|
+
- `gamepad.stick.left.down`
|
|
184
|
+
- `gamepad.stick.left.left`
|
|
185
|
+
- `gamepad.stick.left.right`
|
|
186
|
+
- `gamepad.stick.right.up`
|
|
187
|
+
- `gamepad.stick.right.down`
|
|
188
|
+
- `gamepad.stick.right.left`
|
|
189
|
+
- `gamepad.stick.right.right`
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
<br/><br/>
|
|
194
|
+
<a id="bindings"></a>
|
|
195
|
+
|
|
196
|
+
## 🍋 tact bindings
|
|
197
|
+
> *keybindings! they describe how actions interpret samples*
|
|
198
|
+
|
|
199
|
+
### 🧩 bindings example
|
|
200
|
+
- **let's start with a small example:**
|
|
201
|
+
```ts
|
|
202
|
+
const bindings = tact.asBindings({
|
|
203
|
+
walking: {forward: "KeyW", jump: "Space"},
|
|
204
|
+
gunning: {
|
|
205
|
+
shoot: ["or", "pointer.button.left", "gamepad.trigger.right"],
|
|
206
|
+
},
|
|
207
|
+
})
|
|
208
|
+
```
|
|
209
|
+
- `walking` and `gunning` are **modes**
|
|
210
|
+
- `forward`, `jump`, and `shoot` are **actions**
|
|
211
|
+
- note that whole modes can be enabled or disabled during gameplay
|
|
212
|
+
|
|
213
|
+
### 🧩 bindings are a lispy domain-specific-language
|
|
214
|
+
- **you can do complex stuff**
|
|
215
|
+
```ts
|
|
216
|
+
["or",
|
|
217
|
+
"KeyQ",
|
|
218
|
+
["and",
|
|
219
|
+
"KeyA",
|
|
220
|
+
"KeyD",
|
|
221
|
+
["not", "KeyS"],
|
|
222
|
+
],
|
|
223
|
+
]
|
|
224
|
+
```
|
|
225
|
+
- press Q, or
|
|
226
|
+
- press A + D, while not pressing S
|
|
227
|
+
- **you can get really weird**
|
|
228
|
+
```ts
|
|
229
|
+
["cond",
|
|
230
|
+
["code", "gamepad.trigger.right", {range: [0, 0.5], timing: ["tap"]}],
|
|
231
|
+
["and", "gamepad.bumper.left", ["not", "gamepad.trigger.left"]],
|
|
232
|
+
]
|
|
233
|
+
```
|
|
234
|
+
- hold LB and tap RT halfway while not holding LT
|
|
235
|
+
|
|
236
|
+
### 🧩 bindings atom reference
|
|
237
|
+
- **string** — strings are interpreted as "code" atoms with default settings
|
|
238
|
+
- **"code"** — allows you to customize the settings
|
|
239
|
+
```ts
|
|
240
|
+
["code", "KeyA", {
|
|
241
|
+
scale: 1,
|
|
242
|
+
invert: false,
|
|
243
|
+
timing: ["direct"],
|
|
244
|
+
}]
|
|
245
|
+
```
|
|
246
|
+
- defaults shown
|
|
247
|
+
- `scale` is sensitivity, the value gets multiplied by this
|
|
248
|
+
- `invert` will invert a value by subtracting it from 1
|
|
249
|
+
- `clamp` clamps the value with a lower and upper bound
|
|
250
|
+
- `range` restricts value to the given range, and remaps that range 0 to 1
|
|
251
|
+
- `bottom` zeroes the value if it's less than the given bottom value
|
|
252
|
+
- `top` clamps the value to an upper bound
|
|
253
|
+
- `timing` lets you specify special timing considerations
|
|
254
|
+
- `["direct"]` ignores timing considerations
|
|
255
|
+
- `["tap", 250]` only fires for taps under 250ms
|
|
256
|
+
- `["hold", 250]` only fires for holds over 250ms
|
|
257
|
+
- **"or"** — resolves to the maximum value
|
|
258
|
+
```ts
|
|
259
|
+
["or", "KeyA", "KeyB", "KeyC"]
|
|
260
|
+
```
|
|
261
|
+
- **"and"** — resolves to the minimum value
|
|
262
|
+
```ts
|
|
263
|
+
["and", "KeyA", "KeyB", "KeyC"]
|
|
264
|
+
```
|
|
265
|
+
- **"not"** — resolves to the opposite effect
|
|
266
|
+
```ts
|
|
267
|
+
["not", "KeyA"]
|
|
268
|
+
```
|
|
269
|
+
- **"cond"** — conditional situation (example for modifiers shown)
|
|
270
|
+
```ts
|
|
271
|
+
["cond", "KeyA", ["and",
|
|
272
|
+
["or", "ControlLeft", "ControlRight"],
|
|
273
|
+
["not", ["or", "AltLeft", "AltRight"]],
|
|
274
|
+
["not", ["or", "MetaLeft", "MetaRight"]],
|
|
275
|
+
["not", ["or", "ShiftLeft", "ShiftRight"]],
|
|
276
|
+
]]
|
|
277
|
+
```
|
|
278
|
+
- KeyA is the value that gets used
|
|
279
|
+
- but only if the following condition passes
|
|
280
|
+
- **"mods"** — macro for modifiers
|
|
281
|
+
```ts
|
|
282
|
+
["mods", "KeyA", {ctrl: true}]
|
|
283
|
+
```
|
|
284
|
+
- equivalent to the "cond" example above
|
|
285
|
+
- `ctrl`, `alt`, `meta`, `shift` are available
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
<br/><br/>
|
|
290
|
+
<a id="port"></a>
|
|
291
|
+
|
|
292
|
+
## 🍋 tact port
|
|
293
|
+
> *polling gives you "actions"*
|
|
294
|
+
|
|
295
|
+
a port represents a single playable port, and you poll it each frame to resolve actions for you to read.
|
|
296
|
+
|
|
297
|
+
### 🔌 port setup
|
|
298
|
+
- **make a port**
|
|
299
|
+
```ts
|
|
300
|
+
const port = new tact.Port(bindings)
|
|
301
|
+
```
|
|
302
|
+
- **attach some devices to the port**
|
|
303
|
+
```ts
|
|
304
|
+
port.devices
|
|
305
|
+
.add(new tact.KeyboardDevice())
|
|
306
|
+
.add(new tact.PointerDevice())
|
|
307
|
+
.add(new tact.VpadDevice())
|
|
308
|
+
```
|
|
309
|
+
- you can add/delete devices from the set any time
|
|
310
|
+
- **manipulate modes**
|
|
311
|
+
```ts
|
|
312
|
+
port.modes.clear()
|
|
313
|
+
port.modes.add("walking")
|
|
314
|
+
```
|
|
315
|
+
- actions only happen for enabled modes
|
|
316
|
+
- you can toggle modes on and off by adding/deleting them from the modes set
|
|
317
|
+
- **you can update the bindings any time**
|
|
318
|
+
```ts
|
|
319
|
+
port.bindings = freshBindings
|
|
320
|
+
```
|
|
321
|
+
- **wire up gamepad auto connect/disconnect**
|
|
322
|
+
```ts
|
|
323
|
+
tact.autoGamepads(device => {
|
|
324
|
+
port.devices.add(device)
|
|
325
|
+
return () => port.devices.delete(device)
|
|
326
|
+
})
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### 🔌 interrogating actions
|
|
330
|
+
- **poll the port every frame**
|
|
331
|
+
```ts
|
|
332
|
+
port.resolve()
|
|
333
|
+
```
|
|
334
|
+
- **now you can inspect the `actions`**
|
|
335
|
+
```ts
|
|
336
|
+
port.actions.walking.forward.value // 1
|
|
337
|
+
```
|
|
338
|
+
- `walking` is a `mode`
|
|
339
|
+
- `forward` is an `action`
|
|
340
|
+
- `action.value` — current value
|
|
341
|
+
- `action.previous` — last frame's value
|
|
342
|
+
- `action.changed` — true if value and previous are different
|
|
343
|
+
- `action.pressed` — true if the value > 0
|
|
344
|
+
- `action.down` — true for one frame when the key goes from up to down
|
|
345
|
+
- `action.up` — true for one frame when the key goes from down to up
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
<br/><br/>
|
|
350
|
+
<a id="hub"></a>
|
|
351
|
+
|
|
352
|
+
## 🍋 tact hub
|
|
353
|
+
> *multiple gamepads! couch co-op is so back*
|
|
354
|
+
|
|
355
|
+
you know the way old-timey game consoles had four controller ports on the front?
|
|
356
|
+
|
|
357
|
+
the hub embraces that analogy, helping you coordinate the plugging and unplugging of virtual controller devices into its virtual ports.
|
|
358
|
+
|
|
359
|
+
### 🛞 create a hub with ports
|
|
360
|
+
- **make hub with multiple ports at the ready**
|
|
361
|
+
```ts
|
|
362
|
+
const hub = new tact.Hub([
|
|
363
|
+
new tact.Port(bindings),
|
|
364
|
+
new tact.Port(bindings),
|
|
365
|
+
new tact.Port(bindings),
|
|
366
|
+
new tact.Port(bindings),
|
|
367
|
+
])
|
|
368
|
+
```
|
|
369
|
+
- yes that's right — each player port gets its own bindings 🤯
|
|
370
|
+
|
|
371
|
+
### 🛞 plug in some devices
|
|
372
|
+
- **let's plug in the keyboard/mouse player**
|
|
373
|
+
```ts
|
|
374
|
+
hub.plug(new tact.PrimaryDevice())
|
|
375
|
+
```
|
|
376
|
+
- the hub requires a single device to represent a player, so you can use a `GroupDevice` to combine multple devices into one
|
|
377
|
+
- **wire up gamepad auto connect/disconnect**
|
|
378
|
+
```ts
|
|
379
|
+
tact.autoGamepads(hub.plug)
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### 🛞 now we're gaming
|
|
383
|
+
- **do your polling, interrogate those actions**
|
|
384
|
+
```ts
|
|
385
|
+
const [p1, p2, p3, p4] = hub.poll()
|
|
386
|
+
|
|
387
|
+
p1.actions.walking.jump.value // 1
|
|
388
|
+
p2.actions.walking.jump.value // 0
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
<br/><br/>
|
|
394
|
+
<a id="nubs"></a>
|
|
395
|
+
|
|
396
|
+
## 🍋 tact nubs
|
|
397
|
+
> *mobile ui like virtual thumbsticks and buttons*
|
|
398
|
+
|
|
399
|
+
### 📱 nubs setup
|
|
400
|
+
- **render nub views with sly**
|
|
401
|
+
```ts
|
|
402
|
+
import {dom} from "@e280/sly"
|
|
403
|
+
|
|
404
|
+
const stick = new tact.StickDevice()
|
|
405
|
+
|
|
406
|
+
dom.render(
|
|
407
|
+
dom("#controls"),
|
|
408
|
+
tact.NubStick(stick),
|
|
409
|
+
)
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### 📱 nub stick
|
|
413
|
+
- **place a mount point onto your page**
|
|
414
|
+
```html
|
|
415
|
+
<div id="controls"></div>
|
|
416
|
+
```
|
|
417
|
+
- **make the stick device yourself, then plug it into your hub or whatever**
|
|
418
|
+
```ts
|
|
419
|
+
const stick = new tact.StickDevice()
|
|
420
|
+
|
|
421
|
+
dom.render(
|
|
422
|
+
dom("#controls"),
|
|
423
|
+
tact.NubStick(stick),
|
|
424
|
+
)
|
|
425
|
+
|
|
426
|
+
deck.hub.plug(stick)
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
<br/><br/>
|
|
432
|
+
<a id="benev"></a>
|
|
433
|
+
|
|
434
|
+
## 🍋 tact is by https://benevolent.games/
|
|
435
|
+
> *building the future of web games*
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
|
|
2
|
+
import {Kv} from "@e280/kv"
|
|
3
|
+
import {disposer, range} from "@e280/stz"
|
|
4
|
+
|
|
5
|
+
import {Db} from "./parts/db.js"
|
|
6
|
+
import {Hub} from "../core/hub/hub.js"
|
|
7
|
+
import {Port} from "../core/hub/port.js"
|
|
8
|
+
import {Bindings} from "../core/bindings/types.js"
|
|
9
|
+
import {mergeBindings} from "./parts/merge-bindings.js"
|
|
10
|
+
import {MetaBindings, metaMode} from "../core/hub/types.js"
|
|
11
|
+
import {makeMetaBindings} from "../core/hub/meta-bindings.js"
|
|
12
|
+
import {DeviceSkins} from "./parts/device-skins/device-skin.js"
|
|
13
|
+
import {OverlayVisibility} from "./parts/overlay-visibility.js"
|
|
14
|
+
import {PrimaryDevice} from "../core/devices/standard/primary.js"
|
|
15
|
+
|
|
16
|
+
export type DeckOptions<B extends Bindings, MB extends MetaBindings = any> = {
|
|
17
|
+
kv: Kv
|
|
18
|
+
bindings: B
|
|
19
|
+
portCount: number
|
|
20
|
+
metaBindings?: MB
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class Deck<B extends Bindings, MB extends MetaBindings = any> {
|
|
24
|
+
static async load<B extends Bindings, MB extends MetaBindings = any>(options: DeckOptions<B, MB>) {
|
|
25
|
+
const db = await Db.load(options.kv.store("catalog"))
|
|
26
|
+
|
|
27
|
+
const ports = range(options.portCount)
|
|
28
|
+
.map(index => db.$catalog().getProfileForPort(index))
|
|
29
|
+
.map(profile => mergeBindings(options.bindings, profile?.bindings))
|
|
30
|
+
.map(bindings => new Port<B>(bindings as B))
|
|
31
|
+
|
|
32
|
+
const hub = new Hub<B>(
|
|
33
|
+
ports,
|
|
34
|
+
db.$catalog().metaBindings
|
|
35
|
+
?? options.metaBindings
|
|
36
|
+
?? makeMetaBindings(),
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
return new this(options.bindings, options.metaBindings, hub, db)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
dispose = disposer()
|
|
43
|
+
deviceSkins = new DeviceSkins()
|
|
44
|
+
primaryDevice = new PrimaryDevice()
|
|
45
|
+
overlayVisibility: OverlayVisibility
|
|
46
|
+
|
|
47
|
+
constructor(
|
|
48
|
+
public baseBindings: B,
|
|
49
|
+
public baseMetaBindings: MB,
|
|
50
|
+
public hub: Hub<B, MB>,
|
|
51
|
+
public db: Db,
|
|
52
|
+
) {
|
|
53
|
+
|
|
54
|
+
this.overlayVisibility = new OverlayVisibility(hub, this.deviceSkins)
|
|
55
|
+
|
|
56
|
+
// meta reveal overlay
|
|
57
|
+
this.dispose.schedule(
|
|
58
|
+
hub.metaPort.actions[metaMode].revealOverlay.on(action => {
|
|
59
|
+
if (action.pressed)
|
|
60
|
+
this.overlayVisibility.bump()
|
|
61
|
+
})
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
get catalog() {
|
|
66
|
+
return this.db.$catalog()
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
|
|
2
|
+
@layer vars, core, basics, page;
|
|
3
|
+
|
|
4
|
+
@layer vars {
|
|
5
|
+
:root {
|
|
6
|
+
color-scheme: dark;
|
|
7
|
+
--link: cyan;
|
|
8
|
+
--prime: #ccc;
|
|
9
|
+
--bg: #181818;
|
|
10
|
+
--bg2: #111111;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@layer core {
|
|
15
|
+
* {
|
|
16
|
+
padding: 0;
|
|
17
|
+
margin: 0;
|
|
18
|
+
box-sizing: border-box;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
::-webkit-scrollbar { width: 4px; }
|
|
22
|
+
::-webkit-scrollbar-track { background: transparent; }
|
|
23
|
+
::-webkit-scrollbar-thumb { background: #333; border-radius: 1em; }
|
|
24
|
+
::-webkit-scrollbar-thumb:hover { background: #444; }
|
|
25
|
+
|
|
26
|
+
a {
|
|
27
|
+
color: var(--link);
|
|
28
|
+
text-decoration: none;
|
|
29
|
+
|
|
30
|
+
&:visited {
|
|
31
|
+
color: color-mix(in srgb, var(--link), purple 30%);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
&:hover {
|
|
35
|
+
color: color-mix(in srgb, var(--link), white 10%);
|
|
36
|
+
text-decoration: underline;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
&:active {
|
|
40
|
+
color: color-mix(in srgb, var(--link), white 50%);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@layer basics {
|
|
46
|
+
html { height: 100%; }
|
|
47
|
+
body { min-height: 100%; }
|
|
48
|
+
|
|
49
|
+
html, body {
|
|
50
|
+
font-family: sans-serif;
|
|
51
|
+
font-size: 12px;
|
|
52
|
+
color: var(--prime);
|
|
53
|
+
background: var(--bg);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@layer page {
|
|
58
|
+
body {
|
|
59
|
+
display: flex;
|
|
60
|
+
flex-direction: column;
|
|
61
|
+
align-items: center;
|
|
62
|
+
|
|
63
|
+
gap: 1em;
|
|
64
|
+
padding: 2em;
|
|
65
|
+
|
|
66
|
+
> * {
|
|
67
|
+
width: 100%;
|
|
68
|
+
max-width: 42em;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
> header {
|
|
72
|
+
padding: 0 2em;
|
|
73
|
+
h1 small { font-size: 0.6em; font-weight: normal; }
|
|
74
|
+
* + * { margin-top: 0.5em; }
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
> section {
|
|
78
|
+
padding: 0 2em;
|
|
79
|
+
ul {
|
|
80
|
+
padding-left: 1em;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
|
|
2
|
+
import {template, html, dataSvgEmoji, socialCard} from "@e280/scute"
|
|
3
|
+
|
|
4
|
+
const title = "@benev/tact"
|
|
5
|
+
const domain = "tact.benevolent.games"
|
|
6
|
+
const favicon = "/assets/b.png"
|
|
7
|
+
const description = "keybindings and gamepad support for web games"
|
|
8
|
+
|
|
9
|
+
export default template(import.meta.url, async orb => html`
|
|
10
|
+
<!doctype html>
|
|
11
|
+
<html>
|
|
12
|
+
<head>
|
|
13
|
+
<title>${title}</title>
|
|
14
|
+
|
|
15
|
+
<meta charset="utf-8"/>
|
|
16
|
+
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
|
17
|
+
<meta name="darkreader-lock"/>
|
|
18
|
+
<style>@layer base{html{background:#000}}</style>
|
|
19
|
+
|
|
20
|
+
<link rel="icon" href="${dataSvgEmoji("🎮")}"/>
|
|
21
|
+
<link rel="stylesheet" href="${orb.hashurl("demo/main.css")}"/>
|
|
22
|
+
<script type="module" src="${orb.hashurl("demo/main.bundle.min.js")}"></script>
|
|
23
|
+
|
|
24
|
+
${socialCard({
|
|
25
|
+
title,
|
|
26
|
+
description,
|
|
27
|
+
themeColor: "#f2ea8e",
|
|
28
|
+
siteName: domain,
|
|
29
|
+
image: `https://${domain}${favicon}`,
|
|
30
|
+
})}
|
|
31
|
+
</head>
|
|
32
|
+
<body>
|
|
33
|
+
<header>
|
|
34
|
+
<h1>
|
|
35
|
+
<strong>@benev/tact</strong>
|
|
36
|
+
<small>v${orb.packageVersion()}</small>
|
|
37
|
+
</h1>
|
|
38
|
+
<div class=deets>
|
|
39
|
+
<p><em>"from keypress to couch co-op"</em></p>
|
|
40
|
+
<p>
|
|
41
|
+
tact is a user input toolkit for the web. it's good at customizable keybindings, and multiple gamepad support.
|
|
42
|
+
see <a href="https://github.com/benevolent-games/tact">github</a>,
|
|
43
|
+
see <a href="https://benevolent.games/">benevolent.games</a>.
|
|
44
|
+
</p>
|
|
45
|
+
</div>
|
|
46
|
+
</header>
|
|
47
|
+
|
|
48
|
+
<div id=demo-theater></div>
|
|
49
|
+
|
|
50
|
+
<section>
|
|
51
|
+
<h3>controls</h3>
|
|
52
|
+
<ul>
|
|
53
|
+
<li><strong>keyboard</strong> wasd, left-bracket, right-bracket, backslash.</li>
|
|
54
|
+
<li><strong>gamepad</strong> thumbsticks, hold beta/gamma and press bumpers or dpad left/right.</li>
|
|
55
|
+
<li><strong>virtual</strong> use your mouse to press the little buttons.</li>
|
|
56
|
+
</ul>
|
|
57
|
+
</section>
|
|
58
|
+
</body>
|
|
59
|
+
</html>
|
|
60
|
+
`)
|
|
61
|
+
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
|
|
2
|
+
import {Scalar, Vec2, Xy} from "@benev/math"
|
|
3
|
+
|
|
4
|
+
export function circularClamp(vector: Xy, range: Vec2) {
|
|
5
|
+
const v = Vec2.from(vector)
|
|
6
|
+
const distance = v.distance_(0, 0)
|
|
7
|
+
const modifiedDistance = Scalar.remap(
|
|
8
|
+
distance,
|
|
9
|
+
range.x, range.y,
|
|
10
|
+
0, 1,
|
|
11
|
+
true,
|
|
12
|
+
)
|
|
13
|
+
return v.normalize().mulBy(modifiedDistance)
|
|
14
|
+
}
|