@woosh/meep-engine 2.39.5 → 2.39.9
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/binary/BinaryBuffer.js +1 -0
- package/core/geom/3d/triangle/computeTriangleRayIntersection.js +39 -0
- package/core/math/FLT_EPSILON_32.js +7 -0
- package/core/math/random/seededRandom_Mulberry32.js +1 -1
- package/core/model/stat/LinearModifier.js +7 -0
- package/core/process/task/RemainingTimeEstimator.js +49 -0
- package/core/process/task/Task.js +3 -1
- package/engine/Engine.js +0 -83
- package/engine/asset/AssetManager.d.ts +3 -0
- package/engine/asset/AssetManager.js +5 -4
- package/engine/ecs/terrain/ecs/Terrain.js +33 -0
- package/engine/ecs/terrain/ecs/layers/TerrainLayer.js +13 -0
- package/engine/ecs/terrain/ecs/layers/TerrainLayers.js +44 -2
- package/engine/ecs/terrain/ecs/splat/SplatMapping.js +12 -4
- package/engine/graphics/ecs/path/testPathDisplaySystem.js +58 -53
- package/engine/graphics/ecs/path/tube/PathNormalType.d.ts +4 -0
- package/engine/graphics/ecs/path/tube/PathNormalType.js +11 -0
- package/engine/graphics/ecs/path/tube/TubePathStyle.d.ts +4 -0
- package/engine/graphics/ecs/path/tube/TubePathStyle.js +21 -3
- package/engine/graphics/ecs/path/tube/build/build_geometry_catmullrom.js +4 -1
- package/engine/graphics/ecs/path/tube/build/build_geometry_linear.js +4 -1
- package/engine/graphics/ecs/path/tube/build/computeFrenetFrames.js +41 -24
- package/engine/graphics/geometry/VertexDataSpec.js +24 -0
- package/engine/graphics/geometry/buffered/query/RaycastNearestHitComputingVisitor.js +25 -5
- package/engine/graphics/shaders/TerrainShader.js +3 -7
- package/engine/knowledge/database/StaticKnowledgeDataTable.js +66 -28
- package/engine/navigation/ecs/components/Path.js +58 -232
- package/engine/notify/Notification.js +3 -0
- package/engine/scene/transitionToScene.js +2 -1
- package/engine/ui/notification/AnimatedObjectEmitter.js +3 -2
- package/engine/ui/notification/ViewEmitter.js +8 -0
- package/engine/ui/scene/initializeNotifications.js +3 -0
- package/generation/{GridGenerator.js → GridTaskGroup.js} +21 -5
- package/generation/example/SampleGenerator0.js +2 -2
- package/generation/example/main.js +2 -1
- package/generation/filtering/core/CellFilterUnaryOperation.js +5 -8
- package/generation/filtering/numeric/util/CellFilterDisplaced.js +7 -7
- package/generation/grid/generation/GridTaskSequence.js +5 -3
- package/generation/markers/actions/MarkerNodeActionImaginary.js +86 -0
- package/generation/markers/actions/terrain/MarkerNodeActionPaintTerrain.js +265 -0
- package/generation/theme/TerrainLayerDescription.js +11 -0
- package/generation/theme/ThemeEngine.js +5 -6
- package/package.json +1 -1
- package/samples/terrain/from_image.js +2 -1
- package/view/common/ListView.js +7 -1
- package/view/elements/windrose/WindRoseDiagram.js +13 -0
- package/view/task/TaskLoadingScreen.js +172 -0
- package/view/{common → task}/TaskProgressView.js +4 -36
- package/view/tooltip/gml/GMLEngine.js +13 -0
- package/generation/markers/actions/MarkerNodeActionSelectRandom.js +0 -65
|
@@ -5,6 +5,8 @@ import { MatcapMaterialDefinition } from "./MatcapMaterialDefinition.js";
|
|
|
5
5
|
import { CapType } from "./CapType.js";
|
|
6
6
|
import { StandardMaterialDefinition } from "./StandardMaterialDefinition.js";
|
|
7
7
|
import { BasicMaterialDefinition } from "./BasicMaterialDefinition.js";
|
|
8
|
+
import { PathNormalType } from "./PathNormalType.js";
|
|
9
|
+
import Vector3 from "../../../../../core/geom/Vector3.js";
|
|
8
10
|
|
|
9
11
|
const DEFAULT_COLOR = Object.freeze({ r: 1, g: 1, b: 1 });
|
|
10
12
|
|
|
@@ -51,8 +53,6 @@ export class TubePathStyle {
|
|
|
51
53
|
*/
|
|
52
54
|
this.shape_normals = null;
|
|
53
55
|
|
|
54
|
-
// TODO expose shading style "flat/smooth"
|
|
55
|
-
|
|
56
56
|
/**
|
|
57
57
|
*
|
|
58
58
|
* @type {number}
|
|
@@ -71,6 +71,17 @@ export class TubePathStyle {
|
|
|
71
71
|
*/
|
|
72
72
|
this.receive_shadow = false;
|
|
73
73
|
|
|
74
|
+
/**
|
|
75
|
+
* @type {PathNormalType}
|
|
76
|
+
*/
|
|
77
|
+
this.path_normal_type = PathNormalType.Automatic;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
*
|
|
81
|
+
* @type {Vector3}
|
|
82
|
+
*/
|
|
83
|
+
this.path_normal = Vector3.up;
|
|
84
|
+
|
|
74
85
|
/**
|
|
75
86
|
* Which parts of the path to visualise, in normalized offsets
|
|
76
87
|
* @example [ 0, 1 ] = whole path
|
|
@@ -120,7 +131,9 @@ export class TubePathStyle {
|
|
|
120
131
|
receive_shadow = false,
|
|
121
132
|
path_mask = [0, 1],
|
|
122
133
|
cap_type = CapType.None,
|
|
123
|
-
shape
|
|
134
|
+
shape,
|
|
135
|
+
path_normal = Vector3.up,
|
|
136
|
+
path_normal_type = PathNormalType.Automatic
|
|
124
137
|
}) {
|
|
125
138
|
assert.enum(material_type, TubeMaterialType, 'material_type');
|
|
126
139
|
assert.isNumber(opacity, 'opacity');
|
|
@@ -135,6 +148,7 @@ export class TubePathStyle {
|
|
|
135
148
|
assert.greaterThanOrEqual(path_mask.length, 2, 'path_mask length bust be at least 2');
|
|
136
149
|
assert.ok(path_mask.length % 2 === 0, 'path_mask length bust be multiple of 2');
|
|
137
150
|
assert.enum(cap_type, CapType, 'cap_type');
|
|
151
|
+
assert.enum(path_normal_type, PathNormalType, 'path_normal_type');
|
|
138
152
|
|
|
139
153
|
if (shape === undefined) {
|
|
140
154
|
// legacy API, using circle
|
|
@@ -177,6 +191,10 @@ export class TubePathStyle {
|
|
|
177
191
|
}
|
|
178
192
|
|
|
179
193
|
this.material.fromJSON(material);
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
this.path_normal.fromJSON(path_normal);
|
|
197
|
+
this.path_normal_type = path_normal_type;
|
|
180
198
|
}
|
|
181
199
|
}
|
|
182
200
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { computeFrenetFrames } from "./computeFrenetFrames.js";
|
|
2
2
|
import { makeTubeGeometry } from "./makeTubeGeometry.js";
|
|
3
3
|
import Vector3 from "../../../../../../core/geom/Vector3.js";
|
|
4
|
+
import { PathNormalType } from "../PathNormalType.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
*
|
|
@@ -63,7 +64,9 @@ export function build_geometry_catmullrom(
|
|
|
63
64
|
added_points++;
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
const
|
|
67
|
+
const normal_hint = style.path_normal_type === PathNormalType.FixedStart ? style.path_normal : undefined;
|
|
68
|
+
|
|
69
|
+
const frames = computeFrenetFrames(points_f32, false, normal_hint);
|
|
67
70
|
|
|
68
71
|
return makeTubeGeometry(
|
|
69
72
|
points_f32, frames.normals, frames.binormals, frames.tangents,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { computeFrenetFrames } from "./computeFrenetFrames.js";
|
|
2
2
|
import { makeTubeGeometry } from "./makeTubeGeometry.js";
|
|
3
3
|
import Vector3 from "../../../../../../core/geom/Vector3.js";
|
|
4
|
+
import { PathNormalType } from "../PathNormalType.js";
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
const scratch_array_0 = [];
|
|
@@ -57,7 +58,9 @@ export function build_geometry_linear(
|
|
|
57
58
|
points_added++;
|
|
58
59
|
}
|
|
59
60
|
|
|
60
|
-
const
|
|
61
|
+
const normal_hint = style.path_normal_type === PathNormalType.FixedStart ? style.path_normal : undefined;
|
|
62
|
+
|
|
63
|
+
const frames = computeFrenetFrames(points, false, normal_hint);
|
|
61
64
|
|
|
62
65
|
return makeTubeGeometry(
|
|
63
66
|
points, frames.normals, frames.binormals, frames.tangents,
|
|
@@ -5,13 +5,49 @@ import { clamp } from "../../../../../../core/math/clamp.js";
|
|
|
5
5
|
import { vec3 } from "gl-matrix";
|
|
6
6
|
import { array_copy } from "../../../../../../core/collection/array/copyArray.js";
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Compute a normal vector for Frenet frame based on a tangent (direction in which vertex points)
|
|
10
|
+
* @param {Vector3} result
|
|
11
|
+
* @param {Vector3} tangent
|
|
12
|
+
*/
|
|
13
|
+
function computeNormalHintFromTangent(result, tangent) {
|
|
14
|
+
let min = Number.MAX_VALUE;
|
|
15
|
+
|
|
16
|
+
const tx = Math.abs(tangent.x);
|
|
17
|
+
const ty = Math.abs(tangent.y);
|
|
18
|
+
const tz = Math.abs(tangent.z);
|
|
19
|
+
|
|
20
|
+
if (ty <= min) {
|
|
21
|
+
|
|
22
|
+
min = ty;
|
|
23
|
+
result.set(0, 1, 0);
|
|
24
|
+
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (tz < min) {
|
|
28
|
+
|
|
29
|
+
min = tz;
|
|
30
|
+
result.set(0, 0, 1);
|
|
31
|
+
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (tx < min) {
|
|
35
|
+
|
|
36
|
+
min = tx;
|
|
37
|
+
result.set(1, 0, 0);
|
|
38
|
+
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
}
|
|
42
|
+
|
|
8
43
|
/**
|
|
9
44
|
* @see https://github.com/mrdoob/three.js/blob/c12c9a166a1369cdd58622fff2aff7e3a84305d7/src/extras/core/Curve.js#L260
|
|
10
45
|
* @param {Float32Array|number[]} points
|
|
11
46
|
* @param {boolean} [closed]
|
|
47
|
+
* @param {Vector3} [normal_hint]
|
|
12
48
|
* @returns {{normals:Vector3[], binormals:Vector3[], tangents:Vector3[]}}
|
|
13
49
|
*/
|
|
14
|
-
export function computeFrenetFrames(points, closed = false) {
|
|
50
|
+
export function computeFrenetFrames(points, closed = false, normal_hint) {
|
|
15
51
|
// see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
|
|
16
52
|
|
|
17
53
|
const normal = new Vector3();
|
|
@@ -82,30 +118,11 @@ export function computeFrenetFrames(points, closed = false) {
|
|
|
82
118
|
|
|
83
119
|
normals[0] = new Vector3();
|
|
84
120
|
binormals[0] = new Vector3();
|
|
85
|
-
let min = Number.MAX_VALUE;
|
|
86
|
-
const tx = Math.abs(tangents[0].x);
|
|
87
|
-
const ty = Math.abs(tangents[0].y);
|
|
88
|
-
const tz = Math.abs(tangents[0].z);
|
|
89
|
-
|
|
90
|
-
if (ty <= min) {
|
|
91
|
-
|
|
92
|
-
min = ty;
|
|
93
|
-
normal.set(0, 1, 0);
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (tz < min) {
|
|
98
|
-
min = tz;
|
|
99
|
-
|
|
100
|
-
normal.set(0, 0, 1);
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (tx < min) {
|
|
105
|
-
|
|
106
|
-
min = tx;
|
|
107
|
-
normal.set(1, 0, 0);
|
|
108
121
|
|
|
122
|
+
if (normal_hint !== undefined) {
|
|
123
|
+
normal.copy(normal_hint);
|
|
124
|
+
} else {
|
|
125
|
+
computeNormalHintFromTangent(normal, tangents[0]);
|
|
109
126
|
}
|
|
110
127
|
|
|
111
128
|
vec.crossVectors(tangents[0], normal).normalize();
|
|
@@ -20,6 +20,19 @@ export class VertexDataSpec {
|
|
|
20
20
|
this.__hash = DEFAULT_HASH;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
*
|
|
25
|
+
* @param {AttributeSpec} attributes
|
|
26
|
+
* @returns {VertexDataSpec}
|
|
27
|
+
*/
|
|
28
|
+
static from(...attributes) {
|
|
29
|
+
const r = new VertexDataSpec();
|
|
30
|
+
|
|
31
|
+
r.addMany(attributes);
|
|
32
|
+
|
|
33
|
+
return r;
|
|
34
|
+
}
|
|
35
|
+
|
|
23
36
|
/**
|
|
24
37
|
*
|
|
25
38
|
* @param {string} name
|
|
@@ -61,6 +74,17 @@ export class VertexDataSpec {
|
|
|
61
74
|
return undefined;
|
|
62
75
|
}
|
|
63
76
|
|
|
77
|
+
/**
|
|
78
|
+
*
|
|
79
|
+
* @param {AttributeSpec[]} attributes
|
|
80
|
+
*/
|
|
81
|
+
addMany(attributes) {
|
|
82
|
+
const n = attributes.length;
|
|
83
|
+
for (let i = 0; i < n; i++) {
|
|
84
|
+
this.add(attributes[i]);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
64
88
|
/**
|
|
65
89
|
*
|
|
66
90
|
* @param {AttributeSpec} attribute
|
|
@@ -4,6 +4,7 @@ import Vector3 from "../../../../../core/geom/Vector3.js";
|
|
|
4
4
|
import { computeTriangleRayIntersection } from "../../../../../core/geom/3d/triangle/computeTriangleRayIntersection.js";
|
|
5
5
|
import { GeometrySpatialAcceleratorVisitor } from "./GeometryVisitor.js";
|
|
6
6
|
import { aabb3_intersects_ray } from "../../../../../core/bvh2/aabb3/aabb3_intersects_ray.js";
|
|
7
|
+
import { assert } from "../../../../../core/assert.js";
|
|
7
8
|
|
|
8
9
|
export class RaycastNearestHitComputingVisitor extends GeometrySpatialAcceleratorVisitor {
|
|
9
10
|
constructor() {
|
|
@@ -18,14 +19,14 @@ export class RaycastNearestHitComputingVisitor extends GeometrySpatialAccelerato
|
|
|
18
19
|
this.__nearest_distance = Number.POSITIVE_INFINITY;
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
|
-
*
|
|
22
|
+
* @readonly
|
|
22
23
|
* @type {SurfacePoint3}
|
|
23
24
|
* @private
|
|
24
25
|
*/
|
|
25
26
|
this.__nearest_hit = new SurfacePoint3();
|
|
26
27
|
|
|
27
28
|
/**
|
|
28
|
-
*
|
|
29
|
+
* @readonly
|
|
29
30
|
* @type {SurfacePoint3}
|
|
30
31
|
* @private
|
|
31
32
|
*/
|
|
@@ -39,7 +40,18 @@ export class RaycastNearestHitComputingVisitor extends GeometrySpatialAccelerato
|
|
|
39
40
|
*/
|
|
40
41
|
this.__hit_found = false;
|
|
41
42
|
|
|
43
|
+
/**
|
|
44
|
+
* @readonly
|
|
45
|
+
* @type {Vector3}
|
|
46
|
+
* @private
|
|
47
|
+
*/
|
|
42
48
|
this.__ray_origin = new Vector3();
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @readonly
|
|
52
|
+
* @type {Vector3}
|
|
53
|
+
* @private
|
|
54
|
+
*/
|
|
43
55
|
this.__ray_direction = new Vector3();
|
|
44
56
|
}
|
|
45
57
|
|
|
@@ -98,6 +110,8 @@ export class RaycastNearestHitComputingVisitor extends GeometrySpatialAccelerato
|
|
|
98
110
|
|
|
99
111
|
const indices = this.__buffer_indices;
|
|
100
112
|
|
|
113
|
+
assert.lessThan(index3 + 2, indices.length, 'triangle index overflow, possibly geometry changed but tree was not rebuilt?');
|
|
114
|
+
|
|
101
115
|
const a = indices[index3];
|
|
102
116
|
const b = indices[index3 + 1];
|
|
103
117
|
const c = indices[index3 + 2];
|
|
@@ -111,6 +125,10 @@ export class RaycastNearestHitComputingVisitor extends GeometrySpatialAccelerato
|
|
|
111
125
|
const b_address = b * stride + offset;
|
|
112
126
|
const c_address = c * stride + offset;
|
|
113
127
|
|
|
128
|
+
assert.lessThan(a_address + 2, vertices.length, 'a-vertex overflow');
|
|
129
|
+
assert.lessThan(b_address + 2, vertices.length, 'b-vertex overflow');
|
|
130
|
+
assert.lessThan(c_address + 2, vertices.length, 'c-vertex overflow');
|
|
131
|
+
|
|
114
132
|
const ax = vertices[a_address];
|
|
115
133
|
const ay = vertices[a_address + 1];
|
|
116
134
|
const az = vertices[a_address + 2];
|
|
@@ -123,8 +141,10 @@ export class RaycastNearestHitComputingVisitor extends GeometrySpatialAccelerato
|
|
|
123
141
|
const cy = vertices[c_address + 1];
|
|
124
142
|
const cz = vertices[c_address + 2];
|
|
125
143
|
|
|
144
|
+
const temp_hit = this.__temp_hit;
|
|
145
|
+
|
|
126
146
|
if (computeTriangleRayIntersection(
|
|
127
|
-
|
|
147
|
+
temp_hit,
|
|
128
148
|
rayOrigin.x,
|
|
129
149
|
rayOrigin.y,
|
|
130
150
|
rayOrigin.z,
|
|
@@ -135,10 +155,10 @@ export class RaycastNearestHitComputingVisitor extends GeometrySpatialAccelerato
|
|
|
135
155
|
bx, by, bz,
|
|
136
156
|
cx, cy, cz
|
|
137
157
|
)) {
|
|
138
|
-
const d =
|
|
158
|
+
const d = temp_hit.position.distanceSqrTo(rayOrigin);
|
|
139
159
|
|
|
140
160
|
if (d < this.__nearest_distance) {
|
|
141
|
-
this.__nearest_hit.copy(
|
|
161
|
+
this.__nearest_hit.copy(temp_hit);
|
|
142
162
|
this.__nearest_distance = d;
|
|
143
163
|
|
|
144
164
|
this.__hit_found = true;
|
|
@@ -99,7 +99,7 @@ function fragment() {
|
|
|
99
99
|
precision highp sampler2DArray;
|
|
100
100
|
|
|
101
101
|
uniform sampler2DArray splatWeightMap;
|
|
102
|
-
uniform
|
|
102
|
+
uniform int splatLayerCount;
|
|
103
103
|
|
|
104
104
|
uniform vec2 splatResolution;
|
|
105
105
|
|
|
@@ -280,13 +280,9 @@ function fragment() {
|
|
|
280
280
|
float weightSum = 0.0;
|
|
281
281
|
vec4 colorSum = vec4(0.0);
|
|
282
282
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
for( float i = 0.0; i < splatLayerCount; i++){
|
|
286
|
-
|
|
287
|
-
float nI = i * m;
|
|
283
|
+
for( int i = 0; i < splatLayerCount; i++){
|
|
288
284
|
|
|
289
|
-
vec2 scale =
|
|
285
|
+
vec2 scale = texelFetch(materialScalesMap, ivec2(i, 0), 0 ).xy;
|
|
290
286
|
|
|
291
287
|
vec2 layerUv = vUv * scale;
|
|
292
288
|
|
|
@@ -4,6 +4,33 @@ import Task from "../../../core/process/task/Task.js";
|
|
|
4
4
|
import { assert } from "../../../core/assert.js";
|
|
5
5
|
import TaskSignal from "../../../core/process/task/TaskSignal.js";
|
|
6
6
|
|
|
7
|
+
let id_seed = 0;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* @param {{contains:function(string):boolean}} database
|
|
12
|
+
* @returns {string}
|
|
13
|
+
*/
|
|
14
|
+
function generate_id(database) {
|
|
15
|
+
let retries_left = 10000;
|
|
16
|
+
let id;
|
|
17
|
+
|
|
18
|
+
do {
|
|
19
|
+
id = id_seed.toString(16);
|
|
20
|
+
|
|
21
|
+
id_seed++;
|
|
22
|
+
|
|
23
|
+
retries_left--;
|
|
24
|
+
|
|
25
|
+
if (retries_left <= 0) {
|
|
26
|
+
throw new Error(`Couldn't find a unique ID after maximum number of attempts`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
} while (database.contains(id))
|
|
30
|
+
|
|
31
|
+
return id;
|
|
32
|
+
}
|
|
33
|
+
|
|
7
34
|
/**
|
|
8
35
|
* Base class for managing various kinds of static game data
|
|
9
36
|
* @template T
|
|
@@ -11,31 +38,31 @@ import TaskSignal from "../../../core/process/task/TaskSignal.js";
|
|
|
11
38
|
export class StaticKnowledgeDataTable {
|
|
12
39
|
|
|
13
40
|
/**
|
|
14
|
-
*
|
|
15
|
-
* @
|
|
41
|
+
* Elements mapped by their string ID
|
|
42
|
+
* @type {Object<T>}
|
|
16
43
|
*/
|
|
17
|
-
|
|
44
|
+
elements = {};
|
|
18
45
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
46
|
+
/**
|
|
47
|
+
*
|
|
48
|
+
* @type {Map<string, object>}
|
|
49
|
+
* @protected
|
|
50
|
+
*/
|
|
51
|
+
__json = new Map();
|
|
24
52
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Array representation of elements, useful for fast traversal
|
|
55
|
+
* @type {T[]}
|
|
56
|
+
* @protected
|
|
57
|
+
*/
|
|
58
|
+
__array = [];
|
|
31
59
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
60
|
+
/**
|
|
61
|
+
* Allow automatic ID generation when ID is not present
|
|
62
|
+
* @type {boolean}
|
|
63
|
+
* @protected
|
|
64
|
+
*/
|
|
65
|
+
__automatic_ids = false;
|
|
39
66
|
|
|
40
67
|
reset() {
|
|
41
68
|
Object.keys(this.elements).forEach(id => {
|
|
@@ -208,11 +235,17 @@ export class StaticKnowledgeDataTable {
|
|
|
208
235
|
const task = countTask(0, n, i => {
|
|
209
236
|
const datum = data[i];
|
|
210
237
|
|
|
211
|
-
|
|
238
|
+
let id = datum.id;
|
|
212
239
|
|
|
213
240
|
if (typeof id !== "string") {
|
|
214
|
-
|
|
215
|
-
|
|
241
|
+
|
|
242
|
+
if (this.__automatic_ids) {
|
|
243
|
+
id = generate_id(this);
|
|
244
|
+
} else {
|
|
245
|
+
console.error(`datum.id must be a string, instead was '${typeof id}' (= ${id})`);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
|
|
216
249
|
}
|
|
217
250
|
|
|
218
251
|
let element;
|
|
@@ -221,15 +254,15 @@ export class StaticKnowledgeDataTable {
|
|
|
221
254
|
element = this.parse(datum);
|
|
222
255
|
} catch (e) {
|
|
223
256
|
|
|
224
|
-
let
|
|
257
|
+
let _id;
|
|
225
258
|
//attempt to extract item ID
|
|
226
259
|
try {
|
|
227
|
-
|
|
260
|
+
_id = datum.id;
|
|
228
261
|
} catch (e) {
|
|
229
|
-
|
|
262
|
+
_id = 'ERROR';
|
|
230
263
|
}
|
|
231
264
|
|
|
232
|
-
console.error(`Failed to parse element (id=${
|
|
265
|
+
console.error(`Failed to parse element (id=${_id})`, e, datum);
|
|
233
266
|
return;
|
|
234
267
|
}
|
|
235
268
|
|
|
@@ -250,6 +283,11 @@ export class StaticKnowledgeDataTable {
|
|
|
250
283
|
|
|
251
284
|
this.__json.set(id, datum);
|
|
252
285
|
|
|
286
|
+
if (datum.id !== id) {
|
|
287
|
+
// ID was generated, write it back into the element
|
|
288
|
+
element.id = id;
|
|
289
|
+
}
|
|
290
|
+
|
|
253
291
|
const added = this.add(element);
|
|
254
292
|
|
|
255
293
|
if (!added) {
|