@woosh/meep-engine 2.48.1 → 2.48.5
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/package.json +1 -1
- package/src/core/binary/32BitEncoder.js +11 -3
- package/src/core/binary/BinaryBuffer.js +80 -59
- package/src/core/binary/int32_to_binary_string.js +32 -7
- package/src/core/binary/to_half_float_uint16.js +6 -4
- package/src/core/bvh2/visual/convert_bvh_to_dot_format_string.js +1 -1
- package/src/core/collection/list/List.js +3 -0
- package/src/core/geom/3d/CircleMath.js +13 -2
- package/src/core/geom/3d/matrix/m4_make_translation.js +15 -0
- package/src/core/geom/3d/triangle/computeTrianglePlaneSide.js +4 -13
- package/src/core/geom/Vector3.spec.js +10 -0
- package/src/core/graph/convertGraphToDotString.js +13 -3
- package/src/core/graph/v2/Graph.js +17 -1
- package/src/core/graph/v2/NodeContainer.js +58 -0
- package/src/core/model/ModuleRegistry.js +44 -10
- package/src/core/model/ResourceAccessKind.js +11 -0
- package/src/core/model/ResourceAccessSpecification.js +41 -0
- package/src/engine/Engine.js +1 -1
- package/src/engine/ecs/EntityEventBinding.js +74 -0
- package/src/engine/ecs/EntityManager.js +143 -0
- package/src/engine/ecs/System.js +53 -5
- package/src/engine/ecs/animation/InverseKinematicsSystem.js +6 -0
- package/src/engine/ecs/attachment/AttachmentSystem.js +8 -0
- package/src/engine/ecs/dynamic_actions/DynamicActorSystem.js +5 -0
- package/src/engine/ecs/fow/FogOfWarRevealerSystem.js +7 -3
- package/src/engine/ecs/fow/FogOfWarSystem.js +6 -0
- package/src/engine/ecs/gui/GUIElementSystem.js +1 -1
- package/src/engine/ecs/gui/hud/HeadsUpDisplaySystem.js +8 -0
- package/src/engine/ecs/gui/position/ViewportPositionSystem.js +6 -0
- package/src/engine/ecs/speaker/VoiceSystem.js +13 -0
- package/src/engine/ecs/storage/binary/object/BinaryObjectSerializationAdapter2.js +451 -12
- package/src/engine/ecs/storage/binary/object/BinaryObjectSerializationAdapter2.spec.js +123 -0
- package/src/engine/ecs/system/computeSystemComponentDependencyGraph.js +71 -0
- package/src/engine/ecs/systems/RenderSystem.js +6 -0
- package/src/engine/ecs/terrain/ecs/Terrain.js +26 -44
- package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.js +9 -0
- package/src/engine/ecs/terrain/tiles/TerrainTile.js +5 -0
- package/src/engine/ecs/terrain/tiles/TerrainTileManager.js +26 -6
- package/src/engine/ecs/tooltip/TooltipComponentSystem.js +7 -0
- package/src/engine/graphics/ecs/animation/animator/AnimationGraphSystem.js +6 -0
- package/src/engine/graphics/ecs/camera/CameraSystem.js +6 -0
- package/src/engine/graphics/ecs/camera/pp/PerfectPanner.js +4 -0
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +5 -0
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraLanderSystem.js +6 -0
- package/src/engine/graphics/ecs/light/LightSystem.js +8 -0
- package/src/engine/graphics/ecs/mesh/MeshSystem.js +8 -1
- package/src/engine/graphics/ecs/path/PathDisplaySystem.js +7 -1
- package/src/engine/graphics/ecs/trail2d/Trail2DSystem.js +7 -0
- package/src/engine/graphics/geometry/instancing/InstancedMeshGroup.js +34 -7
- package/src/engine/graphics/particles/ecs/ParticleEmitterSystem.js +6 -0
- package/src/engine/grid/systems/GridPosition2TransformSystem.js +6 -0
- package/src/engine/grid/transform2grid/Transform2GridPositionSystem.js +6 -0
- package/src/engine/intelligence/behavior/Behavior.js +11 -0
- package/src/engine/intelligence/behavior/composite/CompositeBehavior.js +10 -4
- package/src/engine/intelligence/behavior/decorator/AbstractDecoratorBehavior.js +1 -0
- package/src/engine/intelligence/behavior/util/behavior_traverse_tree.js +8 -0
- package/src/engine/navigation/ecs/path_following/PathFollowingSystem.js +8 -0
- package/src/engine/network/RemoteController.js +60 -84
- package/src/engine/network/remoteEditor.js +108 -2
- package/src/engine/sound/SoundEngine.js +81 -79
- package/src/engine/sound/ecs/SoundControllerSystem.js +8 -0
- package/src/engine/sound/ecs/SoundListenerSystem.js +7 -0
- package/src/engine/sound/ecs/emitter/SoundEmitterComponentContext.js +42 -46
- package/src/engine/sound/ecs/emitter/SoundEmitterSystem.js +15 -2
- package/src/engine/sound/ecs/emitter/SoundTrack.js +137 -35
- package/src/engine/sound/ecs/emitter/SoundTrackFlags.js +17 -1
- package/src/engine/sound/ecs/emitter/SoundTrackNodes.js +2 -4
- package/src/engine/sound/ecs/emitter/loadSoundTrackAsset.js +1 -2
- package/src/generation/theme/ThemeEngine.js +20 -3
- package/src/view/{elements/image → common}/HTMLElementCacheKey.js +5 -5
- package/src/view/elements/button/ButtonView.js +10 -2
- package/src/view/elements/image/ImageView.js +1 -1
- package/src/view/elements/video/VideoView.js +1 -1
- package/src/view/interaction/CommandButtonView.js +16 -153
- package/src/view/interaction/createInterfaceCommandButton.js +124 -0
|
@@ -1,48 +1,487 @@
|
|
|
1
|
+
import { assert } from "../../../../../core/assert.js";
|
|
2
|
+
|
|
3
|
+
const HEADER_TAG_NATIVE_CLASS = 0;
|
|
4
|
+
const HEADER_TAG_REF_SCHEMA = 1;
|
|
5
|
+
const HEADER_TAG_INLINE_SCHEMA = 2;
|
|
6
|
+
|
|
7
|
+
const HEADER_TAG_NULL = 4;
|
|
8
|
+
const HEADER_TAG_UNDEFINED = 5;
|
|
9
|
+
const HEADER_TAG_BOOLEAN_TRUE = 6;
|
|
10
|
+
const HEADER_TAG_BOOLEAN_FALSE = 7;
|
|
11
|
+
const HEADER_TAG_POSITIVE_INTEGER = 8;
|
|
12
|
+
const HEADER_TAG_NEGATIVE_INTEGER = 9;
|
|
13
|
+
const HEADER_TAG_FLOAT = 20;
|
|
14
|
+
const HEADER_TAG_STRING = 30;
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class SchemaRecord {
|
|
18
|
+
address = -1
|
|
19
|
+
/**
|
|
20
|
+
*
|
|
21
|
+
* @type {Object|null}
|
|
22
|
+
*/
|
|
23
|
+
schema = null
|
|
24
|
+
/**
|
|
25
|
+
*
|
|
26
|
+
* @type {string|null}
|
|
27
|
+
*/
|
|
28
|
+
typeName = null
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
*
|
|
32
|
+
* @type {{name:string}[]}
|
|
33
|
+
*/
|
|
34
|
+
fields = [];
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
*
|
|
38
|
+
* @param {Object} schema
|
|
39
|
+
*/
|
|
40
|
+
fromSchema(schema) {
|
|
41
|
+
this.schema = schema;
|
|
42
|
+
|
|
43
|
+
this.fields.splice(0, this.fields.length);
|
|
44
|
+
|
|
45
|
+
for (const schemaKey in schema) {
|
|
46
|
+
this.fields.push({
|
|
47
|
+
name: schemaKey
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
buildSchema() {
|
|
53
|
+
const schema = {};
|
|
54
|
+
|
|
55
|
+
const fields = this.fields;
|
|
56
|
+
const field_count = fields.length;
|
|
57
|
+
for (let i = 0; i < field_count; i++) {
|
|
58
|
+
const field = fields[i];
|
|
59
|
+
|
|
60
|
+
schema[field.name] = {};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
this.schema = schema;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Generate a schema from a value object
|
|
69
|
+
* @param {Object} object
|
|
70
|
+
* @returns
|
|
71
|
+
*/
|
|
72
|
+
function autoSchema(object) {
|
|
73
|
+
const schema = {};
|
|
74
|
+
for (const objectKey in object) {
|
|
75
|
+
const field_value = object[objectKey];
|
|
76
|
+
|
|
77
|
+
let field_schema;
|
|
78
|
+
|
|
79
|
+
if (typeof field_value === "object") {
|
|
80
|
+
field_schema = autoSchema(field_value);
|
|
81
|
+
} else {
|
|
82
|
+
// no schema for primitives
|
|
83
|
+
field_schema = undefined;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
schema[objectKey] = field_schema;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return schema;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
class SchemaTable {
|
|
93
|
+
/**
|
|
94
|
+
*
|
|
95
|
+
* @type {Map<number, SchemaRecord>}
|
|
96
|
+
*/
|
|
97
|
+
#address_map = new Map();
|
|
98
|
+
/**
|
|
99
|
+
*
|
|
100
|
+
* @type {Map<Object, SchemaRecord>}
|
|
101
|
+
*/
|
|
102
|
+
#schema_map = new Map();
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
reset() {
|
|
106
|
+
this.#address_map.clear();
|
|
107
|
+
this.#schema_map.clear();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
*
|
|
112
|
+
* @param {number} address
|
|
113
|
+
* @returns {SchemaRecord|undefined}
|
|
114
|
+
*/
|
|
115
|
+
getSchemaAt(address) {
|
|
116
|
+
return this.#address_map.get(address);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
*
|
|
121
|
+
* @param {Object} schema
|
|
122
|
+
* @returns {SchemaRecord}
|
|
123
|
+
*/
|
|
124
|
+
getRecord(schema) {
|
|
125
|
+
return this.#schema_map.get(schema);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
*
|
|
130
|
+
* @param {Object} schema
|
|
131
|
+
* @returns {number} -1 if not found
|
|
132
|
+
*/
|
|
133
|
+
getAddress(schema) {
|
|
134
|
+
const record = this.#schema_map.get(schema);
|
|
135
|
+
|
|
136
|
+
if (record === undefined) {
|
|
137
|
+
return -1;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return record.address;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
*
|
|
145
|
+
* @param {SchemaRecord} record
|
|
146
|
+
*/
|
|
147
|
+
add(record) {
|
|
148
|
+
this.#schema_map.set(record.schema, record);
|
|
149
|
+
this.#address_map.set(record.address, record);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
1
153
|
export class BinaryObjectSerializationAdapter2 {
|
|
2
154
|
/**
|
|
3
155
|
*
|
|
4
156
|
* @type {BinarySerializationRegistry|null}
|
|
5
157
|
*/
|
|
6
|
-
#
|
|
158
|
+
#adapter_registry = null
|
|
159
|
+
/**
|
|
160
|
+
*
|
|
161
|
+
* @type {ModuleRegistry|null}
|
|
162
|
+
*/
|
|
163
|
+
#class_registry = null
|
|
164
|
+
|
|
165
|
+
#schema_table = new SchemaTable();
|
|
166
|
+
|
|
167
|
+
set module_registry(v) {
|
|
168
|
+
this.#class_registry = v;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
get module_registry() {
|
|
172
|
+
return this.#class_registry;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
set adapter_registry(v) {
|
|
176
|
+
this.#adapter_registry = v;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
get adapter_registry() {
|
|
180
|
+
return this.#adapter_registry;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
reset() {
|
|
184
|
+
this.#schema_table.reset();
|
|
185
|
+
}
|
|
7
186
|
|
|
8
187
|
/**
|
|
9
188
|
*
|
|
10
189
|
* @param {BinaryBuffer} buffer
|
|
11
|
-
* @param {Object} object
|
|
12
190
|
* @param {Object} schema
|
|
191
|
+
* @param {string} typeName
|
|
192
|
+
* @returns {SchemaRecord}
|
|
193
|
+
*/
|
|
194
|
+
#writeSchema(buffer, schema, typeName) {
|
|
195
|
+
const address = buffer.position;
|
|
196
|
+
|
|
197
|
+
const record = new SchemaRecord();
|
|
198
|
+
|
|
199
|
+
record.typeName = typeName;
|
|
200
|
+
record.address = address;
|
|
201
|
+
|
|
202
|
+
record.fromSchema(schema);
|
|
203
|
+
|
|
204
|
+
// write type name
|
|
205
|
+
buffer.writeUTF8String(typeName);
|
|
206
|
+
|
|
207
|
+
const fields = record.fields;
|
|
208
|
+
const field_count = fields.length;
|
|
209
|
+
|
|
210
|
+
buffer.writeUintVar(field_count);
|
|
211
|
+
|
|
212
|
+
for (let i = 0; i < field_count; i++) {
|
|
213
|
+
// write field
|
|
214
|
+
const field = fields[i];
|
|
215
|
+
|
|
216
|
+
buffer.writeUTF8String(field.name);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
this.#schema_table.add(record);
|
|
220
|
+
|
|
221
|
+
return record;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
*
|
|
226
|
+
* @param {BinaryBuffer} buffer
|
|
227
|
+
* @returns {SchemaRecord}
|
|
228
|
+
*/
|
|
229
|
+
#readSchema(buffer) {
|
|
230
|
+
const address = buffer.position;
|
|
231
|
+
|
|
232
|
+
const record = new SchemaRecord();
|
|
233
|
+
record.address = address;
|
|
234
|
+
|
|
235
|
+
// read type name
|
|
236
|
+
const typeName = buffer.readUTF8String();
|
|
237
|
+
|
|
238
|
+
record.typeName = typeName;
|
|
239
|
+
|
|
240
|
+
const field_count = buffer.readUintVar();
|
|
241
|
+
|
|
242
|
+
for (let i = 0; i < field_count; i++) {
|
|
243
|
+
const field_name = buffer.readUTF8String();
|
|
244
|
+
|
|
245
|
+
record.fields[i] = {
|
|
246
|
+
name: field_name
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
record.buildSchema();
|
|
251
|
+
|
|
252
|
+
this.#schema_table.add(record);
|
|
253
|
+
|
|
254
|
+
return record;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
*
|
|
259
|
+
* @param {BinaryBuffer} buffer
|
|
260
|
+
* @param {number|string|boolean|null|undefined|object} object
|
|
261
|
+
* @returns {boolean}
|
|
262
|
+
*/
|
|
263
|
+
#trySerializePrimitive(buffer, object) {
|
|
264
|
+
if (object === null) {
|
|
265
|
+
// special case
|
|
266
|
+
buffer.writeUint8(HEADER_TAG_NULL);
|
|
267
|
+
return true;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const typeOfValue = typeof object;
|
|
271
|
+
|
|
272
|
+
if (typeOfValue === "object") {
|
|
273
|
+
return false;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
switch (typeOfValue) {
|
|
278
|
+
case "undefined":
|
|
279
|
+
buffer.writeUint8(HEADER_TAG_UNDEFINED);
|
|
280
|
+
break;
|
|
281
|
+
case "boolean":
|
|
282
|
+
buffer.writeUint8(object ? HEADER_TAG_BOOLEAN_TRUE : HEADER_TAG_BOOLEAN_FALSE);
|
|
283
|
+
break;
|
|
284
|
+
case "number":
|
|
285
|
+
if (Number.isInteger(object)) {
|
|
286
|
+
if (object >= 0) {
|
|
287
|
+
// positive integer
|
|
288
|
+
buffer.writeUint8(HEADER_TAG_POSITIVE_INTEGER);
|
|
289
|
+
buffer.writeUintVar(object);
|
|
290
|
+
} else {
|
|
291
|
+
// negative integer
|
|
292
|
+
buffer.writeUint8(HEADER_TAG_NEGATIVE_INTEGER);
|
|
293
|
+
buffer.writeUintVar(-object);
|
|
294
|
+
}
|
|
295
|
+
} else {
|
|
296
|
+
// float
|
|
297
|
+
buffer.writeUint8(HEADER_TAG_FLOAT);
|
|
298
|
+
buffer.writeFloat64(object);
|
|
299
|
+
}
|
|
300
|
+
break;
|
|
301
|
+
case "string":
|
|
302
|
+
buffer.writeUint8(HEADER_TAG_STRING);
|
|
303
|
+
buffer.writeUTF8String(object);
|
|
304
|
+
break;
|
|
305
|
+
default:
|
|
306
|
+
throw new TypeError(`Unsupported value type '${typeOfValue}'`);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return true;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
*
|
|
314
|
+
* @param {BinaryBuffer} buffer
|
|
315
|
+
* @param {Object} object
|
|
316
|
+
* @param {Object} [schema]
|
|
13
317
|
*/
|
|
14
318
|
serialize(buffer, object, schema) {
|
|
15
|
-
|
|
319
|
+
if (this.#trySerializePrimitive(buffer, object)) {
|
|
320
|
+
// was primitive, serialized
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const ctor = object.constructor;
|
|
325
|
+
|
|
326
|
+
const associatedNames = this.#class_registry.findNamesByModule(ctor);
|
|
16
327
|
|
|
17
|
-
|
|
328
|
+
let typeName;
|
|
18
329
|
|
|
19
|
-
|
|
330
|
+
if (associatedNames.length === 1) {
|
|
331
|
+
typeName = associatedNames[0];
|
|
332
|
+
} else {
|
|
333
|
+
// ambiguous, use type name from constructor
|
|
334
|
+
typeName = ctor.typeName
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
assert.isString(typeName, 'typeName');
|
|
338
|
+
|
|
339
|
+
const nativeAdapter = this.#adapter_registry.getAdapter(typeName);
|
|
340
|
+
|
|
341
|
+
const using_native_serializer = nativeAdapter !== undefined;
|
|
342
|
+
|
|
343
|
+
if (using_native_serializer) {
|
|
344
|
+
|
|
345
|
+
// write header indicating that native serializer is being used
|
|
346
|
+
buffer.writeUint8(HEADER_TAG_NATIVE_CLASS);
|
|
347
|
+
|
|
348
|
+
// name of the type
|
|
349
|
+
buffer.writeUTF8String(typeName);
|
|
20
350
|
|
|
21
|
-
if (nativeAdapter !== undefined) {
|
|
22
351
|
// serialize with native
|
|
23
352
|
nativeAdapter.serialize(buffer, object);
|
|
24
353
|
return;
|
|
25
354
|
}
|
|
26
355
|
|
|
27
|
-
for (const property in schema) {
|
|
28
356
|
|
|
29
|
-
|
|
357
|
+
if (schema === undefined) {
|
|
358
|
+
// no schema specified, generate one
|
|
359
|
+
schema = autoSchema(object);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
let record = this.#schema_table.getRecord(schema);
|
|
364
|
+
|
|
365
|
+
if (record === undefined) {
|
|
366
|
+
// no record
|
|
367
|
+
|
|
368
|
+
// indicating that the full schema follows
|
|
369
|
+
buffer.writeUint8(HEADER_TAG_INLINE_SCHEMA);
|
|
370
|
+
|
|
371
|
+
record = this.#writeSchema(buffer, schema, typeName);
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
} else {
|
|
375
|
+
buffer.writeUint8(HEADER_TAG_REF_SCHEMA);
|
|
376
|
+
// write address of schema
|
|
377
|
+
buffer.writeUintVar(record.address);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
// write data according to schema
|
|
30
382
|
|
|
31
|
-
|
|
383
|
+
const fields = record.fields;
|
|
384
|
+
const field_count = fields.length;
|
|
32
385
|
|
|
33
|
-
|
|
386
|
+
for (let i = 0; i < field_count; i++) {
|
|
387
|
+
const field = fields[i];
|
|
388
|
+
|
|
389
|
+
const field_name = field.name;
|
|
390
|
+
|
|
391
|
+
const actual_value = object[field_name];
|
|
392
|
+
|
|
393
|
+
this.serialize(buffer, actual_value, schema[field_name]);
|
|
34
394
|
}
|
|
35
395
|
|
|
36
396
|
}
|
|
37
397
|
|
|
38
398
|
/**
|
|
39
399
|
*
|
|
400
|
+
* @template T
|
|
40
401
|
* @param {BinaryBuffer} buffer
|
|
41
|
-
* @param {
|
|
402
|
+
* @param {number} tag
|
|
403
|
+
* @returns {T}
|
|
404
|
+
*/
|
|
405
|
+
#deserializeObject(buffer, tag) {
|
|
406
|
+
let record;
|
|
407
|
+
|
|
408
|
+
if (tag === HEADER_TAG_INLINE_SCHEMA) {
|
|
409
|
+
// read full schema here
|
|
410
|
+
record = this.#readSchema(buffer);
|
|
411
|
+
|
|
412
|
+
} else if (tag === HEADER_TAG_REF_SCHEMA) {
|
|
413
|
+
// reference to the schema else-where
|
|
414
|
+
const schema_address = buffer.readUintVar();
|
|
415
|
+
|
|
416
|
+
record = this.#schema_table.getRecord(schema_address);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
const typeName = record.typeName;
|
|
420
|
+
|
|
421
|
+
const Klass = this.#class_registry.get(typeName);
|
|
422
|
+
|
|
423
|
+
const object = new Klass();
|
|
424
|
+
|
|
425
|
+
const fields = record.fields;
|
|
426
|
+
const field_count = fields.length;
|
|
427
|
+
|
|
428
|
+
for (let i = 0; i < field_count; i++) {
|
|
429
|
+
const field = fields[i];
|
|
430
|
+
|
|
431
|
+
object[field.name] = this.deserialize(buffer);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
return object;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* @template T
|
|
439
|
+
* @param {BinaryBuffer} buffer
|
|
440
|
+
* @returns {T}
|
|
42
441
|
*/
|
|
43
|
-
deserialize(buffer
|
|
442
|
+
deserialize(buffer) {
|
|
44
443
|
|
|
45
444
|
// read header
|
|
445
|
+
const header = buffer.readUint8();
|
|
446
|
+
|
|
447
|
+
switch (header) {
|
|
448
|
+
case HEADER_TAG_NATIVE_CLASS:
|
|
449
|
+
// native serializer being used
|
|
450
|
+
const typeName = buffer.readUTF8String();
|
|
451
|
+
|
|
452
|
+
const adapter = this.#adapter_registry.getAdapter(typeName);
|
|
453
|
+
|
|
454
|
+
const Klass = this.#class_registry.get(typeName);
|
|
455
|
+
|
|
456
|
+
const object = new Klass();
|
|
457
|
+
|
|
458
|
+
adapter.deserialize(buffer, object);
|
|
459
|
+
|
|
460
|
+
return object;
|
|
461
|
+
case HEADER_TAG_INLINE_SCHEMA:
|
|
462
|
+
case HEADER_TAG_REF_SCHEMA:
|
|
463
|
+
return this.#deserializeObject(buffer, header);
|
|
464
|
+
|
|
465
|
+
case HEADER_TAG_NULL:
|
|
466
|
+
return null;
|
|
467
|
+
case HEADER_TAG_UNDEFINED:
|
|
468
|
+
return undefined;
|
|
469
|
+
case HEADER_TAG_BOOLEAN_TRUE:
|
|
470
|
+
return true;
|
|
471
|
+
case HEADER_TAG_BOOLEAN_FALSE:
|
|
472
|
+
return false;
|
|
473
|
+
case HEADER_TAG_POSITIVE_INTEGER:
|
|
474
|
+
return buffer.readUintVar();
|
|
475
|
+
case HEADER_TAG_NEGATIVE_INTEGER:
|
|
476
|
+
return -buffer.readUintVar();
|
|
477
|
+
case HEADER_TAG_FLOAT:
|
|
478
|
+
return buffer.readFloat64();
|
|
479
|
+
case HEADER_TAG_STRING:
|
|
480
|
+
return buffer.readUTF8String();
|
|
481
|
+
default:
|
|
482
|
+
throw new Error(`Unsupported tag '${header}'`);
|
|
483
|
+
}
|
|
484
|
+
|
|
46
485
|
|
|
47
486
|
}
|
|
48
487
|
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { BinaryObjectSerializationAdapter2 } from "./BinaryObjectSerializationAdapter2.js";
|
|
2
|
+
import { BinaryBuffer } from "../../../../../core/binary/BinaryBuffer.js";
|
|
3
|
+
import { BinarySerializationRegistry } from "../BinarySerializationRegistry.js";
|
|
4
|
+
import { ModuleRegistry } from "../../../../../core/model/ModuleRegistry.js";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
* @returns {BinaryObjectSerializationAdapter2}
|
|
10
|
+
*/
|
|
11
|
+
function sampleAdapter() {
|
|
12
|
+
|
|
13
|
+
const adapter = new BinaryObjectSerializationAdapter2();
|
|
14
|
+
|
|
15
|
+
adapter.adapter_registry = new BinarySerializationRegistry();
|
|
16
|
+
adapter.module_registry = new ModuleRegistry();
|
|
17
|
+
|
|
18
|
+
adapter.module_registry.add('object', Object);
|
|
19
|
+
|
|
20
|
+
return adapter;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
test("primitive value", () => {
|
|
24
|
+
|
|
25
|
+
const adapter = sampleAdapter();
|
|
26
|
+
|
|
27
|
+
const bin = new BinaryBuffer();
|
|
28
|
+
|
|
29
|
+
function check(expected) {
|
|
30
|
+
// rewind
|
|
31
|
+
bin.position = 0;
|
|
32
|
+
|
|
33
|
+
adapter.serialize(bin, expected);
|
|
34
|
+
|
|
35
|
+
// rewind
|
|
36
|
+
bin.position = 0;
|
|
37
|
+
|
|
38
|
+
const actual = adapter.deserialize(bin);
|
|
39
|
+
|
|
40
|
+
expect(actual).toEqual(expected);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
check(0);
|
|
44
|
+
check(1);
|
|
45
|
+
check(-1);
|
|
46
|
+
check(42.1);
|
|
47
|
+
check(true);
|
|
48
|
+
check(false);
|
|
49
|
+
check("hello");
|
|
50
|
+
check(undefined);
|
|
51
|
+
check(null);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("empty object", () => {
|
|
55
|
+
|
|
56
|
+
const adapter = sampleAdapter();
|
|
57
|
+
|
|
58
|
+
const bin = new BinaryBuffer();
|
|
59
|
+
|
|
60
|
+
adapter.serialize(bin, {});
|
|
61
|
+
|
|
62
|
+
// rewind
|
|
63
|
+
bin.position = 0;
|
|
64
|
+
|
|
65
|
+
const result = adapter.deserialize(bin);
|
|
66
|
+
|
|
67
|
+
expect(typeof result).toBe("object");
|
|
68
|
+
expect(Object.keys(result)).toEqual([]);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("multi-key flat object with different primitive values", () => {
|
|
72
|
+
|
|
73
|
+
const adapter = sampleAdapter();
|
|
74
|
+
|
|
75
|
+
const bin = new BinaryBuffer();
|
|
76
|
+
|
|
77
|
+
const expected = {
|
|
78
|
+
"test": undefined,
|
|
79
|
+
"hello": null,
|
|
80
|
+
"zero": 0,
|
|
81
|
+
"negative integer": -1,
|
|
82
|
+
"unsigned integer": 1,
|
|
83
|
+
"float": 0.01,
|
|
84
|
+
"empty string": "",
|
|
85
|
+
"string": "hello kitty",
|
|
86
|
+
"utf-8": "Ḽơᶉëᶆ ȋṕšᶙṁ",
|
|
87
|
+
"boolean true": true,
|
|
88
|
+
"boolean false": false,
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
adapter.serialize(bin, expected);
|
|
92
|
+
|
|
93
|
+
// rewind
|
|
94
|
+
bin.position = 0;
|
|
95
|
+
|
|
96
|
+
const actual = adapter.deserialize(bin);
|
|
97
|
+
|
|
98
|
+
expect(typeof actual).toBe("object");
|
|
99
|
+
expect(actual).toEqual(expected);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
test("nested objects", () => {
|
|
104
|
+
|
|
105
|
+
const adapter = sampleAdapter();
|
|
106
|
+
const bin = new BinaryBuffer();
|
|
107
|
+
|
|
108
|
+
const expected = {
|
|
109
|
+
second: {
|
|
110
|
+
value: "hello there Mr bear"
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
adapter.serialize(bin, expected);
|
|
115
|
+
|
|
116
|
+
// rewind
|
|
117
|
+
bin.position = 0;
|
|
118
|
+
|
|
119
|
+
const actual = adapter.deserialize(bin);
|
|
120
|
+
|
|
121
|
+
expect(typeof actual).toBe("object");
|
|
122
|
+
expect(actual).toEqual(expected);
|
|
123
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { Graph } from "../../../core/graph/v2/Graph.js";
|
|
2
|
+
import { ResourceAccessKind } from "../../../core/model/ResourceAccessKind.js";
|
|
3
|
+
import { EdgeDirectionType } from "../../../core/graph/Edge.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param {number} system_count
|
|
8
|
+
* @param {System[]} systems
|
|
9
|
+
* @return {Graph}
|
|
10
|
+
*/
|
|
11
|
+
export function computeSystemComponentDependencyGraph(system_count, systems) {
|
|
12
|
+
const dependency_graph = new Graph();
|
|
13
|
+
|
|
14
|
+
for (let i = 0; i < system_count; i++) {
|
|
15
|
+
const system = systems[i];
|
|
16
|
+
|
|
17
|
+
const components = system.referenced_components;
|
|
18
|
+
const component_count = components.length;
|
|
19
|
+
|
|
20
|
+
// ensure that all components are registered
|
|
21
|
+
for (let j = 0; j < component_count; j++) {
|
|
22
|
+
const component = components[j];
|
|
23
|
+
|
|
24
|
+
dependency_graph.addNode(component)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
for (let j = 0; j < component_count; j++) {
|
|
28
|
+
const component_a = components[j];
|
|
29
|
+
|
|
30
|
+
const access_a = system.getAccessForComponent(component_a);
|
|
31
|
+
|
|
32
|
+
if ((access_a & (ResourceAccessKind.Write | ResourceAccessKind.Create)) !== 0) {
|
|
33
|
+
// writing resource, create dependency on read resources
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
for (let k = 0; k < component_count; k++) {
|
|
37
|
+
|
|
38
|
+
if (j === k) {
|
|
39
|
+
// skip self
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const component_b = components[k];
|
|
44
|
+
|
|
45
|
+
const access_b = system.getAccessForComponent(component_b);
|
|
46
|
+
|
|
47
|
+
if ((access_b & ResourceAccessKind.Read) !== 0) {
|
|
48
|
+
// read access
|
|
49
|
+
|
|
50
|
+
if (dependency_graph.getAnyDirectedEdge(component_a, component_b) === undefined) {
|
|
51
|
+
|
|
52
|
+
dependency_graph.createEdge(component_a, component_b, EdgeDirectionType.Forward);
|
|
53
|
+
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
// console.log("DEPENDENCY_GRAPH:", convertGraphToDotString({
|
|
67
|
+
// graph: dependency_graph, nodeToDot: (node) => `[label="${node.typeName}"]`
|
|
68
|
+
// }));
|
|
69
|
+
|
|
70
|
+
return dependency_graph;
|
|
71
|
+
}
|
|
@@ -9,6 +9,8 @@ import { RenderableFlags } from "../components/RenderableFlags.js";
|
|
|
9
9
|
import { rootObject3DFastMatrixUpdate } from "../../graphics/ecs/mesh/rootObject3DFastMatrixUpdate.js";
|
|
10
10
|
import { updateNodeByTransformAndBBB } from "../../graphics/ecs/mesh/updateNodeByTransformAndBBB.js";
|
|
11
11
|
import { three_computeObjectBoundingBox } from "../../graphics/three/three_computeObjectBoundingBox.js";
|
|
12
|
+
import { ResourceAccessSpecification } from "../../../core/model/ResourceAccessSpecification.js";
|
|
13
|
+
import { ResourceAccessKind } from "../../../core/model/ResourceAccessKind.js";
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
/**
|
|
@@ -30,6 +32,10 @@ class RenderSystem extends System {
|
|
|
30
32
|
|
|
31
33
|
this.dependencies = [Renderable, Transform];
|
|
32
34
|
|
|
35
|
+
this.components_used = [
|
|
36
|
+
ResourceAccessSpecification.from(Renderable, ResourceAccessKind.Read | ResourceAccessKind.Write)
|
|
37
|
+
];
|
|
38
|
+
|
|
33
39
|
this.entityData = [];
|
|
34
40
|
|
|
35
41
|
/**
|