@umicat/three-sdk 0.7.0 → 0.7.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/dist/Input3D.js +55 -1
- package/package.json +1 -1
package/dist/Input3D.js
CHANGED
|
@@ -6,6 +6,21 @@
|
|
|
6
6
|
* and makes a quick tap always count. */
|
|
7
7
|
const MIN_PRESS_MS = 80;
|
|
8
8
|
const now = () => (typeof performance !== 'undefined' ? performance.now() : Date.now());
|
|
9
|
+
/**
|
|
10
|
+
* Everything needed to stop a long press from being read as "select this text".
|
|
11
|
+
*
|
|
12
|
+
* A thumbstick REQUIRES holding still, which is exactly the gesture iOS uses to
|
|
13
|
+
* start a selection — so on a phone the Copy / Look Up / Translate callout came
|
|
14
|
+
* up over the game the first time anyone tried to walk. `user-select` alone is
|
|
15
|
+
* not enough: `-webkit-touch-callout` is a separate switch, and neither is
|
|
16
|
+
* implied by `touch-action: none`.
|
|
17
|
+
*/
|
|
18
|
+
const NO_SELECTION = {
|
|
19
|
+
userSelect: 'none',
|
|
20
|
+
WebkitUserSelect: 'none',
|
|
21
|
+
WebkitTouchCallout: 'none',
|
|
22
|
+
WebkitTapHighlightColor: 'transparent',
|
|
23
|
+
};
|
|
9
24
|
const isTouchDevice = () => typeof matchMedia === 'function' &&
|
|
10
25
|
matchMedia('(pointer: coarse)').matches &&
|
|
11
26
|
!matchMedia('(pointer: fine)').matches;
|
|
@@ -155,8 +170,9 @@ export class Input3D {
|
|
|
155
170
|
// some ancestor happens to be positioned, and "happens to be" is not a
|
|
156
171
|
// layout strategy.
|
|
157
172
|
position: 'fixed', inset: '0', pointerEvents: 'none',
|
|
158
|
-
touchAction: 'none',
|
|
173
|
+
touchAction: 'none', zIndex: '10',
|
|
159
174
|
});
|
|
175
|
+
Object.assign(root.style, NO_SELECTION);
|
|
160
176
|
const floating = this.stickMode === 'floating';
|
|
161
177
|
// The zone a thumb may land on to summon the stick. It is the LEFT HALF,
|
|
162
178
|
// not the pad: the whole point is that the player does not have to find
|
|
@@ -166,6 +182,7 @@ export class Input3D {
|
|
|
166
182
|
position: 'absolute', left: '0', top: '0', width: '50%', height: '100%',
|
|
167
183
|
pointerEvents: floating ? 'auto' : 'none',
|
|
168
184
|
});
|
|
185
|
+
Object.assign(zone.style, NO_SELECTION);
|
|
169
186
|
const pad = document.createElement('div');
|
|
170
187
|
Object.assign(pad.style, floating ? {
|
|
171
188
|
position: 'absolute', width: '30vmin', height: '30vmin',
|
|
@@ -213,6 +230,11 @@ export class Input3D {
|
|
|
213
230
|
color: 'rgba(255,255,255,0.85)', font: '600 4vmin/1 system-ui, sans-serif',
|
|
214
231
|
});
|
|
215
232
|
el.textContent = label;
|
|
233
|
+
// Explicitly, not by inheritance. The label IS text -- a glyph in a div
|
|
234
|
+
// -- and long-pressing the attack button is how the iOS Copy / Look Up /
|
|
235
|
+
// Translate callout came up mid-fight, with the selection handles
|
|
236
|
+
// clamped around the little crossed swords.
|
|
237
|
+
Object.assign(el.style, NO_SELECTION);
|
|
216
238
|
return el;
|
|
217
239
|
};
|
|
218
240
|
const btn = makeButton('▲');
|
|
@@ -225,6 +247,34 @@ export class Input3D {
|
|
|
225
247
|
root.append(zone, pad, cluster);
|
|
226
248
|
container.appendChild(root);
|
|
227
249
|
this.root = root;
|
|
250
|
+
// And the page underneath. The overlay covers the controls, but a press
|
|
251
|
+
// that lands on the HUD or the canvas would still summon the callout — and
|
|
252
|
+
// a game is not a document; there is nothing here to select.
|
|
253
|
+
//
|
|
254
|
+
// A stylesheet rather than inline styles, so form fields can opt back IN:
|
|
255
|
+
// blanket `user-select: none` on <body> can stop a player selecting text
|
|
256
|
+
// inside their own name field, and a game that takes typed input would
|
|
257
|
+
// have inherited a bug from its movement controls.
|
|
258
|
+
const doc = container.ownerDocument;
|
|
259
|
+
const style = doc.createElement('style');
|
|
260
|
+
// A DIFFERENT marker from the control layer's. Sharing `data-umicat-touch`
|
|
261
|
+
// put a <style> in <head> ahead of the layer in document order, so
|
|
262
|
+
// `querySelector('[data-umicat-touch]')` started returning the stylesheet
|
|
263
|
+
// and anything looking up the controls found an element with no children.
|
|
264
|
+
style.dataset.umicatTouchCss = '';
|
|
265
|
+
style.textContent = `
|
|
266
|
+
html, body { -webkit-user-select: none; user-select: none;
|
|
267
|
+
-webkit-touch-callout: none;
|
|
268
|
+
-webkit-tap-highlight-color: transparent; }
|
|
269
|
+
input, textarea, select, [contenteditable] {
|
|
270
|
+
-webkit-user-select: text; user-select: text;
|
|
271
|
+
-webkit-touch-callout: default; }
|
|
272
|
+
`;
|
|
273
|
+
doc.head.appendChild(style);
|
|
274
|
+
this.cleanups.push(() => style.remove());
|
|
275
|
+
const noMenu = (e) => e.preventDefault();
|
|
276
|
+
doc.addEventListener('contextmenu', noMenu);
|
|
277
|
+
this.cleanups.push(() => doc.removeEventListener('contextmenu', noMenu));
|
|
228
278
|
// Track by pointerId so a thumb on the stick and a thumb on the button do
|
|
229
279
|
// not fight over one piece of state.
|
|
230
280
|
let stickId = null;
|
|
@@ -281,6 +331,9 @@ export class Input3D {
|
|
|
281
331
|
// not — which is the point: `direction()` reads the same either way.
|
|
282
332
|
const grip = floating ? zone : pad;
|
|
283
333
|
on(grip, 'pointerdown', (e) => {
|
|
334
|
+
// Cancel the default gesture: on iOS, holding still on the screen is how
|
|
335
|
+
// a text selection begins, and holding still is the entire thumbstick.
|
|
336
|
+
e.preventDefault();
|
|
284
337
|
// One thumb drives the stick. A second finger landing in the zone must
|
|
285
338
|
// not move the origin out from under the first.
|
|
286
339
|
if (stickId !== null)
|
|
@@ -315,6 +368,7 @@ export class Input3D {
|
|
|
315
368
|
this.cleanups.push(() => el.removeEventListener(ev, h));
|
|
316
369
|
};
|
|
317
370
|
on('pointerdown', (e) => {
|
|
371
|
+
// Cancels the selection gesture as well as the default press behaviour.
|
|
318
372
|
e.preventDefault();
|
|
319
373
|
el.setPointerCapture(e.pointerId);
|
|
320
374
|
this.touchHeld.add(id);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umicat/three-sdk",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.2",
|
|
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",
|