@umicat/three-sdk 0.8.2 → 0.8.3

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/dist/Input3D.d.ts CHANGED
@@ -84,6 +84,7 @@ export declare class Input3D {
84
84
  private wantLook;
85
85
  private lookSens;
86
86
  private readonly lookDelta;
87
+ private enabled;
87
88
  private readonly touchHeld;
88
89
  private readonly pressedAt;
89
90
  private readonly unconsumed;
@@ -91,6 +92,21 @@ export declare class Input3D {
91
92
  private readonly cleanups;
92
93
  constructor(options?: Input3DOptions | Window);
93
94
  isDown(...codes: string[]): boolean;
95
+ /**
96
+ * Stop accepting input, and take the on-screen controls off the screen.
97
+ *
98
+ * For the moment a game puts a modal up — a game-over screen, a shop, a
99
+ * dialogue box. Two things go wrong otherwise, and the second is worse: the
100
+ * character keeps walking behind the dialog, and the controls' full-screen
101
+ * layer sits ABOVE the game's own DOM at z-index 10, so the button in that
102
+ * modal cannot be tapped at all. "Play Again" that does nothing is this bug.
103
+ *
104
+ * Disabling clears what was held, so a thumb that was pushing the stick when
105
+ * the modal opened does not resume walking when it closes.
106
+ */
107
+ setEnabled(on: boolean): void;
108
+ /** Whether input is currently being accepted. */
109
+ get isEnabled(): boolean;
94
110
  /**
95
111
  * Which way to walk. Keyboard and stick are merged, so both work on a device
96
112
  * with both.
package/dist/Input3D.js CHANGED
@@ -71,6 +71,7 @@ export class Input3D {
71
71
  this.wantLook = true;
72
72
  this.lookSens = 4.6;
73
73
  this.lookDelta = { x: 0, y: 0 };
74
+ this.enabled = true;
74
75
  this.touchHeld = new Set();
75
76
  this.pressedAt = new Map();
76
77
  this.unconsumed = new Set();
@@ -96,7 +97,43 @@ export class Input3D {
96
97
  this.mountTouch(opts.container ?? document.body);
97
98
  }
98
99
  }
99
- isDown(...codes) { return codes.some((c) => this.keysDown.has(c)); }
100
+ isDown(...codes) {
101
+ return this.enabled && codes.some((c) => this.keysDown.has(c));
102
+ }
103
+ /**
104
+ * Stop accepting input, and take the on-screen controls off the screen.
105
+ *
106
+ * For the moment a game puts a modal up — a game-over screen, a shop, a
107
+ * dialogue box. Two things go wrong otherwise, and the second is worse: the
108
+ * character keeps walking behind the dialog, and the controls' full-screen
109
+ * layer sits ABOVE the game's own DOM at z-index 10, so the button in that
110
+ * modal cannot be tapped at all. "Play Again" that does nothing is this bug.
111
+ *
112
+ * Disabling clears what was held, so a thumb that was pushing the stick when
113
+ * the modal opened does not resume walking when it closes.
114
+ */
115
+ setEnabled(on) {
116
+ this.enabled = on;
117
+ if (!on) {
118
+ this.keysDown.clear();
119
+ this.touchHeld.clear();
120
+ this.pressedAt.clear();
121
+ this.unconsumed.clear();
122
+ this.stick.x = 0;
123
+ this.stick.z = 0;
124
+ this.touchJump = false;
125
+ this.lookDelta.x = 0;
126
+ this.lookDelta.y = 0;
127
+ }
128
+ if (this.root) {
129
+ this.root.style.display = on ? '' : 'none';
130
+ // display:none alone would be enough for hit-testing, but a game that
131
+ // fades its modal in wants the controls gone, not just inert.
132
+ this.root.style.pointerEvents = 'none';
133
+ }
134
+ }
135
+ /** Whether input is currently being accepted. */
136
+ get isEnabled() { return this.enabled; }
100
137
  /**
101
138
  * Which way to walk. Keyboard and stick are merged, so both work on a device
102
139
  * with both.
@@ -109,6 +146,8 @@ export class Input3D {
109
146
  * behaviour, which is correct for a camera that never moves.
110
147
  */
111
148
  direction(cameraYaw = 0) {
149
+ if (!this.enabled)
150
+ return { x: 0, z: 0 };
112
151
  let x = this.stick.x, z = this.stick.z;
113
152
  if (this.isDown('KeyW', 'ArrowUp'))
114
153
  z -= 1;
@@ -131,9 +170,13 @@ export class Input3D {
131
170
  }
132
171
  /** Whether the jump control is held right now. Pass it to the controller —
133
172
  * coyote time and buffering live there, not here. */
134
- get jump() { return this.held_('jump', this.touchJump || this.isDown('Space')); }
173
+ get jump() {
174
+ return this.enabled && this.held_('jump', this.touchJump || this.isDown('Space'));
175
+ }
135
176
  /** Whether an action is held right now — button or bound key, same answer. */
136
177
  held(id) {
178
+ if (!this.enabled)
179
+ return false;
137
180
  const a = this.actions.find((x) => x.id === id);
138
181
  return this.held_(id, this.touchHeld.has(id) || (a?.keys ? this.isDown(...a.keys) : false));
139
182
  }
@@ -146,6 +189,8 @@ export class Input3D {
146
189
  * it twice must not apply it twice. Pass straight to `LoadedScene3D.orbit`.
147
190
  */
148
191
  look() {
192
+ if (!this.enabled)
193
+ return { x: 0, y: 0 };
149
194
  const out = { x: this.lookDelta.x, y: this.lookDelta.y };
150
195
  this.lookDelta.x = 0;
151
196
  this.lookDelta.y = 0;
@@ -157,7 +202,7 @@ export class Input3D {
157
202
  * to last frame's, which means a press that begins and ends between two
158
203
  * frames never happened. This latches at the event, so it cannot be missed
159
204
  * — and it clears on read, so holding the button does not chain. */
160
- consume(id) { return this.unconsumed.delete(id); }
205
+ consume(id) { return this.enabled && this.unconsumed.delete(id); }
161
206
  held_(id, physical) {
162
207
  if (physical)
163
208
  return true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umicat/three-sdk",
3
- "version": "0.8.2",
3
+ "version": "0.8.3",
4
4
  "description": "Three.js runtime for Umicat games: the scene3d design format, its loader with physics, a kinematic character controller, and the Umicat platform via @umicat/platform-sdk.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",