@woosh/meep-engine 2.49.7 → 2.49.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/editor/enableEditor.js +1 -8
- package/package.json +1 -1
- package/samples/terrain/editor.js +2 -2
- package/src/core/cache/Cache.js +1 -1
- package/src/core/collection/HashSet.js +1 -1
- package/src/core/collection/table/RowFirstTableSpec.js +110 -92
- package/src/core/collection/table/RowFirstTableSpec.spec.js +49 -0
- package/src/core/color/Color.d.ts +4 -2
- package/src/core/color/Color.js +7 -8
- package/src/core/color/Color.spec.js +93 -0
- package/src/core/color/hex2rgb.spec.js +10 -0
- package/src/core/color/rgb2hex.js +1 -1
- package/src/core/color/rgb2hex.spec.js +13 -0
- package/src/core/fsm/simple/SimpleStateMachine.spec.js +75 -0
- package/src/core/fsm/simple/SimpleStateMachineDescription.js +1 -1
- package/src/core/fsm/simple/SimpleStateMachineDescription.spec.js +32 -0
- package/src/core/geom/2d/Rectangle.spec.js +51 -0
- package/src/core/geom/3d/aabb/aabb3_intersects_ray.spec.js +90 -0
- package/src/core/geom/3d/line/line3_compute_nearest_point_to_point.spec.js +61 -0
- package/src/core/geom/3d/morton/mortonEncode_magicbits.js +1 -34
- package/src/core/geom/3d/morton/split_by_2.js +17 -0
- package/src/core/geom/3d/morton/split_by_3.js +16 -0
- package/src/core/geom/3d/plane/computePlaneLineIntersection.js +6 -1
- package/src/core/geom/3d/sphere/sphere_intersects_ray.spec.js +11 -0
- package/src/core/geom/3d/sphere/sphere_radius_sqr_from_v3_array_transformed.spec.js +8 -0
- package/src/core/geom/3d/topology/samples/sampleFloodFill.js +3 -3
- package/src/core/geom/3d/topology/struct/binary/io/OrderedEdge.js +1 -1
- package/src/core/geom/random/randomPointOnBox.spec.js +57 -0
- package/src/core/math/bessel_i0.spec.js +43 -0
- package/src/core/math/bessel_j0.js +30 -0
- package/src/core/math/hash/murmur3_32.spec.js +8 -0
- package/src/core/math/hash/squirrel3.spec.js +16 -0
- package/src/core/math/interval/NumericInterval.js +1 -0
- package/src/core/math/{bessel_i0.js → modified_bessel_i0.js} +5 -2
- package/src/core/math/noise/{create_noise_2d.js → create_simplex_noise_2d.js} +2 -2
- package/src/core/math/noise/create_simplex_noise_2d.spec.js +21 -0
- package/src/core/math/normalizeArrayVector.spec.js +15 -0
- package/src/core/math/physics/irradiance/interpolate_irradiance_linear.spec.js +20 -0
- package/src/core/math/physics/irradiance/interpolate_irradiance_lograrithmic.js +4 -4
- package/src/core/math/physics/irradiance/interpolate_irradiance_lograrithmic.spec.js +18 -0
- package/src/core/math/physics/irradiance/interpolate_irradiance_smith.js +1 -1
- package/src/core/math/physics/irradiance/interpolate_irradiance_smith.spec.js +20 -0
- package/src/core/math/random/seededRandomMersenneTwister.spec.js +10 -0
- package/src/core/math/spline/spline_bezier3.js +1 -1
- package/src/core/math/spline/spline_bezier3_bounds.js +2 -1
- package/src/core/math/spline/spline_bezier3_bounds.spec.js +37 -0
- package/src/core/math/statistics/computeSampleSize_Cochran.spec.js +12 -0
- package/src/core/math/statistics/computeStatisticalPartialMedian.js +4 -0
- package/src/core/math/statistics/computeStatisticalPartialMedian.spec.js +13 -0
- package/src/engine/Engine.d.ts +4 -2
- package/src/engine/Engine.js +62 -41
- package/src/engine/Engine.spec.js +11 -0
- package/src/engine/InputEngine.js +12 -0
- package/src/engine/achievements/Achievement.spec.js +21 -0
- package/src/engine/animation/curve/compression/prototypeCurveCompression.js +2 -2
- package/src/engine/animation/curve/compression/{animation_curve_to_float_array.js → sample_animation_curve_to_float_array.js} +10 -3
- package/src/engine/animation/curve/compression/sample_animation_curve_to_float_array.spec.js +29 -0
- package/src/engine/animation/curve/draw/build_curve_editor.js +3 -3
- package/src/engine/development/performance/RingBufferMetric.js +1 -1
- package/src/engine/ecs/animation/Animation.js +2 -180
- package/src/engine/ecs/animation/AnimationClip.js +132 -0
- package/src/engine/ecs/animation/AnimationClip.spec.js +5 -0
- package/src/engine/ecs/animation/AnimationClipFlag.js +7 -0
- package/src/engine/ecs/animation/AnimationFlags.js +8 -0
- package/src/engine/ecs/animation/AnimationSerializationAdapter.js +32 -0
- package/src/engine/ecs/systems/AnimationSystem.js +3 -1
- package/src/engine/graphics/GraphicsEngine.js +2 -13
- package/src/engine/graphics/camera/testClippingPlaneComputation.js +1 -1
- package/src/engine/graphics/ecs/animation/AnimationControllerSystem.js +2 -1
- package/src/engine/graphics/ecs/compileAllMaterials.js +1 -1
- package/src/engine/graphics/ecs/mesh/createTaskWaitForMeshesToLoad.js +1 -1
- package/src/engine/graphics/ecs/path/testPathDisplaySystem.js +1 -1
- package/src/engine/graphics/ecs/path/tube/prototypeAnimatedPathMask.js +1 -1
- package/src/engine/graphics/impostors/octahedral/ImpostorBaker.js +1 -1
- package/src/engine/graphics/load_and_set_cubemap_v0.js +21 -0
- package/src/engine/graphics/material/optimization/MaterialOptimizationContext.js +1 -1
- package/src/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +3 -5
- package/src/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +3 -5
- package/src/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +2 -2
- package/src/engine/graphics/render/forward_plus/prototype/prototypeLightManager.js +1 -1
- package/src/engine/graphics/render/visibility/hiz/prototypeHiZ.js +3 -5
- package/src/engine/graphics/sh3/prototypeSH3Probe.js +4 -4
- package/src/engine/graphics/texture/sampler/copy_Sampler2D_channel_data.js +4 -3
- package/src/engine/graphics/texture/sampler/filter/kaiser_1.js +8 -4
- package/src/engine/graphics/texture/sampler/filter/kaiser_bessel_window.js +2 -0
- package/src/engine/graphics/texture/virtual/VirtualTexture.js +9 -0
- package/src/engine/graphics/texture/virtual/VirtualTexture.spec.js +5 -4
- package/src/engine/graphics/texture/virtual/tile/TileLoader.js +5 -0
- package/src/engine/input/devices/PointerDevice.spec.js +7 -0
- package/src/engine/platform/InMemoryEnginePlatform.js +20 -0
- package/src/engine/save/Storage.d.ts +7 -7
- package/src/engine/save/storage/InMemoryStorage.js +34 -0
- package/src/generation/filtering/numeric/complex/CellFilterAngleToNormal.js +11 -4
- package/src/generation/filtering/numeric/complex/CellFilterAngleToNormal.spec.js +30 -0
- package/src/generation/filtering/numeric/complex/CellFilterGaussianBlur.js +18 -2
- package/src/generation/filtering/numeric/complex/CellFilterGaussianBlur.spec.js +17 -0
- package/src/generation/filtering/numeric/complex/CellFilterSimplexNoise.js +2 -2
- package/src/generation/grid/GridData.js +0 -60
- package/src/generation/grid/generation/road/GridTaskGenerateRoads.js +2 -2
- /package/src/core/collection/{IteratorUtils.js → collectIteratorValueToArray.js} +0 -0
- /package/src/core/color/{ColorUtils.js → parseColor.js} +0 -0
- /package/src/engine/ecs/{animation → ik}/IKMath.js +0 -0
- /package/src/engine/ecs/{animation → ik}/IKProblem.js +0 -0
- /package/src/engine/ecs/{animation → ik}/IKSolver.js +0 -0
- /package/src/engine/ecs/{animation → ik}/InverseKinematics.js +0 -0
- /package/src/engine/ecs/{animation → ik}/InverseKinematicsSystem.js +0 -0
- /package/src/engine/ecs/{animation → ik}/OneBoneSurfaceAlignmentSolver.js +0 -0
- /package/src/engine/ecs/{animation → ik}/TwoBoneInverseKinematicsSolver.js +0 -0
package/editor/enableEditor.js
CHANGED
|
@@ -61,14 +61,7 @@ export function enableEditor(engine, initialization = noop) {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
//bind key for toggling editor
|
|
64
|
-
engine.
|
|
65
|
-
on: function () {
|
|
66
|
-
toggleEditor();
|
|
67
|
-
},
|
|
68
|
-
off: function () {
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
});
|
|
64
|
+
engine.devices.keyboard.keys.num_lock.down.add(toggleEditor);
|
|
72
65
|
|
|
73
66
|
console.warn('Editor mode enabled, use NumLock key to toggle editor mode');
|
|
74
67
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { EngineHarness } from "../../src/engine/EngineHarness.js";
|
|
2
2
|
import EmptyView from "../../src/view/elements/EmptyView.js";
|
|
3
3
|
import { EngineConfiguration } from "../../src/engine/EngineConfiguration.js";
|
|
4
|
-
import { buildCubeURLs } from "../../src/engine/graphics/texture/cubemap/buildCubeURLs.js";
|
|
5
4
|
import { ArrayBufferLoader } from "../../src/engine/asset/loaders/ArrayBufferLoader.js";
|
|
6
5
|
import { TerrainFlags } from "../../src/engine/ecs/terrain/ecs/TerrainFlags.js";
|
|
7
6
|
import Signal from "../../src/core/events/signal/Signal.js";
|
|
@@ -22,6 +21,7 @@ import { copy_Sampler2D_channel_data } from "../../src/engine/graphics/texture/s
|
|
|
22
21
|
import { TextureAssetLoader } from "../../src/engine/asset/loaders/texture/TextureAssetLoader.js";
|
|
23
22
|
import { CanvasView } from "../../src/view/elements/CanvasView.js";
|
|
24
23
|
import convertSampler2D2Canvas from "../../src/engine/graphics/texture/sampler/Sampler2D2Canvas.js";
|
|
24
|
+
import { load_and_set_cubemap_v0 } from "../../src/engine/graphics/load_and_set_cubemap_v0.js";
|
|
25
25
|
|
|
26
26
|
const engineHarness = new EngineHarness();
|
|
27
27
|
|
|
@@ -338,7 +338,7 @@ async function init(harness) {
|
|
|
338
338
|
|
|
339
339
|
await makeConfig(engine).apply(engine);
|
|
340
340
|
|
|
341
|
-
await engine.graphics
|
|
341
|
+
await load_and_set_cubemap_v0(engine.graphics, 'data/textures/cubemaps/hip_miramar/32/', '.png');
|
|
342
342
|
|
|
343
343
|
await harness.initialize();
|
|
344
344
|
|
package/src/core/cache/Cache.js
CHANGED
|
@@ -3,7 +3,7 @@ import { HashMap } from "../collection/HashMap.js";
|
|
|
3
3
|
import Signal from "../events/signal/Signal.js";
|
|
4
4
|
import { returnOne, returnZero, strictEquals } from "../function/Functions.js";
|
|
5
5
|
import { CacheElement } from "./CacheElement.js";
|
|
6
|
-
import { collectIteratorValueToArray } from "../collection/
|
|
6
|
+
import { collectIteratorValueToArray } from "../collection/collectIteratorValueToArray.js";
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Hash-based cache, uses LRU (least-recently-used) eviction policy
|
|
@@ -10,6 +10,7 @@ import { isArrayEqualStrict } from "../array/isArrayEqualStrict.js";
|
|
|
10
10
|
import { BinaryDataType } from "../../binary/type/BinaryDataType.js";
|
|
11
11
|
import { DataTypeByteSizes } from "../../binary/type/DataTypeByteSizes.js";
|
|
12
12
|
import { assert } from "../../assert.js";
|
|
13
|
+
import { computeHashArray } from "../array/computeHashArray.js";
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* @readonly
|
|
@@ -152,123 +153,140 @@ function genCellReader(type, offset, endianType = EndianType.BigEndian) {
|
|
|
152
153
|
});
|
|
153
154
|
}
|
|
154
155
|
|
|
155
|
-
|
|
156
|
-
*
|
|
157
|
-
* @param {BinaryDataType[]} types
|
|
158
|
-
* @param {EndianType} [endianType]
|
|
159
|
-
* @constructor
|
|
160
|
-
*/
|
|
161
|
-
export function RowFirstTableSpec(types, endianType = EndianType.BigEndian) {
|
|
162
|
-
assert.isArray(types, 'types');
|
|
163
|
-
|
|
164
|
-
const numTypes = types.length;
|
|
165
|
-
|
|
156
|
+
export class RowFirstTableSpec {
|
|
166
157
|
/**
|
|
167
|
-
*
|
|
168
|
-
* @
|
|
158
|
+
*
|
|
159
|
+
* @param {BinaryDataType[]} types
|
|
160
|
+
* @param {EndianType} [endianType]
|
|
161
|
+
* @constructor
|
|
169
162
|
*/
|
|
170
|
-
|
|
163
|
+
constructor(types, endianType = EndianType.BigEndian) {
|
|
164
|
+
assert.isArray(types, 'types');
|
|
171
165
|
|
|
172
|
-
|
|
173
|
-
* @readonly
|
|
174
|
-
* @type {EndianType}
|
|
175
|
-
*/
|
|
176
|
-
this.endianType = endianType;
|
|
166
|
+
const numTypes = types.length;
|
|
177
167
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
let byteOffset = 0;
|
|
184
|
-
types.forEach((type, index) => {
|
|
185
|
-
this.columnOffsets[index] = byteOffset;
|
|
168
|
+
/**
|
|
169
|
+
* @readonly
|
|
170
|
+
* @type {BinaryDataType[]}
|
|
171
|
+
*/
|
|
172
|
+
this.types = types;
|
|
186
173
|
|
|
187
|
-
|
|
174
|
+
/**
|
|
175
|
+
* @readonly
|
|
176
|
+
* @type {EndianType}
|
|
177
|
+
*/
|
|
178
|
+
this.endianType = endianType;
|
|
188
179
|
|
|
189
|
-
|
|
190
|
-
|
|
180
|
+
/**
|
|
181
|
+
* @readonly
|
|
182
|
+
* @type {number[]}
|
|
183
|
+
*/
|
|
184
|
+
this.columnOffsets = new Uint32Array(numTypes);
|
|
191
185
|
|
|
186
|
+
let byteOffset = 0;
|
|
192
187
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
188
|
+
for (let index = 0; index < numTypes; index++) {
|
|
189
|
+
const type = types[index];
|
|
190
|
+
this.columnOffsets[index] = byteOffset;
|
|
191
|
+
|
|
192
|
+
const columnByteSize = DataTypeByteSizes[type];
|
|
193
|
+
|
|
194
|
+
byteOffset += columnByteSize;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* @readonly
|
|
200
|
+
* @type {number}
|
|
201
|
+
*/
|
|
202
|
+
this.bytesPerRecord = byteOffset;
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* @readonly
|
|
206
|
+
* @type {function(DataView, number, number[]): void}
|
|
207
|
+
*/
|
|
208
|
+
this.readRowMethod = genRowReader(types, endianType);
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* @readonly
|
|
212
|
+
* @type {function(DataView, number, number[]): void}
|
|
213
|
+
*/
|
|
214
|
+
this.writeRowMethod = genRowWriter(types, endianType);
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
//generate cell readers/writers
|
|
218
|
+
this.cellWriters = new Array(numTypes);
|
|
219
|
+
this.cellReaders = new Array(numTypes);
|
|
220
|
+
|
|
221
|
+
for (let i = 0; i < numTypes; i++) {
|
|
222
|
+
this.cellReaders[i] = genCellReader(types[i], this.columnOffsets[i], endianType);
|
|
223
|
+
this.cellWriters[i] = genCellWriter(types[i], this.columnOffsets[i], endianType);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* @readonly
|
|
227
|
+
* @type {boolean}
|
|
228
|
+
*/
|
|
229
|
+
this.isRowFirstTableSpec = true;
|
|
230
|
+
}
|
|
198
231
|
|
|
199
232
|
/**
|
|
200
|
-
*
|
|
201
|
-
* @
|
|
233
|
+
*
|
|
234
|
+
* @return {number}
|
|
202
235
|
*/
|
|
203
|
-
|
|
236
|
+
getColumnCount() {
|
|
237
|
+
return this.types.length;
|
|
238
|
+
}
|
|
204
239
|
|
|
205
240
|
/**
|
|
206
|
-
*
|
|
207
|
-
* @
|
|
241
|
+
*
|
|
242
|
+
* @return {number}
|
|
208
243
|
*/
|
|
209
|
-
|
|
244
|
+
hash() {
|
|
245
|
+
let hash = this.endianType === EndianType.BigEndian ? 1 : 0;
|
|
210
246
|
|
|
247
|
+
hash += computeHashArray(this.types, computeStringHash);
|
|
211
248
|
|
|
212
|
-
|
|
213
|
-
this.cellWriters = new Array(numTypes);
|
|
214
|
-
this.cellReaders = new Array(numTypes);
|
|
215
|
-
|
|
216
|
-
for (let i = 0; i < numTypes; i++) {
|
|
217
|
-
this.cellReaders[i] = genCellReader(types[i], this.columnOffsets[i], endianType);
|
|
218
|
-
this.cellWriters[i] = genCellWriter(types[i], this.columnOffsets[i], endianType);
|
|
249
|
+
return hash;
|
|
219
250
|
}
|
|
220
|
-
}
|
|
221
251
|
|
|
222
|
-
/**
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
252
|
+
/**
|
|
253
|
+
*
|
|
254
|
+
* @param {RowFirstTableSpec} other
|
|
255
|
+
* @returns {boolean}
|
|
256
|
+
*/
|
|
257
|
+
equals(other) {
|
|
258
|
+
if (this.endianType !== other.endianType) {
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
229
261
|
|
|
230
|
-
|
|
231
|
-
*
|
|
232
|
-
* @param {RowFirstTableSpec} other
|
|
233
|
-
* @returns {boolean}
|
|
234
|
-
*/
|
|
235
|
-
RowFirstTableSpec.prototype.equals = function (other) {
|
|
236
|
-
if (this.endianType !== other.endianType) {
|
|
237
|
-
return false;
|
|
262
|
+
return isArrayEqualStrict(this.types, other.types);
|
|
238
263
|
}
|
|
239
264
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
265
|
+
/**
|
|
266
|
+
*
|
|
267
|
+
* @param {BinaryDataType[]} types
|
|
268
|
+
* @param {EndianType} [endianType]
|
|
269
|
+
* @returns {RowFirstTableSpec}
|
|
270
|
+
*/
|
|
271
|
+
static get(types, endianType = EndianType.BigEndian) {
|
|
272
|
+
//compute hash
|
|
273
|
+
const hash = types.join('.') + ':' + endianType;
|
|
249
274
|
|
|
250
|
-
const
|
|
251
|
-
keyHashFunction: computeStringHash
|
|
252
|
-
});
|
|
275
|
+
const cachedValue = cache.get(hash);
|
|
253
276
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
* @param {EndianType} [endianType]
|
|
258
|
-
* @returns {RowFirstTableSpec}
|
|
259
|
-
*/
|
|
260
|
-
RowFirstTableSpec.get = function (types, endianType = EndianType.BigEndian) {
|
|
261
|
-
//compute hash
|
|
262
|
-
const hash = types.join('.') + ':' + endianType;
|
|
277
|
+
if (cachedValue !== null) {
|
|
278
|
+
return cachedValue;
|
|
279
|
+
}
|
|
263
280
|
|
|
264
|
-
|
|
281
|
+
const newValue = new RowFirstTableSpec(types);
|
|
282
|
+
cache.put(hash, newValue);
|
|
265
283
|
|
|
266
|
-
|
|
267
|
-
return cachedValue;
|
|
284
|
+
return newValue;
|
|
268
285
|
}
|
|
286
|
+
}
|
|
269
287
|
|
|
270
|
-
const newValue = new RowFirstTableSpec(types);
|
|
271
|
-
cache.put(hash, newValue);
|
|
272
288
|
|
|
273
|
-
|
|
274
|
-
|
|
289
|
+
const cache = new Cache({
|
|
290
|
+
keyHashFunction: computeStringHash
|
|
291
|
+
});
|
|
292
|
+
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { RowFirstTableSpec } from "./RowFirstTableSpec.js";
|
|
2
|
+
import { BinaryDataType } from "../../binary/type/BinaryDataType.js";
|
|
3
|
+
import { EndianType } from "../../binary/BinaryBuffer.js";
|
|
4
|
+
|
|
5
|
+
test("constructor with 1 column does not throw", () => {
|
|
6
|
+
expect(() => new RowFirstTableSpec([BinaryDataType.Float32])).not.toThrow();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
test("hash produced a valid value", () => {
|
|
10
|
+
const spec = new RowFirstTableSpec([BinaryDataType.Float32]);
|
|
11
|
+
|
|
12
|
+
const hash = spec.hash();
|
|
13
|
+
|
|
14
|
+
expect(typeof hash).toBe("number");
|
|
15
|
+
expect(hash).not.toBeNaN();
|
|
16
|
+
expect(Number.isInteger(hash)).toBe(true);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test("hash is stable", () => {
|
|
20
|
+
|
|
21
|
+
const spec = new RowFirstTableSpec([BinaryDataType.Float32]);
|
|
22
|
+
|
|
23
|
+
expect(spec.hash()).toEqual(spec.hash());
|
|
24
|
+
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test("hashes of identical specs must match", () => {
|
|
28
|
+
const a = new RowFirstTableSpec([BinaryDataType.Float32]);
|
|
29
|
+
const b = new RowFirstTableSpec([BinaryDataType.Float32]);
|
|
30
|
+
|
|
31
|
+
expect(a.hash()).toEqual(b.hash());
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test("equals", () => {
|
|
35
|
+
const a = new RowFirstTableSpec([BinaryDataType.Float32, BinaryDataType.Uint8], EndianType.BigEndian);
|
|
36
|
+
const b = new RowFirstTableSpec([BinaryDataType.Float32, BinaryDataType.Uint8], EndianType.BigEndian);
|
|
37
|
+
|
|
38
|
+
const c = new RowFirstTableSpec([BinaryDataType.Uint8, BinaryDataType.Float32], EndianType.BigEndian);
|
|
39
|
+
|
|
40
|
+
const d = new RowFirstTableSpec([BinaryDataType.Float32, BinaryDataType.Uint8], EndianType.LittleEndian);
|
|
41
|
+
|
|
42
|
+
expect(a.equals(a)).toBe(true);
|
|
43
|
+
expect(a.equals(b)).toBe(true);
|
|
44
|
+
|
|
45
|
+
expect(a.equals(c)).toBe(false);
|
|
46
|
+
expect(c.equals(a)).toBe(false);
|
|
47
|
+
|
|
48
|
+
expect(a.equals(d)).toBe(false);
|
|
49
|
+
});
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import Signal from "../events/signal/Signal";
|
|
2
2
|
|
|
3
3
|
export class Color {
|
|
4
|
-
constructor(r?: number, g?: number, b?: number,a?:number)
|
|
4
|
+
constructor(r?: number, g?: number, b?: number, a?: number)
|
|
5
5
|
|
|
6
6
|
r: number
|
|
7
7
|
g: number
|
|
8
8
|
b: number
|
|
9
|
-
a:number
|
|
9
|
+
a: number
|
|
10
10
|
|
|
11
11
|
readonly onChanged: Signal<number, number, number, number, number, number>
|
|
12
12
|
|
|
@@ -14,6 +14,8 @@ export class Color {
|
|
|
14
14
|
|
|
15
15
|
setRGB(r: number, g: number, b: number): void
|
|
16
16
|
|
|
17
|
+
setA(a: number): void
|
|
18
|
+
|
|
17
19
|
setHSL(h: number, s: number, l: number): void
|
|
18
20
|
|
|
19
21
|
setHCL(h: number, c: number, l: number): void
|
package/src/core/color/Color.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { assert } from "../assert.js";
|
|
2
2
|
import Signal from "../events/signal/Signal.js";
|
|
3
|
-
import { parseColor } from "./
|
|
3
|
+
import { parseColor } from "./parseColor.js";
|
|
4
4
|
import { min2 } from "../math/min2.js";
|
|
5
5
|
import { max2 } from "../math/max2.js";
|
|
6
6
|
import { min3 } from "../math/min3.js";
|
|
7
|
-
import { computeHashIntegerArray } from "../collection/array/computeHashIntegerArray.js";
|
|
8
|
-
import { computeHashFloat } from "../primitives/numbers/computeHashFloat.js";
|
|
9
7
|
import { rgb2hsv } from "./rgb2hsv.js";
|
|
10
8
|
import { rgb2uint24 } from "./rgb2uint24.js";
|
|
11
9
|
import { clamp01 } from "../math/clamp01.js";
|
|
@@ -156,6 +154,11 @@ export class Color {
|
|
|
156
154
|
assert.isNumber(b, 'b');
|
|
157
155
|
assert.isNumber(a, 'a');
|
|
158
156
|
|
|
157
|
+
assert.notNaN(r, 'r');
|
|
158
|
+
assert.notNaN(g, 'g');
|
|
159
|
+
assert.notNaN(b, 'b');
|
|
160
|
+
assert.notNaN(a, 'a');
|
|
161
|
+
|
|
159
162
|
const _r = this.r;
|
|
160
163
|
const _g = this.g;
|
|
161
164
|
const _b = this.b;
|
|
@@ -462,11 +465,7 @@ export class Color {
|
|
|
462
465
|
* @returns {number}
|
|
463
466
|
*/
|
|
464
467
|
hash() {
|
|
465
|
-
return
|
|
466
|
-
computeHashFloat(this.r),
|
|
467
|
-
computeHashFloat(this.g),
|
|
468
|
-
computeHashFloat(this.b)
|
|
469
|
-
);
|
|
468
|
+
return this.toUint();
|
|
470
469
|
}
|
|
471
470
|
|
|
472
471
|
fromJSON({ r, g, b, a = 1 }) {
|
|
@@ -53,3 +53,96 @@ test("setHSV white", () => {
|
|
|
53
53
|
expect(c.g).toBeCloseTo(1);
|
|
54
54
|
expect(c.b).toBeCloseTo(1);
|
|
55
55
|
});
|
|
56
|
+
|
|
57
|
+
test("setA sets alpha nd invokes 'onChanged' signal", () => {
|
|
58
|
+
const c = new Color();
|
|
59
|
+
|
|
60
|
+
const mock = jest.fn();
|
|
61
|
+
|
|
62
|
+
c.onChanged.add(mock);
|
|
63
|
+
|
|
64
|
+
c.setA(0.7);
|
|
65
|
+
|
|
66
|
+
expect(c.a).toBe(0.7);
|
|
67
|
+
expect(mock).toHaveBeenCalledTimes(1);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test("equals", () => {
|
|
71
|
+
|
|
72
|
+
expect(new Color(0, 0, 0, 0).equals(new Color(0, 0, 0, 0)))
|
|
73
|
+
.toBe(true);
|
|
74
|
+
|
|
75
|
+
expect(new Color(0.1, 0.2, 0.3, 0.7).equals(new Color(0.1, 0.2, 0.3, 0.7)))
|
|
76
|
+
.toBe(true);
|
|
77
|
+
|
|
78
|
+
expect(new Color(0, 0, 0, 0).equals(new Color(0, 0, 0, 1)))
|
|
79
|
+
.toBe(false);
|
|
80
|
+
|
|
81
|
+
expect(new Color(0, 0, 0, 0).equals(new Color(0, 0, 1, 0)))
|
|
82
|
+
.toBe(false);
|
|
83
|
+
|
|
84
|
+
expect(new Color(0, 0, 0, 0).equals(new Color(0, 1, 0, 0)))
|
|
85
|
+
.toBe(false);
|
|
86
|
+
|
|
87
|
+
expect(new Color(0, 0, 0, 0).equals(new Color(1, 0, 0, 0)))
|
|
88
|
+
.toBe(false);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("hash is stable", () => {
|
|
92
|
+
expect(new Color(0.1, 0.3, 0.7, 0.11).hash())
|
|
93
|
+
.toEqual(new Color(0.1, 0.3, 0.7, 0.11).hash());
|
|
94
|
+
|
|
95
|
+
const c = new Color(0.1, 0.3, 0.7, 0.11);
|
|
96
|
+
|
|
97
|
+
expect(c.hash()).toEqual(c.hash());
|
|
98
|
+
|
|
99
|
+
const hash = c.hash();
|
|
100
|
+
|
|
101
|
+
expect(typeof hash).toEqual("number");
|
|
102
|
+
expect(Number.isInteger(hash)).toBe(true);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
test("toJSON", () => {
|
|
106
|
+
|
|
107
|
+
expect(new Color(0.1, 0.3, 0.7, 0.11).toJSON())
|
|
108
|
+
.toEqual({
|
|
109
|
+
r: 0.1,
|
|
110
|
+
g: 0.3,
|
|
111
|
+
b: 0.7,
|
|
112
|
+
a: 0.11
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test("fromJSON", () => {
|
|
118
|
+
const c = new Color();
|
|
119
|
+
|
|
120
|
+
c.fromJSON({
|
|
121
|
+
r: 0.1,
|
|
122
|
+
g: 0.3,
|
|
123
|
+
b: 0.7,
|
|
124
|
+
a: 0.11
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
expect(c.r).toBe(0.1);
|
|
128
|
+
expect(c.g).toBe(0.3);
|
|
129
|
+
expect(c.b).toBe(0.7);
|
|
130
|
+
expect(c.a).toBe(0.11);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
test("iterator", () => {
|
|
134
|
+
|
|
135
|
+
const color = new Color(0.1, 0.3, 0.7, 0.11);
|
|
136
|
+
|
|
137
|
+
const iterator = color[Symbol.iterator]();
|
|
138
|
+
|
|
139
|
+
expect(iterator.next().value).toBe(0.1)
|
|
140
|
+
expect(iterator.next().value).toBe(0.3)
|
|
141
|
+
expect(iterator.next().value).toBe(0.7)
|
|
142
|
+
expect(iterator.next().value).toBe(0.11)
|
|
143
|
+
|
|
144
|
+
const last = iterator.next();
|
|
145
|
+
|
|
146
|
+
expect(last.done).toBe(true)
|
|
147
|
+
expect(last.value).toBeUndefined()
|
|
148
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { rgb2hex } from "./rgb2hex.js";
|
|
2
|
+
|
|
3
|
+
test("white", () => {
|
|
4
|
+
expect(rgb2hex(255, 255, 255)).toBe("ffffff");
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
test("black", () => {
|
|
8
|
+
expect(rgb2hex(0, 0, 0)).toBe("000000");
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test("unique channel values", () => {
|
|
12
|
+
expect(rgb2hex(11, 3, 7)).toBe("0b0307");
|
|
13
|
+
});
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { SimpleStateMachine } from "./SimpleStateMachine.js";
|
|
2
|
+
import { SimpleStateMachineDescription } from "./SimpleStateMachineDescription.js";
|
|
3
|
+
|
|
4
|
+
test("constructor does not throw", () => {
|
|
5
|
+
const description = new SimpleStateMachineDescription();
|
|
6
|
+
|
|
7
|
+
expect(() => new SimpleStateMachine(description)).not.toThrow();
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
test("state entry event handler is fired as expected", () => {
|
|
12
|
+
|
|
13
|
+
const description = new SimpleStateMachineDescription();
|
|
14
|
+
|
|
15
|
+
const a = description.createState();
|
|
16
|
+
const b = description.createState();
|
|
17
|
+
|
|
18
|
+
description.createEdge(a, b);
|
|
19
|
+
|
|
20
|
+
const fsm = new SimpleStateMachine(description);
|
|
21
|
+
|
|
22
|
+
fsm.setState(a);
|
|
23
|
+
|
|
24
|
+
const entry_callback = jest.fn();
|
|
25
|
+
|
|
26
|
+
fsm.addEventHandlerStateEntry(b, entry_callback);
|
|
27
|
+
|
|
28
|
+
fsm.setState(b);
|
|
29
|
+
|
|
30
|
+
expect(entry_callback).toHaveBeenCalledTimes(1);
|
|
31
|
+
expect(entry_callback).toHaveBeenCalledWith(b, a);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test("state exit event handler is fired as expected", () => {
|
|
35
|
+
|
|
36
|
+
const description = new SimpleStateMachineDescription();
|
|
37
|
+
|
|
38
|
+
const a = description.createState();
|
|
39
|
+
const b = description.createState();
|
|
40
|
+
|
|
41
|
+
description.createEdge(a, b);
|
|
42
|
+
|
|
43
|
+
const fsm = new SimpleStateMachine(description);
|
|
44
|
+
|
|
45
|
+
fsm.setState(a);
|
|
46
|
+
|
|
47
|
+
const entry_callback = jest.fn();
|
|
48
|
+
|
|
49
|
+
fsm.addEventHandlerStateExit(a, entry_callback);
|
|
50
|
+
|
|
51
|
+
fsm.setState(b);
|
|
52
|
+
|
|
53
|
+
expect(entry_callback).toHaveBeenCalledTimes(1);
|
|
54
|
+
expect(entry_callback).toHaveBeenCalledWith(a, b);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test("'advance' moves us to the next state in the chain", () => {
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
const description = new SimpleStateMachineDescription();
|
|
61
|
+
|
|
62
|
+
const a = description.createState();
|
|
63
|
+
const b = description.createState();
|
|
64
|
+
|
|
65
|
+
description.createEdge(a, b);
|
|
66
|
+
|
|
67
|
+
const fsm = new SimpleStateMachine(description);
|
|
68
|
+
|
|
69
|
+
fsm.setState(a);
|
|
70
|
+
|
|
71
|
+
fsm.advance(0);
|
|
72
|
+
|
|
73
|
+
expect(fsm.getState()).toBe(b);
|
|
74
|
+
|
|
75
|
+
});
|
|
@@ -141,7 +141,7 @@ export class SimpleStateMachineDescription {
|
|
|
141
141
|
*
|
|
142
142
|
* @param {number} start
|
|
143
143
|
* @param {number} goal
|
|
144
|
-
* @returns {number[]}
|
|
144
|
+
* @returns {number[]|null}
|
|
145
145
|
*/
|
|
146
146
|
findPath(start, goal) {
|
|
147
147
|
assert.ok(this.stateExists(start), `start state ${start} doesn't exist`);
|
|
@@ -69,3 +69,35 @@ test('getIncomingStates', () => {
|
|
|
69
69
|
expect(smd.getIncomingStates(b)).toEqual([a]);
|
|
70
70
|
expect(smd.getIncomingStates(c)).toEqual([a]);
|
|
71
71
|
});
|
|
72
|
+
|
|
73
|
+
test('edgeExists', () => {
|
|
74
|
+
|
|
75
|
+
const smd = new SimpleStateMachineDescription();
|
|
76
|
+
|
|
77
|
+
const a = smd.createState();
|
|
78
|
+
const b = smd.createState();
|
|
79
|
+
|
|
80
|
+
expect(smd.edgeExists(a, b)).toBe(false);
|
|
81
|
+
expect(smd.edgeExists(b, a)).toBe(false);
|
|
82
|
+
|
|
83
|
+
smd.createEdge(a, b);
|
|
84
|
+
|
|
85
|
+
expect(smd.edgeExists(a, b)).toEqual(true);
|
|
86
|
+
expect(smd.edgeExists(b, a)).toEqual(false);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("findPath sanity check", () => {
|
|
90
|
+
|
|
91
|
+
const smd = new SimpleStateMachineDescription();
|
|
92
|
+
|
|
93
|
+
const a = smd.createState();
|
|
94
|
+
const b = smd.createState();
|
|
95
|
+
|
|
96
|
+
expect(smd.findPath(a, a)).toEqual([a]);
|
|
97
|
+
|
|
98
|
+
expect(smd.findPath(a, b)).toEqual(null);
|
|
99
|
+
|
|
100
|
+
smd.createEdge(a, b);
|
|
101
|
+
|
|
102
|
+
expect(smd.findPath(a, b)).toEqual([a, b]);
|
|
103
|
+
});
|