pxt-common-packages 12.2.12 → 12.2.14
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/built/common-sim.d.ts +12 -2
- package/built/common-sim.js +45 -4
- package/libs/browser-events/browserEvents.cpp +4 -0
- package/libs/browser-events/browserEvents.ts +115 -36
- package/libs/browser-events/keyboard.ts +147 -41
- package/libs/browser-events/shims.d.ts +2 -0
- package/libs/browser-events/sim/keyboard.ts +36 -3
- package/libs/browser-events/sim/mouseState.ts +15 -1
- package/package.json +1 -1
package/built/common-sim.d.ts
CHANGED
|
@@ -341,15 +341,25 @@ declare namespace pxsim.browserEvents {
|
|
|
341
341
|
ArrowRight = 39,
|
|
342
342
|
PageDown = 34,
|
|
343
343
|
End = 35,
|
|
344
|
-
Home = 36
|
|
344
|
+
Home = 36,
|
|
345
|
+
LeftShift = 1016,
|
|
346
|
+
RightShift = 1017,
|
|
347
|
+
LeftControl = 1018,
|
|
348
|
+
RightControl = 1019,
|
|
349
|
+
Backspace = 8,
|
|
350
|
+
Delete = 46
|
|
345
351
|
}
|
|
346
352
|
function onKeyboardEvent(event: KeyboardEvent, pressed: boolean): void;
|
|
347
|
-
function getValueForKey(event: KeyboardEvent): 0 | Key;
|
|
353
|
+
function getValueForKey(event: KeyboardEvent): 0 | Key.Zero | Key.One | Key.Two | Key.Three | Key.Four | Key.Five | Key.Six | Key.Seven | Key.Eight | Key.Nine | Key.BackTick | Key.Hyphen | Key.Equals | Key.Q | Key.W | Key.E | Key.R | Key.T | Key.Y | Key.U | Key.I | Key.O | Key.P | Key.OpenBracket | Key.CloseBracket | Key.BackSlash | Key.A | Key.S | Key.D | Key.F | Key.G | Key.H | Key.Space | Key.PageUp | Key.J | Key.K | Key.L | Key.SemiColon | Key.Apostrophe | Key.Z | Key.X | Key.C | Key.V | Key.B | Key.N | Key.M | Key.Comma | Key.Period | Key.ForwardSlash | Key.Shift | Key.Enter | Key.CapsLock | Key.Tab | Key.Control | Key.Meta | Key.Alt | Key.ArrowUp | Key.ArrowDown | Key.ArrowLeft | Key.ArrowRight | Key.PageDown | Key.End | Key.Home | Key.Backspace | Key.Delete;
|
|
348
354
|
}
|
|
349
355
|
declare namespace pxsim.browserEvents {
|
|
350
356
|
interface BrowserEventsBoard extends CommonBoard {
|
|
351
357
|
mouseState: MouseState;
|
|
352
358
|
}
|
|
359
|
+
const INTERNAL_KEY_DOWN = 6870;
|
|
360
|
+
const INTERNAL_KEY_UP = 6871;
|
|
361
|
+
const INTERNAL_POINTER_DOWN = 6868;
|
|
362
|
+
const INTERNAL_POINTER_UP = 6869;
|
|
353
363
|
type MouseEvent = "pointerdown" | "pointerup" | "pointermove" | "pointerleave" | "pointerenter" | "pointercancel" | "pointerover" | "pointerout";
|
|
354
364
|
class MouseState {
|
|
355
365
|
protected x: number;
|
package/built/common-sim.js
CHANGED
|
@@ -813,16 +813,42 @@ var pxsim;
|
|
|
813
813
|
Key[Key["PageDown"] = 34] = "PageDown";
|
|
814
814
|
Key[Key["End"] = 35] = "End";
|
|
815
815
|
Key[Key["Home"] = 36] = "Home";
|
|
816
|
+
Key[Key["LeftShift"] = 1016] = "LeftShift";
|
|
817
|
+
Key[Key["RightShift"] = 1017] = "RightShift";
|
|
818
|
+
Key[Key["LeftControl"] = 1018] = "LeftControl";
|
|
819
|
+
Key[Key["RightControl"] = 1019] = "RightControl";
|
|
820
|
+
Key[Key["Backspace"] = 8] = "Backspace";
|
|
821
|
+
Key[Key["Delete"] = 46] = "Delete";
|
|
816
822
|
})(Key = browserEvents.Key || (browserEvents.Key = {}));
|
|
817
823
|
function onKeyboardEvent(event, pressed) {
|
|
824
|
+
const eventValue = getValueForKey(event);
|
|
825
|
+
fireEvent(eventValue, pressed);
|
|
826
|
+
if (eventValue === Key.Shift) {
|
|
827
|
+
if (event.location === event.DOM_KEY_LOCATION_LEFT) {
|
|
828
|
+
fireEvent(Key.LeftShift, pressed);
|
|
829
|
+
}
|
|
830
|
+
else if (event.location === event.DOM_KEY_LOCATION_RIGHT) {
|
|
831
|
+
fireEvent(Key.RightShift, pressed);
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
if (eventValue === Key.Control) {
|
|
835
|
+
if (event.location === event.DOM_KEY_LOCATION_LEFT) {
|
|
836
|
+
fireEvent(Key.LeftControl, pressed);
|
|
837
|
+
}
|
|
838
|
+
else if (event.location === event.DOM_KEY_LOCATION_RIGHT) {
|
|
839
|
+
fireEvent(Key.RightControl, pressed);
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
browserEvents.onKeyboardEvent = onKeyboardEvent;
|
|
844
|
+
function fireEvent(key, pressed) {
|
|
818
845
|
if (pressed) {
|
|
819
|
-
pxsim.board().bus.queue(
|
|
846
|
+
pxsim.board().bus.queue(browserEvents.INTERNAL_KEY_DOWN, key);
|
|
820
847
|
}
|
|
821
848
|
else {
|
|
822
|
-
pxsim.board().bus.queue(
|
|
849
|
+
pxsim.board().bus.queue(browserEvents.INTERNAL_KEY_UP, key);
|
|
823
850
|
}
|
|
824
851
|
}
|
|
825
|
-
browserEvents.onKeyboardEvent = onKeyboardEvent;
|
|
826
852
|
function getValueForKey(event) {
|
|
827
853
|
switch (event.key) {
|
|
828
854
|
case "0":
|
|
@@ -998,6 +1024,10 @@ var pxsim;
|
|
|
998
1024
|
return Key.End;
|
|
999
1025
|
case "Home":
|
|
1000
1026
|
return Key.Home;
|
|
1027
|
+
case "Delete":
|
|
1028
|
+
return Key.Delete;
|
|
1029
|
+
case "Backspace":
|
|
1030
|
+
return Key.Backspace;
|
|
1001
1031
|
default:
|
|
1002
1032
|
return 0;
|
|
1003
1033
|
}
|
|
@@ -1010,6 +1040,10 @@ var pxsim;
|
|
|
1010
1040
|
var browserEvents;
|
|
1011
1041
|
(function (browserEvents) {
|
|
1012
1042
|
const THROTTLE_INTERVAL = 50;
|
|
1043
|
+
browserEvents.INTERNAL_KEY_DOWN = 6870;
|
|
1044
|
+
browserEvents.INTERNAL_KEY_UP = 6871;
|
|
1045
|
+
browserEvents.INTERNAL_POINTER_DOWN = 6868;
|
|
1046
|
+
browserEvents.INTERNAL_POINTER_UP = 6869;
|
|
1013
1047
|
class MouseState {
|
|
1014
1048
|
constructor() {
|
|
1015
1049
|
this.onMove = pxsim.U.throttle(() => {
|
|
@@ -1032,9 +1066,16 @@ var pxsim;
|
|
|
1032
1066
|
"pointerover",
|
|
1033
1067
|
"pointerout",
|
|
1034
1068
|
];
|
|
1069
|
+
let eventId = 6857 + events.indexOf(event.type);
|
|
1070
|
+
if (event.type === "pointerdown") {
|
|
1071
|
+
eventId = browserEvents.INTERNAL_POINTER_DOWN;
|
|
1072
|
+
}
|
|
1073
|
+
else if (event.type === "pointerup") {
|
|
1074
|
+
eventId = browserEvents.INTERNAL_POINTER_UP;
|
|
1075
|
+
}
|
|
1035
1076
|
// We add 1 to the button here because the left button is 0 and
|
|
1036
1077
|
// that's used as a wildcard in our event bus
|
|
1037
|
-
pxsim.board().bus.queue(
|
|
1078
|
+
pxsim.board().bus.queue(eventId, (event.button || 0) + 1);
|
|
1038
1079
|
}
|
|
1039
1080
|
onWheelEvent(dx, dy, dz) {
|
|
1040
1081
|
this.dx = dx;
|
|
@@ -4,66 +4,94 @@
|
|
|
4
4
|
//% block="Browser Events"
|
|
5
5
|
namespace browserEvents {
|
|
6
6
|
export enum Event {
|
|
7
|
+
//% block="pointer down"
|
|
7
8
|
PointerDown = 6857,
|
|
9
|
+
//% block="pointer up"
|
|
8
10
|
PointerUp = 6858,
|
|
11
|
+
//% block="pointer move"
|
|
9
12
|
PointerMove = 6859,
|
|
13
|
+
//% block="pointer leave"
|
|
10
14
|
PointerLeave = 6860,
|
|
15
|
+
//% block="pointer enter"
|
|
11
16
|
PointerEnter = 6861,
|
|
17
|
+
//% block="pointer cancel"
|
|
12
18
|
PointerCancel = 6862,
|
|
19
|
+
//% block="pointer over"
|
|
13
20
|
PointerOver = 6863,
|
|
21
|
+
//% block="pointer out"
|
|
14
22
|
PointerOut = 6864,
|
|
23
|
+
//% block="wheel"
|
|
15
24
|
Wheel = 6865,
|
|
25
|
+
//% block="key down"
|
|
16
26
|
KeyDown = 6866,
|
|
27
|
+
//% block="key up"
|
|
17
28
|
KeyUp = 6867
|
|
18
29
|
}
|
|
19
30
|
|
|
20
31
|
export enum MouseButtonId {
|
|
32
|
+
//% block="left"
|
|
21
33
|
Left = 1,
|
|
34
|
+
//% block="right"
|
|
22
35
|
Right = 3,
|
|
36
|
+
//% block="wheel"
|
|
23
37
|
Wheel = 2,
|
|
38
|
+
//% block="back"
|
|
24
39
|
Back = 4,
|
|
40
|
+
//% block="forward"
|
|
25
41
|
Forward = 5
|
|
26
42
|
}
|
|
27
43
|
|
|
28
44
|
export enum MouseButtonEvent {
|
|
45
|
+
//% block="pressed"
|
|
29
46
|
Pressed = Event.PointerDown,
|
|
47
|
+
//% block="released"
|
|
30
48
|
Released = Event.PointerUp,
|
|
31
49
|
}
|
|
32
50
|
|
|
51
|
+
//% whenUsed
|
|
52
|
+
const INTERNAL_POINTER_DOWN = 6868;
|
|
53
|
+
//% whenUsed
|
|
54
|
+
const INTERNAL_POINTER_UP = 6869;
|
|
55
|
+
|
|
56
|
+
type MouseHandler = (x: number, y: number) => void;
|
|
57
|
+
|
|
33
58
|
//% fixedInstances
|
|
34
59
|
export class MouseButton {
|
|
35
60
|
protected _pressed: boolean;
|
|
36
|
-
|
|
37
|
-
protected
|
|
38
|
-
|
|
39
|
-
protected
|
|
61
|
+
|
|
62
|
+
protected sceneStack: _SceneButtonHandlers<MouseHandler>[];
|
|
63
|
+
|
|
64
|
+
protected get state(): _SceneButtonHandlers<MouseHandler> {
|
|
65
|
+
return this.sceneStack[this.sceneStack.length - 1];
|
|
66
|
+
}
|
|
40
67
|
|
|
41
68
|
constructor(public id: number) {
|
|
42
|
-
control.internalOnEvent(
|
|
43
|
-
control.internalOnEvent(
|
|
69
|
+
control.internalOnEvent(INTERNAL_POINTER_DOWN, this.id, () => this.setPressed(true), 16);
|
|
70
|
+
control.internalOnEvent(INTERNAL_POINTER_UP, this.id, () => this.setPressed(false), 16);
|
|
44
71
|
|
|
45
72
|
this._pressed = false;
|
|
46
|
-
|
|
47
|
-
this.
|
|
73
|
+
|
|
74
|
+
this.sceneStack = [new _SceneButtonHandlers<MouseHandler>(id, invokeMouseHandler)];
|
|
75
|
+
|
|
76
|
+
game.addScenePushHandler(() => {
|
|
77
|
+
this.sceneStack.push(new _SceneButtonHandlers<MouseHandler>(id, invokeMouseHandler));
|
|
78
|
+
});
|
|
79
|
+
game.addScenePopHandler(() => {
|
|
80
|
+
this.sceneStack.pop();
|
|
81
|
+
if (this.sceneStack.length === 0) {
|
|
82
|
+
this.sceneStack = [new _SceneButtonHandlers<MouseHandler>(id, invokeMouseHandler)];
|
|
83
|
+
}
|
|
84
|
+
});
|
|
48
85
|
}
|
|
49
86
|
|
|
50
87
|
setPressed(pressed: boolean) {
|
|
51
88
|
this._pressed = pressed;
|
|
89
|
+
|
|
52
90
|
if (pressed) {
|
|
53
|
-
|
|
54
|
-
this.pressHandler(mouseX(), mouseY());
|
|
55
|
-
}
|
|
56
|
-
for (const handler of this.pressListeners) {
|
|
57
|
-
handler(mouseX(), mouseY());
|
|
58
|
-
}
|
|
91
|
+
control.raiseEvent(MouseButtonEvent.Pressed, this.id);
|
|
59
92
|
}
|
|
60
93
|
else {
|
|
61
|
-
|
|
62
|
-
this.releaseHandler(mouseX(), mouseY());
|
|
63
|
-
}
|
|
64
|
-
for (const handler of this.releaseListeners) {
|
|
65
|
-
handler(mouseX(), mouseY());
|
|
66
|
-
}
|
|
94
|
+
control.raiseEvent(MouseButtonEvent.Released, this.id);
|
|
67
95
|
}
|
|
68
96
|
}
|
|
69
97
|
|
|
@@ -73,12 +101,7 @@ namespace browserEvents {
|
|
|
73
101
|
//% group="Mouse"
|
|
74
102
|
//% weight=50
|
|
75
103
|
onEvent(event: MouseButtonEvent, handler: (x: number, y: number) => void) {
|
|
76
|
-
|
|
77
|
-
this.pressHandler = handler;
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
this.releaseHandler = handler;
|
|
81
|
-
}
|
|
104
|
+
this.state.onEvent(event, handler);
|
|
82
105
|
}
|
|
83
106
|
|
|
84
107
|
//% blockId=browserEvents_mouseButton_isPressed
|
|
@@ -98,24 +121,72 @@ namespace browserEvents {
|
|
|
98
121
|
}
|
|
99
122
|
|
|
100
123
|
addEventListener(event: MouseButtonEvent, handler: (x: number, y: number) => void) {
|
|
101
|
-
|
|
102
|
-
this.pressListeners.push(handler);
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
this.releaseListeners.push(handler);
|
|
106
|
-
}
|
|
124
|
+
this.state.addEventListener(event, handler);
|
|
107
125
|
}
|
|
108
126
|
|
|
109
127
|
removeEventListener(event: MouseButtonEvent, handler: (x: number, y: number) => void) {
|
|
110
|
-
|
|
111
|
-
|
|
128
|
+
this.state.removeEventListener(event, handler);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export class _SceneButtonHandlers<U> {
|
|
133
|
+
protected handlers: ButtonHandler<U>[];
|
|
134
|
+
|
|
135
|
+
constructor(public id: number, protected invokeHandler: (handler: U) => void) {
|
|
136
|
+
this.handlers = [];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
onEvent(event: number, handler: U) {
|
|
140
|
+
this.getHandler(event, true).handler = handler;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
addEventListener(event: number, handler: U) {
|
|
144
|
+
this.getHandler(event, true).listeners.push(handler);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
removeEventListener(event: number, handler: U) {
|
|
148
|
+
const eventHandler = this.getHandler(event);
|
|
149
|
+
|
|
150
|
+
if (eventHandler) {
|
|
151
|
+
eventHandler.listeners = eventHandler.listeners.filter(h => h !== handler);
|
|
112
152
|
}
|
|
113
|
-
|
|
114
|
-
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
protected getHandler(event: number, createIfMissing?: boolean) {
|
|
156
|
+
for (const handler of this.handlers) {
|
|
157
|
+
if (handler.event === event) return handler;
|
|
115
158
|
}
|
|
159
|
+
|
|
160
|
+
if (createIfMissing) {
|
|
161
|
+
const newHandler = new ButtonHandler<U>(event, this.id, this.invokeHandler);
|
|
162
|
+
this.handlers.push(newHandler);
|
|
163
|
+
return newHandler;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return undefined;
|
|
116
167
|
}
|
|
117
168
|
}
|
|
118
169
|
|
|
170
|
+
class ButtonHandler<U> {
|
|
171
|
+
handler: U;
|
|
172
|
+
listeners: U[] = [];
|
|
173
|
+
|
|
174
|
+
constructor(public readonly event: number, id: number, invokeHandler: (handler: U) => void) {
|
|
175
|
+
control.onEvent(event, id, () => {
|
|
176
|
+
if (this.handler) {
|
|
177
|
+
invokeHandler(this.handler);
|
|
178
|
+
}
|
|
179
|
+
for (const listener of this.listeners) {
|
|
180
|
+
invokeHandler(listener);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function invokeMouseHandler(handler: MouseHandler) {
|
|
187
|
+
handler(mouseX(), mouseY());
|
|
188
|
+
}
|
|
189
|
+
|
|
119
190
|
//% blockId=browserEvents_onEvent
|
|
120
191
|
//% block="on browser event $event"
|
|
121
192
|
//% draggableParameters="reporter"
|
|
@@ -147,6 +218,14 @@ namespace browserEvents {
|
|
|
147
218
|
});
|
|
148
219
|
}
|
|
149
220
|
|
|
221
|
+
//% blockId=browserEvents_setCursorVisible
|
|
222
|
+
//% block="set cursor visible $visible"
|
|
223
|
+
//% group="Mouse"
|
|
224
|
+
//% weight=0
|
|
225
|
+
export function setCursorVisible(visible: boolean) {
|
|
226
|
+
_setCursorVisible(visible);
|
|
227
|
+
}
|
|
228
|
+
|
|
150
229
|
//% fixedInstance whenUsed block="left"
|
|
151
230
|
export const MouseLeft = new MouseButton(MouseButtonId.Left);
|
|
152
231
|
|
|
@@ -62,14 +62,29 @@ namespace browserEvents {
|
|
|
62
62
|
ArrowRight = 39,
|
|
63
63
|
PageDown = 34,
|
|
64
64
|
End = 35,
|
|
65
|
-
Home = 36
|
|
65
|
+
Home = 36,
|
|
66
|
+
LeftShift = 1016,
|
|
67
|
+
RightShift = 1017,
|
|
68
|
+
LeftControl = 1018,
|
|
69
|
+
RightControl = 1019,
|
|
70
|
+
Backspace = 8,
|
|
71
|
+
Delete = 46,
|
|
66
72
|
}
|
|
67
73
|
|
|
68
74
|
export enum KeyEvent {
|
|
69
|
-
|
|
70
|
-
|
|
75
|
+
//% block="pressed"
|
|
76
|
+
Pressed = 6872,
|
|
77
|
+
//% block="released"
|
|
78
|
+
Released = 6873,
|
|
79
|
+
//% block="repeat"
|
|
80
|
+
Repeat = 6874
|
|
71
81
|
}
|
|
72
82
|
|
|
83
|
+
//% whenUsed
|
|
84
|
+
const INTERNAL_KEY_DOWN = 6870;
|
|
85
|
+
//% whenUsed
|
|
86
|
+
const INTERNAL_KEY_UP = 6871;
|
|
87
|
+
|
|
73
88
|
export function keyToString(key: Key) {
|
|
74
89
|
switch (key) {
|
|
75
90
|
case Key.Q:
|
|
@@ -198,44 +213,95 @@ namespace browserEvents {
|
|
|
198
213
|
return "-";
|
|
199
214
|
case Key.Equals:
|
|
200
215
|
return "=";
|
|
216
|
+
case Key.LeftShift:
|
|
217
|
+
return "LeftShift";
|
|
218
|
+
case Key.RightShift:
|
|
219
|
+
return "RightShift";
|
|
220
|
+
case Key.LeftControl:
|
|
221
|
+
return "LeftControl";
|
|
222
|
+
case Key.RightControl:
|
|
223
|
+
return "RightControl";
|
|
224
|
+
case Key.Backspace:
|
|
225
|
+
return "Backspace";
|
|
226
|
+
case Key.Delete:
|
|
227
|
+
return "Delete";
|
|
201
228
|
}
|
|
202
229
|
}
|
|
203
230
|
|
|
231
|
+
//% whenUsed
|
|
232
|
+
let _buttonsPendingInit: KeyButton[];
|
|
233
|
+
|
|
234
|
+
let defaultRepeatDelay = 500;
|
|
235
|
+
let defaultRepeatInterval = 30;
|
|
236
|
+
|
|
237
|
+
type KeyHandler = () => void;
|
|
204
238
|
|
|
205
239
|
//% fixedInstances
|
|
206
240
|
export class KeyButton {
|
|
207
241
|
protected _pressed: boolean;
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
242
|
+
public repeatDelay: number;
|
|
243
|
+
public repeatInterval: number;
|
|
244
|
+
private _repeatCount: number;
|
|
245
|
+
private _pressedElapsed: number;
|
|
212
246
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
247
|
+
protected sceneStack: _SceneButtonHandlers<KeyHandler>[];
|
|
248
|
+
|
|
249
|
+
protected get state(): _SceneButtonHandlers<KeyHandler> {
|
|
250
|
+
return this.sceneStack[this.sceneStack.length - 1];
|
|
251
|
+
}
|
|
216
252
|
|
|
253
|
+
constructor(public id: number) {
|
|
254
|
+
// use internalOnEvent so that events fire regardless of the current scene
|
|
255
|
+
control.internalOnEvent(INTERNAL_KEY_UP, this.id, () => this.setPressed(false), 16);
|
|
256
|
+
control.internalOnEvent(INTERNAL_KEY_DOWN, this.id, () => this.setPressed(true), 16);
|
|
217
257
|
this._pressed = false;
|
|
218
|
-
|
|
219
|
-
this.
|
|
258
|
+
|
|
259
|
+
// this code may run before game/scene.ts, in which case calling this.__registerUpdate
|
|
260
|
+
// will trigger an exception. to prevent that, start a thread that pauses until we
|
|
261
|
+
// detect that an event context has been registered and then call it
|
|
262
|
+
if (control.eventContext()) {
|
|
263
|
+
this.__registerUpdate();
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
if (!_buttonsPendingInit) {
|
|
267
|
+
_buttonsPendingInit = [];
|
|
268
|
+
control.runInBackground(() => {
|
|
269
|
+
pauseUntil(() => !!control.eventContext());
|
|
270
|
+
for (const button of _buttonsPendingInit) {
|
|
271
|
+
button.__registerUpdate();
|
|
272
|
+
}
|
|
273
|
+
_buttonsPendingInit = undefined;
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
_buttonsPendingInit.push(this);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
this.sceneStack = [new _SceneButtonHandlers<KeyHandler>(id, invokeKeyHandler)];
|
|
280
|
+
|
|
281
|
+
game.addScenePushHandler(() => {
|
|
282
|
+
this.sceneStack.push(new _SceneButtonHandlers<KeyHandler>(id, invokeKeyHandler));
|
|
283
|
+
this.__registerUpdate();
|
|
284
|
+
});
|
|
285
|
+
game.addScenePopHandler(() => {
|
|
286
|
+
this.sceneStack.pop();
|
|
287
|
+
if (this.sceneStack.length === 0) {
|
|
288
|
+
this.sceneStack = [new _SceneButtonHandlers<KeyHandler>(id, invokeKeyHandler)];
|
|
289
|
+
this.__registerUpdate();
|
|
290
|
+
}
|
|
291
|
+
});
|
|
220
292
|
}
|
|
221
293
|
|
|
222
294
|
setPressed(pressed: boolean) {
|
|
295
|
+
if (this._pressed === pressed) return;
|
|
296
|
+
|
|
223
297
|
this._pressed = pressed;
|
|
224
298
|
if (pressed) {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
for (const handler of this.pressListeners) {
|
|
229
|
-
handler();
|
|
230
|
-
}
|
|
299
|
+
this._repeatCount = 0;
|
|
300
|
+
this._pressedElapsed = 0;
|
|
301
|
+
control.raiseEvent(KeyEvent.Pressed, this.id);
|
|
231
302
|
}
|
|
232
303
|
else {
|
|
233
|
-
|
|
234
|
-
this.releaseHandler();
|
|
235
|
-
}
|
|
236
|
-
for (const handler of this.releaseListeners) {
|
|
237
|
-
handler();
|
|
238
|
-
}
|
|
304
|
+
control.raiseEvent(KeyEvent.Released, this.id);
|
|
239
305
|
}
|
|
240
306
|
}
|
|
241
307
|
|
|
@@ -244,12 +310,7 @@ namespace browserEvents {
|
|
|
244
310
|
//% group="Keyboard"
|
|
245
311
|
//% weight=100
|
|
246
312
|
onEvent(event: KeyEvent, handler: () => void) {
|
|
247
|
-
|
|
248
|
-
this.pressHandler = handler;
|
|
249
|
-
}
|
|
250
|
-
else {
|
|
251
|
-
this.releaseHandler = handler;
|
|
252
|
-
}
|
|
313
|
+
this.state.onEvent(event, handler);
|
|
253
314
|
}
|
|
254
315
|
|
|
255
316
|
//% blockId=browserEvents_key_isPressed
|
|
@@ -269,22 +330,38 @@ namespace browserEvents {
|
|
|
269
330
|
}
|
|
270
331
|
|
|
271
332
|
addEventListener(event: KeyEvent, handler: () => void) {
|
|
272
|
-
|
|
273
|
-
this.pressListeners.push(handler);
|
|
274
|
-
}
|
|
275
|
-
else {
|
|
276
|
-
this.releaseListeners.push(handler);
|
|
277
|
-
}
|
|
333
|
+
this.state.addEventListener(event, handler);
|
|
278
334
|
}
|
|
279
335
|
|
|
280
336
|
removeEventListener(event: KeyEvent, handler: () => void) {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
337
|
+
this.state.removeEventListener(event, handler);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
__update() {
|
|
341
|
+
const delay = this.repeatDelay === undefined ? defaultRepeatDelay : this.repeatDelay;
|
|
342
|
+
const interval = this.repeatInterval === undefined ? defaultRepeatInterval : this.repeatInterval;
|
|
343
|
+
if (!this._pressed) return;
|
|
344
|
+
this._pressedElapsed += game.eventContext().deltaTimeMillis;
|
|
345
|
+
|
|
346
|
+
// inital delay
|
|
347
|
+
if (this._pressedElapsed < delay)
|
|
348
|
+
return;
|
|
349
|
+
|
|
350
|
+
// repeat count for this step
|
|
351
|
+
const count = Math.floor((this._pressedElapsed - delay - interval) / interval);
|
|
352
|
+
if (count != this._repeatCount) {
|
|
353
|
+
this._repeatCount = count;
|
|
354
|
+
control.raiseEvent(KeyEvent.Repeat, this.id);
|
|
286
355
|
}
|
|
287
356
|
}
|
|
357
|
+
|
|
358
|
+
__registerUpdate() {
|
|
359
|
+
game.eventContext().registerFrameHandler(scene.CONTROLLER_PRIORITY, () => this.__update());
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
function invokeKeyHandler(handler: KeyHandler) {
|
|
364
|
+
handler();
|
|
288
365
|
}
|
|
289
366
|
|
|
290
367
|
//% fixedInstance whenUsed
|
|
@@ -476,6 +553,35 @@ namespace browserEvents {
|
|
|
476
553
|
//% fixedInstance whenUsed
|
|
477
554
|
export const Home = new KeyButton(Key.Home);
|
|
478
555
|
|
|
556
|
+
//% fixedInstance whenUsed
|
|
557
|
+
export const LeftShift = new KeyButton(Key.LeftShift);
|
|
558
|
+
|
|
559
|
+
//% fixedInstance whenUsed
|
|
560
|
+
export const RightShift = new KeyButton(Key.RightShift);
|
|
561
|
+
|
|
562
|
+
//% fixedInstance whenUsed
|
|
563
|
+
export const LeftControl = new KeyButton(Key.LeftControl);
|
|
564
|
+
|
|
565
|
+
//% fixedInstance whenUsed
|
|
566
|
+
export const RightControl = new KeyButton(Key.RightControl);
|
|
567
|
+
|
|
568
|
+
//% fixedInstance whenUsed
|
|
569
|
+
export const Backspace = new KeyButton(Key.Backspace);
|
|
570
|
+
|
|
571
|
+
//% fixedInstance whenUsed
|
|
572
|
+
export const Delete = new KeyButton(Key.Delete);
|
|
573
|
+
|
|
479
574
|
//% fixedInstance whenUsed
|
|
480
575
|
export const Any = new KeyButton(0);
|
|
576
|
+
|
|
577
|
+
//% blockId=browser_events_setKeyboardRepeatDefault
|
|
578
|
+
//% block="set keyboard repeat delay $delay ms interval $interval ms"
|
|
579
|
+
//% delay.defl=500
|
|
580
|
+
//% interval.defl=30
|
|
581
|
+
//% group="Keyboard"
|
|
582
|
+
//% weight=0
|
|
583
|
+
export function setKeyboardRepeatDefault(delay: number, interval: number) {
|
|
584
|
+
defaultRepeatDelay = Math.max(delay, 0);
|
|
585
|
+
defaultRepeatInterval = Math.max(interval, 1);
|
|
586
|
+
}
|
|
481
587
|
}
|
|
@@ -9,6 +9,8 @@ declare namespace browserEvents {
|
|
|
9
9
|
function wheelDy(): number;
|
|
10
10
|
//% shim=browserEvents::wheelDz
|
|
11
11
|
function wheelDz(): number;
|
|
12
|
+
//% shim=browserEvents::_setCursorVisible
|
|
13
|
+
function _setCursorVisible(visible: boolean): void;
|
|
12
14
|
|
|
13
15
|
//% shim=browserEvents::currentTime
|
|
14
16
|
function currentTime(): number;
|
|
@@ -62,15 +62,44 @@ namespace pxsim.browserEvents {
|
|
|
62
62
|
ArrowRight = 39,
|
|
63
63
|
PageDown = 34,
|
|
64
64
|
End = 35,
|
|
65
|
-
Home = 36
|
|
65
|
+
Home = 36,
|
|
66
|
+
LeftShift = 1016,
|
|
67
|
+
RightShift = 1017,
|
|
68
|
+
LeftControl = 1018,
|
|
69
|
+
RightControl = 1019,
|
|
70
|
+
Backspace = 8,
|
|
71
|
+
Delete = 46,
|
|
66
72
|
}
|
|
67
73
|
|
|
68
74
|
export function onKeyboardEvent(event: KeyboardEvent, pressed: boolean) {
|
|
75
|
+
const eventValue = getValueForKey(event);
|
|
76
|
+
|
|
77
|
+
fireEvent(eventValue as Key, pressed);
|
|
78
|
+
|
|
79
|
+
if (eventValue === Key.Shift) {
|
|
80
|
+
if (event.location === event.DOM_KEY_LOCATION_LEFT) {
|
|
81
|
+
fireEvent(Key.LeftShift, pressed);
|
|
82
|
+
}
|
|
83
|
+
else if (event.location === event.DOM_KEY_LOCATION_RIGHT) {
|
|
84
|
+
fireEvent(Key.RightShift, pressed);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (eventValue === Key.Control) {
|
|
88
|
+
if (event.location === event.DOM_KEY_LOCATION_LEFT) {
|
|
89
|
+
fireEvent(Key.LeftControl, pressed);
|
|
90
|
+
}
|
|
91
|
+
else if (event.location === event.DOM_KEY_LOCATION_RIGHT) {
|
|
92
|
+
fireEvent(Key.RightControl, pressed);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function fireEvent(key: Key, pressed: boolean) {
|
|
69
98
|
if (pressed) {
|
|
70
|
-
board().bus.queue(
|
|
99
|
+
board().bus.queue(INTERNAL_KEY_DOWN, key);
|
|
71
100
|
}
|
|
72
101
|
else {
|
|
73
|
-
board().bus.queue(
|
|
102
|
+
board().bus.queue(INTERNAL_KEY_UP, key);
|
|
74
103
|
}
|
|
75
104
|
}
|
|
76
105
|
|
|
@@ -249,6 +278,10 @@ namespace pxsim.browserEvents {
|
|
|
249
278
|
return Key.End;
|
|
250
279
|
case "Home":
|
|
251
280
|
return Key.Home;
|
|
281
|
+
case "Delete":
|
|
282
|
+
return Key.Delete;
|
|
283
|
+
case "Backspace":
|
|
284
|
+
return Key.Backspace;
|
|
252
285
|
default:
|
|
253
286
|
return 0;
|
|
254
287
|
}
|
|
@@ -5,6 +5,11 @@ namespace pxsim.browserEvents {
|
|
|
5
5
|
|
|
6
6
|
const THROTTLE_INTERVAL = 50;
|
|
7
7
|
|
|
8
|
+
export const INTERNAL_KEY_DOWN = 6870;
|
|
9
|
+
export const INTERNAL_KEY_UP = 6871;
|
|
10
|
+
export const INTERNAL_POINTER_DOWN = 6868;
|
|
11
|
+
export const INTERNAL_POINTER_UP = 6869;
|
|
12
|
+
|
|
8
13
|
export type MouseEvent = "pointerdown" | "pointerup" | "pointermove" | "pointerleave" | "pointerenter" | "pointercancel" | "pointerover" | "pointerout";
|
|
9
14
|
export class MouseState {
|
|
10
15
|
protected x: number;
|
|
@@ -43,10 +48,19 @@ namespace pxsim.browserEvents {
|
|
|
43
48
|
"pointerout",
|
|
44
49
|
];
|
|
45
50
|
|
|
51
|
+
let eventId = 6857 + events.indexOf(event.type);
|
|
52
|
+
|
|
53
|
+
if (event.type === "pointerdown") {
|
|
54
|
+
eventId = INTERNAL_POINTER_DOWN;
|
|
55
|
+
}
|
|
56
|
+
else if (event.type === "pointerup") {
|
|
57
|
+
eventId = INTERNAL_POINTER_UP;
|
|
58
|
+
}
|
|
59
|
+
|
|
46
60
|
// We add 1 to the button here because the left button is 0 and
|
|
47
61
|
// that's used as a wildcard in our event bus
|
|
48
62
|
board().bus.queue(
|
|
49
|
-
|
|
63
|
+
eventId,
|
|
50
64
|
(event.button || 0) + 1
|
|
51
65
|
);
|
|
52
66
|
}
|