@forgeax/engine-input 0.1.33 → 0.1.34
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/browser-backend.d.ts.map +1 -1
- package/dist/canvas-input-boundary.d.ts.map +1 -1
- package/dist/composite-backend.d.ts.map +1 -1
- package/dist/index.mjs +295 -235
- package/dist/index.mjs.map +1 -1
- package/dist/input-snapshot.d.ts +6 -0
- package/dist/input-snapshot.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/browser-backend-edge-latch.test.ts +12 -0
- package/src/browser-backend.ts +31 -1
- package/src/canvas-input-boundary.ts +9 -0
- package/src/composite-backend.ts +36 -6
- package/src/input-snapshot.ts +6 -0
package/dist/index.mjs
CHANGED
|
@@ -506,6 +506,234 @@ function cloneSwipeHistory(src) {
|
|
|
506
506
|
return out;
|
|
507
507
|
}
|
|
508
508
|
|
|
509
|
+
// src/input-snapshot.ts
|
|
510
|
+
function createEmptyInputBackendSample() {
|
|
511
|
+
return {
|
|
512
|
+
downKeys: /* @__PURE__ */ new Set(),
|
|
513
|
+
upKeys: /* @__PURE__ */ new Set(),
|
|
514
|
+
buttons: [false, false, false],
|
|
515
|
+
movementX: 0,
|
|
516
|
+
movementY: 0,
|
|
517
|
+
wheelDelta: 0,
|
|
518
|
+
focused: true,
|
|
519
|
+
pointerLocked: false
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
function emptyGamepadReader() {
|
|
523
|
+
return Object.freeze({
|
|
524
|
+
connected: false,
|
|
525
|
+
standardMapping: false,
|
|
526
|
+
button(_b) {
|
|
527
|
+
return false;
|
|
528
|
+
},
|
|
529
|
+
buttonValue(_b) {
|
|
530
|
+
return 0;
|
|
531
|
+
},
|
|
532
|
+
justPressed(_b) {
|
|
533
|
+
return false;
|
|
534
|
+
},
|
|
535
|
+
justReleased(_b) {
|
|
536
|
+
return false;
|
|
537
|
+
},
|
|
538
|
+
axis(_a) {
|
|
539
|
+
return 0;
|
|
540
|
+
}
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
function buildGamepadReader(slot) {
|
|
544
|
+
if (!slot.standardMapping) {
|
|
545
|
+
return Object.freeze({
|
|
546
|
+
connected: true,
|
|
547
|
+
standardMapping: false,
|
|
548
|
+
button: emptyGamepadReader().button,
|
|
549
|
+
buttonValue: emptyGamepadReader().buttonValue,
|
|
550
|
+
justPressed: emptyGamepadReader().justPressed,
|
|
551
|
+
justReleased: emptyGamepadReader().justReleased,
|
|
552
|
+
axis: emptyGamepadReader().axis
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
return Object.freeze({
|
|
556
|
+
connected: true,
|
|
557
|
+
standardMapping: true,
|
|
558
|
+
button(b) {
|
|
559
|
+
return slot.pressed.has(b);
|
|
560
|
+
},
|
|
561
|
+
buttonValue(b) {
|
|
562
|
+
return slot.buttonValues.get(b) ?? 0;
|
|
563
|
+
},
|
|
564
|
+
justPressed(b) {
|
|
565
|
+
return slot.justPressed.has(b);
|
|
566
|
+
},
|
|
567
|
+
justReleased(b) {
|
|
568
|
+
return slot.justReleased.has(b);
|
|
569
|
+
},
|
|
570
|
+
axis(a) {
|
|
571
|
+
return slot.axes[a];
|
|
572
|
+
}
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
function snapshotFromSample(sample, actionStates, inputMap, previousSnapshot) {
|
|
576
|
+
const heldKeys = new Set(sample.downKeys);
|
|
577
|
+
const upEdges = new Set(sample.upKeys);
|
|
578
|
+
const justPressedKeys = new Set(sample.pressedKeys);
|
|
579
|
+
if (sample.pressedKeys === void 0) {
|
|
580
|
+
for (const key of heldKeys) {
|
|
581
|
+
if (!previousSnapshot?.keyboard.down(key)) justPressedKeys.add(key);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
const heldCodes = new Set(sample.downCodes ?? []);
|
|
585
|
+
const upCodeEdges = new Set(sample.upCodes ?? []);
|
|
586
|
+
const justPressedCodes = new Set(sample.pressedCodes);
|
|
587
|
+
if (sample.pressedCodes === void 0) {
|
|
588
|
+
for (const code of heldCodes) {
|
|
589
|
+
if (!previousSnapshot?.keyboard.downCode(code)) justPressedCodes.add(code);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
const buttons = [
|
|
593
|
+
sample.buttons[0],
|
|
594
|
+
sample.buttons[1],
|
|
595
|
+
sample.buttons[2]
|
|
596
|
+
];
|
|
597
|
+
const justPressedButtons = sample.pressedButtons === void 0 ? [
|
|
598
|
+
buttons[0] && (previousSnapshot === void 0 || !previousSnapshot.mouse.button(0)),
|
|
599
|
+
buttons[1] && (previousSnapshot === void 0 || !previousSnapshot.mouse.button(1)),
|
|
600
|
+
buttons[2] && (previousSnapshot === void 0 || !previousSnapshot.mouse.button(2))
|
|
601
|
+
] : [sample.pressedButtons[0], sample.pressedButtons[1], sample.pressedButtons[2]];
|
|
602
|
+
const justReleasedButtons = sample.releasedButtons === void 0 ? [
|
|
603
|
+
sample.focusReset !== true && previousSnapshot?.mouse.button(0) === true && !buttons[0],
|
|
604
|
+
sample.focusReset !== true && previousSnapshot?.mouse.button(1) === true && !buttons[1],
|
|
605
|
+
sample.focusReset !== true && previousSnapshot?.mouse.button(2) === true && !buttons[2]
|
|
606
|
+
] : [sample.releasedButtons[0], sample.releasedButtons[1], sample.releasedButtons[2]];
|
|
607
|
+
const movementDelta = Object.freeze({ x: sample.movementX, y: sample.movementY });
|
|
608
|
+
const mousePosition = sample.mouseX === void 0 || sample.mouseY === void 0 ? void 0 : Object.freeze({ x: sample.mouseX, y: sample.mouseY });
|
|
609
|
+
const wheelDelta = sample.wheelDelta;
|
|
610
|
+
const gamepadSlots = sample.gamepads ?? [];
|
|
611
|
+
const caps = sample.capabilities ?? Object.freeze({ gamepad: false, pointer: false });
|
|
612
|
+
const pointerEvts = sample.pointerEvents ?? [];
|
|
613
|
+
const gesture = sample.gestures ?? IDENTITY_GESTURE;
|
|
614
|
+
const gestureEvts = sample.gestureEvents ?? [];
|
|
615
|
+
const _virtualAxes = sample.virtualAxes ?? [];
|
|
616
|
+
const virtualAxesMap = /* @__PURE__ */ new Map();
|
|
617
|
+
for (const va of _virtualAxes) {
|
|
618
|
+
virtualAxesMap.set(va.name, va);
|
|
619
|
+
}
|
|
620
|
+
const gamepadSlotMap = /* @__PURE__ */ new Map();
|
|
621
|
+
for (const slot of gamepadSlots) {
|
|
622
|
+
gamepadSlotMap.set(slot.index, slot);
|
|
623
|
+
}
|
|
624
|
+
const actionMap = /* @__PURE__ */ new Map();
|
|
625
|
+
if (actionStates) {
|
|
626
|
+
for (const a of actionStates) {
|
|
627
|
+
actionMap.set(a.action, a);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
function emptyActionReader() {
|
|
631
|
+
return Object.freeze({
|
|
632
|
+
isPressed: () => false,
|
|
633
|
+
justPressed: () => false,
|
|
634
|
+
justReleased: () => false,
|
|
635
|
+
strength: 0
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
const snapshot = {
|
|
639
|
+
keyboard: {
|
|
640
|
+
down(key) {
|
|
641
|
+
return heldKeys.has(key);
|
|
642
|
+
},
|
|
643
|
+
justPressed(key) {
|
|
644
|
+
return justPressedKeys.has(key);
|
|
645
|
+
},
|
|
646
|
+
up(key) {
|
|
647
|
+
return upEdges.has(key);
|
|
648
|
+
},
|
|
649
|
+
downCode(code) {
|
|
650
|
+
return heldCodes.has(code);
|
|
651
|
+
},
|
|
652
|
+
justPressedCode(code) {
|
|
653
|
+
return justPressedCodes.has(code);
|
|
654
|
+
},
|
|
655
|
+
upCode(code) {
|
|
656
|
+
return upCodeEdges.has(code);
|
|
657
|
+
}
|
|
658
|
+
},
|
|
659
|
+
mouse: {
|
|
660
|
+
position: mousePosition,
|
|
661
|
+
movementDelta,
|
|
662
|
+
pointerLocked: sample.pointerLocked,
|
|
663
|
+
button(i) {
|
|
664
|
+
return buttons[i] === true;
|
|
665
|
+
},
|
|
666
|
+
justPressed(i) {
|
|
667
|
+
return justPressedButtons[i] === true;
|
|
668
|
+
},
|
|
669
|
+
justReleased(i) {
|
|
670
|
+
return justReleasedButtons[i] === true;
|
|
671
|
+
},
|
|
672
|
+
wheelDelta
|
|
673
|
+
},
|
|
674
|
+
gamepad(i) {
|
|
675
|
+
const slot = gamepadSlotMap.get(i);
|
|
676
|
+
if (!slot) return emptyGamepadReader();
|
|
677
|
+
return buildGamepadReader(slot);
|
|
678
|
+
},
|
|
679
|
+
capabilities: caps,
|
|
680
|
+
pointer(id) {
|
|
681
|
+
const entry = (sample.pointers ?? []).find((p) => p.pointerId === id);
|
|
682
|
+
if (!entry) {
|
|
683
|
+
return Object.freeze({
|
|
684
|
+
active: false,
|
|
685
|
+
pointerId: -1,
|
|
686
|
+
x: 0,
|
|
687
|
+
y: 0,
|
|
688
|
+
pressure: 0,
|
|
689
|
+
pointerType: "mouse",
|
|
690
|
+
delta: Object.freeze({ x: 0, y: 0 })
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
return Object.freeze({
|
|
694
|
+
...entry,
|
|
695
|
+
delta: Object.freeze({ x: entry.delta.x, y: entry.delta.y })
|
|
696
|
+
});
|
|
697
|
+
},
|
|
698
|
+
virtualAxis(name) {
|
|
699
|
+
const va = virtualAxesMap.get(name);
|
|
700
|
+
if (!va) return Object.freeze({ x: 0, y: 0 });
|
|
701
|
+
return Object.freeze({ x: va.x, y: va.y });
|
|
702
|
+
},
|
|
703
|
+
action(name) {
|
|
704
|
+
const s = actionMap.get(name);
|
|
705
|
+
if (!s) return emptyActionReader();
|
|
706
|
+
return Object.freeze({
|
|
707
|
+
isPressed: () => s.pressed,
|
|
708
|
+
justPressed: () => s.justPressed,
|
|
709
|
+
justReleased: () => s.justReleased,
|
|
710
|
+
strength: s.strength
|
|
711
|
+
});
|
|
712
|
+
},
|
|
713
|
+
getAxis(neg, pos) {
|
|
714
|
+
if (!actionStates || !inputMap) return 0;
|
|
715
|
+
return getAxis(inputMap, actionStates, neg, pos);
|
|
716
|
+
},
|
|
717
|
+
getVector(negX, posX, negY, posY, opts) {
|
|
718
|
+
if (!actionStates || !inputMap) return { x: 0, y: 0 };
|
|
719
|
+
return getVector(inputMap, actionStates, negX, posX, negY, posY, opts);
|
|
720
|
+
},
|
|
721
|
+
pointerEvents: pointerEvts,
|
|
722
|
+
gesture,
|
|
723
|
+
gestureEvents: gestureEvts
|
|
724
|
+
};
|
|
725
|
+
snapshot._actionStates = actionStates;
|
|
726
|
+
snapshot._inputMap = inputMap;
|
|
727
|
+
return Object.freeze(snapshot);
|
|
728
|
+
}
|
|
729
|
+
function readActionStatesForEdgeDiff(snap) {
|
|
730
|
+
return snap._actionStates;
|
|
731
|
+
}
|
|
732
|
+
function createInputSnapshot() {
|
|
733
|
+
return snapshotFromSample(createEmptyInputBackendSample());
|
|
734
|
+
}
|
|
735
|
+
var INPUT_SNAPSHOT_RESOURCE_KEY = "InputSnapshot";
|
|
736
|
+
|
|
509
737
|
// src/ui-ownership.ts
|
|
510
738
|
function contains(root, value) {
|
|
511
739
|
const NodeCtor = globalThis.Node;
|
|
@@ -609,6 +837,7 @@ function attachBrowserInputBackend(canvas, options = {}) {
|
|
|
609
837
|
let w3cLocked = false;
|
|
610
838
|
let providerLocked = false;
|
|
611
839
|
let gameGate = true;
|
|
840
|
+
let inputAllowed = true;
|
|
612
841
|
function emitLockError(path, cause) {
|
|
613
842
|
try {
|
|
614
843
|
options.onLockError?.({ path, cause });
|
|
@@ -685,6 +914,7 @@ function attachBrowserInputBackend(canvas, options = {}) {
|
|
|
685
914
|
return typeof doc?.hasFocus === "function" ? doc.hasFocus() : true;
|
|
686
915
|
}
|
|
687
916
|
function onKeyDown(ev) {
|
|
917
|
+
if (!inputAllowed) return;
|
|
688
918
|
if (isUiEvent(ev)) {
|
|
689
919
|
clear();
|
|
690
920
|
return;
|
|
@@ -700,6 +930,7 @@ function attachBrowserInputBackend(canvas, options = {}) {
|
|
|
700
930
|
}
|
|
701
931
|
}
|
|
702
932
|
function onKeyUp(ev) {
|
|
933
|
+
if (!inputAllowed) return;
|
|
703
934
|
if (isUiEvent(ev)) return;
|
|
704
935
|
heldKeys.delete(ev.key);
|
|
705
936
|
if (isFocused()) {
|
|
@@ -711,6 +942,7 @@ function attachBrowserInputBackend(canvas, options = {}) {
|
|
|
711
942
|
}
|
|
712
943
|
}
|
|
713
944
|
function onPointerDown(ev) {
|
|
945
|
+
if (!inputAllowed) return;
|
|
714
946
|
if (isUiEvent(ev)) {
|
|
715
947
|
clear();
|
|
716
948
|
return;
|
|
@@ -770,6 +1002,7 @@ function attachBrowserInputBackend(canvas, options = {}) {
|
|
|
770
1002
|
}
|
|
771
1003
|
}
|
|
772
1004
|
function onPointerUp(ev) {
|
|
1005
|
+
if (!inputAllowed) return;
|
|
773
1006
|
if (isUiEvent(ev)) return;
|
|
774
1007
|
if (ev.pointerType === "mouse") {
|
|
775
1008
|
if (ev.button === 0 || ev.button === 1 || ev.button === 2) {
|
|
@@ -794,6 +1027,7 @@ function attachBrowserInputBackend(canvas, options = {}) {
|
|
|
794
1027
|
}
|
|
795
1028
|
}
|
|
796
1029
|
function onPointerMove(ev) {
|
|
1030
|
+
if (!inputAllowed) return;
|
|
797
1031
|
if (isUiEvent(ev)) return;
|
|
798
1032
|
if (ev.pointerType === "mouse") {
|
|
799
1033
|
mvx += ev.movementX;
|
|
@@ -820,6 +1054,7 @@ function attachBrowserInputBackend(canvas, options = {}) {
|
|
|
820
1054
|
}
|
|
821
1055
|
}
|
|
822
1056
|
function onPointerCancel(ev) {
|
|
1057
|
+
if (!inputAllowed) return;
|
|
823
1058
|
if (isUiEvent(ev)) return;
|
|
824
1059
|
const entry = pointerMap.get(ev.pointerId);
|
|
825
1060
|
if (entry) {
|
|
@@ -843,6 +1078,7 @@ function attachBrowserInputBackend(canvas, options = {}) {
|
|
|
843
1078
|
}
|
|
844
1079
|
}
|
|
845
1080
|
function onWheel(ev) {
|
|
1081
|
+
if (!inputAllowed) return;
|
|
846
1082
|
if (isUiEvent(ev)) {
|
|
847
1083
|
clear();
|
|
848
1084
|
return;
|
|
@@ -925,6 +1161,7 @@ function attachBrowserInputBackend(canvas, options = {}) {
|
|
|
925
1161
|
canvas.style.touchAction = "none";
|
|
926
1162
|
}
|
|
927
1163
|
function onCanvasClick() {
|
|
1164
|
+
if (!inputAllowed) return;
|
|
928
1165
|
if (!gameGate) return;
|
|
929
1166
|
if (options.pointerLockAllowed && !options.pointerLockAllowed()) return;
|
|
930
1167
|
if (options.lockProvider) {
|
|
@@ -958,6 +1195,10 @@ function attachBrowserInputBackend(canvas, options = {}) {
|
|
|
958
1195
|
}
|
|
959
1196
|
safeAdd(canvas, "click", onCanvasClick);
|
|
960
1197
|
function sample() {
|
|
1198
|
+
if (!inputAllowed) {
|
|
1199
|
+
clear();
|
|
1200
|
+
return createEmptyInputBackendSample();
|
|
1201
|
+
}
|
|
961
1202
|
let gamepads;
|
|
962
1203
|
if (gamepadAvailable) {
|
|
963
1204
|
try {
|
|
@@ -1074,6 +1315,10 @@ function attachBrowserInputBackend(canvas, options = {}) {
|
|
|
1074
1315
|
releaseProviderLock();
|
|
1075
1316
|
}
|
|
1076
1317
|
}
|
|
1318
|
+
function setInputAllowed(allowed) {
|
|
1319
|
+
inputAllowed = allowed;
|
|
1320
|
+
clear();
|
|
1321
|
+
}
|
|
1077
1322
|
function clear() {
|
|
1078
1323
|
heldKeys.clear();
|
|
1079
1324
|
upEdges.clear();
|
|
@@ -1124,243 +1369,23 @@ function attachBrowserInputBackend(canvas, options = {}) {
|
|
|
1124
1369
|
canvas.style.touchAction = _prevTouchAction;
|
|
1125
1370
|
}
|
|
1126
1371
|
}
|
|
1127
|
-
const backend = {
|
|
1372
|
+
const backend = {
|
|
1373
|
+
sample,
|
|
1374
|
+
clear,
|
|
1375
|
+
detach,
|
|
1376
|
+
setPointerLockAllowed,
|
|
1377
|
+
setInputAllowed
|
|
1378
|
+
};
|
|
1128
1379
|
const handle = Object.assign(detach, { backend });
|
|
1129
1380
|
return handle;
|
|
1130
1381
|
}
|
|
1131
1382
|
|
|
1132
|
-
// src/input-snapshot.ts
|
|
1133
|
-
function createEmptyInputBackendSample() {
|
|
1134
|
-
return {
|
|
1135
|
-
downKeys: /* @__PURE__ */ new Set(),
|
|
1136
|
-
upKeys: /* @__PURE__ */ new Set(),
|
|
1137
|
-
buttons: [false, false, false],
|
|
1138
|
-
movementX: 0,
|
|
1139
|
-
movementY: 0,
|
|
1140
|
-
wheelDelta: 0,
|
|
1141
|
-
focused: true,
|
|
1142
|
-
pointerLocked: false
|
|
1143
|
-
};
|
|
1144
|
-
}
|
|
1145
|
-
function emptyGamepadReader() {
|
|
1146
|
-
return Object.freeze({
|
|
1147
|
-
connected: false,
|
|
1148
|
-
standardMapping: false,
|
|
1149
|
-
button(_b) {
|
|
1150
|
-
return false;
|
|
1151
|
-
},
|
|
1152
|
-
buttonValue(_b) {
|
|
1153
|
-
return 0;
|
|
1154
|
-
},
|
|
1155
|
-
justPressed(_b) {
|
|
1156
|
-
return false;
|
|
1157
|
-
},
|
|
1158
|
-
justReleased(_b) {
|
|
1159
|
-
return false;
|
|
1160
|
-
},
|
|
1161
|
-
axis(_a) {
|
|
1162
|
-
return 0;
|
|
1163
|
-
}
|
|
1164
|
-
});
|
|
1165
|
-
}
|
|
1166
|
-
function buildGamepadReader(slot) {
|
|
1167
|
-
if (!slot.standardMapping) {
|
|
1168
|
-
return Object.freeze({
|
|
1169
|
-
connected: true,
|
|
1170
|
-
standardMapping: false,
|
|
1171
|
-
button: emptyGamepadReader().button,
|
|
1172
|
-
buttonValue: emptyGamepadReader().buttonValue,
|
|
1173
|
-
justPressed: emptyGamepadReader().justPressed,
|
|
1174
|
-
justReleased: emptyGamepadReader().justReleased,
|
|
1175
|
-
axis: emptyGamepadReader().axis
|
|
1176
|
-
});
|
|
1177
|
-
}
|
|
1178
|
-
return Object.freeze({
|
|
1179
|
-
connected: true,
|
|
1180
|
-
standardMapping: true,
|
|
1181
|
-
button(b) {
|
|
1182
|
-
return slot.pressed.has(b);
|
|
1183
|
-
},
|
|
1184
|
-
buttonValue(b) {
|
|
1185
|
-
return slot.buttonValues.get(b) ?? 0;
|
|
1186
|
-
},
|
|
1187
|
-
justPressed(b) {
|
|
1188
|
-
return slot.justPressed.has(b);
|
|
1189
|
-
},
|
|
1190
|
-
justReleased(b) {
|
|
1191
|
-
return slot.justReleased.has(b);
|
|
1192
|
-
},
|
|
1193
|
-
axis(a) {
|
|
1194
|
-
return slot.axes[a];
|
|
1195
|
-
}
|
|
1196
|
-
});
|
|
1197
|
-
}
|
|
1198
|
-
function snapshotFromSample(sample, actionStates, inputMap, previousSnapshot) {
|
|
1199
|
-
const heldKeys = new Set(sample.downKeys);
|
|
1200
|
-
const upEdges = new Set(sample.upKeys);
|
|
1201
|
-
const justPressedKeys = new Set(sample.pressedKeys);
|
|
1202
|
-
if (sample.pressedKeys === void 0) {
|
|
1203
|
-
for (const key of heldKeys) {
|
|
1204
|
-
if (!previousSnapshot?.keyboard.down(key)) justPressedKeys.add(key);
|
|
1205
|
-
}
|
|
1206
|
-
}
|
|
1207
|
-
const heldCodes = new Set(sample.downCodes ?? []);
|
|
1208
|
-
const upCodeEdges = new Set(sample.upCodes ?? []);
|
|
1209
|
-
const justPressedCodes = new Set(sample.pressedCodes);
|
|
1210
|
-
if (sample.pressedCodes === void 0) {
|
|
1211
|
-
for (const code of heldCodes) {
|
|
1212
|
-
if (!previousSnapshot?.keyboard.downCode(code)) justPressedCodes.add(code);
|
|
1213
|
-
}
|
|
1214
|
-
}
|
|
1215
|
-
const buttons = [
|
|
1216
|
-
sample.buttons[0],
|
|
1217
|
-
sample.buttons[1],
|
|
1218
|
-
sample.buttons[2]
|
|
1219
|
-
];
|
|
1220
|
-
const justPressedButtons = sample.pressedButtons === void 0 ? [
|
|
1221
|
-
buttons[0] && (previousSnapshot === void 0 || !previousSnapshot.mouse.button(0)),
|
|
1222
|
-
buttons[1] && (previousSnapshot === void 0 || !previousSnapshot.mouse.button(1)),
|
|
1223
|
-
buttons[2] && (previousSnapshot === void 0 || !previousSnapshot.mouse.button(2))
|
|
1224
|
-
] : [sample.pressedButtons[0], sample.pressedButtons[1], sample.pressedButtons[2]];
|
|
1225
|
-
const justReleasedButtons = sample.releasedButtons === void 0 ? [
|
|
1226
|
-
sample.focusReset !== true && previousSnapshot?.mouse.button(0) === true && !buttons[0],
|
|
1227
|
-
sample.focusReset !== true && previousSnapshot?.mouse.button(1) === true && !buttons[1],
|
|
1228
|
-
sample.focusReset !== true && previousSnapshot?.mouse.button(2) === true && !buttons[2]
|
|
1229
|
-
] : [sample.releasedButtons[0], sample.releasedButtons[1], sample.releasedButtons[2]];
|
|
1230
|
-
const movementDelta = Object.freeze({ x: sample.movementX, y: sample.movementY });
|
|
1231
|
-
const mousePosition = sample.mouseX === void 0 || sample.mouseY === void 0 ? void 0 : Object.freeze({ x: sample.mouseX, y: sample.mouseY });
|
|
1232
|
-
const wheelDelta = sample.wheelDelta;
|
|
1233
|
-
const gamepadSlots = sample.gamepads ?? [];
|
|
1234
|
-
const caps = sample.capabilities ?? Object.freeze({ gamepad: false, pointer: false });
|
|
1235
|
-
const pointerEvts = sample.pointerEvents ?? [];
|
|
1236
|
-
const gesture = sample.gestures ?? IDENTITY_GESTURE;
|
|
1237
|
-
const gestureEvts = sample.gestureEvents ?? [];
|
|
1238
|
-
const _virtualAxes = sample.virtualAxes ?? [];
|
|
1239
|
-
const virtualAxesMap = /* @__PURE__ */ new Map();
|
|
1240
|
-
for (const va of _virtualAxes) {
|
|
1241
|
-
virtualAxesMap.set(va.name, va);
|
|
1242
|
-
}
|
|
1243
|
-
const gamepadSlotMap = /* @__PURE__ */ new Map();
|
|
1244
|
-
for (const slot of gamepadSlots) {
|
|
1245
|
-
gamepadSlotMap.set(slot.index, slot);
|
|
1246
|
-
}
|
|
1247
|
-
const actionMap = /* @__PURE__ */ new Map();
|
|
1248
|
-
if (actionStates) {
|
|
1249
|
-
for (const a of actionStates) {
|
|
1250
|
-
actionMap.set(a.action, a);
|
|
1251
|
-
}
|
|
1252
|
-
}
|
|
1253
|
-
function emptyActionReader() {
|
|
1254
|
-
return Object.freeze({
|
|
1255
|
-
isPressed: () => false,
|
|
1256
|
-
justPressed: () => false,
|
|
1257
|
-
justReleased: () => false,
|
|
1258
|
-
strength: 0
|
|
1259
|
-
});
|
|
1260
|
-
}
|
|
1261
|
-
const snapshot = {
|
|
1262
|
-
keyboard: {
|
|
1263
|
-
down(key) {
|
|
1264
|
-
return heldKeys.has(key);
|
|
1265
|
-
},
|
|
1266
|
-
justPressed(key) {
|
|
1267
|
-
return justPressedKeys.has(key);
|
|
1268
|
-
},
|
|
1269
|
-
up(key) {
|
|
1270
|
-
return upEdges.has(key);
|
|
1271
|
-
},
|
|
1272
|
-
downCode(code) {
|
|
1273
|
-
return heldCodes.has(code);
|
|
1274
|
-
},
|
|
1275
|
-
justPressedCode(code) {
|
|
1276
|
-
return justPressedCodes.has(code);
|
|
1277
|
-
},
|
|
1278
|
-
upCode(code) {
|
|
1279
|
-
return upCodeEdges.has(code);
|
|
1280
|
-
}
|
|
1281
|
-
},
|
|
1282
|
-
mouse: {
|
|
1283
|
-
position: mousePosition,
|
|
1284
|
-
movementDelta,
|
|
1285
|
-
pointerLocked: sample.pointerLocked,
|
|
1286
|
-
button(i) {
|
|
1287
|
-
return buttons[i] === true;
|
|
1288
|
-
},
|
|
1289
|
-
justPressed(i) {
|
|
1290
|
-
return justPressedButtons[i] === true;
|
|
1291
|
-
},
|
|
1292
|
-
justReleased(i) {
|
|
1293
|
-
return justReleasedButtons[i] === true;
|
|
1294
|
-
},
|
|
1295
|
-
wheelDelta
|
|
1296
|
-
},
|
|
1297
|
-
gamepad(i) {
|
|
1298
|
-
const slot = gamepadSlotMap.get(i);
|
|
1299
|
-
if (!slot) return emptyGamepadReader();
|
|
1300
|
-
return buildGamepadReader(slot);
|
|
1301
|
-
},
|
|
1302
|
-
capabilities: caps,
|
|
1303
|
-
pointer(id) {
|
|
1304
|
-
const entry = (sample.pointers ?? []).find((p) => p.pointerId === id);
|
|
1305
|
-
if (!entry) {
|
|
1306
|
-
return Object.freeze({
|
|
1307
|
-
active: false,
|
|
1308
|
-
pointerId: -1,
|
|
1309
|
-
x: 0,
|
|
1310
|
-
y: 0,
|
|
1311
|
-
pressure: 0,
|
|
1312
|
-
pointerType: "mouse",
|
|
1313
|
-
delta: Object.freeze({ x: 0, y: 0 })
|
|
1314
|
-
});
|
|
1315
|
-
}
|
|
1316
|
-
return Object.freeze({
|
|
1317
|
-
...entry,
|
|
1318
|
-
delta: Object.freeze({ x: entry.delta.x, y: entry.delta.y })
|
|
1319
|
-
});
|
|
1320
|
-
},
|
|
1321
|
-
virtualAxis(name) {
|
|
1322
|
-
const va = virtualAxesMap.get(name);
|
|
1323
|
-
if (!va) return Object.freeze({ x: 0, y: 0 });
|
|
1324
|
-
return Object.freeze({ x: va.x, y: va.y });
|
|
1325
|
-
},
|
|
1326
|
-
action(name) {
|
|
1327
|
-
const s = actionMap.get(name);
|
|
1328
|
-
if (!s) return emptyActionReader();
|
|
1329
|
-
return Object.freeze({
|
|
1330
|
-
isPressed: () => s.pressed,
|
|
1331
|
-
justPressed: () => s.justPressed,
|
|
1332
|
-
justReleased: () => s.justReleased,
|
|
1333
|
-
strength: s.strength
|
|
1334
|
-
});
|
|
1335
|
-
},
|
|
1336
|
-
getAxis(neg, pos) {
|
|
1337
|
-
if (!actionStates || !inputMap) return 0;
|
|
1338
|
-
return getAxis(inputMap, actionStates, neg, pos);
|
|
1339
|
-
},
|
|
1340
|
-
getVector(negX, posX, negY, posY, opts) {
|
|
1341
|
-
if (!actionStates || !inputMap) return { x: 0, y: 0 };
|
|
1342
|
-
return getVector(inputMap, actionStates, negX, posX, negY, posY, opts);
|
|
1343
|
-
},
|
|
1344
|
-
pointerEvents: pointerEvts,
|
|
1345
|
-
gesture,
|
|
1346
|
-
gestureEvents: gestureEvts
|
|
1347
|
-
};
|
|
1348
|
-
snapshot._actionStates = actionStates;
|
|
1349
|
-
snapshot._inputMap = inputMap;
|
|
1350
|
-
return Object.freeze(snapshot);
|
|
1351
|
-
}
|
|
1352
|
-
function readActionStatesForEdgeDiff(snap) {
|
|
1353
|
-
return snap._actionStates;
|
|
1354
|
-
}
|
|
1355
|
-
function createInputSnapshot() {
|
|
1356
|
-
return snapshotFromSample(createEmptyInputBackendSample());
|
|
1357
|
-
}
|
|
1358
|
-
var INPUT_SNAPSHOT_RESOURCE_KEY = "InputSnapshot";
|
|
1359
|
-
|
|
1360
1383
|
// src/canvas-input-boundary.ts
|
|
1361
1384
|
function createCanvasInputBoundary(source) {
|
|
1362
1385
|
let active = "editor";
|
|
1363
1386
|
let gamePointerLockAllowed = false;
|
|
1387
|
+
let editorInputAllowed = true;
|
|
1388
|
+
let gameInputAllowed = true;
|
|
1364
1389
|
source.setPointerLockAllowed?.(false);
|
|
1365
1390
|
const empty = () => createEmptyInputBackendSample();
|
|
1366
1391
|
const clear = () => {
|
|
@@ -1377,6 +1402,11 @@ function createCanvasInputBoundary(source) {
|
|
|
1377
1402
|
source.setPointerLockAllowed?.(false);
|
|
1378
1403
|
}
|
|
1379
1404
|
},
|
|
1405
|
+
setInputAllowed: (allowed) => {
|
|
1406
|
+
if (consumer === "game") gameInputAllowed = allowed;
|
|
1407
|
+
else editorInputAllowed = allowed;
|
|
1408
|
+
source.setInputAllowed?.(active === "game" ? gameInputAllowed : editorInputAllowed);
|
|
1409
|
+
},
|
|
1380
1410
|
clear: () => {
|
|
1381
1411
|
if (consumer === active) clear();
|
|
1382
1412
|
},
|
|
@@ -1387,10 +1417,12 @@ function createCanvasInputBoundary(source) {
|
|
|
1387
1417
|
clear();
|
|
1388
1418
|
active = "game";
|
|
1389
1419
|
source.setPointerLockAllowed?.(gamePointerLockAllowed);
|
|
1420
|
+
source.setInputAllowed?.(gameInputAllowed);
|
|
1390
1421
|
};
|
|
1391
1422
|
const revokeGame = () => {
|
|
1392
1423
|
clear();
|
|
1393
1424
|
active = "editor";
|
|
1425
|
+
source.setInputAllowed?.(editorInputAllowed);
|
|
1394
1426
|
};
|
|
1395
1427
|
return {
|
|
1396
1428
|
editor: routed("editor"),
|
|
@@ -1459,6 +1491,7 @@ function normalizeKey(value) {
|
|
|
1459
1491
|
}
|
|
1460
1492
|
function makeCompositeBackend(inner, options) {
|
|
1461
1493
|
let yieldToHuman = options?.yieldToHuman ?? true;
|
|
1494
|
+
let inputAllowed = true;
|
|
1462
1495
|
let leaseRevoked = false;
|
|
1463
1496
|
let leaseGeneration = 0;
|
|
1464
1497
|
const heldKeys = /* @__PURE__ */ new Set();
|
|
@@ -1478,6 +1511,25 @@ function makeCompositeBackend(inner, options) {
|
|
|
1478
1511
|
}
|
|
1479
1512
|
function sample() {
|
|
1480
1513
|
const base = inner.sample();
|
|
1514
|
+
if (!inputAllowed) {
|
|
1515
|
+
clearInjected();
|
|
1516
|
+
return {
|
|
1517
|
+
...base,
|
|
1518
|
+
downKeys: /* @__PURE__ */ new Set(),
|
|
1519
|
+
upKeys: /* @__PURE__ */ new Set(),
|
|
1520
|
+
downCodes: /* @__PURE__ */ new Set(),
|
|
1521
|
+
upCodes: /* @__PURE__ */ new Set(),
|
|
1522
|
+
pressedKeys: /* @__PURE__ */ new Set(),
|
|
1523
|
+
pressedCodes: /* @__PURE__ */ new Set(),
|
|
1524
|
+
buttons: [false, false, false],
|
|
1525
|
+
pressedButtons: [false, false, false],
|
|
1526
|
+
releasedButtons: [false, false, false],
|
|
1527
|
+
movementX: 0,
|
|
1528
|
+
movementY: 0,
|
|
1529
|
+
wheelDelta: 0,
|
|
1530
|
+
pointerLocked: false
|
|
1531
|
+
};
|
|
1532
|
+
}
|
|
1481
1533
|
const downKeys = new Set(base.downKeys);
|
|
1482
1534
|
const downCodes = base.downCodes === void 0 && heldCodes.size === 0 ? void 0 : new Set(base.downCodes ?? []);
|
|
1483
1535
|
for (const k of heldKeys) {
|
|
@@ -1573,6 +1625,13 @@ function makeCompositeBackend(inner, options) {
|
|
|
1573
1625
|
return out;
|
|
1574
1626
|
}
|
|
1575
1627
|
const lockGate = inner.setPointerLockAllowed ? { setPointerLockAllowed: (allowed) => inner.setPointerLockAllowed?.(allowed) } : {};
|
|
1628
|
+
const inputGate = {
|
|
1629
|
+
setInputAllowed: (allowed) => {
|
|
1630
|
+
inputAllowed = allowed;
|
|
1631
|
+
inner.setInputAllowed?.(allowed);
|
|
1632
|
+
clearInjected();
|
|
1633
|
+
}
|
|
1634
|
+
};
|
|
1576
1635
|
const clearInjected = () => {
|
|
1577
1636
|
upEdges.clear();
|
|
1578
1637
|
upCodeEdges.clear();
|
|
@@ -1609,7 +1668,7 @@ function makeCompositeBackend(inner, options) {
|
|
|
1609
1668
|
const createInjectedLease = () => {
|
|
1610
1669
|
beginInjectedLease();
|
|
1611
1670
|
const generation = leaseGeneration;
|
|
1612
|
-
const active = () => !leaseRevoked && generation === leaseGeneration;
|
|
1671
|
+
const active = () => inputAllowed && !leaseRevoked && generation === leaseGeneration;
|
|
1613
1672
|
return {
|
|
1614
1673
|
sample,
|
|
1615
1674
|
detach: () => {
|
|
@@ -1657,6 +1716,7 @@ function makeCompositeBackend(inner, options) {
|
|
|
1657
1716
|
return {
|
|
1658
1717
|
sample,
|
|
1659
1718
|
...lockGate,
|
|
1719
|
+
...inputGate,
|
|
1660
1720
|
// Teardown belongs to the human backend -- revoke the synthetic lease
|
|
1661
1721
|
// first, then forward the physical listener teardown. `clear()` is also
|
|
1662
1722
|
// exposed so an owner can revoke input without detaching the browser.
|
|
@@ -1669,7 +1729,7 @@ function makeCompositeBackend(inner, options) {
|
|
|
1669
1729
|
inner.detach();
|
|
1670
1730
|
},
|
|
1671
1731
|
press(key) {
|
|
1672
|
-
if (leaseRevoked) return;
|
|
1732
|
+
if (leaseRevoked || !inputAllowed) return;
|
|
1673
1733
|
const normalized = normalizeKey(key);
|
|
1674
1734
|
if (!heldKeys.has(normalized.key)) pressedKeys.add(normalized.key);
|
|
1675
1735
|
heldKeys.add(normalized.key);
|
|
@@ -1679,25 +1739,25 @@ function makeCompositeBackend(inner, options) {
|
|
|
1679
1739
|
}
|
|
1680
1740
|
},
|
|
1681
1741
|
release(key) {
|
|
1682
|
-
if (leaseRevoked) return;
|
|
1742
|
+
if (leaseRevoked || !inputAllowed) return;
|
|
1683
1743
|
const normalized = normalizeKey(key);
|
|
1684
1744
|
if (heldKeys.delete(normalized.key)) upEdges.add(normalized.key);
|
|
1685
1745
|
if (normalized.code !== void 0 && heldCodes.delete(normalized.code))
|
|
1686
1746
|
upCodeEdges.add(normalized.code);
|
|
1687
1747
|
},
|
|
1688
1748
|
setButton(slot, down) {
|
|
1689
|
-
if (leaseRevoked) return;
|
|
1749
|
+
if (leaseRevoked || !inputAllowed) return;
|
|
1690
1750
|
if (down && !buttons[slot]) pressedButtons[slot] = true;
|
|
1691
1751
|
if (!down && buttons[slot]) releasedButtons[slot] = true;
|
|
1692
1752
|
buttons[slot] = down;
|
|
1693
1753
|
},
|
|
1694
1754
|
addMovement(dx, dy) {
|
|
1695
|
-
if (leaseRevoked) return;
|
|
1755
|
+
if (leaseRevoked || !inputAllowed) return;
|
|
1696
1756
|
mvx += dx;
|
|
1697
1757
|
mvy += dy;
|
|
1698
1758
|
},
|
|
1699
1759
|
addWheel(notches) {
|
|
1700
|
-
if (leaseRevoked) return;
|
|
1760
|
+
if (leaseRevoked || !inputAllowed) return;
|
|
1701
1761
|
wheel += notches;
|
|
1702
1762
|
},
|
|
1703
1763
|
clearInjected,
|