@woosh/meep-engine 2.47.32 → 2.47.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -60433,11 +60433,13 @@ class MapEntry {
60433
60433
  * @param {number} hash
60434
60434
  */
60435
60435
  constructor(key, value, hash) {
60436
+
60436
60437
  /**
60437
60438
  *
60438
60439
  * @type {K}
60439
60440
  */
60440
60441
  this.key = key;
60442
+
60441
60443
  /**
60442
60444
  *
60443
60445
  * @type {V}
@@ -60449,6 +60451,7 @@ class MapEntry {
60449
60451
  * @type {number}
60450
60452
  */
60451
60453
  this.hash = hash;
60454
+
60452
60455
  }
60453
60456
  }
60454
60457
 
@@ -60464,6 +60467,13 @@ const DEFAULT_INITIAL_CAPACITY = 16;
60464
60467
  */
60465
60468
  const DEFAULT_LOAD_FACTOR = 0.75;
60466
60469
 
60470
+ /**
60471
+ * Multiply previous size by this number when growing the table
60472
+ * @readonly
60473
+ * @type {number}
60474
+ */
60475
+ const GROWTH_FACTOR = 2;
60476
+
60467
60477
  /**
60468
60478
  * Implements part of {@link Map} interface
60469
60479
  * @copyright Alex Goldring (c) 2023
@@ -60488,7 +60498,9 @@ class HashMap {
60488
60498
  assert.isFunction(keyHashFunction, 'keyHashFunction');
60489
60499
  assert.isFunction(keyEqualityFunction, 'keyEqualityFunction');
60490
60500
  assert.isNonNegativeInteger(capacity, 'capacity');
60501
+
60491
60502
  assert.isNumber(loadFactor, 'loadFactor');
60503
+ assert.greaterThan(loadFactor, 0, 'loadFactor must be > 0');
60492
60504
 
60493
60505
  /**
60494
60506
  *
@@ -60601,6 +60613,8 @@ class HashMap {
60601
60613
  * @private
60602
60614
  */
60603
60615
  __compute_bucket_index(hash) {
60616
+ assert.isInteger(hash, 'hash');
60617
+
60604
60618
  // mix the input hash to minimize potential impact of poor hash function spread
60605
60619
  const mixed_hash = (hash >>> 16) ^ hash;
60606
60620
 
@@ -60664,18 +60678,19 @@ class HashMap {
60664
60678
 
60665
60679
  }
60666
60680
 
60667
- bucket.push(new MapEntry(key, value,raw_hash));
60681
+ bucket.push(new MapEntry(key, value, raw_hash));
60668
60682
 
60669
60683
  const old_size = this.size;
60670
60684
  const new_size = old_size + 1;
60671
60685
  this.size = new_size;
60672
60686
 
60673
60687
  // compute actual current load
60674
- const load = new_size / this.__bucket_count;
60688
+ const bucket_count = this.__bucket_count;
60689
+ const load = new_size / bucket_count;
60675
60690
 
60676
60691
  if (load > this.__load_factor) {
60677
60692
  // current load is too high, increase table size
60678
- this.setBucketCount(this.__bucket_count * 2);
60693
+ this.setBucketCount(bucket_count * GROWTH_FACTOR);
60679
60694
  }
60680
60695
  }
60681
60696
 
