@woosh/meep-engine 2.84.8 → 2.84.10
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/README.md +27 -13
- package/build/meep.cjs +213 -140
- package/build/meep.min.js +1 -1
- package/build/meep.module.js +213 -140
- package/editor/process/symbolic/makePositionedIconDisplaySymbol.js +2 -4
- package/editor/view/EditorView.js +48 -204
- package/editor/view/ecs/HierarchicalEntityListView.js +191 -0
- package/editor/view/ecs/HierarchicalEntityListView.module.scss +13 -0
- package/editor/view/prepareMeshLibrary.js +178 -0
- package/editor/view/v2/SplitView.js +104 -0
- package/editor/view/v2/ViewManagementSystem.js +0 -0
- package/editor/view/v2/prototypeEditor.js +127 -0
- package/package.json +10 -5
- package/src/core/cache/Cache.d.ts +2 -0
- package/src/core/cache/Cache.js +58 -8
- package/src/core/cache/Cache.spec.js +38 -0
- package/src/core/cache/CacheElement.js +6 -0
- package/src/core/cache/LoadingCache.js +27 -3
- package/src/core/cache/LoadingCache.spec.js +22 -7
- package/src/core/collection/array/arraySetSortingDiff.js +6 -6
- package/src/core/collection/table/RowFirstTable.js +364 -368
- package/src/core/geom/3d/SurfacePoint3.js +3 -40
- package/src/core/geom/3d/plane/plane3_compute_ray_intersection.js +3 -1
- package/src/core/geom/3d/topology/simplify/prototypeMeshSimplification.js +7 -7
- package/src/core/geom/Vector3.js +25 -14
- package/src/core/model/stat/LinearModifier.spec.js +5 -6
- package/src/core/process/PromiseWatcher.spec.js +27 -23
- package/src/engine/animation/behavior/animateProperty.js +4 -4
- package/src/engine/animation/curve/ecd_bind_animation_curve.js +9 -0
- package/src/engine/ecs/EntityReference.js +12 -0
- package/src/engine/ecs/dynamic_actions/actions/definition/SpeakLineActionDescription.js +1 -1
- package/src/engine/ecs/transform/Transform.js +1 -1
- package/src/engine/ecs/transform/Transform.spec.js +44 -0
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometryFlags.js +8 -1
- package/src/engine/graphics/ecs/mesh-v2/aggregate/prototypeSGMesh.js +23 -19
- package/src/engine/graphics/ecs/mesh-v2/sg_hierarchy_compute_bounding_box_via_parent_entity.js +2 -2
- package/src/engine/graphics/ecs/mesh-v2/three_object_to_entity_composition.js +3 -1
- package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +6 -6
- package/src/engine/intelligence/behavior/ecs/SendEventBehavior.js +43 -0
- package/src/view/View.js +64 -95
- package/src/view/setElementTransform.js +20 -0
- package/src/view/setElementVisibility.js +15 -0
|
@@ -8,493 +8,489 @@ import Signal from "../../events/signal/Signal.js";
|
|
|
8
8
|
import { max2 } from "../../math/max2.js";
|
|
9
9
|
import { array_copy } from "../array/array_copy.js";
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
*
|
|
13
|
-
* @param {RowFirstTableSpec} spec
|
|
14
|
-
* @constructor
|
|
15
|
-
*/
|
|
16
|
-
function RowFirstTable(spec) {
|
|
17
|
-
assert.defined(spec, 'spec');
|
|
18
|
-
assert.notNull(spec, 'spec');
|
|
19
|
-
assert.equal(spec.isRowFirstTableSpec, true, 'spec.isRowFirstTableSpec !== true');
|
|
20
|
-
|
|
11
|
+
export class RowFirstTable {
|
|
21
12
|
/**
|
|
22
13
|
*
|
|
23
|
-
* @
|
|
14
|
+
* @param {RowFirstTableSpec} spec
|
|
15
|
+
* @constructor
|
|
24
16
|
*/
|
|
25
|
-
|
|
17
|
+
constructor(spec) {
|
|
18
|
+
assert.defined(spec, 'spec');
|
|
19
|
+
assert.notNull(spec, 'spec');
|
|
20
|
+
assert.equal(spec.isRowFirstTableSpec, true, 'spec.isRowFirstTableSpec !== true');
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
* @type {RowFirstTableSpec}
|
|
25
|
+
*/
|
|
26
|
+
this.spec = spec;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @readonly
|
|
30
|
+
* @type {Array.<BinaryDataType>}
|
|
31
|
+
*/
|
|
32
|
+
this.types = spec.types;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
*
|
|
36
|
+
* @type {ArrayBuffer}
|
|
37
|
+
*/
|
|
38
|
+
this.data = new ArrayBuffer(0);
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
*
|
|
42
|
+
* @type {number}
|
|
43
|
+
*/
|
|
44
|
+
this.bytesPerRecord = spec.bytesPerRecord;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* number of records
|
|
48
|
+
* @type {number}
|
|
49
|
+
*/
|
|
50
|
+
this.length = 0;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* capacity in number of records
|
|
54
|
+
* @type {number}
|
|
55
|
+
*/
|
|
56
|
+
this.capacity = 0;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
*
|
|
60
|
+
* @type {DataView}
|
|
61
|
+
*/
|
|
62
|
+
this.dataView = null;
|
|
63
|
+
|
|
64
|
+
this.on = {
|
|
65
|
+
added: new Signal()
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
this.initialize();
|
|
69
|
+
}
|
|
26
70
|
|
|
27
71
|
/**
|
|
28
|
-
* @
|
|
29
|
-
* @type {Array.<BinaryDataType>}
|
|
72
|
+
* @private
|
|
30
73
|
*/
|
|
31
|
-
|
|
74
|
+
initialize() {
|
|
75
|
+
const spec = this.spec;
|
|
76
|
+
|
|
77
|
+
this.types = spec.types;
|
|
78
|
+
this.bytesPerRecord = spec.bytesPerRecord;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
*
|
|
82
|
+
* @type {function(DataView, number, number[]): void}
|
|
83
|
+
*/
|
|
84
|
+
this.readRowMethod = spec.readRowMethod;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
*
|
|
88
|
+
* @type {function(DataView, number, number[]): void}
|
|
89
|
+
*/
|
|
90
|
+
this.writeRowMethod = spec.writeRowMethod;
|
|
91
|
+
}
|
|
32
92
|
|
|
33
93
|
/**
|
|
34
94
|
*
|
|
35
|
-
* @
|
|
95
|
+
* @returns {number}
|
|
36
96
|
*/
|
|
37
|
-
|
|
97
|
+
hash() {
|
|
98
|
+
// to keep hash calculation fast, do a fixed number evenly spaced taps inside the data table
|
|
38
99
|
|
|
39
|
-
|
|
40
|
-
*
|
|
41
|
-
* @type {number}
|
|
42
|
-
*/
|
|
43
|
-
this.bytesPerRecord = spec.bytesPerRecord;
|
|
100
|
+
const byteLength = this.data.byteLength;
|
|
44
101
|
|
|
45
|
-
|
|
46
|
-
* number of records
|
|
47
|
-
* @type {number}
|
|
48
|
-
*/
|
|
49
|
-
this.length = 0;
|
|
102
|
+
const tap_count = 31;
|
|
50
103
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
this.capacity = 0;
|
|
104
|
+
const step_size = max2(
|
|
105
|
+
Math.floor(byteLength / (tap_count * 4)),
|
|
106
|
+
1
|
|
107
|
+
);
|
|
56
108
|
|
|
57
|
-
|
|
58
|
-
*
|
|
59
|
-
* @type {DataView}
|
|
60
|
-
*/
|
|
61
|
-
this.dataView = null;
|
|
109
|
+
const step_count = Math.floor(byteLength / step_size);
|
|
62
110
|
|
|
63
|
-
|
|
64
|
-
added: new Signal()
|
|
65
|
-
};
|
|
111
|
+
const dataView = this.dataView;
|
|
66
112
|
|
|
67
|
-
|
|
68
|
-
}
|
|
113
|
+
let result = byteLength;
|
|
69
114
|
|
|
70
|
-
|
|
71
|
-
*
|
|
72
|
-
*/
|
|
73
|
-
RowFirstTable.prototype.initialize = function () {
|
|
74
|
-
const spec = this.spec;
|
|
115
|
+
for (let i = 0; i < step_count; i++) {
|
|
116
|
+
const address = i * step_size * 4;
|
|
75
117
|
|
|
76
|
-
|
|
77
|
-
|
|
118
|
+
result = ((result << 5) - result) + dataView.getUint32(address);
|
|
119
|
+
result |= 0; // Convert to 32bit integer
|
|
120
|
+
}
|
|
78
121
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
* @type {function(DataView, number, number[]): void}
|
|
82
|
-
*/
|
|
83
|
-
this.readRowMethod = spec.readRowMethod;
|
|
122
|
+
return result;
|
|
123
|
+
}
|
|
84
124
|
|
|
85
125
|
/**
|
|
86
126
|
*
|
|
87
|
-
* @
|
|
127
|
+
* @param {int} rowCount
|
|
88
128
|
*/
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
*
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
const byteLength = this.data.byteLength;
|
|
100
|
-
|
|
101
|
-
const tap_count = 31;
|
|
102
|
-
|
|
103
|
-
const step_size = max2(
|
|
104
|
-
Math.floor(byteLength / (tap_count * 4)),
|
|
105
|
-
1
|
|
106
|
-
);
|
|
107
|
-
|
|
108
|
-
const step_count = Math.floor(byteLength / step_size);
|
|
109
|
-
|
|
110
|
-
const dataView = this.dataView;
|
|
111
|
-
|
|
112
|
-
let result = byteLength;
|
|
129
|
+
setCapacity(rowCount) {
|
|
130
|
+
const oldData = this.data;
|
|
131
|
+
|
|
132
|
+
const bytesPerRecord = this.bytesPerRecord;
|
|
133
|
+
const byteSize = rowCount * bytesPerRecord;
|
|
134
|
+
try {
|
|
135
|
+
this.data = new ArrayBuffer(byteSize);
|
|
136
|
+
} catch (e) {
|
|
137
|
+
throw new Error("failed to create a new array buffer of size: " + byteSize);
|
|
138
|
+
}
|
|
113
139
|
|
|
114
|
-
|
|
115
|
-
|
|
140
|
+
//check the size of new array
|
|
141
|
+
if (this.data.byteLength !== byteSize) {
|
|
142
|
+
throw new Error("Generated array was truncated unexpectedly from " + byteSize + " to " + this.data.byteLength);
|
|
143
|
+
}
|
|
116
144
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
145
|
+
const newArray = new Uint8Array(this.data);
|
|
146
|
+
const oldArray = new Uint8Array(oldData);
|
|
147
|
+
|
|
148
|
+
const sourceCopyLength = this.length * bytesPerRecord;
|
|
149
|
+
try {
|
|
150
|
+
newArray.set(oldArray.subarray(0, sourceCopyLength), 0);
|
|
151
|
+
} catch (e) {
|
|
152
|
+
if (e instanceof RangeError) {
|
|
153
|
+
throw new Error("Failed to copy contents of original due to to size violation. OldSize: " + sourceCopyLength + ", NewSize: " + this.data.byteLength);
|
|
154
|
+
} else {
|
|
155
|
+
throw e;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
120
158
|
|
|
121
|
-
|
|
122
|
-
};
|
|
159
|
+
this.capacity = rowCount;
|
|
123
160
|
|
|
124
|
-
|
|
125
|
-
*
|
|
126
|
-
* @param {int} rowCount
|
|
127
|
-
*/
|
|
128
|
-
RowFirstTable.prototype.setCapacity = function (rowCount) {
|
|
129
|
-
const oldData = this.data;
|
|
130
|
-
|
|
131
|
-
const bytesPerRecord = this.bytesPerRecord;
|
|
132
|
-
const byteSize = rowCount * bytesPerRecord;
|
|
133
|
-
try {
|
|
134
|
-
this.data = new ArrayBuffer(byteSize);
|
|
135
|
-
} catch (e) {
|
|
136
|
-
throw new Error("failed to create a new array buffer of size: " + byteSize);
|
|
161
|
+
this.dataView = new DataView(this.data, 0);
|
|
137
162
|
}
|
|
138
163
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
164
|
+
/**
|
|
165
|
+
* Drop excess capacity, setting capacity exactly to the current length
|
|
166
|
+
*/
|
|
167
|
+
trim() {
|
|
168
|
+
this.setCapacity(this.length);
|
|
142
169
|
}
|
|
143
170
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
171
|
+
/**
|
|
172
|
+
*
|
|
173
|
+
* @param {number} rowCount
|
|
174
|
+
*/
|
|
175
|
+
resize(rowCount) {
|
|
176
|
+
if (this.capacity < rowCount) {
|
|
177
|
+
//grow
|
|
178
|
+
const growFactor = 1.5;
|
|
179
|
+
const newSize = Math.ceil(rowCount * growFactor);
|
|
180
|
+
this.setCapacity(newSize);
|
|
181
|
+
} else if (this.capacity * 0.5 > rowCount) {
|
|
182
|
+
//shrink
|
|
183
|
+
this.setCapacity(rowCount);
|
|
155
184
|
}
|
|
156
185
|
}
|
|
157
186
|
|
|
158
|
-
|
|
187
|
+
/**
|
|
188
|
+
*
|
|
189
|
+
* @param {number} rowIndex
|
|
190
|
+
* @param {number} columnIndex
|
|
191
|
+
* @param {number} value
|
|
192
|
+
*/
|
|
193
|
+
writeCellValue(rowIndex, columnIndex, value) {
|
|
194
|
+
const bytesPerRecord = this.bytesPerRecord;
|
|
159
195
|
|
|
160
|
-
|
|
161
|
-
};
|
|
196
|
+
const rowAddress = rowIndex * bytesPerRecord;
|
|
162
197
|
|
|
163
|
-
|
|
164
|
-
* Drop excess capacity, setting capacity exactly to the current length
|
|
165
|
-
*/
|
|
166
|
-
RowFirstTable.prototype.trim = function () {
|
|
167
|
-
this.setCapacity(this.length);
|
|
168
|
-
};
|
|
198
|
+
const spec = this.spec;
|
|
169
199
|
|
|
170
|
-
|
|
171
|
-
*
|
|
172
|
-
* @param {number} rowCount
|
|
173
|
-
*/
|
|
174
|
-
RowFirstTable.prototype.resize = function (rowCount) {
|
|
175
|
-
if (this.capacity < rowCount) {
|
|
176
|
-
//grow
|
|
177
|
-
const growFactor = 1.5;
|
|
178
|
-
const newSize = Math.ceil(rowCount * growFactor);
|
|
179
|
-
this.setCapacity(newSize);
|
|
180
|
-
} else if (this.capacity * 0.5 > rowCount) {
|
|
181
|
-
//shrink
|
|
182
|
-
this.setCapacity(rowCount);
|
|
183
|
-
}
|
|
184
|
-
};
|
|
200
|
+
const cellWriters = spec.cellWriters;
|
|
185
201
|
|
|
186
|
-
|
|
187
|
-
*
|
|
188
|
-
* @param {number} rowIndex
|
|
189
|
-
* @param {number} columnIndex
|
|
190
|
-
* @param {number} value
|
|
191
|
-
*/
|
|
192
|
-
RowFirstTable.prototype.writeCellValue = function (rowIndex, columnIndex, value) {
|
|
193
|
-
const bytesPerRecord = this.bytesPerRecord;
|
|
202
|
+
const cellWriter = cellWriters[columnIndex];
|
|
194
203
|
|
|
195
|
-
|
|
204
|
+
cellWriter(this.dataView, rowAddress, value);
|
|
205
|
+
}
|
|
196
206
|
|
|
197
|
-
|
|
207
|
+
/**
|
|
208
|
+
* read a single cell value from the table
|
|
209
|
+
* @param {number} rowIndex
|
|
210
|
+
* @param {number} columnIndex
|
|
211
|
+
* @returns {number}
|
|
212
|
+
*/
|
|
213
|
+
readCellValue(rowIndex, columnIndex) {
|
|
214
|
+
const bytesPerRecord = this.bytesPerRecord;
|
|
198
215
|
|
|
199
|
-
|
|
216
|
+
const rowAddress = rowIndex * bytesPerRecord;
|
|
200
217
|
|
|
201
|
-
|
|
218
|
+
const spec = this.spec;
|
|
202
219
|
|
|
203
|
-
|
|
204
|
-
};
|
|
220
|
+
const cellReaders = spec.cellReaders;
|
|
205
221
|
|
|
206
|
-
|
|
207
|
-
* read a single cell value from the table
|
|
208
|
-
* @param {number} rowIndex
|
|
209
|
-
* @param {number} columnIndex
|
|
210
|
-
* @returns {number}
|
|
211
|
-
*/
|
|
212
|
-
RowFirstTable.prototype.readCellValue = function (rowIndex, columnIndex) {
|
|
213
|
-
const bytesPerRecord = this.bytesPerRecord;
|
|
222
|
+
const cellReader = cellReaders[columnIndex];
|
|
214
223
|
|
|
215
|
-
|
|
224
|
+
return cellReader(this.dataView, rowAddress);
|
|
225
|
+
}
|
|
216
226
|
|
|
217
|
-
|
|
227
|
+
/**
|
|
228
|
+
* Remove rows from the table
|
|
229
|
+
* @param {number} index starting row
|
|
230
|
+
* @param {number} rowCount number of rows to be removed
|
|
231
|
+
*/
|
|
232
|
+
removeRows(index, rowCount) {
|
|
218
233
|
|
|
219
|
-
|
|
234
|
+
//validate presence to requested rows
|
|
235
|
+
assert.lessThanOrEqual(index + rowCount, this.length, 'underflow');
|
|
220
236
|
|
|
221
|
-
|
|
237
|
+
const data = this.data;
|
|
222
238
|
|
|
223
|
-
|
|
224
|
-
};
|
|
239
|
+
const array = new Uint8Array(data);
|
|
225
240
|
|
|
226
|
-
|
|
227
|
-
* Remove rows from the table
|
|
228
|
-
* @param {number} index starting row
|
|
229
|
-
* @param {number} rowCount number of rows to be removed
|
|
230
|
-
*/
|
|
231
|
-
RowFirstTable.prototype.removeRows = function (index, rowCount) {
|
|
241
|
+
const bytesPerRecord = this.bytesPerRecord;
|
|
232
242
|
|
|
233
|
-
|
|
234
|
-
|
|
243
|
+
//shift tail of the table forward
|
|
244
|
+
const target = index * bytesPerRecord;
|
|
245
|
+
const start = target + rowCount * bytesPerRecord;
|
|
246
|
+
const end = this.length * bytesPerRecord;
|
|
235
247
|
|
|
236
|
-
|
|
248
|
+
array.copyWithin(target, start, end);
|
|
237
249
|
|
|
238
|
-
|
|
250
|
+
//adjust new length
|
|
251
|
+
this.length -= rowCount;
|
|
239
252
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
const target = index * bytesPerRecord;
|
|
244
|
-
const start = target + rowCount * bytesPerRecord;
|
|
245
|
-
const end = this.length * bytesPerRecord;
|
|
253
|
+
//resize table
|
|
254
|
+
this.resize(this.length);
|
|
255
|
+
}
|
|
246
256
|
|
|
247
|
-
|
|
257
|
+
/**
|
|
258
|
+
* Insert a number of blank rows at the given offset
|
|
259
|
+
* NOTE: doesn't send onAdded signal
|
|
260
|
+
* @param {number} index
|
|
261
|
+
* @param {number} rowCount
|
|
262
|
+
*/
|
|
263
|
+
insertRows(index, rowCount) {
|
|
264
|
+
const future_length = this.length + rowCount;
|
|
248
265
|
|
|
249
|
-
|
|
250
|
-
this.length -= rowCount;
|
|
266
|
+
this.resize(future_length);
|
|
251
267
|
|
|
252
|
-
|
|
253
|
-
this.resize(this.length);
|
|
254
|
-
};
|
|
268
|
+
const data = this.data;
|
|
255
269
|
|
|
256
|
-
|
|
257
|
-
* Insert a number of blank rows at the given offset
|
|
258
|
-
* NOTE: doesn't send onAdded signal
|
|
259
|
-
* @param {number} index
|
|
260
|
-
* @param {number} rowCount
|
|
261
|
-
*/
|
|
262
|
-
RowFirstTable.prototype.insertRows = function (index, rowCount) {
|
|
263
|
-
const future_length = this.length + rowCount;
|
|
270
|
+
const bytesPerRecord = this.bytesPerRecord;
|
|
264
271
|
|
|
265
|
-
|
|
272
|
+
const array = new Uint8Array(data);
|
|
266
273
|
|
|
267
|
-
|
|
274
|
+
//shift tail of the table forward
|
|
275
|
+
const target = (index + rowCount) * bytesPerRecord;
|
|
276
|
+
const end = future_length * bytesPerRecord;
|
|
277
|
+
const start = index * bytesPerRecord;
|
|
268
278
|
|
|
269
|
-
|
|
279
|
+
array.copyWithin(target, start, end);
|
|
270
280
|
|
|
271
|
-
|
|
281
|
+
this.length = future_length;
|
|
282
|
+
}
|
|
272
283
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
284
|
+
/**
|
|
285
|
+
*
|
|
286
|
+
* @param {Array.<Number>} values
|
|
287
|
+
*/
|
|
288
|
+
addRow(values) {
|
|
277
289
|
|
|
278
|
-
|
|
290
|
+
const newRowCount = this.length + 1;
|
|
279
291
|
|
|
280
|
-
|
|
281
|
-
};
|
|
292
|
+
this.resize(newRowCount);
|
|
282
293
|
|
|
283
|
-
|
|
284
|
-
*
|
|
285
|
-
* @param {Array.<Number>} values
|
|
286
|
-
*/
|
|
287
|
-
RowFirstTable.prototype.addRow = function (values) {
|
|
294
|
+
const rowIndex = this.length;
|
|
288
295
|
|
|
289
|
-
|
|
296
|
+
this.length = newRowCount;
|
|
290
297
|
|
|
291
|
-
this.resize(newRowCount);
|
|
292
298
|
|
|
293
|
-
|
|
299
|
+
this.writeRowMethod(this.dataView, this.bytesPerRecord * rowIndex, values);
|
|
294
300
|
|
|
295
|
-
|
|
301
|
+
this.on.added.send2(rowIndex, values);
|
|
302
|
+
}
|
|
296
303
|
|
|
304
|
+
/**
|
|
305
|
+
*
|
|
306
|
+
* @param {int} count number of rows to be added
|
|
307
|
+
* @param {function} valueSupplier supplier of row values, called with row index and an empty row to be filled
|
|
308
|
+
*/
|
|
309
|
+
addRows(count, valueSupplier) {
|
|
310
|
+
const newRowCount = this.length + count;
|
|
297
311
|
|
|
298
|
-
|
|
312
|
+
this.resize(newRowCount);
|
|
299
313
|
|
|
300
|
-
|
|
301
|
-
|
|
314
|
+
let i = this.length;
|
|
315
|
+
this.length = newRowCount;
|
|
302
316
|
|
|
303
|
-
|
|
304
|
-
*
|
|
305
|
-
* @param {int} count number of rows to be added
|
|
306
|
-
* @param {function} valueSupplier supplier of row values, called with row index and an empty row to be filled
|
|
307
|
-
*/
|
|
308
|
-
RowFirstTable.prototype.addRows = function (count, valueSupplier) {
|
|
309
|
-
const newRowCount = this.length + count;
|
|
317
|
+
const row = new Array(this.getNumColumns());
|
|
310
318
|
|
|
311
|
-
|
|
319
|
+
const bytesPerRecord = this.bytesPerRecord;
|
|
320
|
+
const dataView = this.dataView;
|
|
321
|
+
const writeRowMethod = this.writeRowMethod;
|
|
312
322
|
|
|
313
|
-
|
|
314
|
-
this.length = newRowCount;
|
|
323
|
+
const onAdded = this.on.added;
|
|
315
324
|
|
|
316
|
-
|
|
325
|
+
function addOneSignaling(index) {
|
|
326
|
+
addOneSilent(index);
|
|
327
|
+
onAdded.send2(index, row);
|
|
328
|
+
}
|
|
317
329
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
330
|
+
function addOneSilent(i) {
|
|
331
|
+
valueSupplier(i, row);
|
|
332
|
+
writeRowMethod(dataView, bytesPerRecord * i, row);
|
|
333
|
+
}
|
|
321
334
|
|
|
322
|
-
|
|
335
|
+
//depending on whether signal is being listened, pick signaling or silent generator
|
|
336
|
+
const addOne = onAdded.hasHandlers() ? addOneSignaling : addOneSilent;
|
|
323
337
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
}
|
|
338
|
+
for (; i < newRowCount; i++) {
|
|
339
|
+
addOne(i);
|
|
340
|
+
}
|
|
328
341
|
|
|
329
|
-
function addOneSilent(i) {
|
|
330
|
-
valueSupplier(i, row);
|
|
331
|
-
writeRowMethod(dataView, bytesPerRecord * i, row);
|
|
332
342
|
}
|
|
333
343
|
|
|
334
|
-
|
|
335
|
-
|
|
344
|
+
/**
|
|
345
|
+
* Copy data from another table. Specs must match.
|
|
346
|
+
* NOTE: does not send onAdded signal
|
|
347
|
+
* @param {RowFirstTable} other
|
|
348
|
+
*/
|
|
349
|
+
copy(other) {
|
|
350
|
+
// check that the spec is equivalent
|
|
351
|
+
if (!this.spec.equals(other.spec)) {
|
|
352
|
+
throw new Error('Different table specs');
|
|
353
|
+
}
|
|
336
354
|
|
|
337
|
-
|
|
338
|
-
addOne(i);
|
|
339
|
-
}
|
|
355
|
+
const record_count = other.length;
|
|
340
356
|
|
|
341
|
-
|
|
357
|
+
this.resize(record_count);
|
|
342
358
|
|
|
343
|
-
|
|
344
|
-
* Copy data from another table. Specs must match.
|
|
345
|
-
* NOTE: does not send onAdded signal
|
|
346
|
-
* @param {RowFirstTable} other
|
|
347
|
-
*/
|
|
348
|
-
RowFirstTable.prototype.copy = function (other) {
|
|
349
|
-
// check that the spec is equivalent
|
|
350
|
-
if (!this.spec.equals(other.spec)) {
|
|
351
|
-
throw new Error('Different table specs');
|
|
352
|
-
}
|
|
359
|
+
this.length = other.length;
|
|
353
360
|
|
|
354
|
-
|
|
361
|
+
const target = new Uint8Array(this.data);
|
|
362
|
+
const source = new Uint8Array(other.data);
|
|
355
363
|
|
|
356
|
-
|
|
364
|
+
// copy data
|
|
365
|
+
const data_byte_count = other.bytesPerRecord * record_count;
|
|
366
|
+
target.set(source.slice(0, data_byte_count));
|
|
357
367
|
|
|
358
|
-
|
|
368
|
+
// TODO consider if we should invoke onAdded signal
|
|
369
|
+
}
|
|
359
370
|
|
|
360
|
-
|
|
361
|
-
|
|
371
|
+
/**
|
|
372
|
+
* @param {RowFirstTable} other
|
|
373
|
+
* @returns {boolean}
|
|
374
|
+
*/
|
|
375
|
+
equals(other) {
|
|
376
|
+
if (!this.spec.equals(other.spec)) {
|
|
377
|
+
return false;
|
|
378
|
+
}
|
|
362
379
|
|
|
363
|
-
|
|
364
|
-
const data_byte_count = other.bytesPerRecord * record_count;
|
|
365
|
-
target.set(source.slice(0, data_byte_count));
|
|
380
|
+
const this_length = this.length;
|
|
366
381
|
|
|
367
|
-
|
|
368
|
-
|
|
382
|
+
if (this_length !== other.length) {
|
|
383
|
+
return false;
|
|
384
|
+
}
|
|
369
385
|
|
|
386
|
+
const total_bytes = this_length * this.bytesPerRecord;
|
|
370
387
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
*/
|
|
375
|
-
RowFirstTable.prototype.equals = function (other) {
|
|
376
|
-
if (!this.spec.equals(other.spec)) {
|
|
377
|
-
return false;
|
|
378
|
-
}
|
|
388
|
+
for (let i = 0; i < total_bytes; i++) {
|
|
389
|
+
const a = this.dataView.getUint8(i);
|
|
390
|
+
const b = other.dataView.getUint8(i);
|
|
379
391
|
|
|
380
|
-
|
|
392
|
+
if (a !== b) {
|
|
393
|
+
return false;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
381
396
|
|
|
382
|
-
|
|
383
|
-
return false;
|
|
397
|
+
return true;
|
|
384
398
|
}
|
|
385
399
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
return false;
|
|
394
|
-
}
|
|
400
|
+
/**
|
|
401
|
+
*
|
|
402
|
+
* @param {int} index
|
|
403
|
+
* @param {Array} result where row values are to be stored
|
|
404
|
+
*/
|
|
405
|
+
getRow(index, result) {
|
|
406
|
+
this.readRowMethod(this.dataView, this.bytesPerRecord * index, result);
|
|
395
407
|
}
|
|
396
408
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
*
|
|
404
|
-
|
|
405
|
-
RowFirstTable.prototype.getRow = function (index, result) {
|
|
406
|
-
this.readRowMethod(this.dataView, this.bytesPerRecord * index, result);
|
|
407
|
-
};
|
|
409
|
+
/**
|
|
410
|
+
*
|
|
411
|
+
* @param {number} index
|
|
412
|
+
* @param {number[]} record
|
|
413
|
+
*/
|
|
414
|
+
setRow(index, record) {
|
|
415
|
+
this.writeRowMethod(this.dataView, this.bytesPerRecord * index, record);
|
|
416
|
+
}
|
|
408
417
|
|
|
409
|
-
/**
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
this.writeRowMethod(this.dataView, this.bytesPerRecord * index, record);
|
|
416
|
-
}
|
|
418
|
+
/**
|
|
419
|
+
* Reverse order of rows, row-0 will end up at and previously last row will become the first row etc.
|
|
420
|
+
*/
|
|
421
|
+
reverse_rows() {
|
|
422
|
+
const bpr = this.bytesPerRecord;
|
|
423
|
+
const copy_buffer = new Uint8Array(bpr);
|
|
417
424
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
*/
|
|
421
|
-
RowFirstTable.prototype.reverse_rows = function () {
|
|
422
|
-
const bpr = this.bytesPerRecord;
|
|
423
|
-
const copy_buffer = new Uint8Array(bpr);
|
|
425
|
+
const buffer = this.data;
|
|
426
|
+
const wrapper = new Uint8Array(buffer);
|
|
424
427
|
|
|
425
|
-
|
|
426
|
-
const wrapper = new Uint8Array(buffer);
|
|
428
|
+
const length = this.length;
|
|
427
429
|
|
|
428
|
-
|
|
430
|
+
if (length <= 1) {
|
|
431
|
+
// need at least 2 rows for reversal to make any change
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
429
434
|
|
|
430
|
-
|
|
431
|
-
// need at least 2 rows for reversal to make any change
|
|
432
|
-
return;
|
|
433
|
-
}
|
|
435
|
+
const last_row_index = length - 1;
|
|
434
436
|
|
|
435
|
-
const last_row_index = length - 1;
|
|
436
437
|
|
|
438
|
+
const traversal_limit = last_row_index >>> 1;
|
|
439
|
+
for (let i = 0; i <= traversal_limit; i++) {
|
|
440
|
+
const address = i * bpr;
|
|
441
|
+
array_copy(wrapper, address, copy_buffer, 0, bpr);
|
|
437
442
|
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
const address = i * bpr;
|
|
441
|
-
array_copy(wrapper, address, copy_buffer, 0, bpr);
|
|
443
|
+
const swap_index = last_row_index - i;
|
|
444
|
+
const swap_address = swap_index * bpr;
|
|
442
445
|
|
|
443
|
-
|
|
444
|
-
|
|
446
|
+
wrapper.copyWithin(address, swap_address, swap_address + bpr)
|
|
447
|
+
wrapper.set(copy_buffer, swap_address);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
445
450
|
|
|
446
|
-
|
|
447
|
-
|
|
451
|
+
/**
|
|
452
|
+
* clear out all the data and free memory
|
|
453
|
+
*/
|
|
454
|
+
clear() {
|
|
455
|
+
//clear out data
|
|
456
|
+
this.length = 0;
|
|
457
|
+
this.setCapacity(0);
|
|
448
458
|
}
|
|
449
|
-
};
|
|
450
459
|
|
|
451
|
-
/**
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
};
|
|
460
|
+
/**
|
|
461
|
+
*
|
|
462
|
+
* @returns {Number}
|
|
463
|
+
*/
|
|
464
|
+
getNumColumns() {
|
|
465
|
+
return this.types.length;
|
|
466
|
+
}
|
|
459
467
|
|
|
468
|
+
/**
|
|
469
|
+
*
|
|
470
|
+
* @returns {number[][]}
|
|
471
|
+
*/
|
|
472
|
+
toRowArray() {
|
|
460
473
|
|
|
461
|
-
|
|
462
|
-
*
|
|
463
|
-
* @returns {Number}
|
|
464
|
-
*/
|
|
465
|
-
RowFirstTable.prototype.getNumColumns = function () {
|
|
466
|
-
return this.types.length;
|
|
467
|
-
};
|
|
474
|
+
const result = [];
|
|
468
475
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
* @returns {number[][]}
|
|
472
|
-
*/
|
|
473
|
-
RowFirstTable.prototype.toRowArray = function () {
|
|
476
|
+
for (let i = 0; i < this.length; i++) {
|
|
477
|
+
const row = [];
|
|
474
478
|
|
|
475
|
-
|
|
479
|
+
this.getRow(i, row);
|
|
476
480
|
|
|
477
|
-
|
|
478
|
-
|
|
481
|
+
result.push(row);
|
|
482
|
+
}
|
|
479
483
|
|
|
480
|
-
|
|
484
|
+
return result;
|
|
481
485
|
|
|
482
|
-
result.push(row);
|
|
483
486
|
}
|
|
484
487
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
* Print the table to console
|
|
491
|
-
*/
|
|
492
|
-
RowFirstTable.prototype.printToConsole = function () {
|
|
493
|
-
const rows = this.toRowArray();
|
|
494
|
-
|
|
495
|
-
console.table(rows);
|
|
496
|
-
};
|
|
488
|
+
/**
|
|
489
|
+
* Print the table to console
|
|
490
|
+
*/
|
|
491
|
+
printToConsole() {
|
|
492
|
+
const rows = this.toRowArray();
|
|
497
493
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
}
|
|
494
|
+
console.table(rows);
|
|
495
|
+
}
|
|
496
|
+
}
|