@woosh/meep-engine 2.49.6 → 2.49.8
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/cache/LoadingCache.d.ts +2 -0
- package/src/core/cache/LoadingCache.js +45 -18
- 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/computeGreatestCommonDivisor.spec.js +9 -0
- package/src/core/math/statistics/computeStatisticalMean.spec.js +9 -0
- package/src/core/math/statistics/halton_sequence.spec.js +6 -1
- package/src/core/model/node-graph/node/Port.spec.js +10 -1
- package/src/core/model/reactive/evaluation/MultiPredicateEvaluator.js +5 -8
- package/src/core/model/reactive/evaluation/MultiPredicateEvaluator.spec.js +41 -0
- package/src/core/model/reactive/trigger/BlackboardTrigger.js +5 -0
- package/src/core/model/reactive/trigger/BlackboardTrigger.spec.js +24 -0
- package/src/core/parser/simple/readBooleanToken.js +38 -0
- package/src/core/parser/simple/readHexToken.js +95 -0
- package/src/core/parser/simple/readHexToken.spec.js +21 -0
- package/src/core/parser/simple/readIdentifierToken.js +43 -0
- package/src/core/parser/simple/readIdentifierToken.spec.js +32 -0
- package/src/core/parser/simple/readLiteralToken.js +96 -0
- package/src/core/parser/simple/readNumberToken.js +73 -0
- package/src/core/parser/simple/readNumberToken.spec.js +17 -0
- package/src/core/parser/simple/readReferenceToken.js +48 -0
- package/src/core/parser/simple/readReferenceToken.spec.js +18 -0
- package/src/core/parser/simple/readStringToken.js +94 -0
- package/src/core/parser/simple/readStringToken.spec.js +57 -0
- package/src/core/parser/simple/{readUnsignedInteger.js → readUnsignedIntegerToken.js} +1 -1
- package/src/core/parser/simple/readUnsignedIntegerToken.spec.js +6 -0
- package/src/core/process/executor/ConcurrentExecutor.js +147 -234
- 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/graphics/GraphicsEngine.js +2 -13
- package/src/engine/graphics/ecs/compileAllMaterials.js +1 -1
- package/src/engine/graphics/ecs/mesh/createTaskWaitForMeshesToLoad.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 +2 -4
- package/src/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +1 -1
- package/src/engine/graphics/render/forward_plus/prototype/prototypeLightManager.js +1 -1
- package/src/engine/graphics/render/visibility/hiz/prototypeHiZ.js +2 -4
- 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/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/intelligence/blackboard/Blackboard.d.ts +4 -0
- package/src/engine/intelligence/blackboard/Blackboard.js +11 -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/grid/generation/road/GridTaskGenerateRoads.js +2 -2
- package/src/view/tooltip/gml/parser/readReferenceValueToken.js +2 -2
- package/src/core/parser/simple/SimpleParser.js +0 -464
- package/src/core/parser/simple/SimpleParser.spec.js +0 -105
- /package/src/core/collection/{IteratorUtils.js → collectIteratorValueToArray.js} +0 -0
- /package/src/core/color/{ColorUtils.js → parseColor.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
|
|
@@ -18,6 +18,10 @@ class Record {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
function current_time_in_seconds() {
|
|
22
|
+
return performance.now() * 1e-3;
|
|
23
|
+
}
|
|
24
|
+
|
|
21
25
|
const DEFAULT_TIME_TO_LIVE = 10;
|
|
22
26
|
|
|
23
27
|
/**
|
|
@@ -98,13 +102,52 @@ export class LoadingCache {
|
|
|
98
102
|
this.#internal.clear();
|
|
99
103
|
}
|
|
100
104
|
|
|
105
|
+
/**
|
|
106
|
+
*
|
|
107
|
+
* @param {K} key
|
|
108
|
+
* @param {number} timestamp
|
|
109
|
+
* @return {Record<Promise<V>>}
|
|
110
|
+
*/
|
|
111
|
+
#load_value(key, timestamp) {
|
|
112
|
+
|
|
113
|
+
let promise;
|
|
114
|
+
|
|
115
|
+
try {
|
|
116
|
+
promise = this.#load(key);
|
|
117
|
+
} catch (e) {
|
|
118
|
+
promise = Promise.reject(e);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const record = new Record(promise, timestamp);
|
|
122
|
+
|
|
123
|
+
this.#internal.put(key, record);
|
|
124
|
+
|
|
125
|
+
promise.catch(() => {
|
|
126
|
+
// mark as failure
|
|
127
|
+
record.failed = true;
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
return record;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Load new value for the key (happens asynchronously)
|
|
135
|
+
* @param {K} key
|
|
136
|
+
* @returns {Promise<V>}
|
|
137
|
+
*/
|
|
138
|
+
refresh(key) {
|
|
139
|
+
const record = this.#load_value(key, current_time_in_seconds());
|
|
140
|
+
|
|
141
|
+
return record.value;
|
|
142
|
+
}
|
|
143
|
+
|
|
101
144
|
/**
|
|
102
145
|
*
|
|
103
146
|
* @param {K} key
|
|
104
147
|
* @return {Promise<V>}
|
|
105
148
|
*/
|
|
106
149
|
async get(key) {
|
|
107
|
-
const currentTime =
|
|
150
|
+
const currentTime = current_time_in_seconds();
|
|
108
151
|
|
|
109
152
|
/**
|
|
110
153
|
*
|
|
@@ -118,23 +161,7 @@ export class LoadingCache {
|
|
|
118
161
|
) {
|
|
119
162
|
|
|
120
163
|
// record needs to be loaded
|
|
121
|
-
|
|
122
|
-
let promise;
|
|
123
|
-
|
|
124
|
-
try {
|
|
125
|
-
promise = this.#load(key);
|
|
126
|
-
}catch (e){
|
|
127
|
-
promise = Promise.reject(e);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
record = new Record(promise, currentTime);
|
|
131
|
-
|
|
132
|
-
this.#internal.put(key, record);
|
|
133
|
-
|
|
134
|
-
promise.catch(() => {
|
|
135
|
-
// mark as failure
|
|
136
|
-
record.failed = true;
|
|
137
|
-
});
|
|
164
|
+
record = this.#load_value(key, currentTime);
|
|
138
165
|
|
|
139
166
|
}
|
|
140
167
|
|
|
@@ -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
|
+
});
|