@typeonce/ritmo-browser 0.10.0 → 0.11.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.
Files changed (58) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/README.md +6 -1
  3. package/dist/Controls.d.ts +495 -0
  4. package/dist/Controls.d.ts.map +1 -0
  5. package/dist/Controls.js +343 -0
  6. package/dist/Controls.js.map +1 -0
  7. package/dist/Gamepad.d.ts +375 -0
  8. package/dist/Gamepad.d.ts.map +1 -0
  9. package/dist/Gamepad.js +452 -0
  10. package/dist/Gamepad.js.map +1 -0
  11. package/dist/InputCapture.d.ts +46 -16
  12. package/dist/InputCapture.d.ts.map +1 -1
  13. package/dist/InputCapture.js +1 -1
  14. package/dist/InputCapture.js.map +1 -1
  15. package/dist/Keyboard.d.ts +184 -21
  16. package/dist/Keyboard.d.ts.map +1 -1
  17. package/dist/Keyboard.js +257 -91
  18. package/dist/Keyboard.js.map +1 -1
  19. package/dist/Pointer.d.ts +231 -62
  20. package/dist/Pointer.d.ts.map +1 -1
  21. package/dist/Pointer.js +205 -145
  22. package/dist/Pointer.js.map +1 -1
  23. package/dist/Touch.d.ts +73 -27
  24. package/dist/Touch.d.ts.map +1 -1
  25. package/dist/Touch.js +25 -30
  26. package/dist/Touch.js.map +1 -1
  27. package/dist/index.d.ts +10 -1
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +10 -1
  30. package/dist/index.js.map +1 -1
  31. package/dist/internal/buttons.d.ts +52 -0
  32. package/dist/internal/buttons.d.ts.map +1 -0
  33. package/dist/internal/buttons.js +211 -0
  34. package/dist/internal/buttons.js.map +1 -0
  35. package/dist/internal/introspect.d.ts +14 -0
  36. package/dist/internal/introspect.d.ts.map +1 -0
  37. package/dist/internal/introspect.js +19 -0
  38. package/dist/internal/introspect.js.map +1 -0
  39. package/dist/internal/used.d.ts +8 -0
  40. package/dist/internal/used.d.ts.map +1 -0
  41. package/dist/internal/used.js +14 -0
  42. package/dist/internal/used.js.map +1 -0
  43. package/dist/internal/vectors.d.ts +24 -0
  44. package/dist/internal/vectors.d.ts.map +1 -0
  45. package/dist/internal/vectors.js +22 -0
  46. package/dist/internal/vectors.js.map +1 -0
  47. package/package.json +4 -3
  48. package/src/Controls.ts +799 -0
  49. package/src/Gamepad.ts +747 -0
  50. package/src/InputCapture.ts +43 -24
  51. package/src/Keyboard.ts +395 -68
  52. package/src/Pointer.ts +392 -164
  53. package/src/Touch.ts +111 -54
  54. package/src/index.ts +10 -1
  55. package/src/internal/buttons.ts +222 -0
  56. package/src/internal/introspect.ts +23 -0
  57. package/src/internal/used.ts +14 -0
  58. package/src/internal/vectors.ts +36 -0
@@ -8,12 +8,22 @@
8
8
  * every system in that run reads the same snapshot and press edges are
9
9
  * observed exactly once per run.
10
10
  *
11
- * The source is any service with `snapshot()`: `Keyboard.actions(...)`
12
- * directly, or a game-specific adapter that merges several devices. The
13
- * resource's value type must be exactly the snapshot type.
11
+ * The source is any service with `snapshot()`: one device such as
12
+ * `Keyboard.actions(...)`, a `Controls` merge of several, or a
13
+ * `Controls.players(...)` pool. The resource's
14
+ * value type must be exactly the snapshot type (declare it as
15
+ * `InputCapture.SnapshotOf<typeof Source>`): not a wider type, and not one
16
+ * with extra optional fields.
14
17
  *
15
- * Its spec is erased, so it does not count as a writer of the resource for
16
- * `Game.System.thisTick(...)` order checks: place it first yourself.
18
+ * The system declares its access like any other: it writes the resource, so
19
+ * a reader declared with `Game.System.thisTick(...)` placed before it does
20
+ * not compile, and it consumes the source (`Game.System.consumeService`), so
21
+ * `describe()` warns with `service-consumed-twice` when one source is
22
+ * captured at more than one placement (in named schedules, or wherever a
23
+ * debug runtime saw it run). Every input source marks `snapshot()` with
24
+ * `System.Consumes`, so another system that declares the source with
25
+ * `Game.System.service` (to rebind it, say) cannot call `snapshot()`.
26
+ * Capture each source once and read the resource everywhere else.
17
27
  *
18
28
  * @module InputCapture
19
29
  * @docGroup browser
@@ -34,14 +44,17 @@
34
44
  * }).value
