@m2c2kit/addons 0.3.15 → 0.3.17
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/index.d.ts +435 -66
- package/dist/index.js +1260 -418
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Composite, WebColors, Shape, Label, CanvasKitHelpers, M2EventType, MutablePath, Easings, Story, Transition, TransitionDirection, LabelHorizontalAlignmentMode, Scene, Dimensions, Sprite, Action } from '@m2c2kit/core';
|
|
1
|
+
import { M2c2KitHelpers, Composite, WebColors, Shape, EventStoreMode, Equal, Label, CanvasKitHelpers, M2EventType, Timer, MutablePath, Easings, Story, Transition, TransitionDirection, LabelHorizontalAlignmentMode, Scene, Dimensions, Sprite, Action } from '@m2c2kit/core';
|
|
2
2
|
|
|
3
3
|
class Grid extends Composite {
|
|
4
4
|
/**
|
|
@@ -13,16 +13,16 @@ class Grid extends Composite {
|
|
|
13
13
|
*/
|
|
14
14
|
constructor(options) {
|
|
15
15
|
super(options);
|
|
16
|
-
this.compositeType = "
|
|
16
|
+
this.compositeType = "Grid";
|
|
17
17
|
// Grid options
|
|
18
|
-
|
|
19
|
-
this.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
this.
|
|
23
|
-
this.
|
|
24
|
-
this.
|
|
25
|
-
this.
|
|
18
|
+
this._rows = 0;
|
|
19
|
+
this._columns = 0;
|
|
20
|
+
// default Grid is: transparent blue, red lines, line width 1
|
|
21
|
+
this._gridBackgroundColor = [0, 0, 255, 0.25];
|
|
22
|
+
this._gridLineColor = WebColors.Red;
|
|
23
|
+
this._gridLineWidth = 1;
|
|
24
|
+
this._gridChildren = new Array();
|
|
25
|
+
this.cellContainers = new Array();
|
|
26
26
|
if (options.size) {
|
|
27
27
|
this.size = options.size;
|
|
28
28
|
} else {
|
|
@@ -32,19 +32,19 @@ class Grid extends Composite {
|
|
|
32
32
|
if (options.rows >= 1) {
|
|
33
33
|
this.rows = options.rows;
|
|
34
34
|
} else {
|
|
35
|
-
throw new Error("rows must be at least 1");
|
|
35
|
+
throw new Error("grid rows must be at least 1");
|
|
36
36
|
}
|
|
37
37
|
} else {
|
|
38
|
-
throw new Error("rows must be specified");
|
|
38
|
+
throw new Error("grid rows must be specified");
|
|
39
39
|
}
|
|
40
40
|
if (options.columns) {
|
|
41
41
|
if (options.columns >= 1) {
|
|
42
42
|
this.columns = options.columns;
|
|
43
43
|
} else {
|
|
44
|
-
throw new Error("columns must be at least 1");
|
|
44
|
+
throw new Error("grid columns must be at least 1");
|
|
45
45
|
}
|
|
46
46
|
} else {
|
|
47
|
-
throw new Error("columns must be specified");
|
|
47
|
+
throw new Error("grid columns must be specified");
|
|
48
48
|
}
|
|
49
49
|
if (options.backgroundColor) {
|
|
50
50
|
this.gridBackgroundColor = options.backgroundColor;
|
|
@@ -57,56 +57,114 @@ class Grid extends Composite {
|
|
|
57
57
|
}
|
|
58
58
|
this.cellWidth = this.size.width / this.columns;
|
|
59
59
|
this.cellHeight = this.size.height / this.rows;
|
|
60
|
+
this.saveNodeNewEvent();
|
|
61
|
+
}
|
|
62
|
+
get completeNodeOptions() {
|
|
63
|
+
return {
|
|
64
|
+
...this.options,
|
|
65
|
+
...this.getNodeOptions(),
|
|
66
|
+
...this.getDrawableOptions(),
|
|
67
|
+
rows: this.rows,
|
|
68
|
+
columns: this.columns,
|
|
69
|
+
size: this.size,
|
|
70
|
+
backgroundColor: this.gridBackgroundColor,
|
|
71
|
+
gridLineWidth: this.gridLineWidth,
|
|
72
|
+
gridLineColor: this.gridLineColor
|
|
73
|
+
};
|
|
60
74
|
}
|
|
61
75
|
initialize() {
|
|
62
|
-
|
|
76
|
+
this.descendants.forEach((d) => {
|
|
77
|
+
if (d.parent === this) {
|
|
78
|
+
super.removeChild(d);
|
|
79
|
+
} else {
|
|
80
|
+
d.parent?.removeChild(d);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
63
83
|
this.gridBackground = new Shape({
|
|
64
|
-
name: "
|
|
84
|
+
name: "__" + this.name + "-gridRectangle",
|
|
65
85
|
rect: { size: this.size },
|
|
66
|
-
//size: this.size,
|
|
67
86
|
fillColor: this.gridBackgroundColor,
|
|
68
87
|
strokeColor: this.gridLineColor,
|
|
69
88
|
lineWidth: this.gridLineWidth,
|
|
70
|
-
isUserInteractionEnabled: this.isUserInteractionEnabled
|
|
89
|
+
isUserInteractionEnabled: this.isUserInteractionEnabled,
|
|
90
|
+
suppressEvents: true
|
|
71
91
|
});
|
|
72
|
-
|
|
92
|
+
super.addChild(this.gridBackground);
|
|
73
93
|
this.gridBackground.isUserInteractionEnabled = this.isUserInteractionEnabled;
|
|
74
94
|
for (let col = 1; col < this.columns; col++) {
|
|
75
95
|
const verticalLine = new Shape({
|
|
76
|
-
name: "
|
|
96
|
+
name: "__" + this.name + "-gridVerticalLine-" + (col - 1),
|
|
77
97
|
rect: {
|
|
78
98
|
size: { width: this.gridLineWidth, height: this.size.height },
|
|
79
99
|
origin: { x: -this.size.width / 2 + this.cellWidth * col, y: 0 }
|
|
80
100
|
},
|
|
81
|
-
fillColor: this.gridLineColor
|
|
101
|
+
fillColor: this.gridLineColor,
|
|
102
|
+
suppressEvents: true
|
|
82
103
|
});
|
|
83
104
|
this.gridBackground.addChild(verticalLine);
|
|
84
105
|
}
|
|
85
106
|
for (let row = 1; row < this.rows; row++) {
|
|
86
107
|
const horizontalLine = new Shape({
|
|
87
|
-
name: "
|
|
108
|
+
name: "__" + this.name + "-gridHorizontalLine-" + (row - 1),
|
|
88
109
|
rect: {
|
|
89
110
|
size: { width: this.size.width, height: this.gridLineWidth },
|
|
90
111
|
origin: { x: 0, y: -this.size.height / 2 + this.cellHeight * row }
|
|
91
112
|
},
|
|
92
|
-
fillColor: this.gridLineColor
|
|
113
|
+
fillColor: this.gridLineColor,
|
|
114
|
+
suppressEvents: true
|
|
93
115
|
});
|
|
94
116
|
this.gridBackground.addChild(horizontalLine);
|
|
95
117
|
}
|
|
96
|
-
|
|
118
|
+
this.cellContainers = new Array(this.rows).fill([]).map(() => new Array(this.columns));
|
|
119
|
+
for (let row = 0; row < this.rows; row++) {
|
|
120
|
+
for (let col = 0; col < this.columns; col++) {
|
|
121
|
+
const cellContainer = new Shape({
|
|
122
|
+
name: "__" + this.name + "-gridCellContainer-" + row + "-" + col,
|
|
123
|
+
rect: {
|
|
124
|
+
size: { width: this.cellWidth, height: this.cellHeight },
|
|
125
|
+
origin: {
|
|
126
|
+
x: -this.size.width / 2 + this.cellWidth * col + this.cellWidth / 2,
|
|
127
|
+
y: -this.size.height / 2 + this.cellHeight * row + this.cellHeight / 2
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
fillColor: WebColors.Transparent,
|
|
131
|
+
lineWidth: 0,
|
|
132
|
+
suppressEvents: true
|
|
133
|
+
});
|
|
134
|
+
this.gridBackground.addChild(cellContainer);
|
|
135
|
+
this.cellContainers[row][col] = cellContainer;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (this.gridChildren.length > 0) {
|
|
97
139
|
this.gridChildren.forEach((gridChild) => {
|
|
98
140
|
if (!this.cellWidth || !this.cellHeight || !this.gridBackground) {
|
|
99
141
|
throw new Error(
|
|
100
142
|
"cellWidth, cellHeight, or gridBackground undefined or null"
|
|
101
143
|
);
|
|
102
144
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
145
|
+
if (this.game.eventStore.mode === EventStoreMode.Replay) {
|
|
146
|
+
const childNode = [
|
|
147
|
+
...this.game.nodes,
|
|
148
|
+
...this.game.materializedNodes
|
|
149
|
+
].find(
|
|
150
|
+
(n) => (
|
|
151
|
+
// gridChild.node is the uuid of the child node here!
|
|
152
|
+
n.uuid === gridChild.node
|
|
153
|
+
)
|
|
154
|
+
);
|
|
155
|
+
if (!childNode) {
|
|
156
|
+
throw new Error("grid: child node not found");
|
|
157
|
+
}
|
|
158
|
+
childNode?.parent?.removeChild(childNode);
|
|
159
|
+
this.cellContainers[gridChild.row][gridChild.column].addChild(
|
|
160
|
+
childNode
|
|
161
|
+
);
|
|
162
|
+
} else {
|
|
163
|
+
gridChild.node.parent?.removeChild(gridChild.node);
|
|
164
|
+
this.cellContainers[gridChild.row][gridChild.column].addChild(
|
|
165
|
+
gridChild.node
|
|
166
|
+
);
|
|
167
|
+
}
|
|
110
168
|
});
|
|
111
169
|
}
|
|
112
170
|
this.needsInitialization = false;
|
|
@@ -120,6 +178,60 @@ class Grid extends Composite {
|
|
|
120
178
|
set gridBackground(gridBackground) {
|
|
121
179
|
this._gridBackground = gridBackground;
|
|
122
180
|
}
|
|
181
|
+
/**
|
|
182
|
+
* note: below we do not have getter and setter for size because the getter
|
|
183
|
+
* and setter in M2Node will handle it.
|
|
184
|
+
*/
|
|
185
|
+
get rows() {
|
|
186
|
+
return this._rows;
|
|
187
|
+
}
|
|
188
|
+
set rows(rows) {
|
|
189
|
+
if (Equal.value(this._rows, rows)) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
this._rows = rows;
|
|
193
|
+
this.needsInitialization = true;
|
|
194
|
+
}
|
|
195
|
+
get columns() {
|
|
196
|
+
return this._columns;
|
|
197
|
+
}
|
|
198
|
+
set columns(columns) {
|
|
199
|
+
if (Equal.value(this._columns, columns)) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
this._columns = columns;
|
|
203
|
+
this.needsInitialization = true;
|
|
204
|
+
}
|
|
205
|
+
get gridBackgroundColor() {
|
|
206
|
+
return this._gridBackgroundColor;
|
|
207
|
+
}
|
|
208
|
+
set gridBackgroundColor(backgroundColor) {
|
|
209
|
+
if (Equal.value(this._gridBackgroundColor, backgroundColor)) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
this._gridBackgroundColor = backgroundColor;
|
|
213
|
+
this.needsInitialization = true;
|
|
214
|
+
}
|
|
215
|
+
get gridLineWidth() {
|
|
216
|
+
return this._gridLineWidth;
|
|
217
|
+
}
|
|
218
|
+
set gridLineWidth(gridLineWidth) {
|
|
219
|
+
if (Equal.value(this._gridLineWidth, gridLineWidth)) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
this._gridLineWidth = gridLineWidth;
|
|
223
|
+
this.needsInitialization = true;
|
|
224
|
+
}
|
|
225
|
+
get gridLineColor() {
|
|
226
|
+
return this._gridLineColor;
|
|
227
|
+
}
|
|
228
|
+
set gridLineColor(gridLineColor) {
|
|
229
|
+
if (Equal.value(this._gridLineColor, gridLineColor)) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
this._gridLineColor = gridLineColor;
|
|
233
|
+
this.needsInitialization = true;
|
|
234
|
+
}
|
|
123
235
|
// all nodes that make up grid are added as children, so they
|
|
124
236
|
// have their own dispose methods
|
|
125
237
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
@@ -168,25 +280,47 @@ class Grid extends Composite {
|
|
|
168
280
|
child.warmup(canvas);
|
|
169
281
|
});
|
|
170
282
|
}
|
|
171
|
-
// override M2Node.RemoveAllChildren() so that when RemoveAllChildren() is called on a Grid,
|
|
172
|
-
// it removes only nodes added to the grid cells (what we call grid children), not the grid lines!
|
|
173
283
|
/**
|
|
174
|
-
*
|
|
284
|
+
* The child nodes that have been added to the grid.
|
|
285
|
+
*
|
|
286
|
+
* @remarks Do not set this property directly. Use the methods for adding
|
|
287
|
+
* and removing grid children, such as `addAtCell()`, `removeAllAtCell()`,
|
|
288
|
+
* `removeGridChild()`, and `removeAllGridChildren()`.
|
|
175
289
|
*/
|
|
176
|
-
|
|
290
|
+
get gridChildren() {
|
|
291
|
+
return this._gridChildren;
|
|
292
|
+
}
|
|
293
|
+
set gridChildren(gridChildren) {
|
|
294
|
+
this._gridChildren = gridChildren;
|
|
295
|
+
this.needsInitialization = true;
|
|
296
|
+
this.savePropertyChangeEvent(
|
|
297
|
+
"gridChildren",
|
|
298
|
+
this.gridChildren.map(
|
|
299
|
+
(gridChild) => ({
|
|
300
|
+
node: gridChild.node.uuid,
|
|
301
|
+
row: gridChild.row,
|
|
302
|
+
column: gridChild.column
|
|
303
|
+
})
|
|
304
|
+
)
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Removes all grid children from the grid.
|
|
309
|
+
*
|
|
310
|
+
* @remarks This retains grid lines and grid appearance.
|
|
311
|
+
*/
|
|
312
|
+
removeAllGridChildren() {
|
|
177
313
|
if (this.gridChildren.length === 0) {
|
|
178
314
|
return;
|
|
179
315
|
}
|
|
180
316
|
while (this.gridChildren.length) {
|
|
181
|
-
|
|
182
|
-
if (gridChild) {
|
|
183
|
-
this.gridBackground.removeChild(gridChild.node);
|
|
184
|
-
}
|
|
317
|
+
this.gridChildren = this.gridChildren.slice(0, -1);
|
|
185
318
|
}
|
|
186
319
|
this.needsInitialization = true;
|
|
187
320
|
}
|
|
188
321
|
/**
|
|
189
|
-
* Adds a node to the grid at the specified row and column
|
|
322
|
+
* Adds a node as a grid child to the grid at the specified row and column
|
|
323
|
+
* position.
|
|
190
324
|
*
|
|
191
325
|
* @param node - node to add to the grid
|
|
192
326
|
* @param row - row position within grid to add node; zero-based indexing
|
|
@@ -198,49 +332,68 @@ class Grid extends Composite {
|
|
|
198
332
|
`warning: addAtCell() requested to add node at row ${row}, column ${column}. This is outside the bounds of grid ${this.name}, which is size ${this.rows}x${this.columns}. Note that addAtCell() uses zero-based indexing. AddAtCell() will proceed, but may draw nodes outside the grid`
|
|
199
333
|
);
|
|
200
334
|
}
|
|
201
|
-
this.gridChildren
|
|
335
|
+
this.gridChildren = [
|
|
336
|
+
...this.gridChildren,
|
|
337
|
+
{ node, row, column }
|
|
338
|
+
];
|
|
202
339
|
this.needsInitialization = true;
|
|
203
340
|
}
|
|
204
341
|
/**
|
|
205
|
-
* Removes all child nodes at the specified row and column position.
|
|
342
|
+
* Removes all grid child nodes at the specified row and column position.
|
|
206
343
|
*
|
|
207
|
-
* @param row - row position within grid at which to remove children; zero-based indexing
|
|
208
|
-
* @param column - column position within grid at which to remove children; zero-based indexing
|
|
344
|
+
* @param row - row position within grid at which to remove grid children; zero-based indexing
|
|
345
|
+
* @param column - column position within grid at which to remove grid children; zero-based indexing
|
|
209
346
|
*/
|
|
210
347
|
removeAllAtCell(row, column) {
|
|
211
|
-
const gridChildrenToRemove = this.gridChildren.filter(
|
|
212
|
-
(gridChild) => gridChild.row === row && gridChild.column === column
|
|
213
|
-
);
|
|
214
|
-
if (gridChildrenToRemove.length === 0) {
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
this.gridBackground.removeChildren(
|
|
218
|
-
gridChildrenToRemove.map((gridChild) => gridChild.node)
|
|
219
|
-
);
|
|
220
348
|
this.gridChildren = this.gridChildren.filter(
|
|
221
349
|
(gridChild) => gridChild.row !== row && gridChild.column !== column
|
|
222
350
|
);
|
|
223
351
|
this.needsInitialization = true;
|
|
224
352
|
}
|
|
225
|
-
// override M2Node.RemoveChild() so that when RemoveChild() is called on a Grid, it removes the
|
|
226
|
-
// node from the gridBackground rectangle AND our grid's own list of children (in gridChildren)
|
|
227
353
|
/**
|
|
228
|
-
* Removes the child node from the grid.
|
|
354
|
+
* Removes the grid child node from the grid.
|
|
229
355
|
*
|
|
230
356
|
* @param node - node to remove
|
|
231
357
|
*/
|
|
232
|
-
|
|
233
|
-
this.gridBackground.removeChild(node);
|
|
358
|
+
removeGridChild(node) {
|
|
234
359
|
this.gridChildren = this.gridChildren.filter(
|
|
235
360
|
(gridChild) => gridChild.node != node
|
|
236
361
|
);
|
|
237
362
|
this.needsInitialization = true;
|
|
238
363
|
}
|
|
364
|
+
// The Grid manages its own children (background, lines, and cell
|
|
365
|
+
// containers). It is probably a mistake when the user tries to add or remove
|
|
366
|
+
// these children. The user probably meant to add or remove grid children
|
|
367
|
+
// instead. Warn the user about this.
|
|
368
|
+
addChild(child) {
|
|
369
|
+
console.warn(
|
|
370
|
+
"Grid.addChild() was called -- did you mean to call addAtCell() instead?"
|
|
371
|
+
);
|
|
372
|
+
super.addChild(child);
|
|
373
|
+
}
|
|
374
|
+
removeAllChildren() {
|
|
375
|
+
console.warn(
|
|
376
|
+
"Grid.removeAllChildren() was called -- did you mean to call removeAllGridChildren() instead?"
|
|
377
|
+
);
|
|
378
|
+
super.removeAllChildren();
|
|
379
|
+
}
|
|
380
|
+
removeChild(child) {
|
|
381
|
+
console.warn(
|
|
382
|
+
"Grid.removeChild() was called -- did you mean to call removeGridChild() instead?"
|
|
383
|
+
);
|
|
384
|
+
super.removeChild(child);
|
|
385
|
+
}
|
|
386
|
+
removeChildren(children) {
|
|
387
|
+
console.warn(
|
|
388
|
+
"Grid.removeChildren() was called -- did you mean to call removeGridChild() instead?"
|
|
389
|
+
);
|
|
390
|
+
super.removeChildren(children);
|
|
391
|
+
}
|
|
239
392
|
}
|
|
393
|
+
M2c2KitHelpers.registerM2NodeClass(Grid);
|
|
240
394
|
|
|
241
395
|
class Button extends Composite {
|
|
242
|
-
//
|
|
243
|
-
// todo: add default "behaviors" (?) like button click animation?
|
|
396
|
+
// TODO: add default "behaviors" (?) like button click animation?
|
|
244
397
|
/**
|
|
245
398
|
* A simple button of rectangle with text centered inside.
|
|
246
399
|
*
|
|
@@ -252,12 +405,12 @@ class Button extends Composite {
|
|
|
252
405
|
*/
|
|
253
406
|
constructor(options) {
|
|
254
407
|
super(options);
|
|
255
|
-
this.compositeType = "
|
|
408
|
+
this.compositeType = "Button";
|
|
409
|
+
this.isText = true;
|
|
256
410
|
// Button options
|
|
257
411
|
this._backgroundColor = WebColors.Black;
|
|
258
|
-
this.
|
|
259
|
-
this.
|
|
260
|
-
this.fontSize = 20;
|
|
412
|
+
this._cornerRadius = 9;
|
|
413
|
+
this._fontSize = 20;
|
|
261
414
|
this._text = "";
|
|
262
415
|
this._fontColor = WebColors.White;
|
|
263
416
|
this._interpolation = {};
|
|
@@ -267,6 +420,8 @@ class Button extends Composite {
|
|
|
267
420
|
}
|
|
268
421
|
if (options.size) {
|
|
269
422
|
this.size = options.size;
|
|
423
|
+
} else {
|
|
424
|
+
this.size = { width: 200, height: 50 };
|
|
270
425
|
}
|
|
271
426
|
if (options.cornerRadius !== void 0) {
|
|
272
427
|
this.cornerRadius = options.cornerRadius;
|
|
@@ -292,6 +447,19 @@ class Button extends Composite {
|
|
|
292
447
|
if (options.localize !== void 0) {
|
|
293
448
|
this.localize = options.localize;
|
|
294
449
|
}
|
|
450
|
+
this.saveNodeNewEvent();
|
|
451
|
+
}
|
|
452
|
+
get completeNodeOptions() {
|
|
453
|
+
return {
|
|
454
|
+
...this.options,
|
|
455
|
+
...this.getNodeOptions(),
|
|
456
|
+
...this.getDrawableOptions(),
|
|
457
|
+
...this.getTextOptions(),
|
|
458
|
+
size: this.size,
|
|
459
|
+
cornerRadius: this.cornerRadius,
|
|
460
|
+
backgroundColor: this.backgroundColor,
|
|
461
|
+
fontNames: this.fontNames
|
|
462
|
+
};
|
|
295
463
|
}
|
|
296
464
|
initialize() {
|
|
297
465
|
this.removeAllChildren();
|
|
@@ -306,19 +474,23 @@ class Button extends Composite {
|
|
|
306
474
|
);
|
|
307
475
|
this.backgroundPaint.setStyle(this.canvasKit.PaintStyle.Fill);
|
|
308
476
|
const buttonRectangle = new Shape({
|
|
477
|
+
name: "__" + this.name + "-buttonRectangle",
|
|
309
478
|
rect: { size: this.size },
|
|
310
479
|
cornerRadius: this.cornerRadius,
|
|
311
|
-
fillColor: this._backgroundColor
|
|
480
|
+
fillColor: this._backgroundColor,
|
|
481
|
+
suppressEvents: true
|
|
312
482
|
});
|
|
313
483
|
this.addChild(buttonRectangle);
|
|
314
484
|
const buttonLabel = new Label({
|
|
485
|
+
name: "__" + this.name + "-buttonLabel",
|
|
315
486
|
text: this.text,
|
|
316
487
|
localize: this.localize,
|
|
317
488
|
interpolation: this.interpolation,
|
|
318
489
|
fontName: this.fontName,
|
|
319
490
|
fontNames: this.fontNames,
|
|
320
491
|
fontSize: this.fontSize,
|
|
321
|
-
fontColor: this.fontColor
|
|
492
|
+
fontColor: this.fontColor,
|
|
493
|
+
suppressEvents: true
|
|
322
494
|
});
|
|
323
495
|
buttonRectangle.addChild(buttonLabel);
|
|
324
496
|
this.needsInitialization = false;
|
|
@@ -330,51 +502,101 @@ class Button extends Composite {
|
|
|
330
502
|
return this._text;
|
|
331
503
|
}
|
|
332
504
|
set text(text) {
|
|
505
|
+
if (Equal.value(this._text, text)) {
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
333
508
|
this._text = text;
|
|
334
509
|
this.needsInitialization = true;
|
|
510
|
+
this.savePropertyChangeEvent("text", text);
|
|
335
511
|
}
|
|
336
512
|
get backgroundColor() {
|
|
337
513
|
return this._backgroundColor;
|
|
338
514
|
}
|
|
339
515
|
set backgroundColor(backgroundColor) {
|
|
516
|
+
if (Equal.value(this._backgroundColor, backgroundColor)) {
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
340
519
|
this._backgroundColor = backgroundColor;
|
|
341
520
|
this.needsInitialization = true;
|
|
521
|
+
this.savePropertyChangeEvent("backgroundColor", backgroundColor);
|
|
342
522
|
}
|
|
343
523
|
get fontColor() {
|
|
344
524
|
return this._fontColor;
|
|
345
525
|
}
|
|
346
526
|
set fontColor(fontColor) {
|
|
527
|
+
if (Equal.value(this._fontColor, fontColor)) {
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
347
530
|
this._fontColor = fontColor;
|
|
348
531
|
this.needsInitialization = true;
|
|
532
|
+
this.savePropertyChangeEvent("fontColor", fontColor);
|
|
349
533
|
}
|
|
350
534
|
get fontName() {
|
|
351
535
|
return this._fontName;
|
|
352
536
|
}
|
|
353
537
|
set fontName(fontName) {
|
|
538
|
+
if (this._fontName === fontName) {
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
354
541
|
this._fontName = fontName;
|
|
355
542
|
this.needsInitialization = true;
|
|
543
|
+
this.savePropertyChangeEvent("fontName", fontName);
|
|
356
544
|
}
|
|
357
545
|
get fontNames() {
|
|
358
546
|
return this._fontNames;
|
|
359
547
|
}
|
|
360
548
|
set fontNames(fontNames) {
|
|
549
|
+
if (Equal.value(this._fontNames, fontNames)) {
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
361
552
|
this._fontNames = fontNames;
|
|
362
553
|
this.needsInitialization = true;
|
|
554
|
+
this.savePropertyChangeEvent("fontNames", fontNames);
|
|
555
|
+
}
|
|
556
|
+
get cornerRadius() {
|
|
557
|
+
return this._cornerRadius;
|
|
558
|
+
}
|
|
559
|
+
set cornerRadius(cornerRadius) {
|
|
560
|
+
if (Equal.value(this._cornerRadius, cornerRadius)) {
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
this._cornerRadius = cornerRadius;
|
|
564
|
+
this.needsInitialization = true;
|
|
565
|
+
this.savePropertyChangeEvent("cornerRadius", cornerRadius);
|
|
566
|
+
}
|
|
567
|
+
get fontSize() {
|
|
568
|
+
return this._fontSize;
|
|
569
|
+
}
|
|
570
|
+
set fontSize(fontSize) {
|
|
571
|
+
if (Equal.value(this._fontSize, fontSize)) {
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
this._fontSize = fontSize;
|
|
575
|
+
this.needsInitialization = true;
|
|
576
|
+
this.savePropertyChangeEvent("fontSize", fontSize);
|
|
363
577
|
}
|
|
364
578
|
get interpolation() {
|
|
365
579
|
return this._interpolation;
|
|
366
580
|
}
|
|
367
581
|
set interpolation(interpolation) {
|
|
582
|
+
if (Equal.value(this._interpolation, interpolation)) {
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
368
585
|
this._interpolation = interpolation;
|
|
369
586
|
Object.freeze(this._interpolation);
|
|
370
587
|
this.needsInitialization = true;
|
|
588
|
+
this.savePropertyChangeEvent("interpolation", interpolation);
|
|
371
589
|
}
|
|
372
590
|
get localize() {
|
|
373
591
|
return this._localize;
|
|
374
592
|
}
|
|
375
593
|
set localize(localize) {
|
|
594
|
+
if (Equal.value(this._localize, localize)) {
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
376
597
|
this._localize = localize;
|
|
377
598
|
this.needsInitialization = true;
|
|
599
|
+
this.savePropertyChangeEvent("localize", localize);
|
|
378
600
|
}
|
|
379
601
|
/**
|
|
380
602
|
* Duplicates a node using deep copy.
|
|
@@ -423,6 +645,7 @@ class Button extends Composite {
|
|
|
423
645
|
});
|
|
424
646
|
}
|
|
425
647
|
}
|
|
648
|
+
M2c2KitHelpers.registerM2NodeClass(Button);
|
|
426
649
|
|
|
427
650
|
var DialogResult = /* @__PURE__ */ ((DialogResult2) => {
|
|
428
651
|
DialogResult2["Dismiss"] = "Dismiss";
|
|
@@ -442,9 +665,9 @@ class Dialog extends Composite {
|
|
|
442
665
|
this.contentText = "";
|
|
443
666
|
this.positiveButtonText = "";
|
|
444
667
|
this.negativeButtonText = "";
|
|
668
|
+
this._fontColor = WebColors.White;
|
|
445
669
|
this.zPosition = Number.MAX_VALUE;
|
|
446
670
|
this.hidden = true;
|
|
447
|
-
this._fontColor = WebColors.White;
|
|
448
671
|
if (!options) {
|
|
449
672
|
return;
|
|
450
673
|
}
|
|
@@ -478,7 +701,7 @@ class Dialog extends Composite {
|
|
|
478
701
|
}
|
|
479
702
|
onDialogResult(callback, options) {
|
|
480
703
|
const eventListener = {
|
|
481
|
-
type: M2EventType.
|
|
704
|
+
type: M2EventType.Composite,
|
|
482
705
|
compositeType: "DialogResult",
|
|
483
706
|
nodeUuid: this.uuid,
|
|
484
707
|
callback
|
|
@@ -494,10 +717,10 @@ class Dialog extends Composite {
|
|
|
494
717
|
this.removeAllChildren();
|
|
495
718
|
const overlay = new Shape({
|
|
496
719
|
rect: {
|
|
497
|
-
width:
|
|
498
|
-
height:
|
|
499
|
-
x:
|
|
500
|
-
y:
|
|
720
|
+
width: m2c2Globals.canvasCssWidth,
|
|
721
|
+
height: m2c2Globals.canvasCssHeight,
|
|
722
|
+
x: m2c2Globals.canvasCssWidth / 2,
|
|
723
|
+
y: m2c2Globals.canvasCssHeight / 2
|
|
501
724
|
},
|
|
502
725
|
fillColor: [0, 0, 0, this.overlayAlpha],
|
|
503
726
|
zPosition: -1,
|
|
@@ -507,12 +730,14 @@ class Dialog extends Composite {
|
|
|
507
730
|
e.handled = true;
|
|
508
731
|
this.hidden = true;
|
|
509
732
|
if (this.eventListeners.length > 0) {
|
|
510
|
-
this.eventListeners.filter((listener) => listener.type === M2EventType.
|
|
733
|
+
this.eventListeners.filter((listener) => listener.type === M2EventType.Composite).forEach((listener) => {
|
|
511
734
|
const dialogEvent = {
|
|
512
|
-
type: M2EventType.
|
|
735
|
+
type: M2EventType.Composite,
|
|
513
736
|
target: this,
|
|
514
737
|
handled: false,
|
|
515
|
-
dialogResult: "Dismiss" /* Dismiss
|
|
738
|
+
dialogResult: "Dismiss" /* Dismiss */,
|
|
739
|
+
timestamp: Timer.now(),
|
|
740
|
+
iso8601Timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
516
741
|
};
|
|
517
742
|
listener.callback(dialogEvent);
|
|
518
743
|
});
|
|
@@ -523,8 +748,8 @@ class Dialog extends Composite {
|
|
|
523
748
|
rect: {
|
|
524
749
|
width: 300,
|
|
525
750
|
height: 150,
|
|
526
|
-
x:
|
|
527
|
-
y:
|
|
751
|
+
x: m2c2Globals.canvasCssWidth / 2,
|
|
752
|
+
y: m2c2Globals.canvasCssHeight / 2
|
|
528
753
|
},
|
|
529
754
|
cornerRadius: this.cornerRadius,
|
|
530
755
|
fillColor: this.backgroundColor,
|
|
@@ -555,12 +780,14 @@ class Dialog extends Composite {
|
|
|
555
780
|
e.handled = true;
|
|
556
781
|
this.hidden = true;
|
|
557
782
|
if (this.eventListeners.length > 0) {
|
|
558
|
-
this.eventListeners.filter((listener) => listener.type === M2EventType.
|
|
783
|
+
this.eventListeners.filter((listener) => listener.type === M2EventType.Composite).forEach((listener) => {
|
|
559
784
|
const dialogEvent = {
|
|
560
|
-
type: M2EventType.
|
|
785
|
+
type: M2EventType.Composite,
|
|
561
786
|
target: this,
|
|
562
787
|
handled: false,
|
|
563
|
-
dialogResult: "Negative" /* Negative
|
|
788
|
+
dialogResult: "Negative" /* Negative */,
|
|
789
|
+
timestamp: Timer.now(),
|
|
790
|
+
iso8601Timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
564
791
|
};
|
|
565
792
|
listener.callback(dialogEvent);
|
|
566
793
|
});
|
|
@@ -577,12 +804,14 @@ class Dialog extends Composite {
|
|
|
577
804
|
e.handled = true;
|
|
578
805
|
this.hidden = true;
|
|
579
806
|
if (this.eventListeners.length > 0) {
|
|
580
|
-
this.eventListeners.filter((listener) => listener.type === M2EventType.
|
|
807
|
+
this.eventListeners.filter((listener) => listener.type === M2EventType.Composite).forEach((listener) => {
|
|
581
808
|
const dialogEvent = {
|
|
582
|
-
type: M2EventType.
|
|
809
|
+
type: M2EventType.Composite,
|
|
583
810
|
target: this,
|
|
584
811
|
handled: false,
|
|
585
|
-
dialogResult: "Positive" /* Positive
|
|
812
|
+
dialogResult: "Positive" /* Positive */,
|
|
813
|
+
timestamp: Timer.now(),
|
|
814
|
+
iso8601Timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
586
815
|
};
|
|
587
816
|
listener.callback(dialogEvent);
|
|
588
817
|
});
|
|
@@ -606,6 +835,13 @@ class Dialog extends Composite {
|
|
|
606
835
|
this._fontColor = fontColor;
|
|
607
836
|
this.needsInitialization = true;
|
|
608
837
|
}
|
|
838
|
+
get hidden() {
|
|
839
|
+
return this._hidden;
|
|
840
|
+
}
|
|
841
|
+
set hidden(hidden) {
|
|
842
|
+
this._hidden = hidden;
|
|
843
|
+
this.needsInitialization;
|
|
844
|
+
}
|
|
609
845
|
/**
|
|
610
846
|
* Duplicates a node using deep copy.
|
|
611
847
|
*
|
|
@@ -617,7 +853,7 @@ class Dialog extends Composite {
|
|
|
617
853
|
* provided, name will be the new uuid
|
|
618
854
|
*/
|
|
619
855
|
duplicate(newName) {
|
|
620
|
-
throw new Error(
|
|
856
|
+
throw new Error(`duplicate not implemented. ${newName}`);
|
|
621
857
|
}
|
|
622
858
|
update() {
|
|
623
859
|
super.update();
|
|
@@ -668,6 +904,7 @@ class DrawPad extends Composite {
|
|
|
668
904
|
* of all interactions with each DrawPadStroke.
|
|
669
905
|
*/
|
|
670
906
|
this.strokes = new Array();
|
|
907
|
+
this.originalOptions = JSON.parse(JSON.stringify(options));
|
|
671
908
|
if (options.isUserInteractionEnabled === void 0) {
|
|
672
909
|
this.isUserInteractionEnabled = true;
|
|
673
910
|
}
|
|
@@ -699,6 +936,15 @@ class DrawPad extends Composite {
|
|
|
699
936
|
if (options.continuousDrawingOnlyExceptionDistance !== void 0) {
|
|
700
937
|
this.continuousDrawingOnlyExceptionDistance = options.continuousDrawingOnlyExceptionDistance;
|
|
701
938
|
}
|
|
939
|
+
this.saveNodeNewEvent();
|
|
940
|
+
}
|
|
941
|
+
get completeNodeOptions() {
|
|
942
|
+
return {
|
|
943
|
+
...this.options,
|
|
944
|
+
...this.getNodeOptions(),
|
|
945
|
+
...this.getDrawableOptions(),
|
|
946
|
+
...this.originalOptions
|
|
947
|
+
};
|
|
702
948
|
}
|
|
703
949
|
initialize() {
|
|
704
950
|
this.initializeDrawShape();
|
|
@@ -721,7 +967,8 @@ class DrawPad extends Composite {
|
|
|
721
967
|
if (!this.drawArea) {
|
|
722
968
|
this.drawArea = new Shape({
|
|
723
969
|
rect: { size: this.size },
|
|
724
|
-
isUserInteractionEnabled: true
|
|
970
|
+
isUserInteractionEnabled: true,
|
|
971
|
+
suppressEvents: true
|
|
725
972
|
});
|
|
726
973
|
this.addChild(this.drawArea);
|
|
727
974
|
this.drawArea.onTapDown((e) => {
|
|
@@ -765,7 +1012,8 @@ class DrawPad extends Composite {
|
|
|
765
1012
|
type: DrawPadEventType.StrokeStart,
|
|
766
1013
|
target: this,
|
|
767
1014
|
handled: false,
|
|
768
|
-
position: e.point
|
|
1015
|
+
position: e.point,
|
|
1016
|
+
...M2c2KitHelpers.createTimestamps()
|
|
769
1017
|
};
|
|
770
1018
|
this.strokes.push([
|
|
771
1019
|
{
|
|
@@ -796,7 +1044,8 @@ class DrawPad extends Composite {
|
|
|
796
1044
|
type: DrawPadEventType.StrokeMove,
|
|
797
1045
|
target: this,
|
|
798
1046
|
handled: false,
|
|
799
|
-
position: interpolatedPoint
|
|
1047
|
+
position: interpolatedPoint,
|
|
1048
|
+
...M2c2KitHelpers.createTimestamps()
|
|
800
1049
|
};
|
|
801
1050
|
this.strokes[strokeCount - 1].push({
|
|
802
1051
|
type: DrawPadEventType.StrokeMove,
|
|
@@ -826,7 +1075,8 @@ class DrawPad extends Composite {
|
|
|
826
1075
|
type: DrawPadEventType.StrokeEnd,
|
|
827
1076
|
position: this.strokes[strokeCount - 1][strokeInteractionCount - 1].position,
|
|
828
1077
|
target: this,
|
|
829
|
-
handled: false
|
|
1078
|
+
handled: false,
|
|
1079
|
+
...M2c2KitHelpers.createTimestamps()
|
|
830
1080
|
};
|
|
831
1081
|
this.strokes[strokeCount - 1].push({
|
|
832
1082
|
type: DrawPadEventType.StrokeEnd,
|
|
@@ -854,7 +1104,8 @@ class DrawPad extends Composite {
|
|
|
854
1104
|
type: DrawPadEventType.StrokeEnd,
|
|
855
1105
|
position: this.strokes[strokeCount - 1][strokeInteractionCount - 1].position,
|
|
856
1106
|
target: this,
|
|
857
|
-
handled: false
|
|
1107
|
+
handled: false,
|
|
1108
|
+
...M2c2KitHelpers.createTimestamps()
|
|
858
1109
|
};
|
|
859
1110
|
this.strokes[strokeCount - 1].push({
|
|
860
1111
|
type: DrawPadEventType.StrokeEnd,
|
|
@@ -882,7 +1133,8 @@ class DrawPad extends Composite {
|
|
|
882
1133
|
type: DrawPadEventType.StrokeMove,
|
|
883
1134
|
target: this,
|
|
884
1135
|
handled: false,
|
|
885
|
-
position: e.point
|
|
1136
|
+
position: e.point,
|
|
1137
|
+
...M2c2KitHelpers.createTimestamps()
|
|
886
1138
|
};
|
|
887
1139
|
const strokeCount = this.strokes.length;
|
|
888
1140
|
this.strokes[strokeCount - 1].push({
|
|
@@ -1037,7 +1289,8 @@ class DrawPad extends Composite {
|
|
|
1037
1289
|
node.isStrokeWithinBounds = true;
|
|
1038
1290
|
const drawPadItemEvent = {
|
|
1039
1291
|
type: DrawPadItemEventType.StrokeEnter,
|
|
1040
|
-
target: node
|
|
1292
|
+
target: node,
|
|
1293
|
+
...M2c2KitHelpers.createTimestamps()
|
|
1041
1294
|
};
|
|
1042
1295
|
this.raiseDrawPadItemEvent(node, drawPadItemEvent);
|
|
1043
1296
|
}
|
|
@@ -1049,7 +1302,8 @@ class DrawPad extends Composite {
|
|
|
1049
1302
|
node.isStrokeWithinBounds = true;
|
|
1050
1303
|
const drawPadItemEvent = {
|
|
1051
1304
|
type: DrawPadItemEventType.StrokeEnter,
|
|
1052
|
-
target: node
|
|
1305
|
+
target: node,
|
|
1306
|
+
...M2c2KitHelpers.createTimestamps()
|
|
1053
1307
|
};
|
|
1054
1308
|
this.raiseDrawPadItemEvent(node, drawPadItemEvent);
|
|
1055
1309
|
}
|
|
@@ -1061,7 +1315,8 @@ class DrawPad extends Composite {
|
|
|
1061
1315
|
node.isStrokeWithinBounds = false;
|
|
1062
1316
|
const drawPadItemEvent = {
|
|
1063
1317
|
type: DrawPadItemEventType.StrokeLeave,
|
|
1064
|
-
target: node
|
|
1318
|
+
target: node,
|
|
1319
|
+
...M2c2KitHelpers.createTimestamps()
|
|
1065
1320
|
};
|
|
1066
1321
|
this.raiseDrawPadItemEvent(node, drawPadItemEvent);
|
|
1067
1322
|
}
|
|
@@ -1072,7 +1327,8 @@ class DrawPad extends Composite {
|
|
|
1072
1327
|
node.isStrokeWithinBounds = false;
|
|
1073
1328
|
const drawPadItemEvent = {
|
|
1074
1329
|
type: DrawPadItemEventType.StrokeLeave,
|
|
1075
|
-
target: node
|
|
1330
|
+
target: node,
|
|
1331
|
+
...M2c2KitHelpers.createTimestamps()
|
|
1076
1332
|
};
|
|
1077
1333
|
this.raiseDrawPadItemEvent(node, drawPadItemEvent);
|
|
1078
1334
|
}
|
|
@@ -1095,10 +1351,10 @@ class DrawPad extends Composite {
|
|
|
1095
1351
|
if (!drawArea) {
|
|
1096
1352
|
throw new Error("DrawPad.takeScreenshot(): no drawArea");
|
|
1097
1353
|
}
|
|
1098
|
-
const sx = (drawArea.absolutePosition.x - drawArea.size.width / 2) *
|
|
1099
|
-
const sy = (drawArea.absolutePosition.y - drawArea.size.height / 2) *
|
|
1100
|
-
const sw = drawArea.size.width *
|
|
1101
|
-
const sh = drawArea.size.height *
|
|
1354
|
+
const sx = (drawArea.absolutePosition.x - drawArea.size.width / 2) * m2c2Globals.canvasScale;
|
|
1355
|
+
const sy = (drawArea.absolutePosition.y - drawArea.size.height / 2) * m2c2Globals.canvasScale;
|
|
1356
|
+
const sw = drawArea.size.width * m2c2Globals.canvasScale;
|
|
1357
|
+
const sh = drawArea.size.height * m2c2Globals.canvasScale;
|
|
1102
1358
|
const imageInfo = {
|
|
1103
1359
|
alphaType: this.game.canvasKit.AlphaType.Unpremul,
|
|
1104
1360
|
colorType: this.game.canvasKit.ColorType.RGBA_8888,
|
|
@@ -1237,9 +1493,10 @@ class DrawPad extends Composite {
|
|
|
1237
1493
|
this.needsInitialization = true;
|
|
1238
1494
|
}
|
|
1239
1495
|
duplicate(newName) {
|
|
1240
|
-
throw new Error(
|
|
1496
|
+
throw new Error(`DrawPad.duplicate(): Method not implemented. ${newName}`);
|
|
1241
1497
|
}
|
|
1242
1498
|
}
|
|
1499
|
+
M2c2KitHelpers.registerM2NodeClass(DrawPad);
|
|
1243
1500
|
|
|
1244
1501
|
class VirtualKeyboard extends Composite {
|
|
1245
1502
|
/**
|
|
@@ -1250,11 +1507,14 @@ class VirtualKeyboard extends Composite {
|
|
|
1250
1507
|
constructor(options) {
|
|
1251
1508
|
super(options);
|
|
1252
1509
|
this.compositeType = "VirtualKeyboard";
|
|
1253
|
-
this.
|
|
1510
|
+
this.keyboardRows = new Array();
|
|
1254
1511
|
this.shiftActivated = false;
|
|
1255
1512
|
this.keyShapes = new Array();
|
|
1256
|
-
|
|
1257
|
-
this.
|
|
1513
|
+
this.keyLabels = new Array();
|
|
1514
|
+
this.originalOptions = JSON.parse(JSON.stringify(options));
|
|
1515
|
+
if (options.isUserInteractionEnabled === void 0) {
|
|
1516
|
+
this._isUserInteractionEnabled = true;
|
|
1517
|
+
}
|
|
1258
1518
|
this.size = options.size;
|
|
1259
1519
|
this.position = options.position ?? { x: 0, y: 0 };
|
|
1260
1520
|
this.keyboardHorizontalPaddingPercent = options.keyboardHorizontalPaddingPercent ?? 0.02;
|
|
@@ -1262,11 +1522,12 @@ class VirtualKeyboard extends Composite {
|
|
|
1262
1522
|
this.keyHorizontalPaddingPercent = options.keyHorizontalPaddingPercent ?? 0.1;
|
|
1263
1523
|
this.keyVerticalPaddingPercent = options.keyVerticalPaddingPercent ?? 0.1;
|
|
1264
1524
|
if (options.rows !== void 0) {
|
|
1265
|
-
this.
|
|
1525
|
+
this.keyboardRows = options.rows.map((row) => {
|
|
1266
1526
|
const internalRow = row.map((key) => {
|
|
1267
1527
|
if (key instanceof Object && !Array.isArray(key)) {
|
|
1268
1528
|
const internalKeyConfig = key;
|
|
1269
1529
|
if (key.keyIconShapeOptions) {
|
|
1530
|
+
key.keyIconShapeOptions.suppressEvents = true;
|
|
1270
1531
|
internalKeyConfig.keyIcon = new Shape(key.keyIconShapeOptions);
|
|
1271
1532
|
internalKeyConfig.keyIconShapeOptions = void 0;
|
|
1272
1533
|
}
|
|
@@ -1288,157 +1549,48 @@ class VirtualKeyboard extends Composite {
|
|
|
1288
1549
|
this.specialKeyDownColor = options.specialKeyDownColor ?? WebColors.LightSteelBlue;
|
|
1289
1550
|
this.backgroundColor = options.backgroundColor ?? [242, 240, 244, 1];
|
|
1290
1551
|
this.showKeyDownPreview = options.showKeyDownPreview ?? true;
|
|
1552
|
+
this.saveNodeNewEvent();
|
|
1553
|
+
}
|
|
1554
|
+
get completeNodeOptions() {
|
|
1555
|
+
return {
|
|
1556
|
+
...this.options,
|
|
1557
|
+
...this.getNodeOptions(),
|
|
1558
|
+
...this.getDrawableOptions(),
|
|
1559
|
+
...this.originalOptions
|
|
1560
|
+
};
|
|
1291
1561
|
}
|
|
1292
1562
|
initialize() {
|
|
1293
|
-
if (this.
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
["5", "%"],
|
|
1300
|
-
["6", "^"],
|
|
1301
|
-
["7", "&"],
|
|
1302
|
-
["8", "*"],
|
|
1303
|
-
["9", "("],
|
|
1304
|
-
["0", ")"]
|
|
1305
|
-
];
|
|
1306
|
-
const row1 = [
|
|
1307
|
-
"q",
|
|
1308
|
-
"w",
|
|
1309
|
-
"e",
|
|
1310
|
-
"r",
|
|
1311
|
-
"t",
|
|
1312
|
-
"y",
|
|
1313
|
-
"u",
|
|
1314
|
-
"i",
|
|
1315
|
-
"o",
|
|
1316
|
-
"p"
|
|
1317
|
-
];
|
|
1318
|
-
const row2 = [
|
|
1319
|
-
"a",
|
|
1320
|
-
"s",
|
|
1321
|
-
"d",
|
|
1322
|
-
"f",
|
|
1323
|
-
"g",
|
|
1324
|
-
"h",
|
|
1325
|
-
"j",
|
|
1326
|
-
"k",
|
|
1327
|
-
"l"
|
|
1328
|
-
];
|
|
1329
|
-
const shiftArrowShapeOptions = {
|
|
1330
|
-
path: {
|
|
1331
|
-
// Public Domain from https://www.freesvg.org
|
|
1332
|
-
pathString: "m288-6.6849e-14 -288 288h144v288h288v-288h144l-288-288z",
|
|
1333
|
-
width: 24
|
|
1334
|
-
},
|
|
1335
|
-
lineWidth: 2,
|
|
1336
|
-
strokeColor: WebColors.Black,
|
|
1337
|
-
fillColor: WebColors.Transparent
|
|
1338
|
-
};
|
|
1339
|
-
const backspaceShapeOptions = {
|
|
1340
|
-
path: {
|
|
1341
|
-
// CC0 from https://www.svgrepo.com
|
|
1342
|
-
pathString: "M10.625 5.09 0 22.09l10.625 17H44.18v-34H10.625zm31.555 32H11.734l-9.375-15 9.375-15H42.18v30zm-23.293-6.293 7.293-7.293 7.293 7.293 1.414-1.414-7.293-7.293 7.293-7.293-1.414-1.414-7.293 7.293-7.293-7.293-1.414 1.414 7.293 7.293-7.293 7.293",
|
|
1343
|
-
width: 24
|
|
1344
|
-
},
|
|
1345
|
-
lineWidth: 1,
|
|
1346
|
-
strokeColor: WebColors.Black,
|
|
1347
|
-
fillColor: WebColors.Red
|
|
1348
|
-
};
|
|
1349
|
-
const row3 = [
|
|
1350
|
-
{
|
|
1351
|
-
code: "Shift",
|
|
1352
|
-
isShift: true,
|
|
1353
|
-
widthRatio: 1.5,
|
|
1354
|
-
keyIcon: new Shape(shiftArrowShapeOptions)
|
|
1355
|
-
},
|
|
1356
|
-
"z",
|
|
1357
|
-
"x",
|
|
1358
|
-
"c",
|
|
1359
|
-
"v",
|
|
1360
|
-
"b",
|
|
1361
|
-
"n",
|
|
1362
|
-
"m",
|
|
1363
|
-
{
|
|
1364
|
-
code: "Backspace",
|
|
1365
|
-
widthRatio: 1.5,
|
|
1366
|
-
keyIcon: new Shape(backspaceShapeOptions)
|
|
1367
|
-
}
|
|
1368
|
-
];
|
|
1369
|
-
const row4 = [
|
|
1370
|
-
{ code: " ", labelText: "SPACE", widthRatio: 5 }
|
|
1371
|
-
];
|
|
1372
|
-
const keyboardRows = [
|
|
1373
|
-
numKeys,
|
|
1374
|
-
row1,
|
|
1375
|
-
row2,
|
|
1376
|
-
row3,
|
|
1377
|
-
row4
|
|
1378
|
-
];
|
|
1379
|
-
this.rowsConfiguration = keyboardRows;
|
|
1380
|
-
this.keysPerRow = this.rowsConfiguration.reduce(
|
|
1563
|
+
if (this.game.eventStore.mode === EventStoreMode.Replay) {
|
|
1564
|
+
this._isUserInteractionEnabled = false;
|
|
1565
|
+
}
|
|
1566
|
+
if (this.keyboardRows.length === 0) {
|
|
1567
|
+
this.keyboardRows = this.createDefaultKeyboardRows();
|
|
1568
|
+
this.keysPerRow = this.keyboardRows.reduce(
|
|
1381
1569
|
(max, row) => Math.max(max, row.length),
|
|
1382
1570
|
0
|
|
1383
1571
|
);
|
|
1384
|
-
this.fontSize = this.size.height / this.
|
|
1572
|
+
this.fontSize = this.size.height / this.keyboardRows.length / 2.5;
|
|
1385
1573
|
}
|
|
1386
1574
|
const keyboardRectangle = new Shape({
|
|
1387
1575
|
rect: { size: this.size },
|
|
1388
|
-
fillColor: this.backgroundColor
|
|
1576
|
+
fillColor: this.backgroundColor,
|
|
1577
|
+
suppressEvents: true
|
|
1389
1578
|
});
|
|
1390
1579
|
this.addChild(keyboardRectangle);
|
|
1391
|
-
const
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
const heightRatio = 1;
|
|
1395
|
-
let code;
|
|
1396
|
-
let label;
|
|
1397
|
-
let labelShifted;
|
|
1398
|
-
let keyIcon;
|
|
1399
|
-
let isShift = false;
|
|
1400
|
-
if (typeof key === "string") {
|
|
1401
|
-
code = key;
|
|
1402
|
-
if (this.capitalLettersOnly) {
|
|
1403
|
-
label = code.toUpperCase();
|
|
1404
|
-
} else {
|
|
1405
|
-
label = code;
|
|
1406
|
-
}
|
|
1407
|
-
labelShifted = code.toUpperCase();
|
|
1408
|
-
} else if (Array.isArray(key)) {
|
|
1409
|
-
code = key[0];
|
|
1410
|
-
label = code;
|
|
1411
|
-
labelShifted = key[1];
|
|
1412
|
-
} else {
|
|
1413
|
-
code = key.code;
|
|
1414
|
-
label = key.labelText ?? "";
|
|
1415
|
-
labelShifted = key.labelTextShifted ?? label;
|
|
1416
|
-
widthRatio = key.widthRatio ?? 1;
|
|
1417
|
-
keyIcon = key.keyIcon;
|
|
1418
|
-
isShift = key.isShift ?? false;
|
|
1419
|
-
}
|
|
1420
|
-
return {
|
|
1421
|
-
widthRatio,
|
|
1422
|
-
heightRatio,
|
|
1423
|
-
code,
|
|
1424
|
-
labelText: label,
|
|
1425
|
-
labelTextShifted: labelShifted,
|
|
1426
|
-
keyIcon,
|
|
1427
|
-
isShift
|
|
1428
|
-
};
|
|
1429
|
-
});
|
|
1430
|
-
});
|
|
1580
|
+
const keyboard = this.internalKeyboardRowsToInternalKeyboardConfiguration(
|
|
1581
|
+
this.keyboardRows
|
|
1582
|
+
);
|
|
1431
1583
|
const keyboardOrigin = {
|
|
1432
1584
|
x: -keyboardRectangle.size.width / 2,
|
|
1433
1585
|
y: -keyboardRectangle.size.height / 2
|
|
1434
1586
|
};
|
|
1435
1587
|
const keyboardVerticalPadding = (this.keyboardVerticalPaddingPercent ?? 0.025) * this.size.height;
|
|
1436
1588
|
const keyboardHorizontalPadding = (this.keyboardHorizontalPaddingPercent ?? 0.02) * this.size.width;
|
|
1437
|
-
const keyBoxHeight = (this.size.height - 2 * keyboardVerticalPadding) /
|
|
1589
|
+
const keyBoxHeight = (this.size.height - 2 * keyboardVerticalPadding) / keyboard.length;
|
|
1438
1590
|
const keyBoxWidth = (this.size.width - 2 * keyboardHorizontalPadding) / this.keysPerRow;
|
|
1439
1591
|
this.keyShapes = [];
|
|
1440
|
-
for (let r = 0; r <
|
|
1441
|
-
const row =
|
|
1592
|
+
for (let r = 0; r < keyboard.length; r++) {
|
|
1593
|
+
const row = keyboard[r];
|
|
1442
1594
|
const rowSumKeyWidths = row.reduce(
|
|
1443
1595
|
(sum, key) => sum + (key.widthRatio ?? 1),
|
|
1444
1596
|
0
|
|
@@ -1449,7 +1601,7 @@ class VirtualKeyboard extends Composite {
|
|
|
1449
1601
|
}
|
|
1450
1602
|
for (let k = 0; k < row.length; k++) {
|
|
1451
1603
|
const key = row[k];
|
|
1452
|
-
if (this.hiddenKeys?.split(",").map((s) => s.trim()).includes(key.code)) {
|
|
1604
|
+
if (this.hiddenKeys?.split(",").map((s) => s === " " ? " " : s.trim()).includes(key.code)) {
|
|
1453
1605
|
continue;
|
|
1454
1606
|
}
|
|
1455
1607
|
const keyBoxWidthsSoFar = row.slice(0, k).reduce((sum, key2) => sum + (key2.widthRatio ?? 1), 0) * keyBoxWidth;
|
|
@@ -1466,7 +1618,8 @@ class VirtualKeyboard extends Composite {
|
|
|
1466
1618
|
position: {
|
|
1467
1619
|
x: extraPadding + keyboardOrigin.x + keyboardHorizontalPadding + keyBoxWidthsSoFar + (key.widthRatio ?? 1) * keyBoxWidth / 2,
|
|
1468
1620
|
y: keyboardOrigin.y + keyboardVerticalPadding + r * keyBoxHeight + keyBoxHeight / 2
|
|
1469
|
-
}
|
|
1621
|
+
},
|
|
1622
|
+
suppressEvents: true
|
|
1470
1623
|
});
|
|
1471
1624
|
const keyWidth = keyBoxWidth * (key.widthRatio ?? 1) - 2 * this.keyHorizontalPaddingPercent * keyBoxWidth;
|
|
1472
1625
|
const keyHeight = keyBoxHeight - (key.heightRatio ?? 1) - 2 * this.keyVerticalPaddingPercent * keyBoxHeight;
|
|
@@ -1475,164 +1628,50 @@ class VirtualKeyboard extends Composite {
|
|
|
1475
1628
|
cornerRadius: 4,
|
|
1476
1629
|
fillColor: this.keyColor,
|
|
1477
1630
|
lineWidth: 0,
|
|
1478
|
-
isUserInteractionEnabled: this.isUserInteractionEnabled
|
|
1631
|
+
isUserInteractionEnabled: this.isUserInteractionEnabled,
|
|
1632
|
+
suppressEvents: true
|
|
1479
1633
|
});
|
|
1634
|
+
keyShape.userData = { code: key.code };
|
|
1480
1635
|
keyBox.addChild(keyShape);
|
|
1481
1636
|
this.keyShapes.push(keyShape);
|
|
1482
|
-
keyShape.onTapUp((tapEvent) => {
|
|
1483
|
-
let keyAsString = "";
|
|
1484
|
-
if (!key.isShift) {
|
|
1485
|
-
if (this.shiftActivated) {
|
|
1486
|
-
this.shiftActivated = false;
|
|
1487
|
-
if (this.shiftKeyShape) {
|
|
1488
|
-
this.shiftKeyShape.fillColor = this.keyColor;
|
|
1489
|
-
if (key.keyIcon) {
|
|
1490
|
-
key.keyIcon.fillColor = WebColors.Transparent;
|
|
1491
|
-
}
|
|
1492
|
-
}
|
|
1493
|
-
rows.flatMap((k2) => k2).forEach((k2) => {
|
|
1494
|
-
if (k2.keyLabel?.text !== void 0) {
|
|
1495
|
-
k2.keyLabel.text = k2.labelText ?? "";
|
|
1496
|
-
}
|
|
1497
|
-
});
|
|
1498
|
-
keyAsString = key.labelTextShifted ?? key.code;
|
|
1499
|
-
} else {
|
|
1500
|
-
keyAsString = key.labelText ?? key.code;
|
|
1501
|
-
}
|
|
1502
|
-
if (key.code === " " || key.code === "Backspace") {
|
|
1503
|
-
keyAsString = key.code;
|
|
1504
|
-
}
|
|
1505
|
-
keyShape.fillColor = this.keyColor;
|
|
1506
|
-
} else {
|
|
1507
|
-
if (!this.shiftActivated) {
|
|
1508
|
-
keyShape.fillColor = this.keyColor;
|
|
1509
|
-
} else {
|
|
1510
|
-
keyShape.fillColor = this.specialKeyDownColor;
|
|
1511
|
-
}
|
|
1512
|
-
keyAsString = key.code;
|
|
1513
|
-
}
|
|
1514
|
-
letterCircle.hidden = true;
|
|
1515
|
-
if (this.eventListeners.length > 0) {
|
|
1516
|
-
this.eventListeners.filter(
|
|
1517
|
-
(listener) => listener.type === M2EventType.CompositeCustom && listener.compositeType === "VirtualKeyboardKeyUp"
|
|
1518
|
-
).forEach((listener) => {
|
|
1519
|
-
const virtualKeyboardEvent = {
|
|
1520
|
-
type: M2EventType.CompositeCustom,
|
|
1521
|
-
target: this,
|
|
1522
|
-
handled: false,
|
|
1523
|
-
key: keyAsString,
|
|
1524
|
-
code: key.code,
|
|
1525
|
-
shiftKey: this.shiftActivated,
|
|
1526
|
-
keyTapMetadata: {
|
|
1527
|
-
size: keyShape.size,
|
|
1528
|
-
point: tapEvent.point,
|
|
1529
|
-
buttons: tapEvent.buttons
|
|
1530
|
-
}
|
|
1531
|
-
};
|
|
1532
|
-
listener.callback(virtualKeyboardEvent);
|
|
1533
|
-
});
|
|
1534
|
-
}
|
|
1535
|
-
});
|
|
1536
|
-
keyShape.onTapDown((tapEvent) => {
|
|
1537
|
-
if (key.isShift) {
|
|
1538
|
-
this.shiftActivated = !this.shiftActivated;
|
|
1539
|
-
if (this.shiftActivated) {
|
|
1540
|
-
keyShape.fillColor = this.specialKeyDownColor;
|
|
1541
|
-
if (key.keyIcon) {
|
|
1542
|
-
key.keyIcon.fillColor = WebColors.Black;
|
|
1543
|
-
}
|
|
1544
|
-
rows.flatMap((k2) => k2).forEach((k2) => {
|
|
1545
|
-
if (k2.keyLabel?.text !== void 0) {
|
|
1546
|
-
k2.keyLabel.text = k2.labelTextShifted ?? k2.labelText ?? "";
|
|
1547
|
-
}
|
|
1548
|
-
});
|
|
1549
|
-
} else {
|
|
1550
|
-
keyShape.fillColor = this.keyColor;
|
|
1551
|
-
if (key.keyIcon) {
|
|
1552
|
-
key.keyIcon.fillColor = WebColors.Transparent;
|
|
1553
|
-
}
|
|
1554
|
-
rows.flatMap((k2) => k2).forEach((k2) => {
|
|
1555
|
-
if (k2.keyLabel?.text !== void 0) {
|
|
1556
|
-
k2.keyLabel.text = k2.labelText ?? "";
|
|
1557
|
-
}
|
|
1558
|
-
});
|
|
1559
|
-
}
|
|
1560
|
-
}
|
|
1561
|
-
let keyAsString = "";
|
|
1562
|
-
if (key.isShift || key.code === " " || key.code === "Backspace") {
|
|
1563
|
-
keyShape.fillColor = this.specialKeyDownColor;
|
|
1564
|
-
keyAsString = key.code;
|
|
1565
|
-
} else {
|
|
1566
|
-
keyShape.fillColor = this.keyDownColor;
|
|
1567
|
-
if (this.showKeyDownPreview) {
|
|
1568
|
-
letterCircle.hidden = false;
|
|
1569
|
-
letterCircle.position.x = keyBox.position.x;
|
|
1570
|
-
letterCircle.position.y = keyBox.position.y - keyHeight * 1.2;
|
|
1571
|
-
if (this.shiftActivated) {
|
|
1572
|
-
letterCircleLabel.text = key.labelTextShifted ?? key.code;
|
|
1573
|
-
} else {
|
|
1574
|
-
letterCircleLabel.text = key.labelText ?? key.code;
|
|
1575
|
-
}
|
|
1576
|
-
}
|
|
1577
|
-
if (this.shiftActivated) {
|
|
1578
|
-
keyAsString = key.labelTextShifted ?? key.code;
|
|
1579
|
-
} else {
|
|
1580
|
-
keyAsString = key.labelText ?? key.code;
|
|
1581
|
-
}
|
|
1582
|
-
}
|
|
1583
|
-
if (this.eventListeners.length > 0) {
|
|
1584
|
-
this.eventListeners.filter(
|
|
1585
|
-
(listener) => listener.type === M2EventType.CompositeCustom && listener.compositeType === "VirtualKeyboardKeyDown"
|
|
1586
|
-
).forEach((listener) => {
|
|
1587
|
-
const virtualKeyboardEvent = {
|
|
1588
|
-
type: M2EventType.CompositeCustom,
|
|
1589
|
-
target: this,
|
|
1590
|
-
handled: false,
|
|
1591
|
-
key: keyAsString,
|
|
1592
|
-
code: key.code,
|
|
1593
|
-
shiftKey: this.shiftActivated,
|
|
1594
|
-
keyTapMetadata: {
|
|
1595
|
-
size: keyShape.size,
|
|
1596
|
-
point: tapEvent.point,
|
|
1597
|
-
buttons: tapEvent.buttons
|
|
1598
|
-
}
|
|
1599
|
-
};
|
|
1600
|
-
listener.callback(virtualKeyboardEvent);
|
|
1601
|
-
});
|
|
1602
|
-
}
|
|
1603
|
-
});
|
|
1604
|
-
keyShape.onTapLeave(() => {
|
|
1605
|
-
keyShape.fillColor = this.keyColor;
|
|
1606
|
-
letterCircle.hidden = true;
|
|
1607
|
-
});
|
|
1608
1637
|
const keyLabel = new Label({
|
|
1609
1638
|
text: key.labelText,
|
|
1610
1639
|
fontSize: this.fontSize,
|
|
1611
|
-
fontNames: this.fontNames
|
|
1640
|
+
fontNames: this.fontNames,
|
|
1641
|
+
suppressEvents: true
|
|
1612
1642
|
});
|
|
1643
|
+
keyLabel.userData = { code: key.code };
|
|
1613
1644
|
keyBox.addChild(keyLabel);
|
|
1614
|
-
|
|
1615
|
-
if (key.isShift) {
|
|
1616
|
-
this.shiftKeyShape = keyShape;
|
|
1617
|
-
}
|
|
1645
|
+
this.keyLabels.push(keyLabel);
|
|
1618
1646
|
if (key.keyIcon) {
|
|
1619
1647
|
keyBox.addChild(key.keyIcon);
|
|
1620
1648
|
}
|
|
1621
1649
|
keyboardRectangle.addChild(keyBox);
|
|
1650
|
+
keyShape.onTapUp((tapEvent) => {
|
|
1651
|
+
this.handleKeyShapeTapUp(key, keyShape, tapEvent);
|
|
1652
|
+
});
|
|
1653
|
+
keyShape.onTapDown((tapEvent) => {
|
|
1654
|
+
this.handleKeyShapeTapDown(key, keyShape, tapEvent);
|
|
1655
|
+
});
|
|
1656
|
+
keyShape.onTapLeave((tapEvent) => {
|
|
1657
|
+
this.handleKeyShapeTapLeave(key, keyShape, tapEvent);
|
|
1658
|
+
});
|
|
1622
1659
|
}
|
|
1623
1660
|
}
|
|
1624
|
-
|
|
1661
|
+
this.letterCircle = new Shape({
|
|
1625
1662
|
circleOfRadius: 28,
|
|
1626
1663
|
fillColor: WebColors.Silver,
|
|
1627
|
-
hidden: true
|
|
1664
|
+
hidden: true,
|
|
1665
|
+
suppressEvents: true
|
|
1628
1666
|
});
|
|
1629
|
-
keyboardRectangle.addChild(letterCircle);
|
|
1630
|
-
|
|
1667
|
+
keyboardRectangle.addChild(this.letterCircle);
|
|
1668
|
+
this.letterCircleLabel = new Label({
|
|
1631
1669
|
text: "",
|
|
1632
1670
|
fontSize: this.fontSize,
|
|
1633
|
-
fontNames: this.fontNames
|
|
1671
|
+
fontNames: this.fontNames,
|
|
1672
|
+
suppressEvents: true
|
|
1634
1673
|
});
|
|
1635
|
-
letterCircle.addChild(letterCircleLabel);
|
|
1674
|
+
this.letterCircle.addChild(this.letterCircleLabel);
|
|
1636
1675
|
this.needsInitialization = false;
|
|
1637
1676
|
}
|
|
1638
1677
|
/**
|
|
@@ -1643,8 +1682,9 @@ class VirtualKeyboard extends Composite {
|
|
|
1643
1682
|
*/
|
|
1644
1683
|
onKeyDown(callback, options) {
|
|
1645
1684
|
const eventListener = {
|
|
1646
|
-
type: M2EventType.
|
|
1647
|
-
|
|
1685
|
+
type: M2EventType.Composite,
|
|
1686
|
+
compositeEventType: "VirtualKeyboardKeyDown",
|
|
1687
|
+
compositeType: this.compositeType,
|
|
1648
1688
|
nodeUuid: this.uuid,
|
|
1649
1689
|
callback
|
|
1650
1690
|
};
|
|
@@ -1658,15 +1698,435 @@ class VirtualKeyboard extends Composite {
|
|
|
1658
1698
|
*/
|
|
1659
1699
|
onKeyUp(callback, options) {
|
|
1660
1700
|
const eventListener = {
|
|
1661
|
-
type: M2EventType.
|
|
1662
|
-
|
|
1701
|
+
type: M2EventType.Composite,
|
|
1702
|
+
compositeEventType: "VirtualKeyboardKeyUp",
|
|
1703
|
+
compositeType: this.compositeType,
|
|
1663
1704
|
nodeUuid: this.uuid,
|
|
1664
1705
|
callback
|
|
1665
1706
|
};
|
|
1666
1707
|
this.addVirtualKeyboardEventListener(eventListener, options);
|
|
1667
1708
|
}
|
|
1668
|
-
|
|
1669
|
-
|
|
1709
|
+
/**
|
|
1710
|
+
* Executes a callback when the user has pressed a key with the pointer, but
|
|
1711
|
+
* moves the pointer outside the key bounds before releasing the pointer.
|
|
1712
|
+
*
|
|
1713
|
+
* @remarks Typically, this event will not be used, since it is a user's
|
|
1714
|
+
* inaccurate interaction with the keyboard. However, it can be used to
|
|
1715
|
+
* provide feedback to the user that they have moved the pointer outside the
|
|
1716
|
+
* key bounds, and thus the key stroke will not be registered.
|
|
1717
|
+
*
|
|
1718
|
+
* @param callback - function to execute
|
|
1719
|
+
* @param options
|
|
1720
|
+
*/
|
|
1721
|
+
onKeyLeave(callback, options) {
|
|
1722
|
+
const eventListener = {
|
|
1723
|
+
type: M2EventType.Composite,
|
|
1724
|
+
compositeEventType: "VirtualKeyboardKeyLeave",
|
|
1725
|
+
compositeType: this.compositeType,
|
|
1726
|
+
nodeUuid: this.uuid,
|
|
1727
|
+
callback
|
|
1728
|
+
};
|
|
1729
|
+
this.addVirtualKeyboardEventListener(eventListener, options);
|
|
1730
|
+
}
|
|
1731
|
+
update() {
|
|
1732
|
+
super.update();
|
|
1733
|
+
}
|
|
1734
|
+
draw(canvas) {
|
|
1735
|
+
super.drawChildren(canvas);
|
|
1736
|
+
}
|
|
1737
|
+
warmup(canvas) {
|
|
1738
|
+
this.initialize();
|
|
1739
|
+
this.children.filter((child) => child.isDrawable).forEach((child) => {
|
|
1740
|
+
child.warmup(canvas);
|
|
1741
|
+
});
|
|
1742
|
+
}
|
|
1743
|
+
duplicate(newName) {
|
|
1744
|
+
throw new Error(`Method not implemented. ${newName}`);
|
|
1745
|
+
}
|
|
1746
|
+
handleKeyShapeTapDown(key, keyShape, tapEvent) {
|
|
1747
|
+
if (key.isShift) {
|
|
1748
|
+
this.shiftActivated = !this.shiftActivated;
|
|
1749
|
+
}
|
|
1750
|
+
const keyAsString = this.getKeyAsString(key);
|
|
1751
|
+
const virtualKeyboardEvent = {
|
|
1752
|
+
type: M2EventType.Composite,
|
|
1753
|
+
compositeType: "VirtualKeyboard",
|
|
1754
|
+
compositeEventType: "VirtualKeyboardKeyDown",
|
|
1755
|
+
target: this,
|
|
1756
|
+
handled: false,
|
|
1757
|
+
key: keyAsString,
|
|
1758
|
+
code: key.code,
|
|
1759
|
+
shiftKey: this.shiftActivated,
|
|
1760
|
+
keyTapMetadata: {
|
|
1761
|
+
size: keyShape.size,
|
|
1762
|
+
point: tapEvent.point,
|
|
1763
|
+
buttons: tapEvent.buttons
|
|
1764
|
+
},
|
|
1765
|
+
...M2c2KitHelpers.createTimestamps()
|
|
1766
|
+
};
|
|
1767
|
+
this.handleCompositeEvent(virtualKeyboardEvent);
|
|
1768
|
+
this.saveEvent(virtualKeyboardEvent);
|
|
1769
|
+
if (this.eventListeners.length > 0) {
|
|
1770
|
+
this.eventListeners.filter(
|
|
1771
|
+
(listener) => listener.type === M2EventType.Composite && listener.compositeType === "VirtualKeyboard" && listener.compositeEventType === "VirtualKeyboardKeyDown"
|
|
1772
|
+
).forEach((listener) => {
|
|
1773
|
+
listener.callback(virtualKeyboardEvent);
|
|
1774
|
+
});
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
handleKeyShapeTapUp(key, keyShape, tapEvent) {
|
|
1778
|
+
const keyAsString = this.getKeyAsString(key);
|
|
1779
|
+
const virtualKeyboardEvent = {
|
|
1780
|
+
type: M2EventType.Composite,
|
|
1781
|
+
compositeType: "VirtualKeyboard",
|
|
1782
|
+
compositeEventType: "VirtualKeyboardKeyUp",
|
|
1783
|
+
target: this,
|
|
1784
|
+
handled: false,
|
|
1785
|
+
key: keyAsString,
|
|
1786
|
+
code: key.code,
|
|
1787
|
+
shiftKey: this.shiftActivated,
|
|
1788
|
+
keyTapMetadata: {
|
|
1789
|
+
size: keyShape.size,
|
|
1790
|
+
point: tapEvent.point,
|
|
1791
|
+
buttons: tapEvent.buttons
|
|
1792
|
+
},
|
|
1793
|
+
...M2c2KitHelpers.createTimestamps()
|
|
1794
|
+
};
|
|
1795
|
+
this.handleCompositeEvent(virtualKeyboardEvent);
|
|
1796
|
+
this.saveEvent(virtualKeyboardEvent);
|
|
1797
|
+
if (this.eventListeners.length > 0) {
|
|
1798
|
+
this.eventListeners.filter(
|
|
1799
|
+
(listener) => listener.type === M2EventType.Composite && listener.compositeType === "VirtualKeyboard" && listener.compositeEventType === "VirtualKeyboardKeyUp"
|
|
1800
|
+
).forEach((listener) => {
|
|
1801
|
+
listener.callback(virtualKeyboardEvent);
|
|
1802
|
+
});
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
handleKeyShapeTapLeave(key, keyShape, tapEvent) {
|
|
1806
|
+
const keyAsString = this.getKeyAsString(key);
|
|
1807
|
+
const virtualKeyboardEvent = {
|
|
1808
|
+
type: M2EventType.Composite,
|
|
1809
|
+
compositeType: "VirtualKeyboard",
|
|
1810
|
+
compositeEventType: "VirtualKeyboardKeyLeave",
|
|
1811
|
+
target: this,
|
|
1812
|
+
handled: false,
|
|
1813
|
+
key: keyAsString,
|
|
1814
|
+
code: key.code,
|
|
1815
|
+
shiftKey: this.shiftActivated,
|
|
1816
|
+
keyTapMetadata: {
|
|
1817
|
+
size: keyShape.size,
|
|
1818
|
+
point: tapEvent.point,
|
|
1819
|
+
buttons: tapEvent.buttons
|
|
1820
|
+
},
|
|
1821
|
+
...M2c2KitHelpers.createTimestamps()
|
|
1822
|
+
};
|
|
1823
|
+
this.handleCompositeEvent(virtualKeyboardEvent);
|
|
1824
|
+
this.saveEvent(virtualKeyboardEvent);
|
|
1825
|
+
if (this.eventListeners.length > 0) {
|
|
1826
|
+
this.eventListeners.filter(
|
|
1827
|
+
(listener) => listener.type === M2EventType.Composite && listener.compositeType === "VirtualKeyboard" && listener.compositeEventType === "VirtualKeyboardKeyLeave"
|
|
1828
|
+
).forEach((listener) => {
|
|
1829
|
+
listener.callback(virtualKeyboardEvent);
|
|
1830
|
+
});
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
getKeyAsString(key) {
|
|
1834
|
+
if (key.isShift || key.code === " " || key.code === "Backspace") {
|
|
1835
|
+
return key.code;
|
|
1836
|
+
} else {
|
|
1837
|
+
if (this.shiftActivated) {
|
|
1838
|
+
return key.labelTextShifted ?? key.code;
|
|
1839
|
+
} else {
|
|
1840
|
+
return key.labelText ?? key.code;
|
|
1841
|
+
}
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
/**
|
|
1845
|
+
* Converts the keyboard rows to the internal keyboard configuration.
|
|
1846
|
+
*
|
|
1847
|
+
* @remarks This normalizes the keyboard rows so that each key is a
|
|
1848
|
+
* full `KeyConfigurationWithShape` object, instead of a string or array of
|
|
1849
|
+
* strings.
|
|
1850
|
+
*
|
|
1851
|
+
* @param keyboardRows
|
|
1852
|
+
* @returns the keyboard for internal use
|
|
1853
|
+
*/
|
|
1854
|
+
internalKeyboardRowsToInternalKeyboardConfiguration(keyboardRows) {
|
|
1855
|
+
return keyboardRows.map((row) => {
|
|
1856
|
+
return row.map((key) => {
|
|
1857
|
+
let widthRatio = 1;
|
|
1858
|
+
const heightRatio = 1;
|
|
1859
|
+
let code;
|
|
1860
|
+
let label;
|
|
1861
|
+
let labelShifted;
|
|
1862
|
+
let keyIcon;
|
|
1863
|
+
let isShift = false;
|
|
1864
|
+
if (typeof key === "string") {
|
|
1865
|
+
code = key;
|
|
1866
|
+
if (this.capitalLettersOnly) {
|
|
1867
|
+
label = code.toUpperCase();
|
|
1868
|
+
} else {
|
|
1869
|
+
label = code;
|
|
1870
|
+
}
|
|
1871
|
+
labelShifted = code.toUpperCase();
|
|
1872
|
+
} else if (Array.isArray(key)) {
|
|
1873
|
+
code = key[0];
|
|
1874
|
+
label = code;
|
|
1875
|
+
labelShifted = key[1];
|
|
1876
|
+
} else {
|
|
1877
|
+
code = key.code;
|
|
1878
|
+
label = key.labelText ?? "";
|
|
1879
|
+
labelShifted = key.labelTextShifted ?? label;
|
|
1880
|
+
widthRatio = key.widthRatio ?? 1;
|
|
1881
|
+
keyIcon = key.keyIcon;
|
|
1882
|
+
isShift = key.isShift ?? false;
|
|
1883
|
+
}
|
|
1884
|
+
return {
|
|
1885
|
+
widthRatio,
|
|
1886
|
+
heightRatio,
|
|
1887
|
+
code,
|
|
1888
|
+
labelText: label,
|
|
1889
|
+
labelTextShifted: labelShifted,
|
|
1890
|
+
keyIcon,
|
|
1891
|
+
isShift
|
|
1892
|
+
};
|
|
1893
|
+
});
|
|
1894
|
+
});
|
|
1895
|
+
}
|
|
1896
|
+
handleCompositeEvent(event) {
|
|
1897
|
+
const keyboard = this.internalKeyboardRowsToInternalKeyboardConfiguration(
|
|
1898
|
+
this.keyboardRows
|
|
1899
|
+
);
|
|
1900
|
+
const keyShape = this.keyShapes.find((k) => k.userData.code === event.code);
|
|
1901
|
+
if (!keyShape) {
|
|
1902
|
+
throw new Error("keyShape is not defined");
|
|
1903
|
+
}
|
|
1904
|
+
this.shiftActivated = event.shiftKey;
|
|
1905
|
+
switch (event.compositeEventType) {
|
|
1906
|
+
case "VirtualKeyboardKeyDown": {
|
|
1907
|
+
this.handleKeyDownEvent(event, keyboard, keyShape);
|
|
1908
|
+
break;
|
|
1909
|
+
}
|
|
1910
|
+
case "VirtualKeyboardKeyUp": {
|
|
1911
|
+
this.handleKeyUpEvent(event, keyboard, keyShape);
|
|
1912
|
+
break;
|
|
1913
|
+
}
|
|
1914
|
+
case "VirtualKeyboardKeyLeave": {
|
|
1915
|
+
this.handleKeyLeaveEvent(event, keyboard, keyShape);
|
|
1916
|
+
break;
|
|
1917
|
+
}
|
|
1918
|
+
default: {
|
|
1919
|
+
throw new Error(
|
|
1920
|
+
`Unknown VirtualKeyboardEvent: ${event.compositeEventType}`
|
|
1921
|
+
);
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
1925
|
+
handleKeyDownEvent(event, keyboard, keyShape) {
|
|
1926
|
+
if (event.code.toLowerCase().includes("shift")) {
|
|
1927
|
+
if (event.shiftKey) {
|
|
1928
|
+
this.showKeyboardShifted(keyboard);
|
|
1929
|
+
} else {
|
|
1930
|
+
this.showKeyboardNotShifted(keyboard);
|
|
1931
|
+
}
|
|
1932
|
+
} else if (event.code === " " || event.code === "Backspace") {
|
|
1933
|
+
keyShape.fillColor = this.specialKeyDownColor;
|
|
1934
|
+
} else {
|
|
1935
|
+
keyShape.fillColor = this.keyDownColor;
|
|
1936
|
+
if (this.showKeyDownPreview) {
|
|
1937
|
+
if (!this.letterCircle || !this.letterCircleLabel) {
|
|
1938
|
+
throw new Error("letterCircle is not defined");
|
|
1939
|
+
}
|
|
1940
|
+
this.letterCircle.hidden = false;
|
|
1941
|
+
const keyBox = keyShape.parent;
|
|
1942
|
+
this.letterCircle.position.x = keyBox.position.x;
|
|
1943
|
+
if (keyShape.rect?.size?.height === void 0) {
|
|
1944
|
+
throw new Error("keyShape.rect.height is undefined");
|
|
1945
|
+
}
|
|
1946
|
+
this.letterCircle.position.y = keyBox.position.y - keyShape.rect.size.height * 1.2;
|
|
1947
|
+
const keyboard2 = this.internalKeyboardRowsToInternalKeyboardConfiguration(
|
|
1948
|
+
this.keyboardRows
|
|
1949
|
+
);
|
|
1950
|
+
const key = keyboard2.flat().find((k) => k.code === event.code);
|
|
1951
|
+
if (!key) {
|
|
1952
|
+
throw new Error("key is not defined");
|
|
1953
|
+
}
|
|
1954
|
+
if (this.shiftActivated) {
|
|
1955
|
+
this.letterCircleLabel.text = key.labelTextShifted ?? key.code;
|
|
1956
|
+
} else {
|
|
1957
|
+
this.letterCircleLabel.text = key.labelText ?? key.code;
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1962
|
+
handleKeyUpEvent(event, keyboard, keyShape) {
|
|
1963
|
+
if (event.code.toLowerCase().includes("shift") && event.shiftKey) {
|
|
1964
|
+
return;
|
|
1965
|
+
}
|
|
1966
|
+
if (event.code.toLowerCase().includes("shift") && !event.shiftKey) {
|
|
1967
|
+
this.shiftActivated = false;
|
|
1968
|
+
this.showKeyboardNotShifted(keyboard);
|
|
1969
|
+
return;
|
|
1970
|
+
}
|
|
1971
|
+
keyShape.fillColor = this.keyColor;
|
|
1972
|
+
if (!this.letterCircle) {
|
|
1973
|
+
throw new Error("letterCircle is not defined");
|
|
1974
|
+
}
|
|
1975
|
+
this.letterCircle.hidden = true;
|
|
1976
|
+
if (!event.code.toLowerCase().includes("shift") && event.shiftKey) {
|
|
1977
|
+
this.shiftActivated = false;
|
|
1978
|
+
this.showKeyboardNotShifted(keyboard);
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
handleKeyLeaveEvent(event, keyboard, keyShape) {
|
|
1982
|
+
if (event.code.toLowerCase().includes("shift")) {
|
|
1983
|
+
if (event.shiftKey) {
|
|
1984
|
+
this.showKeyboardNotShifted(keyboard);
|
|
1985
|
+
this.shiftActivated = false;
|
|
1986
|
+
} else {
|
|
1987
|
+
this.showKeyboardShifted(keyboard);
|
|
1988
|
+
this.shiftActivated = true;
|
|
1989
|
+
}
|
|
1990
|
+
return;
|
|
1991
|
+
}
|
|
1992
|
+
keyShape.fillColor = this.keyColor;
|
|
1993
|
+
if (!this.letterCircle) {
|
|
1994
|
+
throw new Error("letterCircle is not defined");
|
|
1995
|
+
}
|
|
1996
|
+
this.letterCircle.hidden = true;
|
|
1997
|
+
}
|
|
1998
|
+
showKeyboardShifted(keyboard) {
|
|
1999
|
+
const shiftKeyShapes = this.keyShapes.filter(
|
|
2000
|
+
(shape) => shape.userData.code.toLowerCase().includes("shift")
|
|
2001
|
+
);
|
|
2002
|
+
shiftKeyShapes.forEach((shape) => {
|
|
2003
|
+
shape.fillColor = this.specialKeyDownColor;
|
|
2004
|
+
});
|
|
2005
|
+
const shiftKeys = keyboard.flat().filter((k) => k.isShift);
|
|
2006
|
+
shiftKeys.forEach((k) => {
|
|
2007
|
+
if (k.keyIcon) {
|
|
2008
|
+
k.keyIcon.fillColor = WebColors.Black;
|
|
2009
|
+
}
|
|
2010
|
+
});
|
|
2011
|
+
keyboard.flatMap((k) => k).forEach((k) => {
|
|
2012
|
+
const keyLabel = this.keyLabels.find((l) => l.userData.code === k.code);
|
|
2013
|
+
if (!keyLabel) {
|
|
2014
|
+
throw new Error("keyLabel is not defined");
|
|
2015
|
+
}
|
|
2016
|
+
if (keyLabel.text !== void 0) {
|
|
2017
|
+
keyLabel.text = k.labelTextShifted ?? "";
|
|
2018
|
+
}
|
|
2019
|
+
});
|
|
2020
|
+
}
|
|
2021
|
+
showKeyboardNotShifted(keyboard) {
|
|
2022
|
+
const shiftKeyShapes = this.keyShapes.filter(
|
|
2023
|
+
(shape) => shape.userData.code.toLowerCase().includes("shift")
|
|
2024
|
+
);
|
|
2025
|
+
shiftKeyShapes.forEach((shape) => {
|
|
2026
|
+
shape.fillColor = this.keyColor;
|
|
2027
|
+
});
|
|
2028
|
+
const shiftKeys = keyboard.flat().filter((k) => k.isShift);
|
|
2029
|
+
shiftKeys.forEach((k) => {
|
|
2030
|
+
if (k.keyIcon) {
|
|
2031
|
+
k.keyIcon.fillColor = WebColors.Transparent;
|
|
2032
|
+
}
|
|
2033
|
+
});
|
|
2034
|
+
keyboard.flatMap((k) => k).forEach((k) => {
|
|
2035
|
+
const keyLabel = this.keyLabels.find((l) => l.userData.code === k.code);
|
|
2036
|
+
if (!keyLabel) {
|
|
2037
|
+
throw new Error("keyLabel is not defined");
|
|
2038
|
+
}
|
|
2039
|
+
if (keyLabel.text !== void 0) {
|
|
2040
|
+
keyLabel.text = k.labelText ?? "";
|
|
2041
|
+
}
|
|
2042
|
+
});
|
|
2043
|
+
}
|
|
2044
|
+
createDefaultKeyboardRows() {
|
|
2045
|
+
const numKeys = [
|
|
2046
|
+
["1", "!"],
|
|
2047
|
+
["2", "@"],
|
|
2048
|
+
["3", "#"],
|
|
2049
|
+
["4", "$"],
|
|
2050
|
+
["5", "%"],
|
|
2051
|
+
["6", "^"],
|
|
2052
|
+
["7", "&"],
|
|
2053
|
+
["8", "*"],
|
|
2054
|
+
["9", "("],
|
|
2055
|
+
["0", ")"]
|
|
2056
|
+
];
|
|
2057
|
+
const row1 = [
|
|
2058
|
+
"q",
|
|
2059
|
+
"w",
|
|
2060
|
+
"e",
|
|
2061
|
+
"r",
|
|
2062
|
+
"t",
|
|
2063
|
+
"y",
|
|
2064
|
+
"u",
|
|
2065
|
+
"i",
|
|
2066
|
+
"o",
|
|
2067
|
+
"p"
|
|
2068
|
+
];
|
|
2069
|
+
const row2 = [
|
|
2070
|
+
"a",
|
|
2071
|
+
"s",
|
|
2072
|
+
"d",
|
|
2073
|
+
"f",
|
|
2074
|
+
"g",
|
|
2075
|
+
"h",
|
|
2076
|
+
"j",
|
|
2077
|
+
"k",
|
|
2078
|
+
"l"
|
|
2079
|
+
];
|
|
2080
|
+
const shiftArrowShapeOptions = {
|
|
2081
|
+
path: {
|
|
2082
|
+
// Public Domain from https://www.freesvg.org
|
|
2083
|
+
pathString: "m288-6.6849e-14 -288 288h144v288h288v-288h144l-288-288z",
|
|
2084
|
+
width: 24
|
|
2085
|
+
},
|
|
2086
|
+
lineWidth: 2,
|
|
2087
|
+
strokeColor: WebColors.Black,
|
|
2088
|
+
fillColor: WebColors.Transparent,
|
|
2089
|
+
suppressEvents: true
|
|
2090
|
+
};
|
|
2091
|
+
const backspaceShapeOptions = {
|
|
2092
|
+
path: {
|
|
2093
|
+
// CC0 from https://www.svgrepo.com
|
|
2094
|
+
pathString: "M10.625 5.09 0 22.09l10.625 17H44.18v-34H10.625zm31.555 32H11.734l-9.375-15 9.375-15H42.18v30zm-23.293-6.293 7.293-7.293 7.293 7.293 1.414-1.414-7.293-7.293 7.293-7.293-1.414-1.414-7.293 7.293-7.293-7.293-1.414 1.414 7.293 7.293-7.293 7.293",
|
|
2095
|
+
width: 24
|
|
2096
|
+
},
|
|
2097
|
+
lineWidth: 1,
|
|
2098
|
+
strokeColor: WebColors.Black,
|
|
2099
|
+
fillColor: WebColors.Red,
|
|
2100
|
+
suppressEvents: true
|
|
2101
|
+
};
|
|
2102
|
+
const row3 = [
|
|
2103
|
+
{
|
|
2104
|
+
code: "Shift",
|
|
2105
|
+
isShift: true,
|
|
2106
|
+
widthRatio: 1.5,
|
|
2107
|
+
keyIcon: new Shape(shiftArrowShapeOptions)
|
|
2108
|
+
},
|
|
2109
|
+
"z",
|
|
2110
|
+
"x",
|
|
2111
|
+
"c",
|
|
2112
|
+
"v",
|
|
2113
|
+
"b",
|
|
2114
|
+
"n",
|
|
2115
|
+
"m",
|
|
2116
|
+
{
|
|
2117
|
+
code: "Backspace",
|
|
2118
|
+
widthRatio: 1.5,
|
|
2119
|
+
keyIcon: new Shape(backspaceShapeOptions)
|
|
2120
|
+
}
|
|
2121
|
+
];
|
|
2122
|
+
const row4 = [
|
|
2123
|
+
{ code: " ", labelText: "SPACE", widthRatio: 5 }
|
|
2124
|
+
];
|
|
2125
|
+
const keyboardRows = [numKeys, row1, row2, row3, row4];
|
|
2126
|
+
return keyboardRows;
|
|
2127
|
+
}
|
|
2128
|
+
addVirtualKeyboardEventListener(eventListener, options) {
|
|
2129
|
+
if (options?.replaceExisting) {
|
|
1670
2130
|
this.eventListeners = this.eventListeners.filter(
|
|
1671
2131
|
(listener) => !(listener.nodeUuid === eventListener.nodeUuid && listener.type === eventListener.type && listener.compositeType === eventListener.compositeType)
|
|
1672
2132
|
);
|
|
@@ -1684,26 +2144,14 @@ class VirtualKeyboard extends Composite {
|
|
|
1684
2144
|
*/
|
|
1685
2145
|
set isUserInteractionEnabled(isUserInteractionEnabled) {
|
|
1686
2146
|
this._isUserInteractionEnabled = isUserInteractionEnabled;
|
|
1687
|
-
this.keyShapes
|
|
2147
|
+
this.keyShapes?.forEach((keyShape) => {
|
|
1688
2148
|
keyShape.isUserInteractionEnabled = isUserInteractionEnabled;
|
|
1689
2149
|
});
|
|
1690
2150
|
}
|
|
1691
|
-
update() {
|
|
1692
|
-
super.update();
|
|
1693
|
-
}
|
|
1694
|
-
draw(canvas) {
|
|
1695
|
-
super.drawChildren(canvas);
|
|
1696
|
-
}
|
|
1697
|
-
warmup(canvas) {
|
|
1698
|
-
this.initialize();
|
|
1699
|
-
this.children.filter((child) => child.isDrawable).forEach((child) => {
|
|
1700
|
-
child.warmup(canvas);
|
|
1701
|
-
});
|
|
1702
|
-
}
|
|
1703
|
-
duplicate(newName) {
|
|
1704
|
-
throw new Error(`Method not implemented. ${newName}`);
|
|
1705
|
-
}
|
|
1706
2151
|
}
|
|
2152
|
+
M2c2KitHelpers.registerM2NodeClass(
|
|
2153
|
+
VirtualKeyboard
|
|
2154
|
+
);
|
|
1707
2155
|
|
|
1708
2156
|
const SCENE_TRANSITION_EASING$1 = Easings.sinusoidalInOut;
|
|
1709
2157
|
const SCENE_TRANSITION_DURATION = 500;
|
|
@@ -1948,7 +2396,7 @@ class CountdownScene extends Scene {
|
|
|
1948
2396
|
bottomToBottomOf: this,
|
|
1949
2397
|
startToStartOf: this,
|
|
1950
2398
|
endToEndOf: this,
|
|
1951
|
-
verticalBias: options?.
|
|
2399
|
+
verticalBias: options?.shapeVerticalBias ?? 0.5
|
|
1952
2400
|
}
|
|
1953
2401
|
},
|
|
1954
2402
|
fillColor: options?.timerShape?.fillColor ?? WebColors.RoyalBlue
|
|
@@ -1967,7 +2415,7 @@ class CountdownScene extends Scene {
|
|
|
1967
2415
|
bottomToBottomOf: this,
|
|
1968
2416
|
startToStartOf: this,
|
|
1969
2417
|
endToEndOf: this,
|
|
1970
|
-
verticalBias: options
|
|
2418
|
+
verticalBias: options.shapeVerticalBias ?? 0.5
|
|
1971
2419
|
}
|
|
1972
2420
|
},
|
|
1973
2421
|
fillColor: options?.timerShape?.fillColor ?? WebColors.RoyalBlue
|
|
@@ -2015,7 +2463,7 @@ class CountdownScene extends Scene {
|
|
|
2015
2463
|
countdownSequence.push(
|
|
2016
2464
|
Action.custom({
|
|
2017
2465
|
callback: () => {
|
|
2018
|
-
timerNumberLabel.text = options?.
|
|
2466
|
+
timerNumberLabel.text = options?.zeroString ?? "0";
|
|
2019
2467
|
}
|
|
2020
2468
|
})
|
|
2021
2469
|
);
|
|
@@ -2079,7 +2527,6 @@ class LocalePicker extends Composite {
|
|
|
2079
2527
|
constructor(options) {
|
|
2080
2528
|
super(options);
|
|
2081
2529
|
this.compositeType = "LocalePicker";
|
|
2082
|
-
this.zPosition = Number.MAX_VALUE;
|
|
2083
2530
|
this.DEFAULT_FONT_SIZE = 24;
|
|
2084
2531
|
this.automaticallyChangeLocale = true;
|
|
2085
2532
|
this._localeOptions = new Array();
|
|
@@ -2107,6 +2554,7 @@ class LocalePicker extends Composite {
|
|
|
2107
2554
|
*/
|
|
2108
2555
|
this.LEFT_SELECTION_INDICATOR = "\xAB";
|
|
2109
2556
|
this.RIGHT_SELECTION_INDICATOR = "\xBB";
|
|
2557
|
+
this.zPosition = Number.MAX_VALUE;
|
|
2110
2558
|
if (!options) {
|
|
2111
2559
|
return;
|
|
2112
2560
|
}
|
|
@@ -2146,7 +2594,7 @@ class LocalePicker extends Composite {
|
|
|
2146
2594
|
*/
|
|
2147
2595
|
onResult(callback, options) {
|
|
2148
2596
|
const eventListener = {
|
|
2149
|
-
type: M2EventType.
|
|
2597
|
+
type: M2EventType.Composite,
|
|
2150
2598
|
compositeType: "LocalePickerResult",
|
|
2151
2599
|
nodeUuid: this.uuid,
|
|
2152
2600
|
callback
|
|
@@ -2200,10 +2648,10 @@ class LocalePicker extends Composite {
|
|
|
2200
2648
|
}
|
|
2201
2649
|
const overlay = new Shape({
|
|
2202
2650
|
rect: {
|
|
2203
|
-
width:
|
|
2204
|
-
height:
|
|
2205
|
-
x:
|
|
2206
|
-
y:
|
|
2651
|
+
width: m2c2Globals.canvasCssWidth,
|
|
2652
|
+
height: m2c2Globals.canvasCssHeight,
|
|
2653
|
+
x: m2c2Globals.canvasCssWidth / 2,
|
|
2654
|
+
y: m2c2Globals.canvasCssHeight / 2
|
|
2207
2655
|
},
|
|
2208
2656
|
fillColor: [0, 0, 0, this.overlayAlpha],
|
|
2209
2657
|
zPosition: -1,
|
|
@@ -2215,12 +2663,16 @@ class LocalePicker extends Composite {
|
|
|
2215
2663
|
if (this.eventListeners.length > 0) {
|
|
2216
2664
|
this.eventListeners.filter((listener) => listener.type === "LocalePickerResult").forEach((listener) => {
|
|
2217
2665
|
const languagePickerEvent = {
|
|
2218
|
-
type:
|
|
2666
|
+
type: M2EventType.Composite,
|
|
2667
|
+
compositeType: this.compositeType,
|
|
2668
|
+
compositeEventType: "LocalePickerResult",
|
|
2219
2669
|
target: this,
|
|
2220
2670
|
handled: false,
|
|
2221
2671
|
result: {
|
|
2222
2672
|
locale: void 0
|
|
2223
|
-
}
|
|
2673
|
+
},
|
|
2674
|
+
timestamp: Timer.now(),
|
|
2675
|
+
iso8601Timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2224
2676
|
};
|
|
2225
2677
|
listener.callback(languagePickerEvent);
|
|
2226
2678
|
});
|
|
@@ -2230,10 +2682,10 @@ class LocalePicker extends Composite {
|
|
|
2230
2682
|
this.addChild(overlay);
|
|
2231
2683
|
const lineHeight = this.fontSize / this.DEFAULT_FONT_SIZE * 50;
|
|
2232
2684
|
const dialogHeight = this.localeOptions.length * lineHeight;
|
|
2233
|
-
const dialogWidth =
|
|
2685
|
+
const dialogWidth = m2c2Globals.canvasCssWidth / 2;
|
|
2234
2686
|
const sceneCenter = {
|
|
2235
|
-
x:
|
|
2236
|
-
y:
|
|
2687
|
+
x: m2c2Globals.canvasCssWidth / 2,
|
|
2688
|
+
y: m2c2Globals.canvasCssHeight / 2
|
|
2237
2689
|
};
|
|
2238
2690
|
const localeDialog = new Shape({
|
|
2239
2691
|
rect: {
|
|
@@ -2335,16 +2787,19 @@ class LocalePicker extends Composite {
|
|
|
2335
2787
|
e.handled = true;
|
|
2336
2788
|
if (this.eventListeners.length > 0) {
|
|
2337
2789
|
this.eventListeners.filter(
|
|
2338
|
-
(listener) => listener.type === M2EventType.
|
|
2790
|
+
(listener) => listener.type === M2EventType.Composite && listener.compositeType === "LocalePickerResult" && listener.nodeUuid == this.uuid
|
|
2339
2791
|
).forEach((listener) => {
|
|
2340
2792
|
const languagePickerEvent = {
|
|
2341
|
-
type: M2EventType.
|
|
2342
|
-
compositeType:
|
|
2793
|
+
type: M2EventType.Composite,
|
|
2794
|
+
compositeType: this.compositeType,
|
|
2795
|
+
compositeEventType: "LocalePickerResult",
|
|
2343
2796
|
target: this,
|
|
2344
2797
|
handled: false,
|
|
2345
2798
|
result: {
|
|
2346
2799
|
locale: localeOption.locale
|
|
2347
|
-
}
|
|
2800
|
+
},
|
|
2801
|
+
timestamp: Timer.now(),
|
|
2802
|
+
iso8601Timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2348
2803
|
};
|
|
2349
2804
|
listener.callback(languagePickerEvent);
|
|
2350
2805
|
});
|
|
@@ -2508,7 +2963,394 @@ class LocalePicker extends Composite {
|
|
|
2508
2963
|
}
|
|
2509
2964
|
}
|
|
2510
2965
|
|
|
2511
|
-
|
|
2966
|
+
class CountdownTimer extends Composite {
|
|
2967
|
+
/**
|
|
2968
|
+
* A countdown timer displays a number that counts down to zero.
|
|
2969
|
+
*
|
|
2970
|
+
* @param options
|
|
2971
|
+
*/
|
|
2972
|
+
constructor(options) {
|
|
2973
|
+
super(options);
|
|
2974
|
+
this.compositeType = "CountdownTimer";
|
|
2975
|
+
this._milliseconds = 3e3;
|
|
2976
|
+
this._tickIntervalMilliseconds = 1e3;
|
|
2977
|
+
this._fontSize = 50;
|
|
2978
|
+
this._fontColor = WebColors.White;
|
|
2979
|
+
this._zeroString = "0";
|
|
2980
|
+
this._timerShape = {
|
|
2981
|
+
circle: {
|
|
2982
|
+
radius: 100
|
|
2983
|
+
},
|
|
2984
|
+
fillColor: WebColors.RoyalBlue
|
|
2985
|
+
};
|
|
2986
|
+
this._textVerticalBias = 0.5;
|
|
2987
|
+
this.countdownSequence = new Array();
|
|
2988
|
+
this._isRunning = false;
|
|
2989
|
+
this.hasStopped = false;
|
|
2990
|
+
this.originalOptions = JSON.parse(JSON.stringify(options));
|
|
2991
|
+
if (options.milliseconds) {
|
|
2992
|
+
this.milliseconds = options.milliseconds;
|
|
2993
|
+
}
|
|
2994
|
+
if (options.tickIntervalMilliseconds) {
|
|
2995
|
+
this.tickIntervalMilliseconds = options.tickIntervalMilliseconds;
|
|
2996
|
+
}
|
|
2997
|
+
if (options.fontName) {
|
|
2998
|
+
this.fontName = options.fontName;
|
|
2999
|
+
}
|
|
3000
|
+
if (options.fontSize !== void 0) {
|
|
3001
|
+
this.fontSize = options.fontSize;
|
|
3002
|
+
}
|
|
3003
|
+
if (options.fontColor) {
|
|
3004
|
+
this.fontColor = options.fontColor;
|
|
3005
|
+
}
|
|
3006
|
+
if (options.zeroString !== void 0) {
|
|
3007
|
+
this.zeroString = options.zeroString;
|
|
3008
|
+
}
|
|
3009
|
+
if (options.timerShape) {
|
|
3010
|
+
this.timerShape = options.timerShape;
|
|
3011
|
+
}
|
|
3012
|
+
if (options.textVerticalBias !== void 0) {
|
|
3013
|
+
this.textVerticalBias = options.textVerticalBias;
|
|
3014
|
+
}
|
|
3015
|
+
this.saveNodeNewEvent();
|
|
3016
|
+
}
|
|
3017
|
+
get completeNodeOptions() {
|
|
3018
|
+
return {
|
|
3019
|
+
...this.options,
|
|
3020
|
+
...this.getNodeOptions(),
|
|
3021
|
+
...this.getDrawableOptions(),
|
|
3022
|
+
...this.originalOptions
|
|
3023
|
+
};
|
|
3024
|
+
}
|
|
3025
|
+
initialize() {
|
|
3026
|
+
this.removeAllChildren();
|
|
3027
|
+
if (this.timerShape?.circle === void 0 && this.timerShape?.rectangle === void 0 || this.timerShape?.circle !== void 0) {
|
|
3028
|
+
this.timerShapeNode = new Shape({
|
|
3029
|
+
circleOfRadius: this.timerShape.circle?.radius ?? 100,
|
|
3030
|
+
fillColor: this.timerShape?.fillColor ?? WebColors.RoyalBlue
|
|
3031
|
+
});
|
|
3032
|
+
this.addChild(this.timerShapeNode);
|
|
3033
|
+
} else if (this.timerShape?.rectangle !== void 0) {
|
|
3034
|
+
this.timerShapeNode = new Shape({
|
|
3035
|
+
rect: {
|
|
3036
|
+
width: this.timerShape?.rectangle?.width ?? 200,
|
|
3037
|
+
height: this.timerShape?.rectangle?.height ?? 200
|
|
3038
|
+
},
|
|
3039
|
+
cornerRadius: this.timerShape?.rectangle?.cornerRadius,
|
|
3040
|
+
fillColor: this.timerShape?.fillColor ?? WebColors.RoyalBlue
|
|
3041
|
+
});
|
|
3042
|
+
this.addChild(this.timerShapeNode);
|
|
3043
|
+
} else {
|
|
3044
|
+
throw new Error("Invalid timer shape options.");
|
|
3045
|
+
}
|
|
3046
|
+
this.size = this.timerShapeNode.size;
|
|
3047
|
+
if (this.milliseconds % 1e3 !== 0) {
|
|
3048
|
+
throw new Error(
|
|
3049
|
+
"CountdownTimer milliseconds must be a multiple of 1000."
|
|
3050
|
+
);
|
|
3051
|
+
}
|
|
3052
|
+
const timerInitialNumber = Math.floor(this.milliseconds / 1e3);
|
|
3053
|
+
this.timerNumberLabel = new Label({
|
|
3054
|
+
text: timerInitialNumber.toString(),
|
|
3055
|
+
fontSize: this.fontSize,
|
|
3056
|
+
fontName: this._fontName,
|
|
3057
|
+
fontColor: this.fontColor,
|
|
3058
|
+
layout: {
|
|
3059
|
+
constraints: {
|
|
3060
|
+
topToTopOf: this.timerShapeNode,
|
|
3061
|
+
bottomToBottomOf: this.timerShapeNode,
|
|
3062
|
+
startToStartOf: this.timerShapeNode,
|
|
3063
|
+
endToEndOf: this.timerShapeNode,
|
|
3064
|
+
verticalBias: this.textVerticalBias
|
|
3065
|
+
}
|
|
3066
|
+
}
|
|
3067
|
+
});
|
|
3068
|
+
this.timerShapeNode.addChild(this.timerNumberLabel);
|
|
3069
|
+
this.countdownSequence = new Array();
|
|
3070
|
+
for (let i = this.milliseconds; i > this.tickIntervalMilliseconds; i = i - this.tickIntervalMilliseconds) {
|
|
3071
|
+
this.countdownSequence.push(
|
|
3072
|
+
Action.wait({ duration: this.tickIntervalMilliseconds })
|
|
3073
|
+
);
|
|
3074
|
+
this.countdownSequence.push(
|
|
3075
|
+
Action.custom({
|
|
3076
|
+
callback: () => {
|
|
3077
|
+
this.tick(i - this.tickIntervalMilliseconds);
|
|
3078
|
+
}
|
|
3079
|
+
})
|
|
3080
|
+
);
|
|
3081
|
+
}
|
|
3082
|
+
this.countdownSequence.push(
|
|
3083
|
+
Action.wait({ duration: this.tickIntervalMilliseconds })
|
|
3084
|
+
);
|
|
3085
|
+
this.countdownSequence.push(
|
|
3086
|
+
Action.custom({
|
|
3087
|
+
callback: () => {
|
|
3088
|
+
this.tick(0);
|
|
3089
|
+
const countdownTimerEvent = {
|
|
3090
|
+
type: M2EventType.Composite,
|
|
3091
|
+
compositeType: this.compositeType,
|
|
3092
|
+
compositeEventType: "CountdownTimerComplete",
|
|
3093
|
+
target: this,
|
|
3094
|
+
handled: false,
|
|
3095
|
+
millisecondsRemaining: 0,
|
|
3096
|
+
...M2c2KitHelpers.createTimestamps()
|
|
3097
|
+
};
|
|
3098
|
+
this.handleCompositeEvent(countdownTimerEvent);
|
|
3099
|
+
this.saveEvent(countdownTimerEvent);
|
|
3100
|
+
if (this.eventListeners.length > 0) {
|
|
3101
|
+
this.eventListeners.filter(
|
|
3102
|
+
(listener) => listener.type === M2EventType.Composite && listener.compositeType === "CountdownTimer" && listener.compositeEventType === "CountdownTimerComplete"
|
|
3103
|
+
).forEach((listener) => {
|
|
3104
|
+
listener.callback(countdownTimerEvent);
|
|
3105
|
+
});
|
|
3106
|
+
}
|
|
3107
|
+
}
|
|
3108
|
+
})
|
|
3109
|
+
);
|
|
3110
|
+
this.needsInitialization = false;
|
|
3111
|
+
}
|
|
3112
|
+
tick(millisecondsRemaining) {
|
|
3113
|
+
const countdownTimerEvent = {
|
|
3114
|
+
type: M2EventType.Composite,
|
|
3115
|
+
compositeType: this.compositeType,
|
|
3116
|
+
compositeEventType: "CountdownTimerTick",
|
|
3117
|
+
target: this,
|
|
3118
|
+
handled: false,
|
|
3119
|
+
millisecondsRemaining,
|
|
3120
|
+
...M2c2KitHelpers.createTimestamps()
|
|
3121
|
+
};
|
|
3122
|
+
this.handleCompositeEvent(countdownTimerEvent);
|
|
3123
|
+
this.saveEvent(countdownTimerEvent);
|
|
3124
|
+
if (this.eventListeners.length > 0) {
|
|
3125
|
+
this.eventListeners.filter(
|
|
3126
|
+
(listener) => listener.type === M2EventType.Composite && listener.compositeType === "CountdownTimer" && listener.compositeEventType === "CountdownTimerTick"
|
|
3127
|
+
).forEach((listener) => {
|
|
3128
|
+
listener.callback(countdownTimerEvent);
|
|
3129
|
+
});
|
|
3130
|
+
}
|
|
3131
|
+
}
|
|
3132
|
+
/**
|
|
3133
|
+
* Starts the countdown timer.
|
|
3134
|
+
*
|
|
3135
|
+
* @remarks Calling start on a running timer or a stopped timer will raise
|
|
3136
|
+
* an error.
|
|
3137
|
+
*/
|
|
3138
|
+
start() {
|
|
3139
|
+
if (this.isRunning) {
|
|
3140
|
+
throw new Error("CountdownTimer: cannot start. It is already running.");
|
|
3141
|
+
}
|
|
3142
|
+
if (this.hasStopped) {
|
|
3143
|
+
throw new Error(
|
|
3144
|
+
"CountdownTimer: It has stopped. You cannot start a stopped CountdownTimer. Instead, create a new CountdownTimer."
|
|
3145
|
+
);
|
|
3146
|
+
}
|
|
3147
|
+
this.run(
|
|
3148
|
+
Action.sequence(this.countdownSequence),
|
|
3149
|
+
"__countdownSequenceAction"
|
|
3150
|
+
);
|
|
3151
|
+
this._isRunning = true;
|
|
3152
|
+
}
|
|
3153
|
+
/**
|
|
3154
|
+
* Stops the countdown timer.
|
|
3155
|
+
*
|
|
3156
|
+
* @remarks This method is idempotent. Calling stop() on a stopped timer has
|
|
3157
|
+
* no effect and will not raise an error.
|
|
3158
|
+
*/
|
|
3159
|
+
stop() {
|
|
3160
|
+
if (this.isRunning) {
|
|
3161
|
+
this.removeAction("__countdownSequenceAction");
|
|
3162
|
+
this._isRunning = false;
|
|
3163
|
+
this.hasStopped = true;
|
|
3164
|
+
}
|
|
3165
|
+
}
|
|
3166
|
+
/**
|
|
3167
|
+
* Returns true if the countdown timer is running.
|
|
3168
|
+
*/
|
|
3169
|
+
get isRunning() {
|
|
3170
|
+
return this._isRunning;
|
|
3171
|
+
}
|
|
3172
|
+
handleCompositeEvent(event) {
|
|
3173
|
+
if (!this.timerNumberLabel) {
|
|
3174
|
+
throw new Error("Timer number label not found.");
|
|
3175
|
+
}
|
|
3176
|
+
switch (event.compositeEventType) {
|
|
3177
|
+
case "CountdownTimerTick": {
|
|
3178
|
+
this.timerNumberLabel.text = Math.ceil(
|
|
3179
|
+
event.millisecondsRemaining / 1e3
|
|
3180
|
+
).toString();
|
|
3181
|
+
break;
|
|
3182
|
+
}
|
|
3183
|
+
case "CountdownTimerComplete": {
|
|
3184
|
+
this.timerNumberLabel.text = this.zeroString;
|
|
3185
|
+
break;
|
|
3186
|
+
}
|
|
3187
|
+
default:
|
|
3188
|
+
throw new Error(
|
|
3189
|
+
`Invalid TimerCountdown event type: ${event.compositeEventType}`
|
|
3190
|
+
);
|
|
3191
|
+
}
|
|
3192
|
+
}
|
|
3193
|
+
/**
|
|
3194
|
+
* Executes a callback when the timer ticks.
|
|
3195
|
+
*
|
|
3196
|
+
* @remarks The callback is also executed when the timer completes.
|
|
3197
|
+
*
|
|
3198
|
+
* @param callback - function to execute
|
|
3199
|
+
* @param options
|
|
3200
|
+
*/
|
|
3201
|
+
onTick(callback, options) {
|
|
3202
|
+
const eventListener = {
|
|
3203
|
+
type: M2EventType.Composite,
|
|
3204
|
+
compositeEventType: "CountdownTimerTick",
|
|
3205
|
+
compositeType: this.compositeType,
|
|
3206
|
+
nodeUuid: this.uuid,
|
|
3207
|
+
callback
|
|
3208
|
+
};
|
|
3209
|
+
this.addCountdownTimerEventListener(eventListener, options);
|
|
3210
|
+
}
|
|
3211
|
+
/**
|
|
3212
|
+
* Executes a callback when the timer completes.
|
|
3213
|
+
*
|
|
3214
|
+
* @remarks This is the last tick of the timer.
|
|
3215
|
+
*
|
|
3216
|
+
* @param callback - function to execute.
|
|
3217
|
+
* @param options
|
|
3218
|
+
*/
|
|
3219
|
+
onComplete(callback, options) {
|
|
3220
|
+
const eventListener = {
|
|
3221
|
+
type: M2EventType.Composite,
|
|
3222
|
+
compositeEventType: "CountdownTimerComplete",
|
|
3223
|
+
compositeType: this.compositeType,
|
|
3224
|
+
nodeUuid: this.uuid,
|
|
3225
|
+
callback
|
|
3226
|
+
};
|
|
3227
|
+
this.addCountdownTimerEventListener(eventListener, options);
|
|
3228
|
+
}
|
|
3229
|
+
addCountdownTimerEventListener(eventListener, options) {
|
|
3230
|
+
if (options?.replaceExisting) {
|
|
3231
|
+
this.eventListeners = this.eventListeners.filter(
|
|
3232
|
+
(listener) => !(listener.nodeUuid === eventListener.nodeUuid && listener.type === eventListener.type && listener.compositeType === eventListener.compositeType)
|
|
3233
|
+
);
|
|
3234
|
+
}
|
|
3235
|
+
this.eventListeners.push(eventListener);
|
|
3236
|
+
}
|
|
3237
|
+
get milliseconds() {
|
|
3238
|
+
return this._milliseconds;
|
|
3239
|
+
}
|
|
3240
|
+
set milliseconds(milliseconds) {
|
|
3241
|
+
if (Equal.value(this._milliseconds, milliseconds)) {
|
|
3242
|
+
return;
|
|
3243
|
+
}
|
|
3244
|
+
this._milliseconds = milliseconds;
|
|
3245
|
+
this.savePropertyChangeEvent("milliseconds", milliseconds);
|
|
3246
|
+
}
|
|
3247
|
+
get tickIntervalMilliseconds() {
|
|
3248
|
+
return this._tickIntervalMilliseconds;
|
|
3249
|
+
}
|
|
3250
|
+
set tickIntervalMilliseconds(tickIntervalMilliseconds) {
|
|
3251
|
+
if (Equal.value(this._tickIntervalMilliseconds, tickIntervalMilliseconds)) {
|
|
3252
|
+
return;
|
|
3253
|
+
}
|
|
3254
|
+
this._tickIntervalMilliseconds = tickIntervalMilliseconds;
|
|
3255
|
+
this.savePropertyChangeEvent(
|
|
3256
|
+
"tickIntervalMilliseconds",
|
|
3257
|
+
tickIntervalMilliseconds
|
|
3258
|
+
);
|
|
3259
|
+
}
|
|
3260
|
+
get fontColor() {
|
|
3261
|
+
return this._fontColor;
|
|
3262
|
+
}
|
|
3263
|
+
set fontColor(fontColor) {
|
|
3264
|
+
if (Equal.value(this._fontColor, fontColor)) {
|
|
3265
|
+
return;
|
|
3266
|
+
}
|
|
3267
|
+
this._fontColor = fontColor;
|
|
3268
|
+
this.needsInitialization = true;
|
|
3269
|
+
this.savePropertyChangeEvent("fontColor", fontColor);
|
|
3270
|
+
}
|
|
3271
|
+
get fontName() {
|
|
3272
|
+
return this._fontName;
|
|
3273
|
+
}
|
|
3274
|
+
set fontName(fontName) {
|
|
3275
|
+
if (this._fontName === fontName) {
|
|
3276
|
+
return;
|
|
3277
|
+
}
|
|
3278
|
+
this._fontName = fontName;
|
|
3279
|
+
this.needsInitialization = true;
|
|
3280
|
+
this.savePropertyChangeEvent("fontName", fontName);
|
|
3281
|
+
}
|
|
3282
|
+
get fontSize() {
|
|
3283
|
+
return this._fontSize;
|
|
3284
|
+
}
|
|
3285
|
+
set fontSize(fontSize) {
|
|
3286
|
+
if (Equal.value(this._fontSize, fontSize)) {
|
|
3287
|
+
return;
|
|
3288
|
+
}
|
|
3289
|
+
this._fontSize = fontSize;
|
|
3290
|
+
this.needsInitialization = true;
|
|
3291
|
+
this.savePropertyChangeEvent("fontSize", fontSize);
|
|
3292
|
+
}
|
|
3293
|
+
get zeroString() {
|
|
3294
|
+
return this._zeroString;
|
|
3295
|
+
}
|
|
3296
|
+
set zeroString(zeroString) {
|
|
3297
|
+
if (this._zeroString === zeroString) {
|
|
3298
|
+
return;
|
|
3299
|
+
}
|
|
3300
|
+
this._zeroString = zeroString;
|
|
3301
|
+
this.savePropertyChangeEvent("zeroString", zeroString);
|
|
3302
|
+
}
|
|
3303
|
+
get timerShape() {
|
|
3304
|
+
return this._timerShape;
|
|
3305
|
+
}
|
|
3306
|
+
set timerShape(shape) {
|
|
3307
|
+
if (Equal.value(this._timerShape, shape)) {
|
|
3308
|
+
return;
|
|
3309
|
+
}
|
|
3310
|
+
this._timerShape = shape;
|
|
3311
|
+
this.savePropertyChangeEvent("timerShape", shape);
|
|
3312
|
+
}
|
|
3313
|
+
get textVerticalBias() {
|
|
3314
|
+
return this._textVerticalBias;
|
|
3315
|
+
}
|
|
3316
|
+
set textVerticalBias(textVerticalBias) {
|
|
3317
|
+
if (Equal.value(this._textVerticalBias, textVerticalBias)) {
|
|
3318
|
+
return;
|
|
3319
|
+
}
|
|
3320
|
+
this._textVerticalBias = textVerticalBias;
|
|
3321
|
+
this.savePropertyChangeEvent("textVerticalBias", textVerticalBias);
|
|
3322
|
+
}
|
|
3323
|
+
/**
|
|
3324
|
+
* Duplicates a node using deep copy.
|
|
3325
|
+
*
|
|
3326
|
+
* @remarks This is a deep recursive clone (node and children).
|
|
3327
|
+
* The uuid property of all duplicated nodes will be newly created,
|
|
3328
|
+
* because uuid must be unique.
|
|
3329
|
+
*
|
|
3330
|
+
* @param newName - optional name of the new, duplicated node. If not
|
|
3331
|
+
* provided, name will be the new uuid
|
|
3332
|
+
*/
|
|
3333
|
+
duplicate(newName) {
|
|
3334
|
+
throw new Error(`Method not implemented. ${newName}`);
|
|
3335
|
+
}
|
|
3336
|
+
update() {
|
|
3337
|
+
super.update();
|
|
3338
|
+
}
|
|
3339
|
+
draw(canvas) {
|
|
3340
|
+
super.drawChildren(canvas);
|
|
3341
|
+
}
|
|
3342
|
+
warmup(canvas) {
|
|
3343
|
+
this.initialize();
|
|
3344
|
+
this.children.filter((child) => child.isDrawable).forEach((child) => {
|
|
3345
|
+
child.warmup(canvas);
|
|
3346
|
+
});
|
|
3347
|
+
}
|
|
3348
|
+
}
|
|
3349
|
+
M2c2KitHelpers.registerM2NodeClass(
|
|
3350
|
+
CountdownTimer
|
|
3351
|
+
);
|
|
3352
|
+
|
|
3353
|
+
console.log("\u26AA @m2c2kit/addons version 0.3.17 (faa531ea)");
|
|
2512
3354
|
|
|
2513
|
-
export { Button, CountdownScene, Dialog, DialogResult, DrawPad, DrawPadEventType, DrawPadItemEventType, Grid, Instructions, LocalePicker, VirtualKeyboard };
|
|
3355
|
+
export { Button, CountdownScene, CountdownTimer, Dialog, DialogResult, DrawPad, DrawPadEventType, DrawPadItemEventType, Grid, Instructions, LocalePicker, VirtualKeyboard };
|
|
2514
3356
|
//# sourceMappingURL=index.js.map
|