@woosh/meep-engine 2.39.38 → 2.39.39

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.
@@ -3,13 +3,21 @@
3
3
  * @author Jameson Little
4
4
  */
5
5
 
6
- var lookup = [];
7
- var revLookup = [];
8
- var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array;
6
+ /**
7
+ *
8
+ * @type {string[]}
9
+ */
10
+ const lookup = [];
11
+ /**
12
+ *
13
+ * @type {number[]}
14
+ */
15
+ const revLookup = [];
16
+ const Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array;
9
17
 
10
- var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
18
+ const code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
11
19
 
12
- for (var i = 0, len = code.length; i < len; ++i) {
20
+ for (let i = 0, len = code.length; i < len; ++i) {
13
21
  lookup[i] = code[i];
14
22
  revLookup[code.charCodeAt(i)] = i;
15
23
  }
@@ -19,6 +27,11 @@ for (var i = 0, len = code.length; i < len; ++i) {
19
27
  revLookup['-'.charCodeAt(0)] = 62;
20
28
  revLookup['_'.charCodeAt(0)] = 63;
21
29
 
30
+ /**
31
+ *
32
+ * @param {string} b64
33
+ * @return {number[]}
34
+ */
22
35
  function getLens(b64) {
23
36
  var len = b64.length;
24
37
 
@@ -41,12 +54,6 @@ function getLens(b64) {
41
54
  }
42
55
 
43
56
  // base64 is 4/3 + up to two characters of the original data
44
- function byteLength(b64) {
45
- var lens = getLens(b64);
46
- var validLen = lens[0];
47
- var placeHoldersLen = lens[1];
48
- return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen;
49
- }
50
57
 
51
58
  function _byteLength(b64, validLen, placeHoldersLen) {
52
59
  return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen;
@@ -99,37 +106,57 @@ function toByteArray(b64) {
99
106
  }
100
107
 
101
108
  function tripletToBase64(num) {
102
- return lookup[num >> 18 & 0x3F] +
103
- lookup[num >> 12 & 0x3F] +
104
- lookup[num >> 6 & 0x3F] +
105
- lookup[num & 0x3F];
109
+ return lookup[num >> 18 & 0x3F]
110
+ + lookup[num >> 12 & 0x3F]
111
+ + lookup[num >> 6 & 0x3F]
112
+ + lookup[num & 0x3F]
113
+ ;
106
114
  }
107
115
 
116
+ /**
117
+ *
118
+ * @param {Uint8Array} uint8
119
+ * @param {number} start
120
+ * @param {number} end
121
+ * @return {string}
122
+ */
108
123
  function encodeChunk(uint8, start, end) {
109
- var tmp;
110
- var output = [];
111
- for (var i = start; i < end; i += 3) {
112
- tmp =
113
- ((uint8[i] << 16) & 0xFF0000) +
114
- ((uint8[i + 1] << 8) & 0xFF00) +
115
- (uint8[i + 2] & 0xFF);
124
+ const output = [];
125
+
126
+ for (let i = start; i < end; i += 3) {
127
+
128
+ const tmp = ((uint8[i] << 16) & 0xFF0000)
129
+ + ((uint8[i + 1] << 8) & 0xFF00)
130
+ + (uint8[i + 2] & 0xFF);
131
+
116
132
  output.push(tripletToBase64(tmp));
117
133
  }
134
+
118
135
  return output.join('');
119
136
  }
120
137
 
138
+ /**
139
+ *
140
+ * @param {Uint8Array} uint8
141
+ * @return {string}
142
+ */
121
143
  function fromByteArray(uint8) {
122
- var tmp;
123
- var len = uint8.length;
124
- var extraBytes = len % 3; // if we have 1 byte left, pad 2 bytes
125
- var parts = [];
126
- var maxChunkLength = 16383; // must be multiple of 3
144
+ let tmp;
145
+
146
+ const len = uint8.length;
147
+ const extraBytes = len % 3; // if we have 1 byte left, pad 2 bytes
148
+ const parts = [];
149
+ const maxChunkLength = 16383; // must be multiple of 3
127
150
 
128
151
  // go through the array every three bytes, we'll deal with trailing stuff later
129
- for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
130
- parts.push(encodeChunk(
131
- uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)
132
- ));
152
+ const len2 = len - extraBytes;
153
+
154
+ for (let i = 0; i < len2; i += maxChunkLength) {
155
+ const end = (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength);
156
+
157
+ const chunk = encodeChunk(uint8, i, end);
158
+
159
+ parts.push(chunk);
133
160
  }
134
161
 
135
162
  // pad the end with zeros, but make sure to not forget the extra bytes
@@ -0,0 +1,14 @@
1
+ import { Base64 } from "./Base64.js";
2
+
3
+ test("to/from consistency", () => {
4
+ const source = new Uint8Array(256);
5
+ for (let i = 0; i < source.length; i++) {
6
+ source[i] = i;
7
+ }
8
+
9
+ const encoded = Base64.encode(source.buffer);
10
+
11
+ const decoded = Base64.decode(encoded);
12
+
13
+ expect(Array.from(new Uint8Array(decoded))).toEqual(Array.from(source));
14
+ });
@@ -301,12 +301,15 @@ export class Color {
301
301
  * @param {number} v 0..1
302
302
  */
303
303
  setHSV(h, s, v) {
304
- let _h = h % 1;
304
+ let _h = h;
305
305
 
306
306
  if (_h < 0) {
307
- _h = h + 1;
307
+ // move into positive range
308
+ _h = _h + Math.ceil(Math.abs(_h));
308
309
  }
309
310
 
311
+ _h = _h % 1
312
+
310
313
  const _s = clamp01(s);
311
314
  const _v = clamp01(v);
312
315
 
@@ -409,7 +412,8 @@ export class Color {
409
412
  * @param {Color} other
410
413
  */
411
414
  copy(other) {
412
- this.setRGB(this.r, this.g, this.b);
415
+ this.a = other.a;
416
+ this.setRGB(other.r, other.g, other.b);
413
417
  }
414
418
 
415
419
  /**
@@ -8,7 +8,7 @@ import { assert } from "../assert.js";
8
8
  import Signal from "../events/signal/Signal.js";
9
9
  import { clamp } from "../math/clamp.js";
10
10
  import { lerp } from "../math/lerp.js";
11
- import { EPSILON, epsilonEquals, PI2 } from "../math/MathUtils.js";
11
+ import { EPSILON, epsilonEquals } from "../math/MathUtils.js";
12
12
  import Vector3 from "./Vector3.js";
13
13
  import { v3_dot } from "./v3_dot.js";
14
14
  import { min2 } from "../math/min2.js";
@@ -20,12 +20,6 @@ const forward = new Vector3();
20
20
  const up = new Vector3();
21
21
  const right = new Vector3();
22
22
 
23
- const rotAxis = new Vector3();
24
-
25
- function normalizeAngle(v) {
26
- return v % PI2;
27
- }
28
-
29
23
  /**
30
24
  *
31
25
  * @param {number[]|Float32Array} out
@@ -518,7 +512,12 @@ class Quaternion {
518
512
  * @return {number}
519
513
  */
520
514
  length() {
521
- return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
515
+ const x = this.x;
516
+ const y = this.y;
517
+ const z = this.z;
518
+ const w = this.w;
519
+
520
+ return Math.sqrt(x * x + y * y + z * z + w * w);
522
521
  }
523
522
 
524
523
  /**
@@ -827,13 +826,16 @@ class Quaternion {
827
826
  const scaled_y = y * 0.5;
828
827
  const scaled_z = z * 0.5;
829
828
 
830
- const s1 = Math.sin(scaled_x);
831
- const s2 = Math.sin(scaled_y);
832
- const s3 = Math.sin(scaled_z);
829
+ const sin = Math.sin;
830
+ const cos = Math.cos;
831
+
832
+ const s1 = sin(scaled_x);
833
+ const s2 = sin(scaled_y);
834
+ const s3 = sin(scaled_z);
833
835
 
834
- const c1 = Math.cos(scaled_x);
835
- const c2 = Math.cos(scaled_y);
836
- const c3 = Math.cos(scaled_z);
836
+ const c1 = cos(scaled_x);
837
+ const c2 = cos(scaled_y);
838
+ const c3 = cos(scaled_z);
837
839
 
838
840
  const _x = s1 * c2 * c3 + c1 * s2 * s3;
839
841
  const _y = c1 * s2 * c3 - s1 * c2 * s3;
@@ -857,13 +859,16 @@ class Quaternion {
857
859
  const scaled_y = y * 0.5;
858
860
  const scaled_z = z * 0.5;
859
861
 
860
- const s1 = Math.sin(scaled_x);
861
- const s2 = Math.sin(scaled_y);
862
- const s3 = Math.sin(scaled_z);
862
+ const sin = Math.sin;
863
+ const cos = Math.cos;
864
+
865
+ const s1 = sin(scaled_x);
866
+ const s2 = sin(scaled_y);
867
+ const s3 = sin(scaled_z);
863
868
 
864
- const c1 = Math.cos(scaled_x);
865
- const c2 = Math.cos(scaled_y);
866
- const c3 = Math.cos(scaled_z);
869
+ const c1 = cos(scaled_x);
870
+ const c2 = cos(scaled_y);
871
+ const c3 = cos(scaled_z);
867
872
 
868
873
  const _x = s1 * c2 * c3 - c1 * s2 * s3;
869
874
  const _y = c1 * s2 * c3 + s1 * c2 * s3;
@@ -887,13 +892,16 @@ class Quaternion {
887
892
  const scaled_y = y * 0.5;
888
893
  const scaled_z = z * 0.5;
889
894
 
890
- const s1 = Math.sin(scaled_x);
891
- const s2 = Math.sin(scaled_y);
892
- const s3 = Math.sin(scaled_z);
895
+ const sin = Math.sin;
896
+ const cos = Math.cos;
897
+
898
+ const s1 = sin(scaled_x);
899
+ const s2 = sin(scaled_y);
900
+ const s3 = sin(scaled_z);
893
901
 
894
- const c1 = Math.cos(scaled_x);
895
- const c2 = Math.cos(scaled_y);
896
- const c3 = Math.cos(scaled_z);
902
+ const c1 = cos(scaled_x);
903
+ const c2 = cos(scaled_y);
904
+ const c3 = cos(scaled_z);
897
905
 
898
906
  const _x = s1 * c2 * c3 - c1 * s2 * s3;
899
907
  const _y = c1 * s2 * c3 + s1 * c2 * s3;
@@ -917,13 +925,16 @@ class Quaternion {
917
925
  const scaled_y = y * 0.5;
918
926
  const scaled_z = z * 0.5;
919
927
 
920
- const s1 = Math.sin(scaled_x);
921
- const s2 = Math.sin(scaled_y);
922
- const s3 = Math.sin(scaled_z);
928
+ const sin = Math.sin;
929
+ const cos = Math.cos;
930
+
931
+ const s1 = sin(scaled_x);
932
+ const s2 = sin(scaled_y);
933
+ const s3 = sin(scaled_z);
923
934
 
924
- const c1 = Math.cos(scaled_x);
925
- const c2 = Math.cos(scaled_y);
926
- const c3 = Math.cos(scaled_z);
935
+ const c1 = cos(scaled_x);
936
+ const c2 = cos(scaled_y);
937
+ const c3 = cos(scaled_z);
927
938
 
928
939
  const _x = s1 * c2 * c3 + c1 * s2 * s3;
929
940
  const _y = c1 * s2 * c3 + s1 * c2 * s3;
@@ -947,13 +958,16 @@ class Quaternion {
947
958
  const scaled_y = y * 0.5;
948
959
  const scaled_z = z * 0.5;
949
960
 
950
- const s1 = Math.sin(scaled_x);
951
- const s2 = Math.sin(scaled_y);
952
- const s3 = Math.sin(scaled_z);
961
+ const sin = Math.sin;
962
+ const cos = Math.cos;
963
+
964
+ const s1 = sin(scaled_x);
965
+ const s2 = sin(scaled_y);
966
+ const s3 = sin(scaled_z);
953
967
 
954
- const c1 = Math.cos(scaled_x);
955
- const c2 = Math.cos(scaled_y);
956
- const c3 = Math.cos(scaled_z);
968
+ const c1 = cos(scaled_x);
969
+ const c2 = cos(scaled_y);
970
+ const c3 = cos(scaled_z);
957
971
 
958
972
  const _x = s1 * c2 * c3 - c1 * s2 * s3;
959
973
  const _y = c1 * s2 * c3 - s1 * c2 * s3;
@@ -32,7 +32,7 @@ export class ModuleRegistry {
32
32
 
33
33
  /**
34
34
  *
35
- * @param {function(name:string, module:*)} visitor
35
+ * @param {(name:string, module:*)=>void} visitor
36
36
  */
37
37
  traverse(visitor) {
38
38
  this.__elements.forEach((klass, name) => visitor(name, klass));
@@ -57,7 +57,7 @@ export class ReactiveReference extends ReactiveExpression {
57
57
  }
58
58
 
59
59
  update(v, oldV) {
60
- this.onChanged.dispatch(v, oldV);
60
+ this.onChanged.send2(v, oldV);
61
61
  }
62
62
 
63
63
  connect(source) {
@@ -10,7 +10,7 @@ export class ReactiveTrigger {
10
10
  */
11
11
  constructor(code) {
12
12
 
13
- assert.typeOf(code, "string", code);
13
+ assert.isString(code, "code");
14
14
 
15
15
  /**
16
16
  *
@@ -55,15 +55,25 @@ export class ReactiveTrigger {
55
55
  * @param {Object} data
56
56
  */
57
57
  connect(data) {
58
- this.references.forEach(ref => {
58
+ const references = this.references;
59
+ const ref_count = references.length;
60
+
61
+ for (let i = 0; i < ref_count; i++) {
62
+ const ref = references[i];
59
63
  const refName = ref.name;
60
64
  const datum = data[refName];
61
65
 
62
66
  ref.connect(datum);
63
- });
67
+ }
64
68
  }
65
69
 
66
70
  disconnect() {
67
- this.references.forEach(ref => ref.disconnect());
71
+ const references = this.references;
72
+ const ref_count = references.length;
73
+
74
+ for (let i = 0; i < ref_count; i++) {
75
+ const ref = references[i];
76
+ ref.disconnect();
77
+ }
68
78
  }
69
79
  }
@@ -4,6 +4,49 @@ import EmptyView from "../../../../view/elements/EmptyView.js";
4
4
  import ImageView from "../../../../view/elements/image/ImageView.js";
5
5
  import ObservedString from "../../../../core/model/ObservedString.js";
6
6
  import { ObservedStringEditor } from "./ObservedStringEditor.js";
7
+ import ButtonView from "../../../../view/elements/button/ButtonView.js";
8
+
9
+ /**
10
+ *
11
+ * @param {string} url
12
+ * @return {boolean}
13
+ */
14
+ function is_data_url(url) {
15
+ if (typeof url !== "string") {
16
+ return false;
17
+ }
18
+
19
+ return url.startsWith('data:');
20
+ }
21
+
22
+ /**
23
+ *
24
+ * @param {string} url
25
+ * @returns {string}
26
+ */
27
+ async function url_to_data_url(url) {
28
+ return fetch(url)
29
+ .then(response => {
30
+ return response.blob();
31
+ })
32
+ .then(blob => {
33
+ const fr = new FileReader();
34
+
35
+ return new Promise((resolve, reject) => {
36
+
37
+ fr.onload = () => {
38
+ resolve(fr.result);
39
+ };
40
+
41
+ fr.onerror = reject;
42
+ fr.onabort = reject;
43
+
44
+ fr.readAsDataURL(blob);
45
+
46
+ });
47
+
48
+ });
49
+ }
7
50
 
8
51
  export class ImagePathEditor extends TypeEditor {
9
52
  inline = true;
@@ -36,8 +79,46 @@ export class ImagePathEditor extends TypeEditor {
36
79
 
37
80
  vPreview.size.set(32, 32);
38
81
 
82
+ const b_toDataURL = new ButtonView({
83
+ classList: ['convert-to-data-url', 'embed'],
84
+ async action() {
85
+ const url = await url_to_data_url(field.adapter.read(parent, field.name));
86
+
87
+ field.adapter.write(parent, field.name, url);
88
+
89
+ // update editor value
90
+ vEditor.el.value = url;
91
+
92
+ update();
93
+ }
94
+ });
95
+
96
+ b_toDataURL.attr({
97
+ title:'Convert URL into DATA_URL, embedding the data. This allows to bypass CORRS restrictions if the URL points to a different origin from the one where the texture resides'
98
+ });
99
+
100
+ function update_data_url_status() {
101
+ const url = field.adapter.read(parent, field.name);
102
+
103
+ const can_convert = typeof url === "string"
104
+ && field.adapter.writable
105
+ && !is_data_url(url)
106
+ ;
107
+
108
+ if (can_convert) {
109
+ // offer encoding option
110
+ r.addChild(b_toDataURL);
111
+ } else {
112
+ // nothing
113
+ if (r.hasChild(b_toDataURL)) {
114
+ r.removeChild(b_toDataURL);
115
+ }
116
+ }
117
+ }
118
+
39
119
  function update() {
40
120
  vPreview.__setSource(vEditor.el.value);
121
+ update_data_url_status();
41
122
  }
42
123
 
43
124
  r.addChild(vPreview);
@@ -45,6 +126,8 @@ export class ImagePathEditor extends TypeEditor {
45
126
 
46
127
  vEditor.el.addEventListener('input', update);
47
128
 
129
+ r.on.linked.add(update_data_url_status);
130
+
48
131
  return r;
49
132
  }
50
133
  }
@@ -8,6 +8,7 @@ import { scaleSampler2D } from "../../../../graphics/texture/sampler/scaleSample
8
8
  import { countTask } from "../../../../../core/process/task/TaskUtils.js";
9
9
  import { array_copy } from "../../../../../core/collection/array/copyArray.js";
10
10
  import { typed_array_copy } from "../../../../../core/collection/array/typed/typed_array_copy.js";
11
+ import { Base64 } from "../../../../../core/binary/Base64.js";
11
12
 
12
13
 
13
14
  /**
@@ -52,20 +53,42 @@ export class SplatMapping {
52
53
  }
53
54
 
54
55
  toJSON() {
56
+ const encoded = Base64.encode(this.weightData.buffer);
57
+
55
58
  return {
56
59
  size: this.size.toJSON(),
57
60
  depth: this.depth,
58
- data: Array.from(this.weightData)
61
+ data: encoded
59
62
  };
60
63
  }
61
64
 
62
65
  fromJSON({
63
66
  size = { x: 1, y: 1 },
64
67
  depth = 0,
65
- data = []
66
- } = {}) {
68
+ data
69
+ } = {}) {
67
70
  this.resize(size.x, size.y, depth);
68
- array_copy(data, 0, this.weightData, 0, data.length);
71
+
72
+ let uint_data;
73
+
74
+ if (typeof data === "string") {
75
+
76
+ const decoded_data = Base64.decode(data);
77
+ uint_data = new Uint8Array(decoded_data);
78
+
79
+ } else if (Array.isArray(data)) {
80
+
81
+ // deprecated
82
+ console.warn('Array JSON format is deprecated, please upgrade your data as soon as possible');
83
+ uint_data = data;
84
+
85
+ } else {
86
+
87
+ throw new Error('Unsupported data format');
88
+
89
+ }
90
+
91
+ array_copy(uint_data, 0, this.weightData, 0, data.length);
69
92
 
70
93
  this.weightTexture.needsUpdate = true;
71
94
  }
@@ -281,15 +281,23 @@ export class ShadedGeometry {
281
281
 
282
282
  const min = gbb.min;
283
283
 
284
- scratch_aabb3_array[0] = min.x;
285
- scratch_aabb3_array[1] = min.y;
286
- scratch_aabb3_array[2] = min.z;
284
+ const x0 = min.x;
285
+ const y0 = min.y;
286
+ const z0 = min.z;
287
287
 
288
288
  const max = gbb.max;
289
289
 
290
- scratch_aabb3_array[3] = max.x;
291
- scratch_aabb3_array[4] = max.y;
292
- scratch_aabb3_array[5] = max.z;
290
+ const x1 = max.x;
291
+ const y1 = max.y;
292
+ const z1 = max.z;
293
+
294
+ scratch_aabb3_array[0] = x0;
295
+ scratch_aabb3_array[1] = y0;
296
+ scratch_aabb3_array[2] = z0;
297
+
298
+ scratch_aabb3_array[3] = x1;
299
+ scratch_aabb3_array[4] = y1;
300
+ scratch_aabb3_array[5] = z1;
293
301
 
294
302
  aabb3_matrix4_project(this.__bvh_aabb, scratch_aabb3_array, this.transform);
295
303
  }
@@ -3,7 +3,8 @@ import { AABB3 } from "../../../../../core/bvh2/aabb3/AABB3.js";
3
3
 
4
4
  export const SGMeshFlags = {
5
5
  CastShadow: 1,
6
- ReceiveShadow: 2
6
+ ReceiveShadow: 2,
7
+ Loaded: 4
7
8
  };
8
9
 
9
10
  export class SGMesh {
@@ -17,6 +17,13 @@ import { min2 } from "../../../../../core/math/min2.js";
17
17
  */
18
18
  const MAX_CYCLE_COUNT = 128;
19
19
 
20
+ /**
21
+ * In milliseconds
22
+ * @readonly
23
+ * @type {number}
24
+ */
25
+ const MAX_CYCLE_TIME = 40;
26
+
20
27
  export class SGMeshSystem extends System {
21
28
  /**
22
29
  *
@@ -235,10 +242,11 @@ export class SGMeshSystem extends System {
235
242
 
236
243
  if (l > 0) {
237
244
 
238
- let pointer = this.__wait_queue_process_index;
245
+ const time_0 = performance.now();
239
246
 
247
+ let pointer = this.__wait_queue_process_index;
240
248
 
241
- let pointer_limit = pointer + min2(l, MAX_CYCLE_COUNT);
249
+ const pointer_limit = pointer + min2(l, MAX_CYCLE_COUNT);
242
250
 
243
251
  while (pointer < pointer_limit) {
244
252
 
@@ -260,6 +268,13 @@ export class SGMeshSystem extends System {
260
268
 
261
269
  this.process(entity, mesh, transform);
262
270
 
271
+ const time_1 = performance.now();
272
+
273
+ if ((time_1 - time_0) > MAX_CYCLE_TIME) {
274
+ // too much time has passed
275
+ break;
276
+ }
277
+
263
278
  }
264
279
 
265
280
  this.__wait_queue_process_index = pointer;
@@ -14,6 +14,7 @@ import { typedArrayToDataType } from "../../../../core/collection/array/typedArr
14
14
  import {
15
15
  compute_typed_array_constructor_from_data_type
16
16
  } from "../../../../core/collection/table/DataType2TypedArrayConstructorMapping.js";
17
+ import { Base64 } from "../../../../core/binary/Base64.js";
17
18
 
18
19
  /**
19
20
  * @class
@@ -1450,19 +1451,38 @@ export class Sampler2D {
1450
1451
  }
1451
1452
 
1452
1453
  toJSON() {
1454
+ const encoded = Base64.encode(this.data.buffer);
1455
+
1453
1456
  return {
1454
1457
  height: this.height,
1455
1458
  width: this.width,
1456
1459
  itemSize: this.itemSize,
1457
1460
  type: typedArrayToDataType(this.data),
1458
- data: Array.from(this.data)
1461
+ data: encoded
1459
1462
  }
1460
1463
  }
1461
1464
 
1462
1465
  fromJSON({ height, width, itemSize, type, data }) {
1463
1466
  const CTOR = compute_typed_array_constructor_from_data_type(type);
1464
1467
 
1465
- this.data = new CTOR(data);
1468
+ if (typeof data === "string") {
1469
+
1470
+ const decoded = Base64.decode(data);
1471
+
1472
+ this.data = new CTOR(decoded);
1473
+
1474
+ } else if (Array.isArray(data)) {
1475
+ // deprecated
1476
+ console.warn('Array JSON format is deprecated, please upgrade your data as soon as possible');
1477
+
1478
+ this.data = new CTOR(data);
1479
+
1480
+ }else{
1481
+
1482
+ throw new Error('Unsupported data format');
1483
+
1484
+ }
1485
+
1466
1486
  this.height = height;
1467
1487
  this.width = width;
1468
1488
  this.itemSize = itemSize;
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "productName": "Meep",
6
6
  "description": "production-ready JavaScript game engine based on Entity Component System Architecture",
7
7
  "author": "Alexander Goldring",
8
- "version": "2.39.38",
8
+ "version": "2.39.39",
9
9
  "dependencies": {
10
10
  "gl-matrix": "3.4.3",
11
11
  "fast-levenshtein": "2.0.6",
@@ -50,7 +50,18 @@ class ButtonView extends View {
50
50
 
51
51
  this.el.addEventListener('click', (event) => {
52
52
  if (this.__enabled) {
53
- action(event);
53
+ const p = action(event);
54
+
55
+ if (p instanceof Promise) {
56
+ // async resolution, wait until done, disable button for now
57
+ this.enabled = false;
58
+
59
+ p.finally(() => {
60
+ // restore
61
+ this.enabled = true;
62
+ });
63
+
64
+ }
54
65
  } else {
55
66
  console.warn('Button is disabled, no action');
56
67
  }