35
45
  * ```
36
46
  */
47
+ import type * as System from "@typeonce/ritmo/System"
37
48
  import type { Descriptor } from "@typeonce/ritmo/Descriptor"
38
- import type { Condition, ConditionNeedsFromConditions } from "@typeonce/ritmo/Machine"
49
+ import type { Condition } from "@typeonce/ritmo/Machine"
39
50
  import type { Schema } from "@typeonce/ritmo/Schema"
40
51
 
41
52
  /**
42
- * Anything that produces one input snapshot per call.
53
+ * Anything that produces one input snapshot per call. `snapshot()` drains
54
+ * the source, so only a system that declares it with
55
+ * `Game.System.consumeService` (like `InputCapture.system`) calls it.
43
56
  */
44
- export interface Source<Value> {
57
+ export interface Source<Value> extends System.Consumes<"snapshot"> {
45
58
  readonly snapshot: () => Value
46
59
  }
47
60
 
@@ -55,18 +68,29 @@ type ResourceDescriptor = Descriptor<"resource", string, any>
55
68
  export type SnapshotOf<Service extends ServiceDescriptor> =
56
69
  Descriptor.Value<Service> extends Source<infer Value> ? Value : never
57
70
 
71
+ /** Whether `A` and `B` are the same type, not merely assignable both ways. */
72
+ type Same<A, B> = (<T>() => T extends A ? 1 : 2) extends (<T>() => T extends B ? 1 : 2) ? true : false
73
+
74
+ /** The resource when its value type is exactly the source's snapshot type, otherwise an error naming the fix. */
75
+ type MatchingResource<Resource extends ResourceDescriptor, Service extends ServiceDescriptor> =
76
+ Same<Descriptor.Value<Resource>, SnapshotOf<Service>> extends true
77
+ ? Resource
78
+ : "The resource's value type must be exactly the source's snapshot type: declare it with InputCapture.SnapshotOf<typeof Source>"
79
+
80
+ /** Options for {@link system}. */
58
81
  export interface Options<
59
82
  S extends Schema.Any,
60
83
  Service extends ServiceDescriptor,
61
84
  Resource extends Schema.ResourceDescriptor<S>,
62
- When extends ReadonlyArray<Condition> = readonly []
85
+ When extends ReadonlyArray<Condition> = readonly [],
86
+ Name extends string = string
63
87
  > {
64
88
  /** The system name. */
65
- readonly name: string
89
+ readonly name: Name
66
90
  /** The service to read snapshots from; its value must have `snapshot()`. */
67
91
  readonly source: Descriptor.Value<Service> extends Source<any> ? Service : "The source service must provide snapshot()"
68
92
  /** The resource to write each snapshot into; its value type must be exactly the snapshot type. */
69
- readonly resource: Resource & Descriptor<"resource", string, SnapshotOf<Service>>
93
+ readonly resource: MatchingResource<Resource, Service>
70
94
  /**
71
95
  * Run conditions, like a system's `when`. While they fail, snapshots are
72
96
  * not taken, so presses stay in the device until capture resumes (for
@@ -75,12 +99,6 @@ export interface Options<
75
99
  readonly when?: When
76
100
  }
77
101
 
78
- /**
79
- * The generated system. It requires the source service and the resource.
80
- */
81
- export type CaptureSystem<S extends Schema.Any, Root, Needs extends ServiceDescriptor | ResourceDescriptor | ConditionNeedsFromConditions<ReadonlyArray<Condition>>> =
82
- Schema.BoundSystem<S, Root, any, never, string, Needs>
83
-
84
102
  /**
85
103
  * Builds the system that writes `source.snapshot()` into `resource`.
86
104
  */
@@ -89,15 +107,16 @@ export const system = <
89
107
  Root,
90
108
  const Service extends ServiceDescriptor,
91
109
  const Resource extends Schema.ResourceDescriptor<S>,
92
- const When extends ReadonlyArray<Condition<Root>> = readonly []
110
+ const When extends ReadonlyArray<Condition<Root>> = readonly [],
111
+ const Name extends string = string
93
112
  >(
94
113
  Game: Schema.Game<S, Root>,
95
- options: Options<S, Service, Resource, When>
96
- ): CaptureSystem<S, Root, Service | Resource | ConditionNeedsFromConditions<When>> =>
114
+ options: Options<S, Service, Resource, When, Name>
115
+ ) =>
97
116
  Game.System(options.name, {
98
- resources: { input: Game.System.writeResource(options.resource) },
99
- services: { source: Game.System.service(options.source as Service) },
100
- when: (options.when ?? []) as ReadonlyArray<Condition<Root>>
117
+ resources: { input: Game.System.writeResource(options.resource as Resource) },
118
+ services: { source: Game.System.consumeService(options.source as Service) },
119
+ when: (options.when ?? []) as When
101
120
  }, ({ resources, services }) => {
102
121
  resources.input.set(services.source.snapshot() as never)
103
- }) as unknown as CaptureSystem<S, Root, Service | Resource | ConditionNeedsFromConditions<When>>
122
+ })