@@ -60800,8 +60815,11 @@ class HashMap {
60800
60815
  /**
60801
60816
  *
60802
60817
  * @param {function(message:string, key:K, value:V)} callback
60818
+ * @param {*} [thisArg]
60819
+ * @returns {boolean}
60803
60820
  */
60804
- verifyHashes(callback) {
60821
+ verifyHashes(callback, thisArg) {
60822
+ let all_hashes_valid = true;
60805
60823
 
60806
60824
  let h, i;
60807
60825
 
@@ -60827,15 +60845,25 @@ class HashMap {
60827
60845
  //check hash
60828
60846
  const raw_hash = this.keyHashFunction(entry.key);
60829
60847
 
60848
+ if (entry.hash !== raw_hash) {
60849
+ callback.call(thisArg, `Hash stored on the entry(=${entry.hash}) is different from the computed key hash(=${raw_hash}).`, entry.key, entry.value);
60850
+
60851
+ all_hashes_valid = false;
60852
+ }
60853
+
60830
60854
  const actual_bucket_index = this.__compute_bucket_index(raw_hash);
60831
60855
 
60832
60856
  const stored_bucket_index = parseInt(h);
60833
60857
 
60834
60858
  if (actual_bucket_index !== stored_bucket_index) {
60835
- callback(`Hash of key has changed. old=${stored_bucket_index}, new=${actual_bucket_index}`, entry.key, entry.value);
60859
+ callback.call(thisArg, `Hash of key has changed. old=${stored_bucket_index}, new=${actual_bucket_index}`, entry.key, entry.value);
60860
+
60861
+ all_hashes_valid = false;
60836
60862
  }
60837
60863
  }
60838
60864
  }
60865
+
60866
+ return all_hashes_valid;
60839
60867
  }
60840
60868
 
60841
60869
  /**
@@ -61499,6 +61527,18 @@ class Cache {
61499
61527
 
61500
61528
  this.weight = 0;
61501
61529
  }
61530
+
61531
+ /**
61532
+ *
61533
+ * @param {function(message:string, key:Key, value:Value)} callback
61534
+ * @param {*} [thisArg]
61535
+ * @returns {boolean}
61536
+ */
61537
+ validate(callback, thisArg) {
61538
+ return this.data.verifyHashes((msg, key, entry) => {
61539
+ callback.call(thisArg, msg, key, entry.value);
61540
+ });
61541
+ }
61502
61542
  }
61503
61543
 
61504
61544
  /**
@@ -77809,6 +77849,24 @@ class StaticMaterialCache {
77809
77849
  return material;
77810
77850
 
77811
77851
  }
77852
+
77853
+ /**
77854
+ *
77855
+ * @param {function(string)} error_consumer
77856
+ * @param {*} [thisArg]
77857
+ * @returns {boolean}
77858
+ */
77859
+ validate(error_consumer, thisArg) {
77860
+ const materials_valid = this.materialCache.validate((message, key, value) => {
77861
+ error_consumer.call(thisArg, `Material error: ${message}. Material ${key}`);
77862
+ });
77863
+ const textures_valid = this.textureCache.validate((message, key, value) => {
77864
+ error_consumer.call(thisArg, `Texture error: ${message}. Texture ${key}`);
77865
+ });
77866
+
77867
+ return materials_valid
77868
+ && textures_valid;
77869
+ }
77812
77870
  }
77813
77871
 
77814
77872
  /**
@@ -78461,42 +78519,90 @@ class InstancedMeshGroup {
78461
78519
  }
78462
78520
  }
78463
78521
 
78522
+ class SGCacheKey {
78523
+ geometry = -1;
78524
+ material = -1;
78525
+ /**
78526
+ *
78527
+ * @type {DrawMode}
78528
+ */
78529
+ mode = DrawMode.Triangles;
78530
+
78531
+ flags = 0;
78532
+
78533
+ hash(){
78534
+ return this.geometry ^ this.material;
78535
+ }
78536
+
78537
+ /**
78538
+ *
78539
+ * @param {SGCacheKey} other
78540
+ * @returns {boolean}
78541
+ */
78542
+ equals(other){
78543
+ return this.geometry === other.geometry
78544
+ && this.material === other.material
78545
+ && this.mode === other.mode
78546
+ && this.flags === other.flags;
78547
+ }
78548
+
78549
+ /**
78550
+ *
78551
+ * @param {SGCacheKey} other
78552
+ */
78553
+ copy(other){
78554
+ this.geometry = other.geometry;
78555
+ this.material = other.material;
78556
+ this.mode = other.mode;
78557
+ this.flags = other.flags;
78558
+ }
78559
+
78560
+ clone(){
78561
+ const r = new SGCacheKey();
78562
+
78563
+ r.copy(this);
78564
+
78565
+ return r;
78566
+ }
78567
+
78568
+ /**
78569
+ *
78570
+ * @param {ShadedGeometry} sg
78571
+ */
78572
+ fromSG(sg){
78573
+ this.geometry = sg.geometry.id;
78574
+ this.material = sg.material.id;
78575
+ this.mode = sg.mode;
78576
+ this.flags = sg.flags;
78577
+ }
78578
+ }
78579
+
78464
78580
  const INSTANCED_EQUALITY_FLAGS = ShadedGeometryFlags.CastShadow
