@woosh/meep-engine 2.37.1 → 2.37.4
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/core/geom/Quaternion.js +31 -0
- package/core/model/ModuleRegistry.d.ts +3 -0
- package/core/process/undo/ActionProcessor.js +86 -74
- package/editor/ecs/component/ObjectEditor.js +0 -0
- package/editor/ecs/component/createObjectEditor.js +155 -0
- package/editor/tools/SelectionTool.js +22 -1
- package/engine/ecs/transform/Transform.js +106 -5
- package/engine/ecs/transform/TransformFlags.js +8 -0
- package/engine/ecs/transform-attachment/TransformAttachmentSystem.js +1 -11
- package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +10 -35
- package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +6 -1
- package/engine/graphics/ecs/mesh-v2/aggregate/SGMeshSystem.js +16 -1
- package/engine/graphics/ecs/mesh-v2/allocate_transform_m4.js +51 -0
- package/engine/graphics/ecs/mesh-v2/sample/load_gltf.js +41 -4
- package/engine/graphics/ecs/mesh-v2/three_object_to_entity_composition.js +4 -2
- package/engine/graphics/ecs/path/entity/EntityPathStyle.d.ts +2 -2
- package/package.json +1 -1
- package/core/model/ClassRegistry.d.ts +0 -3
package/core/geom/Quaternion.js
CHANGED
|
@@ -763,6 +763,7 @@ class Quaternion {
|
|
|
763
763
|
}
|
|
764
764
|
|
|
765
765
|
/**
|
|
766
|
+
* XYZ order
|
|
766
767
|
* @source: https://stackoverflow.com/questions/12088610/conversion-between-euler-quaternion-like-in-unity3d-engine
|
|
767
768
|
* @param {number} x angle in X axis in radians
|
|
768
769
|
* @param {number} y angle in Y axis in radians
|
|
@@ -788,6 +789,36 @@ class Quaternion {
|
|
|
788
789
|
this.set(_x, _y, _z, _w);
|
|
789
790
|
}
|
|
790
791
|
|
|
792
|
+
/**
|
|
793
|
+
* XYZ order
|
|
794
|
+
* @source: https://stackoverflow.com/questions/12088610/conversion-between-euler-quaternion-like-in-unity3d-engine
|
|
795
|
+
* @see http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m
|
|
796
|
+
* @see https://github.com/mrdoob/three.js/blob/510705cde208b165fd87946b0f8504a1cd6dbe83/src/math/Quaternion.js#L206
|
|
797
|
+
* @param {number} x angle in X axis in radians
|
|
798
|
+
* @param {number} y angle in Y axis in radians
|
|
799
|
+
* @param {number} z angle in Z axis in radians
|
|
800
|
+
*/
|
|
801
|
+
fromEulerAnglesXYZ(x, y, z) {
|
|
802
|
+
const scaled_x = x * 0.5;
|
|
803
|
+
const scaled_y = y * 0.5;
|
|
804
|
+
const scaled_z = z * 0.5;
|
|
805
|
+
|
|
806
|
+
const s1 = Math.sin(scaled_x);
|
|
807
|
+
const s2 = Math.sin(scaled_y);
|
|
808
|
+
const s3 = Math.sin(scaled_z);
|
|
809
|
+
|
|
810
|
+
const c1 = Math.cos(scaled_x);
|
|
811
|
+
const c2 = Math.cos(scaled_y);
|
|
812
|
+
const c3 = Math.cos(scaled_z);
|
|
813
|
+
|
|
814
|
+
const _x = s1 * c2 * c3 + c1 * s2 * s3;
|
|
815
|
+
const _y = c1 * s2 * c3 - s1 * c2 * s3;
|
|
816
|
+
const _z = c1 * c2 * s3 + s1 * s2 * c3;
|
|
817
|
+
const _w = c1 * c2 * c3 - s1 * s2 * s3;
|
|
818
|
+
|
|
819
|
+
this.set(_x, _y, _z, _w);
|
|
820
|
+
}
|
|
821
|
+
|
|
791
822
|
/**
|
|
792
823
|
* Writes Pitch(Y), Yaw(Z), Roll(X) to a given vector
|
|
793
824
|
* @source http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/
|
|
@@ -9,7 +9,6 @@ import List from "../../collection/list/List.js";
|
|
|
9
9
|
import Signal from "../../events/signal/Signal.js";
|
|
10
10
|
import { min2 } from "../../math/min2.js";
|
|
11
11
|
import { Mark } from "./Mark.js";
|
|
12
|
-
import { IllegalStateException } from "../../fsm/exceptions/IllegalStateException.js";
|
|
13
12
|
|
|
14
13
|
/**
|
|
15
14
|
* @template C, M
|
|
@@ -75,13 +74,6 @@ export class ActionProcessor {
|
|
|
75
74
|
*/
|
|
76
75
|
this.onMarkRemoved = new Signal();
|
|
77
76
|
|
|
78
|
-
/**
|
|
79
|
-
*
|
|
80
|
-
* @type {boolean}
|
|
81
|
-
* @private
|
|
82
|
-
*/
|
|
83
|
-
this.__action_in_progress = false;
|
|
84
|
-
|
|
85
77
|
/**
|
|
86
78
|
*
|
|
87
79
|
* @type {Promise<never>}
|
|
@@ -172,10 +164,8 @@ export class ActionProcessor {
|
|
|
172
164
|
* Insert a mark into the timeline, all actions between marks are grouped logically for UNDO and REDO mechanism
|
|
173
165
|
* @param {D} description
|
|
174
166
|
*/
|
|
175
|
-
mark(description) {
|
|
176
|
-
|
|
177
|
-
throw new IllegalStateException('Action is currently in progress');
|
|
178
|
-
}
|
|
167
|
+
async mark(description) {
|
|
168
|
+
await this.__barrier();
|
|
179
169
|
|
|
180
170
|
const marks = this.marks;
|
|
181
171
|
const numMarks = marks.length;
|
|
@@ -265,6 +255,24 @@ export class ActionProcessor {
|
|
|
265
255
|
* @throws {Error} when mark is non-unique
|
|
266
256
|
*/
|
|
267
257
|
async navigateTo(mark_descriptor) {
|
|
258
|
+
await this.__barrier();
|
|
259
|
+
|
|
260
|
+
const p = this.__unsafe_navigateTo(mark_descriptor);
|
|
261
|
+
|
|
262
|
+
this.__last_promise = p;
|
|
263
|
+
|
|
264
|
+
return await p;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Navigate to a specific mark back or forward
|
|
269
|
+
* @param {M} mark_descriptor specific mark description
|
|
270
|
+
* @returns {boolean} true on success, false otherwise (e.g. mark not found)
|
|
271
|
+
* @throws {Error} when mark is non-unique
|
|
272
|
+
* @private
|
|
273
|
+
*/
|
|
274
|
+
async __unsafe_navigateTo(mark_descriptor) {
|
|
275
|
+
|
|
268
276
|
// find all matching marks
|
|
269
277
|
const matching_marks = this.__find_mark_indices_by_description(mark_descriptor);
|
|
270
278
|
|
|
@@ -293,7 +301,7 @@ export class ActionProcessor {
|
|
|
293
301
|
|
|
294
302
|
while (target > this.cursor) {
|
|
295
303
|
// navigate forward
|
|
296
|
-
await this.
|
|
304
|
+
await this.__unsafe_redo();
|
|
297
305
|
|
|
298
306
|
if (temp_cursor === this.cursor) {
|
|
299
307
|
// no cursor change
|
|
@@ -307,7 +315,7 @@ export class ActionProcessor {
|
|
|
307
315
|
|
|
308
316
|
while (target < this.cursor) {
|
|
309
317
|
// navigate backwards
|
|
310
|
-
await this.
|
|
318
|
+
await this.__unsafe_undo();
|
|
311
319
|
|
|
312
320
|
if (temp_cursor === this.cursor) {
|
|
313
321
|
// no cursor change
|
|
@@ -323,6 +331,21 @@ export class ActionProcessor {
|
|
|
323
331
|
}
|
|
324
332
|
|
|
325
333
|
async undo() {
|
|
334
|
+
await this.__barrier();
|
|
335
|
+
|
|
336
|
+
const p = this.__unsafe_undo();
|
|
337
|
+
|
|
338
|
+
this.__last_promise = p;
|
|
339
|
+
|
|
340
|
+
await p;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
*
|
|
345
|
+
* @returns {Promise<void>}
|
|
346
|
+
* @private
|
|
347
|
+
*/
|
|
348
|
+
async __unsafe_undo() {
|
|
326
349
|
let markAddress = 0;
|
|
327
350
|
/**
|
|
328
351
|
*
|
|
@@ -351,7 +374,7 @@ export class ActionProcessor {
|
|
|
351
374
|
this.cursor--;
|
|
352
375
|
const action = this.history.get(this.cursor);
|
|
353
376
|
|
|
354
|
-
await this.
|
|
377
|
+
await action.revert(this.context);
|
|
355
378
|
}
|
|
356
379
|
|
|
357
380
|
if (mark !== null) {
|
|
@@ -363,8 +386,23 @@ export class ActionProcessor {
|
|
|
363
386
|
* redo previous sequence of actions on the timeline, up to the next mark
|
|
364
387
|
*/
|
|
365
388
|
async redo() {
|
|
389
|
+
await this.__barrier();
|
|
390
|
+
|
|
391
|
+
const p = this.__unsafe_redo();
|
|
366
392
|
|
|
393
|
+
this.__last_promise = p;
|
|
394
|
+
|
|
395
|
+
await p;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
*
|
|
400
|
+
* @returns {Promise<void>}
|
|
401
|
+
* @private
|
|
402
|
+
*/
|
|
403
|
+
async __unsafe_redo() {
|
|
367
404
|
let mark = this.history.length;
|
|
405
|
+
|
|
368
406
|
//find mark
|
|
369
407
|
const marks = this.marks;
|
|
370
408
|
|
|
@@ -382,7 +420,7 @@ export class ActionProcessor {
|
|
|
382
420
|
while (this.cursor < mark) {
|
|
383
421
|
const action = this.history.get(this.cursor);
|
|
384
422
|
|
|
385
|
-
await this.
|
|
423
|
+
await action.apply(this.context);
|
|
386
424
|
|
|
387
425
|
this.historyMemoryUsage += action.computeByteSize();
|
|
388
426
|
|
|
@@ -395,15 +433,26 @@ export class ActionProcessor {
|
|
|
395
433
|
* @param {Action[]} actions
|
|
396
434
|
*/
|
|
397
435
|
async doMany(actions) {
|
|
398
|
-
|
|
436
|
+
await this.__barrier();
|
|
399
437
|
|
|
400
|
-
|
|
438
|
+
const p = new Promise(async (resolve, reject) => {
|
|
401
439
|
|
|
402
|
-
const
|
|
440
|
+
const n = actions.length;
|
|
403
441
|
|
|
404
|
-
|
|
442
|
+
for (let i = 0; i < n; i++) {
|
|
405
443
|
|
|
406
|
-
|
|
444
|
+
const action = actions[i];
|
|
445
|
+
|
|
446
|
+
await this.__unsafe_do(action);
|
|
447
|
+
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
resolve();
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
this.__last_promise = p;
|
|
454
|
+
|
|
455
|
+
await p;
|
|
407
456
|
}
|
|
408
457
|
|
|
409
458
|
/**
|
|
@@ -411,21 +460,13 @@ export class ActionProcessor {
|
|
|
411
460
|
* @param {Action} action
|
|
412
461
|
*/
|
|
413
462
|
async do(action) {
|
|
414
|
-
await this.
|
|
463
|
+
await this.__barrier();
|
|
415
464
|
|
|
416
|
-
|
|
465
|
+
const p = this.__unsafe_do(action);
|
|
417
466
|
|
|
418
|
-
|
|
467
|
+
this.__last_promise = p;
|
|
419
468
|
|
|
420
|
-
|
|
421
|
-
if (this.cursor < history.length) {
|
|
422
|
-
history.crop(0, this.cursor);
|
|
423
|
-
// TODO clear future marks
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
history.add(action);
|
|
427
|
-
|
|
428
|
-
this.cursor++;
|
|
469
|
+
await p;
|
|
429
470
|
}
|
|
430
471
|
|
|
431
472
|
/**
|
|
@@ -434,63 +475,34 @@ export class ActionProcessor {
|
|
|
434
475
|
* @returns {Promise<void>}
|
|
435
476
|
* @private
|
|
436
477
|
*/
|
|
437
|
-
async
|
|
438
|
-
|
|
439
|
-
await this.__last_promise;
|
|
440
|
-
} catch (e) {
|
|
441
|
-
// ignore
|
|
442
|
-
}
|
|
478
|
+
async __unsafe_do(action) {
|
|
479
|
+
await action.apply(this.context);
|
|
443
480
|
|
|
444
|
-
|
|
445
|
-
throw new IllegalStateException();
|
|
446
|
-
}
|
|
481
|
+
this.historyMemoryUsage += action.computeByteSize();
|
|
447
482
|
|
|
448
|
-
|
|
483
|
+
const history = this.history;
|
|
449
484
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
this.__action_in_progress = false;
|
|
485
|
+
//doing action invalidates "future" branch of history, we need to clear all actions beyond cursor
|
|
486
|
+
if (this.cursor < history.length) {
|
|
487
|
+
history.crop(0, this.cursor);
|
|
488
|
+
// TODO clear future marks
|
|
455
489
|
}
|
|
456
490
|
|
|
457
|
-
|
|
458
|
-
this.__last_promise = p;
|
|
459
|
-
await p;
|
|
460
|
-
}
|
|
491
|
+
history.add(action);
|
|
461
492
|
|
|
493
|
+
this.cursor++;
|
|
462
494
|
}
|
|
463
495
|
|
|
464
496
|
/**
|
|
465
|
-
*
|
|
466
|
-
* @param {Action} action
|
|
497
|
+
* Await for synchronization barrier
|
|
467
498
|
* @returns {Promise<void>}
|
|
468
499
|
* @private
|
|
469
500
|
*/
|
|
470
|
-
async
|
|
501
|
+
async __barrier() {
|
|
471
502
|
try {
|
|
472
503
|
await this.__last_promise;
|
|
473
504
|
} catch (e) {
|
|
474
505
|
// ignore
|
|
475
506
|
}
|
|
476
|
-
|
|
477
|
-
if (this.__action_in_progress) {
|
|
478
|
-
throw new IllegalStateException();
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
this.__action_in_progress = true;
|
|
482
|
-
|
|
483
|
-
let p;
|
|
484
|
-
try {
|
|
485
|
-
p = action.revert(this.context);
|
|
486
|
-
} finally {
|
|
487
|
-
this.__action_in_progress = false;
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
if (p !== undefined) {
|
|
491
|
-
this.__last_promise = p;
|
|
492
|
-
await p;
|
|
493
|
-
}
|
|
494
|
-
|
|
495
507
|
}
|
|
496
508
|
}
|
|
File without changes
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import EmptyView from "../../../view/elements/EmptyView.js";
|
|
2
|
+
import LabelView from "../../../view/common/LabelView.js";
|
|
3
|
+
|
|
4
|
+
class FieldValueAdapter {
|
|
5
|
+
read(object, field_name) {
|
|
6
|
+
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
write(object, field_name, value) {
|
|
10
|
+
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @template T
|
|
16
|
+
*/
|
|
17
|
+
class FieldDescriptor {
|
|
18
|
+
constructor() {
|
|
19
|
+
/**
|
|
20
|
+
*
|
|
21
|
+
* @type {string}
|
|
22
|
+
*/
|
|
23
|
+
this.name = "";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* typeof field
|
|
27
|
+
* @type {Class<T>}
|
|
28
|
+
*/
|
|
29
|
+
this.type = null;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
*
|
|
33
|
+
* @type {FieldValueAdapter|null}
|
|
34
|
+
*/
|
|
35
|
+
this.adapter = null;
|
|
36
|
+
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @template T
|
|
42
|
+
* @param {T} value
|
|
43
|
+
*/
|
|
44
|
+
function objectToClass(value) {
|
|
45
|
+
const type = typeof value;
|
|
46
|
+
|
|
47
|
+
switch (type) {
|
|
48
|
+
case "object":
|
|
49
|
+
return value.__ptoto__.constructor;
|
|
50
|
+
case "boolean":
|
|
51
|
+
return Boolean;
|
|
52
|
+
case "function":
|
|
53
|
+
return Function;
|
|
54
|
+
case "string":
|
|
55
|
+
return String;
|
|
56
|
+
case "number":
|
|
57
|
+
return Number;
|
|
58
|
+
default:
|
|
59
|
+
throw new Error(`Unsupported type '${type}'`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
*
|
|
65
|
+
* @param {Object} object
|
|
66
|
+
* @param {string} field_name
|
|
67
|
+
* @returns {boolean}
|
|
68
|
+
*/
|
|
69
|
+
function isPublicField(object, field_name) {
|
|
70
|
+
if (field_name.startsWith('_')) {
|
|
71
|
+
// private
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
*
|
|
80
|
+
* @param {Object} object
|
|
81
|
+
* @returns {FieldDescriptor[]}
|
|
82
|
+
*/
|
|
83
|
+
function extractObjectFields(object) {
|
|
84
|
+
const result = [];
|
|
85
|
+
const keys = Object.keys(object);
|
|
86
|
+
|
|
87
|
+
for (let i = 0; i < keys.length; i++) {
|
|
88
|
+
const key = keys[i];
|
|
89
|
+
|
|
90
|
+
if (!isPublicField(object, key)) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const field_type = objectToClass(object[key]);
|
|
95
|
+
|
|
96
|
+
if (field_type === undefined) {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const descriptor = new FieldDescriptor();
|
|
101
|
+
descriptor.name = key;
|
|
102
|
+
descriptor.type = field_type;
|
|
103
|
+
|
|
104
|
+
result.push(descriptor);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
*
|
|
112
|
+
* @param {Object} object
|
|
113
|
+
* @param {FieldDescriptor} field
|
|
114
|
+
* @param {Map<*, (parent:*, field:FieldDescriptor)=>View>} registry
|
|
115
|
+
*/
|
|
116
|
+
export function createFieldEditor(object, field, registry) {
|
|
117
|
+
const vResult = new EmptyView({});
|
|
118
|
+
|
|
119
|
+
vResult.addChild(new LabelView(field.name));
|
|
120
|
+
|
|
121
|
+
let vValue;
|
|
122
|
+
|
|
123
|
+
const factory = registry.get(field.type);
|
|
124
|
+
|
|
125
|
+
if (factory !== undefined) {
|
|
126
|
+
vValue = factory(object, field);
|
|
127
|
+
} else {
|
|
128
|
+
vValue = createObjectEditor(object, registry);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
vResult.addChild(vValue);
|
|
132
|
+
|
|
133
|
+
return vResult;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
*
|
|
138
|
+
* @param {Object} object
|
|
139
|
+
* @param {Map<*, (parent:*, field:FieldDescriptor)=>View>} registry
|
|
140
|
+
*/
|
|
141
|
+
export function createObjectEditor(object, registry) {
|
|
142
|
+
const fields = extractObjectFields(object);
|
|
143
|
+
|
|
144
|
+
const vResult = new EmptyView({});
|
|
145
|
+
|
|
146
|
+
for (let i = 0; i < fields.length; i++) {
|
|
147
|
+
const field = fields[i];
|
|
148
|
+
|
|
149
|
+
const vField = createFieldEditor(object, field, registry);
|
|
150
|
+
|
|
151
|
+
vResult.addChild(vField);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return vResult;
|
|
155
|
+
}
|
|
@@ -18,6 +18,7 @@ import EditorEntity from "../ecs/EditorEntity.js";
|
|
|
18
18
|
import Terrain from "../../engine/ecs/terrain/ecs/Terrain.js";
|
|
19
19
|
import { SurfacePoint3 } from "../../core/geom/3d/SurfacePoint3.js";
|
|
20
20
|
import { makeScreenScissorFrustum } from "../../engine/graphics/camera/makeScreenScissorFrustum.js";
|
|
21
|
+
import { ShadedGeometrySystem } from "../../engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js";
|
|
21
22
|
|
|
22
23
|
class SelectionView extends View {
|
|
23
24
|
constructor() {
|
|
@@ -220,7 +221,8 @@ function findEntityOfNode(node) {
|
|
|
220
221
|
*/
|
|
221
222
|
export function pickingEntitySelection(point, engine, camera) {
|
|
222
223
|
|
|
223
|
-
const
|
|
224
|
+
const em = engine.entityManager;
|
|
225
|
+
const dataset = em.dataset;
|
|
224
226
|
|
|
225
227
|
const graphicsEngine = engine.graphics;
|
|
226
228
|
|
|
@@ -262,6 +264,25 @@ export function pickingEntitySelection(point, engine, camera) {
|
|
|
262
264
|
}
|
|
263
265
|
}
|
|
264
266
|
|
|
267
|
+
/**
|
|
268
|
+
*
|
|
269
|
+
* @type {ShadedGeometrySystem|undefined}
|
|
270
|
+
*/
|
|
271
|
+
const sgm = em.getSystem(ShadedGeometrySystem);
|
|
272
|
+
|
|
273
|
+
if (sgm !== undefined) {
|
|
274
|
+
const hits = sgm.raycast(
|
|
275
|
+
source.x, source.y, source.y,
|
|
276
|
+
rayDirection.x, rayDirection.y, rayDirection.z
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
for (let i = 0; i < hits.length; i++) {
|
|
280
|
+
const hit = hits[i];
|
|
281
|
+
|
|
282
|
+
tryAddEntity(hit.entity, hit.contact.position);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
265
286
|
//query render layers
|
|
266
287
|
engine.graphics.layers.traverse(function (layer) {
|
|
267
288
|
/**
|
|
@@ -7,13 +7,16 @@ import Quaternion from "../../../core/geom/Quaternion.js";
|
|
|
7
7
|
import { decompose_matrix_4_array } from "../../../core/geom/3d/decompose_matrix_4_array.js";
|
|
8
8
|
import { mat4 } from "gl-matrix";
|
|
9
9
|
import { compose_matrix4_array } from "../../../core/geom/3d/compose_matrix4_array.js";
|
|
10
|
+
import { TransformFlags } from "./TransformFlags.js";
|
|
11
|
+
import { allocate_transform_m4 } from "../../graphics/ecs/mesh-v2/allocate_transform_m4.js";
|
|
10
12
|
|
|
11
13
|
const delta = new Vector3();
|
|
12
14
|
|
|
13
|
-
const scratch_buffer = new ArrayBuffer(
|
|
15
|
+
const scratch_buffer = new ArrayBuffer(16 * 4);
|
|
14
16
|
|
|
15
17
|
const m4_0 = new Float32Array(scratch_buffer, 0, 16);
|
|
16
|
-
|
|
18
|
+
|
|
19
|
+
const FLAGS_DEFAULT = TransformFlags.AutomaticChangeDetection;
|
|
17
20
|
|
|
18
21
|
export class Transform {
|
|
19
22
|
/**
|
|
@@ -43,6 +46,79 @@ export class Transform {
|
|
|
43
46
|
*/
|
|
44
47
|
this.scale = new Vector3(1, 1, 1);
|
|
45
48
|
|
|
49
|
+
/**
|
|
50
|
+
* @readonly
|
|
51
|
+
* @type {Float32Array}
|
|
52
|
+
*/
|
|
53
|
+
this.matrix = allocate_transform_m4();
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @protected
|
|
57
|
+
* @type {number}
|
|
58
|
+
*/
|
|
59
|
+
this.flags = FLAGS_DEFAULT;
|
|
60
|
+
|
|
61
|
+
// watch changes
|
|
62
|
+
this.position.onChanged.add(this.__handle_component_change, this);
|
|
63
|
+
this.rotation.onChanged.add(this.__handle_component_change, this);
|
|
64
|
+
this.scale.onChanged.add(this.__handle_component_change, this);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
*
|
|
69
|
+
* @private
|
|
70
|
+
*/
|
|
71
|
+
__handle_component_change() {
|
|
72
|
+
if (this.getFlag(TransformFlags.AutomaticChangeDetection)) {
|
|
73
|
+
this.setFlag(TransformFlags.MatrixNeedsUpdate);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
*
|
|
79
|
+
* @param {number|TransformFlags} flag
|
|
80
|
+
* @returns {void}
|
|
81
|
+
*/
|
|
82
|
+
setFlag(flag) {
|
|
83
|
+
this.flags |= flag;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
*
|
|
88
|
+
* @param {number|TransformFlags} flag
|
|
89
|
+
* @returns {void}
|
|
90
|
+
*/
|
|
91
|
+
clearFlag(flag) {
|
|
92
|
+
this.flags &= ~flag;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
*
|
|
97
|
+
* @param {number|TransformFlags} flag
|
|
98
|
+
* @param {boolean} value
|
|
99
|
+
*/
|
|
100
|
+
writeFlag(flag, value) {
|
|
101
|
+
if (value) {
|
|
102
|
+
this.setFlag(flag);
|
|
103
|
+
} else {
|
|
104
|
+
this.clearFlag(flag);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
*
|
|
110
|
+
* @param {number|TransformFlags} flag
|
|
111
|
+
* @returns {boolean}
|
|
112
|
+
*/
|
|
113
|
+
getFlag(flag) {
|
|
114
|
+
return (this.flags & flag) === flag;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
updateMatrix() {
|
|
119
|
+
compose_matrix4_array(this.matrix, this.position, this.rotation, this.scale);
|
|
120
|
+
|
|
121
|
+
this.clearFlag(TransformFlags.MatrixNeedsUpdate);
|
|
46
122
|
}
|
|
47
123
|
|
|
48
124
|
/**
|
|
@@ -82,6 +158,8 @@ export class Transform {
|
|
|
82
158
|
} else {
|
|
83
159
|
this.scale.copy(Vector3.one);
|
|
84
160
|
}
|
|
161
|
+
|
|
162
|
+
this.setFlag(TransformFlags.MatrixNeedsUpdate);
|
|
85
163
|
}
|
|
86
164
|
|
|
87
165
|
toJSON() {
|
|
@@ -100,6 +178,10 @@ export class Transform {
|
|
|
100
178
|
this.position.copy(other.position);
|
|
101
179
|
this.rotation.copy(other.rotation);
|
|
102
180
|
this.scale.copy(other.scale);
|
|
181
|
+
|
|
182
|
+
this.matrix.set(other.matrix);
|
|
183
|
+
|
|
184
|
+
this.flags = other.flags;
|
|
103
185
|
}
|
|
104
186
|
|
|
105
187
|
/**
|
|
@@ -154,10 +236,15 @@ export class Transform {
|
|
|
154
236
|
* @param {Transform} b
|
|
155
237
|
*/
|
|
156
238
|
multiplyTransforms(a, b) {
|
|
157
|
-
|
|
158
|
-
|
|
239
|
+
if (a.getFlag(TransformFlags.MatrixNeedsUpdate)) {
|
|
240
|
+
a.updateMatrix();
|
|
241
|
+
}
|
|
159
242
|
|
|
160
|
-
|
|
243
|
+
if (b.getFlag(TransformFlags.MatrixNeedsUpdate)) {
|
|
244
|
+
b.updateMatrix();
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
mat4.multiply(m4_0, a.matrix, b.matrix);
|
|
161
248
|
|
|
162
249
|
this.fromMatrix4(m4_0);
|
|
163
250
|
}
|
|
@@ -183,7 +270,17 @@ export class Transform {
|
|
|
183
270
|
* @param {mat4|number[]|Float32Array} m
|
|
184
271
|
*/
|
|
185
272
|
fromMatrix4(m) {
|
|
273
|
+
const ad = this.getFlag(TransformFlags.AutomaticChangeDetection);
|
|
274
|
+
|
|
275
|
+
this.clearFlag(TransformFlags.AutomaticChangeDetection);
|
|
276
|
+
|
|
277
|
+
this.matrix.set(m);
|
|
278
|
+
|
|
186
279
|
decompose_matrix_4_array(m, this.position, this.rotation, this.scale);
|
|
280
|
+
|
|
281
|
+
this.clearFlag(TransformFlags.MatrixNeedsUpdate);
|
|
282
|
+
|
|
283
|
+
this.writeFlag(TransformFlags.AutomaticChangeDetection, ad);
|
|
187
284
|
}
|
|
188
285
|
|
|
189
286
|
/**
|
|
@@ -195,6 +292,10 @@ export class Transform {
|
|
|
195
292
|
}
|
|
196
293
|
}
|
|
197
294
|
|
|
295
|
+
/**
|
|
296
|
+
* @readonly
|
|
297
|
+
* @type {string}
|
|
298
|
+
*/
|
|
198
299
|
Transform.typeName = "Transform";
|
|
199
300
|
|
|
200
301
|
/**
|
|
@@ -2,16 +2,6 @@ import { System } from "../System.js";
|
|
|
2
2
|
import { TransformAttachment, TransformAttachmentFlags } from "./TransformAttachment.js";
|
|
3
3
|
import { Transform } from "../transform/Transform.js";
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
*
|
|
7
|
-
* @param {Transform} parent_transform
|
|
8
|
-
* @param {Transform} attachment_transform
|
|
9
|
-
* @param {Transform} child_transform
|
|
10
|
-
*/
|
|
11
|
-
function update(parent_transform, attachment_transform, child_transform) {
|
|
12
|
-
child_transform.multiplyTransforms(parent_transform, attachment_transform);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
5
|
class UpdateContext {
|
|
16
6
|
constructor() {
|
|
17
7
|
/**
|
|
@@ -40,7 +30,7 @@ class UpdateContext {
|
|
|
40
30
|
}
|
|
41
31
|
|
|
42
32
|
update() {
|
|
43
|
-
|
|
33
|
+
this.transform.multiplyTransforms(this.parent_transform, this.attachment.transform);
|
|
44
34
|
}
|
|
45
35
|
|
|
46
36
|
link() {
|
|
@@ -3,6 +3,8 @@ import { AABB3 } from "../../../../core/bvh2/aabb3/AABB3.js";
|
|
|
3
3
|
import { DrawMode } from "./DrawMode.js";
|
|
4
4
|
import { ShadedGeometryFlags } from "./ShadedGeometryFlags.js";
|
|
5
5
|
import { aabb3_matrix4_project } from "../../../../core/geom/3d/aabb/aabb3_matrix4_project.js";
|
|
6
|
+
import { allocate_transform_m4 } from "./allocate_transform_m4.js";
|
|
7
|
+
import { TransformFlags } from "../../../ecs/transform/TransformFlags.js";
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* @readonly
|
|
@@ -18,39 +20,6 @@ const FLAG_SET_EQUALITY = ShadedGeometryFlags.CastShadow
|
|
|
18
20
|
| ShadedGeometryFlags.ReceiveShadow
|
|
19
21
|
;
|
|
20
22
|
|
|
21
|
-
/**
|
|
22
|
-
*
|
|
23
|
-
* @type {number}
|
|
24
|
-
*/
|
|
25
|
-
const TRANSFORM_ALLOCATOR_BUCKET_CAPACITY = 16;
|
|
26
|
-
/**
|
|
27
|
-
*
|
|
28
|
-
* @type {ArrayBuffer|null}
|
|
29
|
-
*/
|
|
30
|
-
let transform_bucket = null;
|
|
31
|
-
/**
|
|
32
|
-
*
|
|
33
|
-
* @type {number}
|
|
34
|
-
*/
|
|
35
|
-
let transform_bucket_cursor = TRANSFORM_ALLOCATOR_BUCKET_CAPACITY;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* custom Float32Array allocator, allocated memory in continuous chunks
|
|
39
|
-
* @returns {Float32Array}
|
|
40
|
-
*/
|
|
41
|
-
function allocate_transform_m4() {
|
|
42
|
-
if (transform_bucket_cursor >= TRANSFORM_ALLOCATOR_BUCKET_CAPACITY) {
|
|
43
|
-
transform_bucket = new ArrayBuffer(TRANSFORM_ALLOCATOR_BUCKET_CAPACITY * 4 * 16);
|
|
44
|
-
transform_bucket_cursor = 0;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const result = new Float32Array(transform_bucket, transform_bucket_cursor * 16 * 4, 16);
|
|
48
|
-
|
|
49
|
-
transform_bucket_cursor++;
|
|
50
|
-
|
|
51
|
-
return result;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
23
|
export class ShadedGeometry {
|
|
55
24
|
constructor() {
|
|
56
25
|
/**
|
|
@@ -216,7 +185,7 @@ export class ShadedGeometry {
|
|
|
216
185
|
* @return {null|number[]}
|
|
217
186
|
*/
|
|
218
187
|
get transform() {
|
|
219
|
-
return this.
|
|
188
|
+
return this.__c_transform.matrix;
|
|
220
189
|
}
|
|
221
190
|
|
|
222
191
|
/**
|
|
@@ -270,8 +239,14 @@ export class ShadedGeometry {
|
|
|
270
239
|
}
|
|
271
240
|
|
|
272
241
|
updateTransform() {
|
|
242
|
+
const t = this.__c_transform;
|
|
243
|
+
|
|
244
|
+
if (t.getFlag(TransformFlags.MatrixNeedsUpdate)) {
|
|
245
|
+
t.updateMatrix();
|
|
246
|
+
}
|
|
247
|
+
|
|
273
248
|
//
|
|
274
|
-
this.
|
|
249
|
+
this.__transform.set(t.matrix);
|
|
275
250
|
|
|
276
251
|
this.update_bounds();
|
|
277
252
|
|
|
@@ -22,6 +22,7 @@ import TaskState from "../../../../core/process/task/TaskState.js";
|
|
|
22
22
|
import {
|
|
23
23
|
bvh_query_user_data_overlaps_frustum
|
|
24
24
|
} from "../../../../core/bvh2/bvh3/bvh_query_user_data_overlaps_frustum.js";
|
|
25
|
+
import { TransformFlags } from "../../../ecs/transform/TransformFlags.js";
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
/**
|
|
@@ -250,7 +251,11 @@ export class ShadedGeometrySystem extends System {
|
|
|
250
251
|
t.rotation.onChanged.add(sg.updateTransform, sg);
|
|
251
252
|
t.scale.onChanged.add(sg.updateTransform, sg);
|
|
252
253
|
|
|
253
|
-
t.
|
|
254
|
+
if (t.getFlag(TransformFlags.MatrixNeedsUpdate)) {
|
|
255
|
+
t.updateMatrix();
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
sg.__transform.set(t.matrix);
|
|
254
259
|
sg.update_bounds();
|
|
255
260
|
|
|
256
261
|
// remember entity for lookups
|
|
@@ -7,6 +7,7 @@ import { ShadedGeometry } from "../ShadedGeometry.js";
|
|
|
7
7
|
import { ShadedGeometryFlags } from "../ShadedGeometryFlags.js";
|
|
8
8
|
import { SGMeshEvents } from "./SGMeshEvents.js";
|
|
9
9
|
import { ParentEntity } from "../../../../ecs/parent/ParentEntity.js";
|
|
10
|
+
import { EntityNode } from "../../../../ecs/parent/EntityNode.js";
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
/**
|
|
@@ -76,7 +77,21 @@ export class SGMeshSystem extends System {
|
|
|
76
77
|
|
|
77
78
|
// TODO check that entity still exists, as we get to this point asynchronously
|
|
78
79
|
|
|
79
|
-
|
|
80
|
+
let entity_node = three_object_to_entity_composition(asset.create());
|
|
81
|
+
|
|
82
|
+
if (asset.has_root_transform) {
|
|
83
|
+
// apply root transform
|
|
84
|
+
|
|
85
|
+
const new_root = new EntityNode();
|
|
86
|
+
|
|
87
|
+
new_root.entity.add(new Transform());
|
|
88
|
+
|
|
89
|
+
entity_node.transform.copy(asset.root_transform);
|
|
90
|
+
|
|
91
|
+
new_root.addChild(entity_node);
|
|
92
|
+
|
|
93
|
+
entity_node = new_root;
|
|
94
|
+
}
|
|
80
95
|
|
|
81
96
|
// attach parent entity to link hierarchy to this entity
|
|
82
97
|
entity_node.entity.add(ParentEntity.from(entity));
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Larger bucket sizes provide better cache locality
|
|
3
|
+
* Larger bucket sizes also cause more hanging GC references, as if one matrix element is still held - ENTIRE bucket is still referenced
|
|
4
|
+
* @type {number}
|
|
5
|
+
*/
|
|
6
|
+
const TRANSFORM_ALLOCATOR_BUCKET_CAPACITY = 16;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
*
|
|
10
|
+
* @type {ArrayBuffer|null}
|
|
11
|
+
*/
|
|
12
|
+
let transform_bucket = null;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
* @type {number}
|
|
17
|
+
*/
|
|
18
|
+
let transform_bucket_cursor = TRANSFORM_ALLOCATOR_BUCKET_CAPACITY;
|
|
19
|
+
|
|
20
|
+
const MATRIX_BYTE_SIZE = 4 * 16;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
* @type {Float32Array}
|
|
25
|
+
*/
|
|
26
|
+
const MATRIX_IDENTITY = new Float32Array([
|
|
27
|
+
1, 0, 0, 0,
|
|
28
|
+
0, 1, 0, 0,
|
|
29
|
+
0, 0, 1, 0,
|
|
30
|
+
0, 0, 0, 1
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* custom Float32Array allocator, allocated memory in continuous chunks
|
|
35
|
+
* @returns {Float32Array}
|
|
36
|
+
*/
|
|
37
|
+
export function allocate_transform_m4() {
|
|
38
|
+
if (transform_bucket_cursor >= TRANSFORM_ALLOCATOR_BUCKET_CAPACITY) {
|
|
39
|
+
transform_bucket = new ArrayBuffer(TRANSFORM_ALLOCATOR_BUCKET_CAPACITY * MATRIX_BYTE_SIZE);
|
|
40
|
+
transform_bucket_cursor = 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const result = new Float32Array(transform_bucket, transform_bucket_cursor * MATRIX_BYTE_SIZE, 16);
|
|
44
|
+
|
|
45
|
+
// initialize matrix
|
|
46
|
+
result.set(MATRIX_IDENTITY);
|
|
47
|
+
|
|
48
|
+
transform_bucket_cursor++;
|
|
49
|
+
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
@@ -4,10 +4,11 @@ import { GameAssetType } from "../../../../asset/GameAssetType.js";
|
|
|
4
4
|
import { EngineConfiguration } from "../../../../EngineConfiguration.js";
|
|
5
5
|
import { GLTFAssetLoader } from "../../../../asset/loaders/GLTFAssetLoader.js";
|
|
6
6
|
import { three_object_to_entity_composition } from "../three_object_to_entity_composition.js";
|
|
7
|
-
import { AttachmentSystem } from "../../../../ecs/attachment/AttachmentSystem.js";
|
|
8
7
|
import { TransformAttachmentSystem } from "../../../../ecs/transform-attachment/TransformAttachmentSystem.js";
|
|
9
8
|
import { Camera } from "../../camera/Camera.js";
|
|
10
9
|
import { MicronRenderPlugin } from "../../../micron/plugin/MicronRenderPlugin.js";
|
|
10
|
+
import { enableEditor } from "../../../../../editor/enableEditor.js";
|
|
11
|
+
import { MeshSystem } from "../../mesh/MeshSystem.js";
|
|
11
12
|
|
|
12
13
|
const eh = new EngineHarness();
|
|
13
14
|
|
|
@@ -22,14 +23,20 @@ async function init(harness) {
|
|
|
22
23
|
const config = new EngineConfiguration();
|
|
23
24
|
|
|
24
25
|
config.addSystem(new ShadedGeometrySystem(engine));
|
|
25
|
-
config.addSystem(new AttachmentSystem());
|
|
26
26
|
config.addSystem(new TransformAttachmentSystem());
|
|
27
|
-
config.
|
|
27
|
+
config.addSystem(new MeshSystem(engine));
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
const gltfAssetLoader = new GLTFAssetLoader();
|
|
30
|
+
|
|
31
|
+
config.addLoader(GameAssetType.ModelGLTF_JSON, gltfAssetLoader);
|
|
32
|
+
config.addLoader(GameAssetType.ModelGLTF, gltfAssetLoader);
|
|
33
|
+
|
|
34
|
+
config.addPlugin(MicronRenderPlugin);
|
|
30
35
|
|
|
31
36
|
await config.apply(engine);
|
|
32
37
|
|
|
38
|
+
enableEditor(engine);
|
|
39
|
+
|
|
33
40
|
eh.initialize().then(main);
|
|
34
41
|
}
|
|
35
42
|
|
|
@@ -51,12 +58,32 @@ async function load_gltf(path, engine) {
|
|
|
51
58
|
const composition = three_object_to_entity_composition(three_object);
|
|
52
59
|
console.timeEnd('composition conversion');
|
|
53
60
|
|
|
61
|
+
if (asset.has_root_transform) {
|
|
62
|
+
composition.transform.multiplyTransforms(composition.transform, asset.root_transform);
|
|
63
|
+
}
|
|
64
|
+
|
|
54
65
|
console.time('composition build');
|
|
55
66
|
// console.profile('composition build');
|
|
56
67
|
composition.build(ecd);
|
|
57
68
|
// console.profileEnd('composition build');
|
|
58
69
|
console.timeEnd('composition build');
|
|
59
70
|
|
|
71
|
+
|
|
72
|
+
// console.log(composition);
|
|
73
|
+
// console.log(three_object);
|
|
74
|
+
//
|
|
75
|
+
// new EntityBuilder()
|
|
76
|
+
// .add(Mesh.fromJSON({
|
|
77
|
+
// url: path
|
|
78
|
+
// }))
|
|
79
|
+
// .add(Transform.fromJSON({
|
|
80
|
+
// position: {
|
|
81
|
+
// x: 5,
|
|
82
|
+
// y: 0,
|
|
83
|
+
// z: 0
|
|
84
|
+
// }
|
|
85
|
+
// }))
|
|
86
|
+
// .build(ecd);
|
|
60
87
|
}
|
|
61
88
|
|
|
62
89
|
async function timeout(t = 1) {
|
|
@@ -88,6 +115,16 @@ async function main(engine) {
|
|
|
88
115
|
// load_gltf('moicon/06_04_hapro/05-ground-floor/model.gltf', engine);
|
|
89
116
|
// load_gltf('moicon/06_04_hapro/04-1st-floor/model.gltf', engine);
|
|
90
117
|
// load_gltf('moicon/06_04_hapro/03-2nd-floor/model.gltf', engine);
|
|
118
|
+
|
|
119
|
+
// for (let i = 1; i <= 6; i++) {
|
|
120
|
+
// load_gltf(`moicon/10_Feb_22_Demo/${i}/model.gltf`, engine);
|
|
121
|
+
// }
|
|
122
|
+
// load_gltf(`moicon/10_Feb_22_Demo/1/model.gltf`, engine);
|
|
123
|
+
// load_gltf(`moicon/10_Feb_22_Demo/2/model.gltf`, engine);
|
|
124
|
+
// load_gltf(`moicon/10_Feb_22_Demo/3/model.gltf`, engine);
|
|
125
|
+
|
|
126
|
+
// load_gltf(`data/models/samples/transform-hierarchy.glb`, engine);
|
|
127
|
+
|
|
91
128
|
}
|
|
92
129
|
|
|
93
130
|
init(eh);
|
|
@@ -15,8 +15,10 @@ export function three_object_to_entity_composition(root) {
|
|
|
15
15
|
// copy object transform
|
|
16
16
|
node_transform.position.copy(root.position);
|
|
17
17
|
node_transform.scale.copy(root.scale);
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
node_transform.rotation.copy(root.quaternion);
|
|
19
|
+
|
|
20
|
+
//
|
|
21
|
+
node_transform.matrix.set(root.matrix.elements);
|
|
20
22
|
|
|
21
23
|
const entity = node.entity;
|
|
22
24
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {ModuleRegistry} from "../../../../../core/model/ModuleRegistry";
|
|
2
2
|
import {EntityPathMarkerDefinition} from "./EntityPathMarkerDefinition";
|
|
3
3
|
|
|
4
4
|
export class EntityPathStyle {
|
|
@@ -8,5 +8,5 @@ export class EntityPathStyle {
|
|
|
8
8
|
|
|
9
9
|
public spacing: number
|
|
10
10
|
|
|
11
|
-
fromJSON(json: { marker_start: any, marker_end: any, marker_main: any, spacing?: number }, registry:
|
|
11
|
+
fromJSON(json: { marker_start: any, marker_end: any, marker_main: any, spacing?: number }, registry: ModuleRegistry): void
|
|
12
12
|
}
|
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.37.
|
|
8
|
+
"version": "2.37.4",
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"gl-matrix": "3.4.3",
|
|
11
11
|
"fast-levenshtein": "2.0.6",
|