@benev/tact 0.1.0 → 0.2.0-0
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 +30 -16
- package/package.json +13 -12
- package/s/core/bindings/parts/lens-algo.ts +2 -1
- package/s/core/core.test.ts +66 -35
- package/s/core/testing/testing.ts +11 -10
- package/s/deck/deck.ts +1 -14
- package/s/deck/index.ts +1 -2
- package/s/deck/parts/db.ts +2 -3
- package/s/deck/views/bindings/view.ts +95 -0
- package/s/deck/views/overlay/view.ts +46 -0
- package/s/demo/game/parts/renderer.ts +4 -5
- package/s/demo/game/parts/state.ts +1 -2
- package/s/demo/main.bundle.ts +1 -4
- package/s/demo/ui/theater/styles.css.ts +1 -2
- package/s/demo/ui/theater/view.ts +47 -52
- package/s/demo/ui/theater/virtual/view.ts +10 -12
- package/s/index.html.ts +53 -44
- package/s/nubs/index.ts +3 -4
- package/s/nubs/lookpad/{component.ts → view.ts} +10 -16
- package/s/nubs/stick/{component.ts → view.ts} +27 -34
- package/s/nubs/vpad/{component.ts → view.ts} +25 -33
- package/s/utils/circular-clamp.ts +1 -2
- package/s/utils/gamepads.ts +2 -2
- package/x/core/bindings/parts/lens-algo.js +1 -1
- package/x/core/bindings/parts/lens-algo.js.map +1 -1
- package/x/core/core.test.d.ts +1 -1
- package/x/core/core.test.js +58 -36
- package/x/core/core.test.js.map +1 -1
- package/x/core/devices/standard/stick.d.ts +2 -2
- package/x/core/testing/testing.d.ts +13 -6
- package/x/core/testing/testing.js +11 -10
- package/x/core/testing/testing.js.map +1 -1
- package/x/deck/deck.d.ts +0 -7
- package/x/deck/deck.js +1 -9
- package/x/deck/deck.js.map +1 -1
- package/x/deck/index.d.ts +1 -2
- package/x/deck/index.js +1 -2
- package/x/deck/index.js.map +1 -1
- package/x/deck/parts/db.d.ts +3 -3
- package/x/deck/parts/db.js.map +1 -1
- package/x/deck/parts/overlay-visibility.d.ts +3 -3
- package/x/deck/views/bindings/style.css.js.map +1 -0
- package/x/deck/views/bindings/view.d.ts +2 -0
- package/x/deck/views/bindings/view.js +80 -0
- package/x/deck/views/bindings/view.js.map +1 -0
- package/x/deck/views/overlay/style.css.js.map +1 -0
- package/x/deck/views/overlay/view.d.ts +2 -0
- package/x/deck/views/overlay/view.js +40 -0
- package/x/deck/views/overlay/view.js.map +1 -0
- package/x/demo/game/parts/renderer.js +4 -4
- package/x/demo/game/parts/renderer.js.map +1 -1
- package/x/demo/game/parts/state.js +1 -1
- package/x/demo/game/parts/state.js.map +1 -1
- package/x/demo/main.bundle.js +1 -5
- package/x/demo/main.bundle.js.map +1 -1
- package/x/demo/main.bundle.min.js +235 -237
- package/x/demo/main.bundle.min.js.map +4 -4
- package/x/demo/ui/theater/styles.css.js +1 -1
- package/x/demo/ui/theater/view.d.ts +1 -367
- package/x/demo/ui/theater/view.js +27 -32
- package/x/demo/ui/theater/view.js.map +1 -1
- package/x/demo/ui/theater/virtual/view.d.ts +1 -1
- package/x/demo/ui/theater/virtual/view.js +6 -6
- package/x/demo/ui/theater/virtual/view.js.map +1 -1
- package/x/index.html +41 -125
- package/x/index.html.js +50 -39
- package/x/index.html.js.map +1 -1
- package/x/nubs/index.d.ts +3 -4
- package/x/nubs/index.js +3 -4
- package/x/nubs/index.js.map +1 -1
- package/x/nubs/lookpad/view.d.ts +1 -0
- package/x/nubs/lookpad/{component.js → view.js} +11 -14
- package/x/nubs/lookpad/view.js.map +1 -0
- package/x/nubs/stick/view.d.ts +2 -0
- package/x/nubs/stick/{component.js → view.js} +28 -34
- package/x/nubs/stick/view.js.map +1 -0
- package/x/nubs/vpad/view.d.ts +2 -0
- package/x/nubs/vpad/{component.js → view.js} +26 -32
- package/x/nubs/vpad/view.js.map +1 -0
- package/x/utils/circular-clamp.js +1 -1
- package/x/utils/circular-clamp.js.map +1 -1
- package/x/utils/gamepads.js +2 -2
- package/s/deck/components/components.ts +0 -22
- package/s/deck/components/deck-bindings/component.ts +0 -99
- package/s/deck/components/deck-overlay/component.ts +0 -51
- package/s/deck/components/framework.ts +0 -17
- package/s/nubs/components.ts +0 -14
- package/s/utils/types.ts +0 -19
- package/x/deck/components/components.d.ts +0 -14
- package/x/deck/components/components.js +0 -9
- package/x/deck/components/components.js.map +0 -1
- package/x/deck/components/deck-bindings/component.d.ts +0 -6
- package/x/deck/components/deck-bindings/component.js +0 -83
- package/x/deck/components/deck-bindings/component.js.map +0 -1
- package/x/deck/components/deck-bindings/style.css.js.map +0 -1
- package/x/deck/components/deck-overlay/component.d.ts +0 -6
- package/x/deck/components/deck-overlay/component.js +0 -44
- package/x/deck/components/deck-overlay/component.js.map +0 -1
- package/x/deck/components/deck-overlay/style.css.js.map +0 -1
- package/x/deck/components/framework.d.ts +0 -7
- package/x/deck/components/framework.js +0 -13
- package/x/deck/components/framework.js.map +0 -1
- package/x/nubs/components.d.ts +0 -9
- package/x/nubs/components.js +0 -11
- package/x/nubs/components.js.map +0 -1
- package/x/nubs/lookpad/component.d.ts +0 -4
- package/x/nubs/lookpad/component.js.map +0 -1
- package/x/nubs/stick/component.d.ts +0 -368
- package/x/nubs/stick/component.js.map +0 -1
- package/x/nubs/vpad/component.d.ts +0 -368
- package/x/nubs/vpad/component.js.map +0 -1
- package/x/utils/types.d.ts +0 -3
- package/x/utils/types.js +0 -3
- package/x/utils/types.js.map +0 -1
- /package/s/deck/{components/deck-bindings → views/bindings}/style.css.ts +0 -0
- /package/s/deck/{components/deck-overlay → views/overlay}/style.css.ts +0 -0
- /package/x/deck/{components/deck-bindings → views/bindings}/style.css.d.ts +0 -0
- /package/x/deck/{components/deck-bindings → views/bindings}/style.css.js +0 -0
- /package/x/deck/{components/deck-overlay → views/overlay}/style.css.d.ts +0 -0
- /package/x/deck/{components/deck-overlay → views/overlay}/style.css.js +0 -0
package/README.md
CHANGED
|
@@ -23,7 +23,9 @@ it's good at user-customizable keybindings, multiple gamepad support, and mobile
|
|
|
23
23
|
## 🍋 tact deck
|
|
24
24
|
> *full setup with ui, batteries included*
|
|
25
25
|
|
|
26
|
-
the deck ties together all the important pieces of tact into a single user experience, complete with ui
|
|
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).
|
|
27
29
|
|
|
28
30
|
### 🛹 deck setup
|
|
29
31
|
- **import stuff from tact**
|
|
@@ -77,13 +79,18 @@ the deck ties together all the important pieces of tact into a single user exper
|
|
|
77
79
|
```
|
|
78
80
|
|
|
79
81
|
### 🛹 deck ui: the overlay
|
|
80
|
-
- **
|
|
82
|
+
- **render the deck overlay with sly**
|
|
81
83
|
```ts
|
|
82
|
-
|
|
84
|
+
import {dom} from "@e280/sly"
|
|
85
|
+
|
|
86
|
+
dom.render(
|
|
87
|
+
dom("#game-ui"),
|
|
88
|
+
tact.DeckOverlay(deck),
|
|
89
|
+
)
|
|
83
90
|
```
|
|
84
91
|
- **place the ui on top of your game canvas**
|
|
85
92
|
```html
|
|
86
|
-
<
|
|
93
|
+
<div id="game-ui"></div>
|
|
87
94
|
```
|
|
88
95
|
|
|
89
96
|
|
|
@@ -390,25 +397,33 @@ the hub embraces that analogy, helping you coordinate the plugging and unpluggin
|
|
|
390
397
|
> *mobile ui like virtual thumbsticks and buttons*
|
|
391
398
|
|
|
392
399
|
### 📱 nubs setup
|
|
393
|
-
- **
|
|
400
|
+
- **render nub views with sly**
|
|
394
401
|
```ts
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
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
|
+
)
|
|
400
410
|
```
|
|
401
411
|
|
|
402
412
|
### 📱 nub stick
|
|
403
|
-
- **place a
|
|
413
|
+
- **place a mount point onto your page**
|
|
404
414
|
```html
|
|
405
|
-
<
|
|
415
|
+
<div id="controls"></div>
|
|
406
416
|
```
|
|
407
|
-
- **
|
|
417
|
+
- **make the stick device yourself, then plug it into your hub or whatever**
|
|
408
418
|
```ts
|
|
409
|
-
const
|
|
419
|
+
const stick = new tact.StickDevice()
|
|
410
420
|
|
|
411
|
-
|
|
421
|
+
dom.render(
|
|
422
|
+
dom("#controls"),
|
|
423
|
+
tact.NubStick(stick),
|
|
424
|
+
)
|
|
425
|
+
|
|
426
|
+
deck.hub.plug(stick)
|
|
412
427
|
```
|
|
413
428
|
|
|
414
429
|
|
|
@@ -418,4 +433,3 @@ the hub embraces that analogy, helping you coordinate the plugging and unpluggin
|
|
|
418
433
|
|
|
419
434
|
## 🍋 tact is by https://benevolent.games/
|
|
420
435
|
> *building the future of web games*
|
|
421
|
-
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@benev/tact",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0-0",
|
|
4
4
|
"description": "keybindings and gamepad support for web games",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Chase Moskal <chasemoskal@gmail.com>",
|
|
@@ -16,34 +16,35 @@
|
|
|
16
16
|
"s"
|
|
17
17
|
],
|
|
18
18
|
"scripts": {
|
|
19
|
-
"build": "
|
|
19
|
+
"build": "octo-s --npm-run _clean _tsc _ln _scute",
|
|
20
|
+
"dev": "octo 'scute -vw' 'tsc -w' 'node --watch x/tests.test.js' 'hottie x'",
|
|
20
21
|
"_clean": "rm -rf x",
|
|
21
22
|
"_tsc": "tsc",
|
|
22
23
|
"_scute": "scute -v",
|
|
23
|
-
"start": "octo 'scute -vw' 'tsc -w' 'node --watch x/tests.test.js' 'http-server x -c-1'",
|
|
24
24
|
"_ln": "run-s _ln-s _ln-assets",
|
|
25
25
|
"_ln-s": "ln -s \"$(realpath s)\" x/s",
|
|
26
26
|
"_ln-assets": "ln -s \"$(realpath assets)\" x/assets",
|
|
27
27
|
"test": "node x/tests.test.js",
|
|
28
|
-
"test-debug": "node inspect x/tests.test.js",
|
|
29
28
|
"count": "find s -path '*/_archive' -prune -o -name '*.ts' -exec wc -l {} +"
|
|
30
29
|
},
|
|
31
30
|
"peerDependencies": {
|
|
32
31
|
"lit": "^3.3.2"
|
|
33
32
|
},
|
|
34
33
|
"dependencies": {
|
|
35
|
-
"@benev/math": "^0.
|
|
36
|
-
"@e280/kv": "^0.1.
|
|
37
|
-
"@e280/sly": "^0.
|
|
38
|
-
"@e280/strata": "^0.
|
|
39
|
-
"@e280/stz": "^0.2.
|
|
34
|
+
"@benev/math": "^0.3.0-5",
|
|
35
|
+
"@e280/kv": "^0.1.2",
|
|
36
|
+
"@e280/sly": "^0.3.1",
|
|
37
|
+
"@e280/strata": "^0.3.1",
|
|
38
|
+
"@e280/stz": "^0.2.27"
|
|
40
39
|
},
|
|
41
40
|
"devDependencies": {
|
|
42
|
-
"@e280/
|
|
43
|
-
"@e280/
|
|
41
|
+
"@e280/hottie": "^0.1.0",
|
|
42
|
+
"@e280/octo": "^0.1.0",
|
|
43
|
+
"@e280/science": "^0.1.9",
|
|
44
|
+
"@e280/scute": "^0.3.1",
|
|
44
45
|
"http-server": "^14.1.1",
|
|
45
46
|
"npm-run-all": "^4.1.5",
|
|
46
|
-
"typescript": "^
|
|
47
|
+
"typescript": "^6.0.2"
|
|
47
48
|
},
|
|
48
49
|
"repository": {
|
|
49
50
|
"type": "git",
|
|
@@ -54,11 +54,12 @@ export const lensAlgo = (
|
|
|
54
54
|
|
|
55
55
|
const isFreshlyPressed = !isPressed(state.lastValue) && isPressed(value)
|
|
56
56
|
const isFreshlyReleased = isPressed(state.lastValue) && !isPressed(value)
|
|
57
|
-
const isHolding = (now - state.holdStart) >= holdTime
|
|
58
57
|
|
|
59
58
|
if (isFreshlyPressed)
|
|
60
59
|
state.holdStart = now
|
|
61
60
|
|
|
61
|
+
const isHolding = (now - state.holdStart) >= holdTime
|
|
62
|
+
|
|
62
63
|
state.lastValue = value
|
|
63
64
|
|
|
64
65
|
switch (settings.timing[0]) {
|
package/s/core/core.test.ts
CHANGED
|
@@ -6,16 +6,16 @@ import {testPlug, testSetupAlpha, testSetupBravo} from "./testing/testing.js"
|
|
|
6
6
|
|
|
7
7
|
export default Science.suite({
|
|
8
8
|
"sample to action value": test(async() => {
|
|
9
|
-
const {
|
|
9
|
+
const {clock, device, resolve} = testSetupAlpha()
|
|
10
10
|
{
|
|
11
|
-
|
|
11
|
+
clock.frame = 1
|
|
12
12
|
device.setSample("Space", 1)
|
|
13
13
|
const actions = resolve()
|
|
14
14
|
expect(actions.basic.jump.value).is(1)
|
|
15
15
|
expect(actions.basic.shoot.value).is(0)
|
|
16
16
|
}
|
|
17
17
|
{
|
|
18
|
-
|
|
18
|
+
clock.frame = 2
|
|
19
19
|
device.setSample("Space", 2)
|
|
20
20
|
device.setSample("pointer.button.left", 3)
|
|
21
21
|
const actions = resolve()
|
|
@@ -24,97 +24,128 @@ export default Science.suite({
|
|
|
24
24
|
}
|
|
25
25
|
}),
|
|
26
26
|
|
|
27
|
-
"hold timing": test(async() => {
|
|
28
|
-
const {
|
|
29
|
-
{
|
|
30
|
-
time
|
|
31
|
-
device.setSample("KeyG",
|
|
32
|
-
|
|
33
|
-
expect(actions.basic.grenade.value).is(0)
|
|
34
|
-
}
|
|
35
|
-
{
|
|
36
|
-
time.frame = 2
|
|
37
|
-
device.setSample("KeyG", 1)
|
|
38
|
-
const actions = resolve()
|
|
39
|
-
expect(actions.basic.grenade.value).is(0)
|
|
40
|
-
}
|
|
41
|
-
{
|
|
42
|
-
time.frame = 15
|
|
43
|
-
device.setSample("KeyG", 1)
|
|
44
|
-
const actions = resolve()
|
|
45
|
-
expect(actions.basic.grenade.value).is(1)
|
|
27
|
+
"hold timing and behavior": test(async() => {
|
|
28
|
+
const {clock, device, resolve, actions} = testSetupAlpha()
|
|
29
|
+
const proceed = (options: {time: number, value: number}) => {
|
|
30
|
+
clock.time = options.time
|
|
31
|
+
device.setSample("KeyG", options.value)
|
|
32
|
+
resolve()
|
|
46
33
|
}
|
|
34
|
+
|
|
35
|
+
let count = 0
|
|
36
|
+
actions.basic.grenade.onDown(() => { count++ })
|
|
37
|
+
const getValue = () => actions.basic.grenade.value
|
|
38
|
+
|
|
39
|
+
// start doing nothing
|
|
40
|
+
proceed({time: 0, value: 0})
|
|
41
|
+
expect(getValue()).is(0)
|
|
42
|
+
expect(count).is(0)
|
|
43
|
+
|
|
44
|
+
// start holding
|
|
45
|
+
proceed({time: 10, value: 1})
|
|
46
|
+
expect(getValue()).is(0)
|
|
47
|
+
expect(count).is(0)
|
|
48
|
+
|
|
49
|
+
// keep holding
|
|
50
|
+
proceed({time: 20, value: 1})
|
|
51
|
+
expect(getValue()).is(0)
|
|
52
|
+
expect(count).is(0)
|
|
53
|
+
|
|
54
|
+
// held long enough to trigger down
|
|
55
|
+
proceed({time: 210, value: 1})
|
|
56
|
+
expect(getValue()).is(1)
|
|
57
|
+
expect(count).is(1)
|
|
58
|
+
|
|
59
|
+
// release, shouldn't trigger new down
|
|
60
|
+
proceed({time: 220, value: 0})
|
|
61
|
+
expect(getValue()).is(0)
|
|
62
|
+
expect(count).is(1)
|
|
63
|
+
|
|
64
|
+
// start holding again
|
|
65
|
+
proceed({time: 230, value: 1})
|
|
66
|
+
expect(getValue()).is(0)
|
|
67
|
+
expect(count).is(1)
|
|
68
|
+
|
|
69
|
+
// keep holding again
|
|
70
|
+
proceed({time: 330, value: 1})
|
|
71
|
+
expect(getValue()).is(0)
|
|
72
|
+
expect(count).is(1)
|
|
73
|
+
|
|
74
|
+
// held long enough again to trigger down
|
|
75
|
+
proceed({time: 430, value: 1})
|
|
76
|
+
expect(getValue()).is(1)
|
|
77
|
+
expect(count).is(2)
|
|
47
78
|
}),
|
|
48
79
|
|
|
49
80
|
"hub": Science.suite({
|
|
50
81
|
"device inputs work": test(async() => {
|
|
51
|
-
const {hub,
|
|
82
|
+
const {hub, clock} = testSetupBravo()
|
|
52
83
|
const d1 = testPlug(hub, new SamplerDevice())
|
|
53
84
|
d1.setSample("Space", 1)
|
|
54
|
-
const [p1, p2] = hub.poll(time
|
|
85
|
+
const [p1, p2] = hub.poll(clock.time)
|
|
55
86
|
expect(p1.actions.basic.jump.value).is(1)
|
|
56
87
|
expect(p2.actions.basic.jump.value).is(0)
|
|
57
88
|
}),
|
|
58
89
|
|
|
59
90
|
"reveal overlay works": test(async() => {
|
|
60
|
-
const {hub,
|
|
91
|
+
const {hub, clock} = testSetupBravo()
|
|
61
92
|
const d1 = testPlug(hub, new SamplerDevice())
|
|
62
93
|
d1.setSample("Backslash", 1)
|
|
63
|
-
hub.poll(time
|
|
94
|
+
hub.poll(clock.time)
|
|
64
95
|
expect(hub.metaPort.actions[metaMode].revealOverlay.value)
|
|
65
96
|
.is(1)
|
|
66
97
|
}),
|
|
67
98
|
|
|
68
99
|
"two devices playing on separate ports": test(async() => {
|
|
69
|
-
const {hub,
|
|
100
|
+
const {hub, clock} = testSetupBravo()
|
|
70
101
|
const c1 = testPlug(hub, new SamplerDevice())
|
|
71
102
|
const c2 = testPlug(hub, new SamplerDevice())
|
|
72
103
|
c1.setSample("Space", 1)
|
|
73
104
|
c2.setSample("Space", 2)
|
|
74
|
-
const [p1, p2] = hub.poll(time
|
|
105
|
+
const [p1, p2] = hub.poll(clock.time)
|
|
75
106
|
expect(p1.actions.basic.jump.value).is(1)
|
|
76
107
|
expect(p2.actions.basic.jump.value).is(2)
|
|
77
108
|
}),
|
|
78
109
|
|
|
79
110
|
"device can shimmy": test(async() => {
|
|
80
|
-
const {hub,
|
|
111
|
+
const {hub, clock} = testSetupBravo()
|
|
81
112
|
const c1 = testPlug(hub, new SamplerDevice())
|
|
82
113
|
hub.shimmy(c1, 1)
|
|
83
114
|
c1.setSample("Space", 1)
|
|
84
|
-
const [p1, p2] = hub.poll(time
|
|
115
|
+
const [p1, p2] = hub.poll(clock.time)
|
|
85
116
|
expect(p1.actions.basic.jump.value).is(0)
|
|
86
117
|
expect(p2.actions.basic.jump.value).is(1)
|
|
87
118
|
}),
|
|
88
119
|
|
|
89
120
|
"two devices can share a port": test(async() => {
|
|
90
|
-
const {hub,
|
|
121
|
+
const {hub, clock} = testSetupBravo()
|
|
91
122
|
const c1 = testPlug(hub, new SamplerDevice())
|
|
92
123
|
const c2 = testPlug(hub, new SamplerDevice())
|
|
93
124
|
hub.shimmy(c2, -1)
|
|
94
125
|
expect(hub.portByDevice(c1)).is(hub.portByDevice(c2))
|
|
95
126
|
{
|
|
96
127
|
c1.setSample("Space", 1)
|
|
97
|
-
const [p1, p2] = hub.poll(time
|
|
128
|
+
const [p1, p2] = hub.poll(clock.time)
|
|
98
129
|
expect(p1.actions.basic.jump.value).is(1)
|
|
99
130
|
expect(p2.actions.basic.jump.value).is(0)
|
|
100
131
|
}
|
|
101
132
|
{
|
|
102
133
|
c2.setSample("Space", 1)
|
|
103
|
-
const [p1, p2] = hub.poll(time
|
|
134
|
+
const [p1, p2] = hub.poll(clock.time)
|
|
104
135
|
expect(p1.actions.basic.jump.value).is(1)
|
|
105
136
|
expect(p2.actions.basic.jump.value).is(0)
|
|
106
137
|
}
|
|
107
138
|
{
|
|
108
139
|
c1.setSample("Space", 1)
|
|
109
140
|
c2.setSample("Space", 2)
|
|
110
|
-
const [p1, p2] = hub.poll(time
|
|
141
|
+
const [p1, p2] = hub.poll(clock.time)
|
|
111
142
|
expect(p1.actions.basic.jump.value).is(2)
|
|
112
143
|
expect(p2.actions.basic.jump.value).is(0)
|
|
113
144
|
}
|
|
114
145
|
{
|
|
115
146
|
c1.setSample("Space", 2)
|
|
116
147
|
c2.setSample("Space", 1)
|
|
117
|
-
const [p1, p2] = hub.poll(time
|
|
148
|
+
const [p1, p2] = hub.poll(clock.time)
|
|
118
149
|
expect(p1.actions.basic.jump.value).is(2)
|
|
119
150
|
expect(p2.actions.basic.jump.value).is(0)
|
|
120
151
|
}
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
import {Hub} from "../hub/hub.js"
|
|
3
3
|
import {Port} from "../hub/port.js"
|
|
4
4
|
import {Device} from "../devices/device.js"
|
|
5
|
-
import {asBindings, Code} from "../bindings/types.js"
|
|
6
5
|
import {Resolver} from "../bindings/resolver.js"
|
|
7
6
|
import {SampleMap} from "../bindings/sample-map.js"
|
|
7
|
+
import {asBindings, Code} from "../bindings/types.js"
|
|
8
8
|
import {SamplerDevice} from "../devices/infra/sampler.js"
|
|
9
9
|
|
|
10
|
-
export class
|
|
11
|
-
|
|
10
|
+
export class TestClock {
|
|
11
|
+
time = 0
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
set frame(frame: number) {
|
|
14
|
+
this.time = frame * (1000 / 60)
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -31,26 +31,27 @@ export function testPlug<C extends Device>(hub: Hub<any>, device: C) {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
export function testSetupAlpha() {
|
|
34
|
-
const
|
|
34
|
+
const clock = new TestClock()
|
|
35
35
|
const device = new SamplerDevice()
|
|
36
36
|
const resolver = new Resolver(testBindings())
|
|
37
37
|
const modes = new Set(Object.keys(resolver.bindings))
|
|
38
|
+
const actions = resolver.actions
|
|
38
39
|
const resolve = () => resolver.resolve(
|
|
39
|
-
time
|
|
40
|
+
clock.time,
|
|
40
41
|
modes as any,
|
|
41
42
|
new SampleMap(device.samples())
|
|
42
43
|
)
|
|
43
|
-
return {device, resolver, resolve,
|
|
44
|
+
return {device, resolver, resolve, clock, actions}
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
export function testSetupBravo() {
|
|
47
|
-
const
|
|
48
|
+
const clock = new TestClock()
|
|
48
49
|
const port = () => {
|
|
49
50
|
const port = new Port(testBindings())
|
|
50
51
|
port.modes.adds("basic")
|
|
51
52
|
return port
|
|
52
53
|
}
|
|
53
54
|
const hub = new Hub([port(), port(), port(), port()])
|
|
54
|
-
return {hub,
|
|
55
|
+
return {hub, clock}
|
|
55
56
|
}
|
|
56
57
|
|
package/s/deck/deck.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
import {Kv} from "@e280/kv"
|
|
3
|
-
import {
|
|
4
|
-
import {disposer, ob, range} from "@e280/stz"
|
|
3
|
+
import {disposer, range} from "@e280/stz"
|
|
5
4
|
|
|
6
5
|
import {Db} from "./parts/db.js"
|
|
7
6
|
import {Hub} from "../core/hub/hub.js"
|
|
@@ -13,7 +12,6 @@ import {makeMetaBindings} from "../core/hub/meta-bindings.js"
|
|
|
13
12
|
import {DeviceSkins} from "./parts/device-skins/device-skin.js"
|
|
14
13
|
import {OverlayVisibility} from "./parts/overlay-visibility.js"
|
|
15
14
|
import {PrimaryDevice} from "../core/devices/standard/primary.js"
|
|
16
|
-
import {deckComponents, DeckViews} from "./components/components.js"
|
|
17
15
|
|
|
18
16
|
export type DeckOptions<B extends Bindings, MB extends MetaBindings = any> = {
|
|
19
17
|
kv: Kv
|
|
@@ -46,17 +44,6 @@ export class Deck<B extends Bindings, MB extends MetaBindings = any> {
|
|
|
46
44
|
primaryDevice = new PrimaryDevice()
|
|
47
45
|
overlayVisibility: OverlayVisibility
|
|
48
46
|
|
|
49
|
-
components = deckComponents(this)
|
|
50
|
-
|
|
51
|
-
views = (
|
|
52
|
-
ob(this.components as any)
|
|
53
|
-
.map(c => (...a: any[]) => c.view(this, ...a))
|
|
54
|
-
) as DeckViews
|
|
55
|
-
|
|
56
|
-
registerComponents() {
|
|
57
|
-
dom.register(this.components)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
47
|
constructor(
|
|
61
48
|
public baseBindings: B,
|
|
62
49
|
public baseMetaBindings: MB,
|
package/s/deck/index.ts
CHANGED
|
@@ -7,8 +7,7 @@ export * from "./parts/local-storage-kv.js"
|
|
|
7
7
|
export * from "./parts/merge-bindings.js"
|
|
8
8
|
export * from "./parts/overlay-visibility.js"
|
|
9
9
|
|
|
10
|
-
export * from "./
|
|
11
|
-
export * from "./components/deck-overlay/style.css.js"
|
|
10
|
+
export * from "./views/overlay/view.js"
|
|
12
11
|
|
|
13
12
|
export * from "./deck.js"
|
|
14
13
|
|
package/s/deck/parts/db.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
import {disposer, Hex} from "@e280/stz"
|
|
3
|
-
import {signal,
|
|
3
|
+
import {signal, Signal} from "@e280/strata"
|
|
4
4
|
import {StorageDriver, Store} from "@e280/kv"
|
|
5
5
|
|
|
6
6
|
import {Bindings} from "../../core/bindings/types.js"
|
|
@@ -16,7 +16,7 @@ export class Db {
|
|
|
16
16
|
|
|
17
17
|
constructor(
|
|
18
18
|
private store: Store<CatalogData>,
|
|
19
|
-
public $catalog:
|
|
19
|
+
public $catalog: Signal<Catalog>,
|
|
20
20
|
) {
|
|
21
21
|
|
|
22
22
|
this.dispose.schedule(
|
|
@@ -63,4 +63,3 @@ export class Db {
|
|
|
63
63
|
})
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
|
-
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
|
|
2
|
+
import {html} from "lit"
|
|
3
|
+
import {bytename} from "@e280/stz"
|
|
4
|
+
import {cssReset, shadow, useCss, useName, useSignal} from "@e280/sly"
|
|
5
|
+
|
|
6
|
+
import {Deck} from "../../deck.js"
|
|
7
|
+
import styleCss from "./style.css.js"
|
|
8
|
+
import {Port} from "../../../core/hub/port.js"
|
|
9
|
+
import {Profile} from "../../parts/catalog.js"
|
|
10
|
+
import {Atom, Bindings, Bracket} from "../../../core/bindings/types.js"
|
|
11
|
+
|
|
12
|
+
export const DeckBindings = shadow((deck: Deck<any>) => {
|
|
13
|
+
useCss(cssReset, styleCss)
|
|
14
|
+
useName("deck-bindings")
|
|
15
|
+
const {db, hub} = deck
|
|
16
|
+
|
|
17
|
+
const catalog = db.$catalog()
|
|
18
|
+
const defaultProfile: Profile = {id: "default", label: "default", bindings: deck.baseBindings}
|
|
19
|
+
const allProfiles = [defaultProfile, ...catalog.profiles.values()]
|
|
20
|
+
const $selectedProfileId = useSignal("default")
|
|
21
|
+
const profile = db.$catalog().getProfile($selectedProfileId()) ?? defaultProfile
|
|
22
|
+
|
|
23
|
+
function renderPort(_port: Port<Bindings>, index: number) {
|
|
24
|
+
const portProfile = catalog.getProfileForPort(index) ?? defaultProfile
|
|
25
|
+
return html`
|
|
26
|
+
<div class=port>
|
|
27
|
+
<span>port ${index + 1}</span>
|
|
28
|
+
<select>
|
|
29
|
+
${allProfiles.map(profile => html`
|
|
30
|
+
<option
|
|
31
|
+
data-id="${profile.id}"
|
|
32
|
+
?selected="${profile.id === portProfile.id}">
|
|
33
|
+
${profile.label}
|
|
34
|
+
</option>
|
|
35
|
+
`)}
|
|
36
|
+
</select>
|
|
37
|
+
</div>
|
|
38
|
+
`
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function renderBindingBracket(entry: [string, unknown]) {
|
|
42
|
+
const [mode, bracket] = entry as [string, Bracket]
|
|
43
|
+
return html`
|
|
44
|
+
<div class=bracket>
|
|
45
|
+
<strong class=mode>${mode}</strong>
|
|
46
|
+
<div>${Object.entries(bracket).map(renderBinds)}</div>
|
|
47
|
+
</div>
|
|
48
|
+
`
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function renderBinds([action, _atom]: [action: string, atom: Atom]) {
|
|
52
|
+
return html`
|
|
53
|
+
<div class=bind>
|
|
54
|
+
<span class=action>${action}</span>
|
|
55
|
+
</div>
|
|
56
|
+
`
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const clickClone = async() => {
|
|
60
|
+
const {bindings} = profile
|
|
61
|
+
const label = bytename.random(4)
|
|
62
|
+
const p = await db.createProfile(label, bindings)
|
|
63
|
+
$selectedProfileId(p.id)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const deleteProfile = (id: string) => async() => {
|
|
67
|
+
await db.deleteProfile(id)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const onSelected = (event: InputEvent) => {
|
|
71
|
+
const select = event.target as HTMLSelectElement
|
|
72
|
+
const id = select.value
|
|
73
|
+
$selectedProfileId(id)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return html`
|
|
77
|
+
<div class=portlist>
|
|
78
|
+
${hub.ports.map(renderPort)}
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
<div class=bindable>
|
|
82
|
+
<select @input="${onSelected}">
|
|
83
|
+
${allProfiles.map(p => html`
|
|
84
|
+
<option value="${p.id}" ?selected="${p.id === profile.id}">${p.label}</option>
|
|
85
|
+
`)}
|
|
86
|
+
</select>
|
|
87
|
+
<button @click="${clickClone}">clone</button>
|
|
88
|
+
<button ?disabled="${profile.id === defaultProfile.id}" @click="${deleteProfile(profile.id)}">delete</button>
|
|
89
|
+
<div class=bindings>
|
|
90
|
+
${Object.entries(profile.bindings).map(renderBindingBracket)}
|
|
91
|
+
</div>
|
|
92
|
+
</div>
|
|
93
|
+
`
|
|
94
|
+
})
|
|
95
|
+
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
|
|
2
|
+
import {html} from "lit"
|
|
3
|
+
import {cssReset, shadow, useCss, useName} from "@e280/sly"
|
|
4
|
+
import {Deck} from "../../deck.js"
|
|
5
|
+
import styleCss from "./style.css.js"
|
|
6
|
+
import {Device} from "../../../core/devices/device.js"
|
|
7
|
+
|
|
8
|
+
export const DeckOverlay = shadow((deck: Deck<any>) => {
|
|
9
|
+
useCss(cssReset, styleCss)
|
|
10
|
+
useName("deck-overlay")
|
|
11
|
+
const {hub, deviceSkins, overlayVisibility: {$visible, $showLabels}} = deck
|
|
12
|
+
|
|
13
|
+
function renderDevice(device: Device) {
|
|
14
|
+
const skin = deviceSkins.get(device)
|
|
15
|
+
const style = `--color: ${skin.color};`
|
|
16
|
+
const next = () => hub.shimmy(device, 1)
|
|
17
|
+
const previous = () => hub.shimmy(device, -1)
|
|
18
|
+
return html`
|
|
19
|
+
<div class=device style="${style}">
|
|
20
|
+
<div class="primary row">
|
|
21
|
+
<button @click="${previous}"><</button>
|
|
22
|
+
<div class=icon>${skin.icon}</div>
|
|
23
|
+
<button @click="${next}">></button>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
${$showLabels() ? html`
|
|
27
|
+
<div class="secondary row">
|
|
28
|
+
<div class=label>${skin.label}</div>
|
|
29
|
+
</div>
|
|
30
|
+
` : null}
|
|
31
|
+
</div>
|
|
32
|
+
`
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return html`
|
|
36
|
+
<div class=portlist ?data-active="${$visible()}">
|
|
37
|
+
${hub.ports.map((port, index) => html`
|
|
38
|
+
<div class=port>
|
|
39
|
+
<header>P${index + 1}</header>
|
|
40
|
+
${port.devices.array().map(renderDevice)}
|
|
41
|
+
</div>
|
|
42
|
+
`)}
|
|
43
|
+
</div>
|
|
44
|
+
`
|
|
45
|
+
})
|
|
46
|
+
|
|
@@ -22,16 +22,16 @@ export class Renderer {
|
|
|
22
22
|
|
|
23
23
|
/** take a game-state position and resolve it into canvas coordinates */
|
|
24
24
|
resolve(position: Vec2) {
|
|
25
|
-
return position.
|
|
25
|
+
return position.dup()
|
|
26
26
|
|
|
27
27
|
// 0-1 relative to arena scale
|
|
28
|
-
.
|
|
28
|
+
.div(this.state.arenaSize)
|
|
29
29
|
|
|
30
30
|
// flip y axis
|
|
31
|
-
.morph(v => {v.y = 1 - v.y})
|
|
31
|
+
.morph((v: Vec2) => {v.y = 1 - v.y})
|
|
32
32
|
|
|
33
33
|
// stretch to the size of the canvas
|
|
34
|
-
.
|
|
34
|
+
.mul_(this.canvas.width, this.canvas.height)
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
render() {
|
|
@@ -110,4 +110,3 @@ export class Renderer {
|
|
|
110
110
|
ctx.fillText(agent.label, x, y)
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
|
-
|
package/s/demo/main.bundle.ts
CHANGED