78465
78581
  | ShadedGeometryFlags.ReceiveShadow
78466
78582
  ;
78467
78583
 
78584
+ /**
78585
+ * @readonly
78586
+ * @type {SGCacheKey}
78587
+ */
78588
+ const scratch_key = new SGCacheKey();
78589
+
78468
78590
  class InstancedRendererAdapter extends AbstractRenderAdapter {
78469
- constructor() {
78470
- super();
78471
78591
 
78472
- /**
78473
- *
78474
- * @type {HashMap<ShadedGeometry, InstancedMeshGroup>}
78475
- * @private
78476
- */
78477
- this.__instanced_meshes = new HashMap({
78478
- keyHashFunction(sg) {
78479
- return sg.geometry.id
78480
- ^ sg.material.id
78481
- ^ sg.mode
78482
- ;
78483
- },
78484
- keyEqualityFunction(a, b) {
78485
- return a.material.id === b.material.id
78486
- && a.geometry.id === b.geometry.id
78487
- && a.mode === b.mode
78488
- && (a.flags & INSTANCED_EQUALITY_FLAGS) === (b.flags & INSTANCED_EQUALITY_FLAGS)
78489
- ;
78490
- }
78491
- });
78592
+ /**
78593
+ *
78594
+ * @type {HashMap<SGCacheKey, InstancedMeshGroup>}
78595
+ * @private
78596
+ */
78597
+ __instanced_meshes = new HashMap();
78598
+
78599
+ /**
78600
+ *
78601
+ * @type {Set<InstancedMeshGroup>}
78602
+ * @private
78603
+ */
78604
+ __active_meshes = new Set();
78492
78605
 
78493
- /**
78494
- *
78495
- * @type {Set<InstancedMeshGroup>}
78496
- * @private
78497
- */
78498
- this.__active_meshes = new Set();
78499
- }
78500
78606
 
78501
78607
  score(geometry, material, instance_count) {
78502
78608
  if (instance_count > 16) {
@@ -78515,7 +78621,12 @@ class InstancedRendererAdapter extends AbstractRenderAdapter {
78515
78621
  * @private
78516
78622
  */
78517
78623
  __get_instanced_mesh(sg) {
78518
- let im = this.__instanced_meshes.get(sg);
78624
+ scratch_key.fromSG(sg);
78625
+
78626
+ // mask out some flags
78627
+ scratch_key.flags &= INSTANCED_EQUALITY_FLAGS;
78628
+
78629
+ let im = this.__instanced_meshes.get(scratch_key);
78519
78630
 
78520
78631
 
78521
78632
  if (im !== undefined) {
@@ -78536,7 +78647,7 @@ class InstancedRendererAdapter extends AbstractRenderAdapter {
78536
78647
  im.mesh.castShadow = sg.getFlag(ShadedGeometryFlags.CastShadow);
78537
78648
  im.mesh.receiveShadow = sg.getFlag(ShadedGeometryFlags.ReceiveShadow);
78538
78649
 
78539
- this.__instanced_meshes.set(sg, im);
78650
+ this.__instanced_meshes.set(scratch_key.clone(), im);
78540
78651
 
78541
78652
  return im;
78542
78653
 
@@ -78588,8 +78699,8 @@ class InstancedRendererAdapter extends AbstractRenderAdapter {
78588
78699
 
78589
78700
  const meshes = this.__active_meshes;
78590
78701
 
78591
- for (const activeMesh of meshes) {
78592
- activeMesh.setCount(0);
78702
+ for (const mesh of meshes) {
78703
+ mesh.setCount(0);
78593
78704
  }
78594
78705
 
78595
78706
  meshes.clear();
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "description": "Fully featured ECS game engine written in JavaScript",
6
6
  "type": "module",
7
7
  "author": "Alexander Goldring",
8
- "version": "2.47.32",
8
+ "version": "2.47.34",
9
9
  "main": "build/meep.module.js",
10
10
  "module": "build/meep.module.js",
11
11
  "exports": {
@@ -440,6 +440,18 @@ export class Cache {
440
440
 
441
441
  this.weight = 0;
442
442
  }
443
+
444
+ /**
445
+ *
446
+ * @param {function(message:string, key:Key, value:Value)} callback
447
+ * @param {*} [thisArg]
448
+ * @returns {boolean}
449
+ */
450
+ validate(callback, thisArg) {
451
+ return this.data.verifyHashes((msg, key, entry) => {
452
+ callback.call(thisArg, msg, key, entry.value);
453
+ });
454
+ }
443
455
  }
444
456
 
445
457
  /**
@@ -14,11 +14,13 @@ class MapEntry {
14
14
  * @param {number} hash
15
15
  */
16
16
  constructor(key, value, hash) {
17
+
17
18
  /**
18
19
  *
19
20
  * @type {K}
20
21
  */
21
22
  this.key = key;
23
+
22
24
  /**
23
25
  *
24
26
  * @type {V}
@@ -30,6 +32,7 @@ class MapEntry {
30
32
  * @type {number}
31
33
  */
32
34
  this.hash = hash;
35
+
33
36
  }
34
37
  }
35
38
 
@@ -45,6 +48,13 @@ const DEFAULT_INITIAL_CAPACITY = 16;
45
48
  */
46
49
  const DEFAULT_LOAD_FACTOR = 0.75;
47
50
 
51
+ /**
52
+ * Multiply previous size by this number when growing the table
53
+ * @readonly
54
+ * @type {number}
55
+ */
56
+ const GROWTH_FACTOR = 2;
57
+
48
58
  /**
49
59
  * Implements part of {@link Map} interface
50
60
  * @copyright Alex Goldring (c) 2023
@@ -69,7 +79,9 @@ export class HashMap {
69
79
  assert.isFunction(keyHashFunction, 'keyHashFunction');
70
80
  assert.isFunction(keyEqualityFunction, 'keyEqualityFunction');
71
81
  assert.isNonNegativeInteger(capacity, 'capacity');
82
+
72
83
  assert.isNumber(loadFactor, 'loadFactor');
84
+ assert.greaterThan(loadFactor, 0, 'loadFactor must be > 0');
73
85
 
74
86
  /**
75
87
  *
@@ -182,6 +194,8 @@ export class HashMap {
182
194
  * @private
183
195
  */
184
196
  __compute_bucket_index(hash) {
197
+ assert.isInteger(hash, 'hash');
198
+
185
199
  // mix the input hash to minimize potential impact of poor hash function spread
186
200
  const mixed_hash = (hash >>> 16) ^ hash;
187
201
 
@@ -245,18 +259,19 @@ export class HashMap {
245
259
 
246
260
  }
247
261
 
248
- bucket.push(new MapEntry(key, value,raw_hash));
262
+ bucket.push(new MapEntry(key, value, raw_hash));
249
263
 
250
264
  const old_size = this.size;
251
265
  const new_size = old_size + 1;
252
266
  this.size = new_size;
253
267
 
254
268
  // compute actual current load
255
- const load = new_size / this.__bucket_count;
269
+ const bucket_count = this.__bucket_count;
270
+ const load = new_size / bucket_count;
256
271
 
257
272
  if (load > this.__load_factor) {
258
273
  // current load is too high, increase table size
259
- this.setBucketCount(this.__bucket_count * 2);
274
+ this.setBucketCount(bucket_count * GROWTH_FACTOR);
260
275
  }
261
276
  }
262
277
 
@@ -381,8 +396,11 @@ export class HashMap {
381
396
  /**
382
397
  *
383
398
  * @param {function(message:string, key:K, value:V)} callback
399
+ * @param {*} [thisArg]
400
+ * @returns {boolean}
384
401
  */
385
- verifyHashes(callback) {
402
+ verifyHashes(callback, thisArg) {
403
+ let all_hashes_valid = true;
386
404
 
387
405
  let h, i;
388
406
 
@@ -408,15 +426,25 @@ export class HashMap {
408
426
  //check hash
409
427
  const raw_hash = this.keyHashFunction(entry.key);
410
428
 
429
+ if (entry.hash !== raw_hash) {
430
+ callback.call(thisArg, `Hash stored on the entry(=${entry.hash}) is different from the computed key hash(=${raw_hash}).`, entry.key, entry.value)
431
+
432
+ all_hashes_valid = false;
433
+ }
434
+
411
435
  const actual_bucket_index = this.__compute_bucket_index(raw_hash);
412
436
 
413
437
  const stored_bucket_index = parseInt(h);
414
438
 
415
439
  if (actual_bucket_index !== stored_bucket_index) {
416
- callback(`Hash of key has changed. old=${stored_bucket_index}, new=${actual_bucket_index}`, entry.key, entry.value);
440
+ callback.call(thisArg, `Hash of key has changed. old=${stored_bucket_index}, new=${actual_bucket_index}`, entry.key, entry.value);
441
+
442
+ all_hashes_valid = false;
417
443
  }
418
444
  }
419
445
  }
446
+
447
+ return all_hashes_valid;
420
448
  }
421
449
 
422
450
  /**
@@ -1,10 +1,11 @@
1
1
  import { HashMap } from "./HashMap.js";
2
+ import { passThrough, strictEquals } from "../function/Functions.js";
2
3
 
3
4
  /**
4
5
  *
5
6
  * @returns {HashMap}
6
7
  */
7
- function makeA() {
8
+ function makeSample() {
8
9
  return new HashMap({
9
10
  keyHashFunction(k) {
10
11
  return 1;
@@ -16,7 +17,7 @@ function makeA() {
16
17
  }
17
18
 
18
19
  test('put and get same value', () => {
19
- const m = makeA();
20
+ const m = makeSample();
20
21
 
21
22
  m.set("hey", 42);
22
23
 
@@ -26,7 +27,7 @@ test('put and get same value', () => {
26
27
  });
27
28
 
28
29
  test("map has a key", () => {
29
- const m = makeA();
30
+ const m = makeSample();
30
31
 
31
32
  expect(m.has('cat')).toBe(false);
32
33
 
@@ -38,7 +39,7 @@ test("map has a key", () => {
38
39
  test("put 2 values with same hash", () => {
39
40
 
40
41
 
41
- const m = makeA();
42
+ const m = makeSample();
42
43
 
43
44
  m.set("a", 7);
44
45
  m.set("b", 42);
@@ -48,3 +49,28 @@ test("put 2 values with same hash", () => {
48
49
  expect(m.get("a")).toBe(7);
49
50
  expect(m.get("b")).toBe(42);
50
51
  });
52
+
53
+ test("retrieval works as intended after hash map grows", () => {
54
+ const m = new HashMap({
55
+ keyHashFunction: passThrough,
56
+ keyEqualityFunction: strictEquals,
57
+ capacity: 1,
58
+ loadFactor: 1
59
+ });
60
+
61
+ m.set(1, "a");
62
+
63
+ expect(m.get(1)).toEqual("a")
64
+
65
+ m.set(150, "b");
66
+
67
+ expect(m.get(1)).toEqual("a");
68
+ expect(m.get(150)).toEqual("b");
69
+
70
+ m.set(-7, "c");
71
+
72
+ expect(m.get(1)).toEqual("a");
73
+ expect(m.get(150)).toEqual("b");
74
+ expect(m.get(-7)).toEqual("c");
75
+
76
+ });
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Matrix-transform an array of 3d direction vectors
3
+ * Code is inlined for speed
4
+ * @param {number[]|Float32Array|Float64Array} source
5
+ * @param {number} source_offset
6
+ * @param {number[]|Float32Array|Float64Array} destination
7
+ * @param {number} destination_offset
8
+ * @param {number} vertex_count
9
+ * @param {mat4|number[]|Float32Array} mat4
10
+ */
11
+ export function apply_mat4_transform_to_direction_v3_array(source, source_offset, destination, destination_offset, vertex_count, mat4) {
12
+
13
+ const a0 = mat4[0];
14
+ const a1 = mat4[1];
15
+ const a2 = mat4[2];
16
+
17
+ const b0 = mat4[4];
18
+ const b1 = mat4[5];
19
+ const b2 = mat4[6];
20
+
21
+ const c0 = mat4[8];
22
+ const c1 = mat4[9];
23
+ const c2 = mat4[10];
24
+
25
+ for (let i = 0; i < vertex_count; i++) {
26
+ const i3 = i * 3;
27
+
28
+ const source_vertex_address = source_offset + i3;
29
+
30
+ const _x = source[source_vertex_address];
31
+ const _y = source[source_vertex_address + 1];
32
+ const _z = source[source_vertex_address + 2];
33
+
34
+ const x = a0 * _x + b0 * _y + c0 * _z;
35
+ const y = a1 * _x + b1 * _y + c1 * _z;
36
+ const z = a2 * _x + b2 * _y + c2 * _z;
37
+
38
+ const normal_multiplier = 1 / Math.hypot(x, y, z);
39
+
40
+ const destination_vertex_address = destination_offset + i3;
41
+
42
+ destination[destination_vertex_address] = x * normal_multiplier;
43
+ destination[destination_vertex_address + 1] = y * normal_multiplier;
44
+ destination[destination_vertex_address + 2] = z * normal_multiplier;
45
+
46
+
47
+ }
48
+
49
+ }
@@ -5,10 +5,10 @@
5
5
  * @param {number} source_offset
6
6
  * @param {number[]|Float32Array|Float64Array} destination
7
7
  * @param {number} destination_offset
8
- * @param {number} count
8
+ * @param {number} vertex_count
9
9
  * @param {mat4|number[]|Float32Array} mat4
10
10
  */
11
- export function apply_mat4_transform_to_v3_array(source, source_offset, destination, destination_offset, count, mat4) {
11
+ export function apply_mat4_transform_to_v3_array(source, source_offset, destination, destination_offset, vertex_count, mat4) {
12
12
 
13
13
  const a0 = mat4[0];
14
14
  const a1 = mat4[1];
@@ -26,7 +26,7 @@ export function apply_mat4_transform_to_v3_array(source, source_offset, destinat
26
26
  const d1 = mat4[13];
27
27
  const d2 = mat4[14];
28
28
 
29
- for (let i = 0; i < count; i++) {
29
+ for (let i = 0; i < vertex_count; i++) {
30
30
  const i3 = i * 3;
31
31
 
32
32
  const source_vertex_address = source_offset + i3;
@@ -49,3 +49,4 @@ export function apply_mat4_transform_to_v3_array(source, source_offset, destinat
49
49
  }
50
50
 
51
51
  }
52
+
@@ -83,6 +83,15 @@ export class NodeDescription {
83
83
  };
84
84
  }
85
85
 
86
+ /**
87
+ * Perform additional processing on the node instance
88
+ * This gives us an opportunity to add/change ports based on current state of a specific node instance
89
+ * @param {NodeInstance} instance
90
+ */
91
+ configureNode(instance){
92
+ // override in subclasses as necessary
93
+ }
94
+
86
95
  /**
87
96
  * Output ports
88
97
  * @returns {Port[]}
@@ -32,7 +32,6 @@ export class NodeInstance {
32
32
  */
33
33
  this.endpoints = [];
34
34
 
35
-
36
35
  /**
37
36
  * Internal instance data
38
37
  * @type {Object}
@@ -51,6 +50,14 @@ export class NodeInstance {
51
50
  */
52
51
  this.connections = new List();
53
52
 
53
+ /**
54
+ * Extra ports that are present just on this instance, these exist in addition to ports from the description
55
+ * IDs of these ports must not collide with IDs of ports on the description
56
+ * @protected
57
+ * @type {Port[]}
58
+ */
59
+ this.dynamicPorts = [];
60
+
54
61
  /**
55
62
  * @readonly
56
63
  */
@@ -254,6 +261,8 @@ export class NodeInstance {
254
261
  setDescription(node) {
255
262
  this.description = node;
256
263
 
264
+ node.configureNode(this);
265
+
257
266
  //generate endpoints
258
267
  this.endpoints = node.getPorts().map((port, port_index) => {
259
268
  const endpoint = new NodeInstancePortReference();
@@ -96,6 +96,24 @@ export class StaticMaterialCache {
96
96
  return material;
97
97
 
98
98
  }
99
+
100
+ /**
101
+ *
102
+ * @param {function(string)} error_consumer
103
+ * @param {*} [thisArg]
104
+ * @returns {boolean}
105
+ */
106
+ validate(error_consumer, thisArg) {
107
+ const materials_valid = this.materialCache.validate((message, key, value) => {
108
+ error_consumer.call(thisArg, `Material error: ${message}. Material ${key}`);
109
+ });
110
+ const textures_valid = this.textureCache.validate((message, key, value) => {
111
+ error_consumer.call(thisArg, `Texture error: ${message}. Texture ${key}`);
112
+ });
113
+
114
+ return materials_valid
115
+ && textures_valid;
116
+ }
99
117
  }
100
118
 
101
119
  /**