@woosh/meep-engine 2.47.12 → 2.47.13
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/build/meep.cjs +13 -9
- package/build/meep.min.js +1 -1
- package/build/meep.module.js +13 -9
- package/package.json +1 -1
- package/src/core/binary/BitSet.js +10 -6
- package/src/core/json/abstractJSONDeserializer.js +25 -0
- package/src/core/json/abstractJSONSerializer.js +48 -0
- package/src/core/model/node-graph/json/deserializeNodeGraphFromJSON.js +118 -0
- package/src/core/model/node-graph/json/serializeNodeGraphToJSON.js +106 -0
- package/src/core/model/node-graph/node/NodeDescription.js +8 -0
- package/src/core/process/executor/ConcurrentExecutor.d.ts +1 -1
- package/src/core/process/executor/ConcurrentExecutor.js +3 -3
- package/src/engine/asset/AssetManager.d.ts +4 -0
- package/src/engine/asset/AssetManager.spec.js +12 -4
- package/src/engine/graphics/particles/node-based/editor/ParticleSpecificationEditorView.js +6 -4
- package/src/generation/markers/transform/MarkerNodeTransformerYRotateByFilterGradient.spec.js +3 -3
- package/src/core/model/node-graph/deserializeNodeGraphFromJSON.js +0 -62
- package/src/core/model/node-graph/serializeNodeGraphToJSON.js +0 -40
package/build/meep.module.js
CHANGED
|
@@ -73247,6 +73247,14 @@ BitSet.prototype.__resize = function (bitCapacity) {
|
|
|
73247
73247
|
this.__capacity = uint32_capacity * 32;
|
|
73248
73248
|
};
|
|
73249
73249
|
|
|
73250
|
+
BitSet.prototype.__updateLength = function () {
|
|
73251
|
+
const found_length = this.previousSetBit(this.__length) + 1;
|
|
73252
|
+
|
|
73253
|
+
if (found_length < this.__length) {
|
|
73254
|
+
this.__setLength(found_length);
|
|
73255
|
+
}
|
|
73256
|
+
};
|
|
73257
|
+
|
|
73250
73258
|
/**
|
|
73251
73259
|
*
|
|
73252
73260
|
* @param {int} new_length
|
|
@@ -73470,12 +73478,8 @@ BitSet.prototype.set = function (bitIndex, value) {
|
|
|
73470
73478
|
//clear
|
|
73471
73479
|
this.__data_uint32[word_offset] &= ~word_mask;
|
|
73472
73480
|
|
|
73473
|
-
|
|
73474
|
-
|
|
73475
|
-
// const newLastSetBit = this.previousSetBit(bitIndex);
|
|
73476
|
-
|
|
73477
|
-
this.__setLength(bitIndex );
|
|
73478
|
-
}
|
|
73481
|
+
// trim down set size potentially
|
|
73482
|
+
this.__updateLength();
|
|
73479
73483
|
}
|
|
73480
73484
|
|
|
73481
73485
|
//DEBUG validate firstClearBit value
|
|
@@ -82231,11 +82235,11 @@ function isGroup(t) {
|
|
|
82231
82235
|
class ConcurrentExecutor {
|
|
82232
82236
|
/**
|
|
82233
82237
|
*
|
|
82234
|
-
* @param {number} quietTime in milliseconds
|
|
82235
|
-
* @param {number} workTime in milliseconds
|
|
82238
|
+
* @param {number} [quietTime] in milliseconds
|
|
82239
|
+
* @param {number} [workTime] in milliseconds
|
|
82236
82240
|
* @constructor
|
|
82237
82241
|
*/
|
|
82238
|
-
constructor(quietTime, workTime) {
|
|
82242
|
+
constructor(quietTime=1, workTime=15) {
|
|
82239
82243
|
/**
|
|
82240
82244
|
*
|
|
82241
82245
|
* @type {number}
|
package/package.json
CHANGED
|
@@ -162,6 +162,14 @@ BitSet.prototype.__resize = function (bitCapacity) {
|
|
|
162
162
|
this.__capacity = uint32_capacity * 32;
|
|
163
163
|
};
|
|
164
164
|
|
|
165
|
+
BitSet.prototype.__updateLength = function () {
|
|
166
|
+
const found_length = this.previousSetBit(this.__length) + 1;
|
|
167
|
+
|
|
168
|
+
if (found_length < this.__length) {
|
|
169
|
+
this.__setLength(found_length);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
165
173
|
/**
|
|
166
174
|
*
|
|
167
175
|
* @param {int} new_length
|
|
@@ -385,12 +393,8 @@ BitSet.prototype.set = function (bitIndex, value) {
|
|
|
385
393
|
//clear
|
|
386
394
|
this.__data_uint32[word_offset] &= ~word_mask;
|
|
387
395
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
// const newLastSetBit = this.previousSetBit(bitIndex);
|
|
391
|
-
|
|
392
|
-
this.__setLength(bitIndex );
|
|
393
|
-
}
|
|
396
|
+
// trim down set size potentially
|
|
397
|
+
this.__updateLength();
|
|
394
398
|
}
|
|
395
399
|
|
|
396
400
|
//DEBUG validate firstClearBit value
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @template T
|
|
3
|
+
* @param {T} json
|
|
4
|
+
* @param {Map<string, function>} deserializers
|
|
5
|
+
*/
|
|
6
|
+
export function abstractJSONDeserializer(json, deserializers) {
|
|
7
|
+
if (typeof json !== "object") {
|
|
8
|
+
// primitive type
|
|
9
|
+
return json;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const typeName = json.type;
|
|
13
|
+
|
|
14
|
+
if (typeof typeName !== "string") {
|
|
15
|
+
throw new Error(`Expected json.typeName to be a string, instead was '${typeof typeName}'(=${typeName})`);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const deserializer = deserializers.get(typeName);
|
|
19
|
+
|
|
20
|
+
if (deserializer === undefined) {
|
|
21
|
+
throw new Error(`No deserializer found for type '${typeName}'`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return deserializer(json.data);
|
|
25
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @template T
|
|
3
|
+
* @param {T} source
|
|
4
|
+
* @param {Map<string, function(v:Object):Object>} serializers
|
|
5
|
+
* @param {Map<*,string>} classNames
|
|
6
|
+
*/
|
|
7
|
+
export function abstractJSONSerializer(source, serializers, classNames) {
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
if (typeof source !== "object") {
|
|
11
|
+
// primitive type
|
|
12
|
+
return source;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// parameter is an object
|
|
16
|
+
|
|
17
|
+
// extract type name
|
|
18
|
+
const Klass = source.constructor;
|
|
19
|
+
let typeName = classNames.get(Klass);
|
|
20
|
+
|
|
21
|
+
if (typeName === undefined) {
|
|
22
|
+
// try fallback to "typeName" field on constructor
|
|
23
|
+
typeName = Klass.typeName;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (typeName === undefined) {
|
|
27
|
+
throw new Error(`Failed to resolve type name for parameter '${key}'. No name found in classNames registry and no .typeName field on the constructor`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let serializer = serializers.get(typeName);
|
|
31
|
+
let serializerContext = undefined;
|
|
32
|
+
|
|
33
|
+
if (serializer === undefined) {
|
|
34
|
+
serializer = source.toJSON;
|
|
35
|
+
serializerContext = source;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (serializer === undefined) {
|
|
39
|
+
throw new Error(`Failed to resolve serializer for object type '${typeName}'. No serializer found in serializers registry and no .toJSON method on object itself`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
type: typeName,
|
|
44
|
+
data: serializer.call(serializerContext, source)
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { assert } from "../../../assert.js";
|
|
2
|
+
import { NodeInstance } from "../node/NodeInstance.d.ts";
|
|
3
|
+
import { abstractJSONDeserializer } from "../../../json/abstractJSONDeserializer.js";
|
|
4
|
+
import { NodeRegistry } from "../node/NodeRegistry.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* @param {NodeInstance} node
|
|
9
|
+
* @param {*} json
|
|
10
|
+
* @param {Map<string, function>} deserializers
|
|
11
|
+
*/
|
|
12
|
+
function nodeParametersFromJSON(node, json, deserializers) {
|
|
13
|
+
|
|
14
|
+
for (const key in json) {
|
|
15
|
+
|
|
16
|
+
const jParameter = json[key];
|
|
17
|
+
|
|
18
|
+
const value = abstractJSONDeserializer(jParameter, deserializers);
|
|
19
|
+
|
|
20
|
+
node.setParameterValue(key, value);
|
|
21
|
+
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
*
|
|
28
|
+
* @param {NodeGraph} graph
|
|
29
|
+
* @param {{nodes:[], connections:[], descriptions:[]}} json
|
|
30
|
+
* @param {NodeRegistry} [node_registry]
|
|
31
|
+
* @param {Map<string, function>} [deserializers]
|
|
32
|
+
*/
|
|
33
|
+
export function deserializeNodeGraphFromJSON({
|
|
34
|
+
graph,
|
|
35
|
+
json,
|
|
36
|
+
node_registry = new NodeRegistry(),
|
|
37
|
+
deserializers = new Map()
|
|
38
|
+
}) {
|
|
39
|
+
|
|
40
|
+
const j_nodes = json.nodes;
|
|
41
|
+
const j_connections = json.connections;
|
|
42
|
+
const j_descriptions = json.descriptions;
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
assert.defined(j_nodes, 'json.nodes');
|
|
46
|
+
assert.defined(j_connections, 'json.connections');
|
|
47
|
+
assert.defined(j_descriptions, 'json.descriptions');
|
|
48
|
+
|
|
49
|
+
graph.reset();
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
*
|
|
53
|
+
* @type {NodeDescription[]}
|
|
54
|
+
*/
|
|
55
|
+
const descriptions = [];
|
|
56
|
+
|
|
57
|
+
// parse node descriptions
|
|
58
|
+
for (let i = 0; i < j_descriptions.length; i++) {
|
|
59
|
+
const jDescription = j_descriptions[i];
|
|
60
|
+
|
|
61
|
+
const nodeDescription = abstractJSONDeserializer(jDescription, deserializers);
|
|
62
|
+
|
|
63
|
+
if (
|
|
64
|
+
typeof nodeDescription !== "object"
|
|
65
|
+
|| nodeDescription.isNodeDescription !== true
|
|
66
|
+
) {
|
|
67
|
+
throw new Error(`Deserialized object was expected to be a NodeDescription, instead got something else. Source JSON[${i}]: ${jDescription}`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
descriptions[i] = nodeDescription;
|
|
71
|
+
|
|
72
|
+
// make sure to register the node
|
|
73
|
+
node_registry.addNode(nodeDescription);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// parse nodes
|
|
77
|
+
const node_count = j_nodes.length;
|
|
78
|
+
|
|
79
|
+
for (let i = 0; i < node_count; i++) {
|
|
80
|
+
const jNode = j_nodes[i];
|
|
81
|
+
|
|
82
|
+
const node_id = jNode.id;
|
|
83
|
+
|
|
84
|
+
assert.isNonNegativeInteger(node_id, 'node.id');
|
|
85
|
+
|
|
86
|
+
const description_index = jNode.description;
|
|
87
|
+
|
|
88
|
+
const jParameters = jNode.parameters;
|
|
89
|
+
|
|
90
|
+
// get node description
|
|
91
|
+
const node_description = descriptions[description_index];
|
|
92
|
+
|
|
93
|
+
if (node_description === undefined) {
|
|
94
|
+
throw new Error(`Index ${description_index} not found in .description`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const nodeInstance = new NodeInstance();
|
|
98
|
+
|
|
99
|
+
nodeInstance.id = node_id;
|
|
100
|
+
nodeInstance.setDescription(node_description);
|
|
101
|
+
|
|
102
|
+
nodeParametersFromJSON(nodeInstance, jParameters, deserializers);
|
|
103
|
+
|
|
104
|
+
graph.addNode(nodeInstance);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// parse connections
|
|
108
|
+
const connection_count = j_connections.length;
|
|
109
|
+
|
|
110
|
+
for (let i = 0; i < connection_count; i++) {
|
|
111
|
+
const jConnection = j_connections[i];
|
|
112
|
+
|
|
113
|
+
const jSource = jConnection.source;
|
|
114
|
+
const jTarget = jConnection.target;
|
|
115
|
+
|
|
116
|
+
graph.createConnection(jSource.instance, jSource.port, jTarget.instance, jTarget.port);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { abstractJSONSerializer } from "../../../json/abstractJSONSerializer.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param {NodeInstance} node
|
|
6
|
+
* @param {Map<string, function(v:Object):Object>} serializers
|
|
7
|
+
* @param {Map<*,string>} classNames
|
|
8
|
+
*/
|
|
9
|
+
function nodeParametersToJSON(node, serializers, classNames) {
|
|
10
|
+
const result = {};
|
|
11
|
+
|
|
12
|
+
const parameters = node.parameters;
|
|
13
|
+
|
|
14
|
+
for (const key in parameters) {
|
|
15
|
+
|
|
16
|
+
const source = parameters[key];
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
result[key] = abstractJSONSerializer(source, serializers, classNames);
|
|
20
|
+
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
* @param {NodeGraph} graph
|
|
30
|
+
* @param {Map<string, function(v:Object):Object>} [serializers]
|
|
31
|
+
* @param {Map<*,string>} [classNames]
|
|
32
|
+
*/
|
|
33
|
+
export function serializeNodeGraphToJSON({ graph, serializers = new Map(), classNames = new Map() }) {
|
|
34
|
+
/**
|
|
35
|
+
*
|
|
36
|
+
* @type {NodeDescription[]}
|
|
37
|
+
*/
|
|
38
|
+
const description_objects = [];
|
|
39
|
+
/**
|
|
40
|
+
*
|
|
41
|
+
* @type {Map<NodeDescription, number>}
|
|
42
|
+
*/
|
|
43
|
+
const description_to_index_map = new Map();
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* JSON versions of descriptions
|
|
47
|
+
* @type {Object[]}
|
|
48
|
+
*/
|
|
49
|
+
const descriptions = [];
|
|
50
|
+
|
|
51
|
+
// extract node descriptions
|
|
52
|
+
graph.traverseNodes(node => {
|
|
53
|
+
|
|
54
|
+
const description = node.description;
|
|
55
|
+
|
|
56
|
+
let index = description_objects.indexOf(description);
|
|
57
|
+
|
|
58
|
+
if (index !== -1) {
|
|
59
|
+
// already recorded
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
index = description_objects.length;
|
|
64
|
+
description_objects.push(description);
|
|
65
|
+
|
|
66
|
+
description_to_index_map.set(description, index);
|
|
67
|
+
|
|
68
|
+
descriptions[index] = abstractJSONSerializer(description, serializers, classNames);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const nodes = [];
|
|
72
|
+
|
|
73
|
+
graph.traverseNodes(node => {
|
|
74
|
+
|
|
75
|
+
nodes.push({
|
|
76
|
+
id: node.id,
|
|
77
|
+
description: description_to_index_map.get(node.description),
|
|
78
|
+
parameters: nodeParametersToJSON(node, serializers, classNames)
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const connections = [];
|
|
84
|
+
|
|
85
|
+
graph.traverseConnections(connection => {
|
|
86
|
+
|
|
87
|
+
connections.push({
|
|
88
|
+
source: {
|
|
89
|
+
instance: connection.source.instance.id,
|
|
90
|
+
port: connection.source.port.id
|
|
91
|
+
},
|
|
92
|
+
target: {
|
|
93
|
+
instance: connection.target.instance.id,
|
|
94
|
+
port: connection.target.port.id
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
nodes,
|
|
102
|
+
connections,
|
|
103
|
+
descriptions
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
@@ -24,11 +24,11 @@ function isGroup(t) {
|
|
|
24
24
|
class ConcurrentExecutor {
|
|
25
25
|
/**
|
|
26
26
|
*
|
|
27
|
-
* @param {number} quietTime in milliseconds
|
|
28
|
-
* @param {number} workTime in milliseconds
|
|
27
|
+
* @param {number} [quietTime] in milliseconds
|
|
28
|
+
* @param {number} [workTime] in milliseconds
|
|
29
29
|
* @constructor
|
|
30
30
|
*/
|
|
31
|
-
constructor(quietTime, workTime) {
|
|
31
|
+
constructor(quietTime=1, workTime=15) {
|
|
32
32
|
/**
|
|
33
33
|
*
|
|
34
34
|
* @type {number}
|
|
@@ -15,6 +15,10 @@ export class AssetManager {
|
|
|
15
15
|
|
|
16
16
|
load_concurrency: number
|
|
17
17
|
|
|
18
|
+
startup(): void
|
|
19
|
+
|
|
20
|
+
shutdown(immediate?: boolean): Promise<void>
|
|
21
|
+
|
|
18
22
|
promise<T>(path: string, type: string, options?: PromiseOptions): Promise<Asset<T>>
|
|
19
23
|
|
|
20
24
|
remove(path: string, type: string): boolean
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import { Asset } from "./Asset.js";
|
|
2
2
|
import { AssetManager } from "./AssetManager.js";
|
|
3
3
|
import { AssetLoader } from "./loaders/AssetLoader.js";
|
|
4
|
+
import ConcurrentExecutor from "../../core/process/executor/ConcurrentExecutor.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
*
|
|
7
8
|
* @return {Engine}
|
|
8
9
|
*/
|
|
9
10
|
function dummyEngine() {
|
|
10
|
-
|
|
11
|
+
const executor = new ConcurrentExecutor();
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
executor: executor
|
|
15
|
+
};
|
|
11
16
|
}
|
|
12
17
|
|
|
13
18
|
class DummyLoader extends AssetLoader {
|
|
@@ -16,11 +21,12 @@ class DummyLoader extends AssetLoader {
|
|
|
16
21
|
}
|
|
17
22
|
}
|
|
18
23
|
|
|
19
|
-
test('successful get', () => {
|
|
24
|
+
test('successful get', async () => {
|
|
20
25
|
const am = new AssetManager(dummyEngine());
|
|
21
26
|
|
|
22
|
-
am.registerLoader('a', new DummyLoader());
|
|
27
|
+
await am.registerLoader('a', new DummyLoader());
|
|
23
28
|
|
|
29
|
+
am.startup();
|
|
24
30
|
|
|
25
31
|
return new Promise(function (resolve, reject) {
|
|
26
32
|
am.get('bla', 'a', resolve, reject);
|
|
@@ -30,7 +36,9 @@ test('successful get', () => {
|
|
|
30
36
|
test('tryGet loaded resource', async () => {
|
|
31
37
|
const am = new AssetManager(dummyEngine());
|
|
32
38
|
|
|
33
|
-
am.
|
|
39
|
+
am.startup();
|
|
40
|
+
|
|
41
|
+
await am.registerLoader('a', new DummyLoader());
|
|
34
42
|
|
|
35
43
|
await am.promise('bla', 'a');
|
|
36
44
|
|
|
@@ -7,9 +7,11 @@ import LabelView from "../../../../../view/common/LabelView.js";
|
|
|
7
7
|
import { MouseEvents } from "../../../../input/devices/events/MouseEvents.js";
|
|
8
8
|
import InterfaceCommand from "../../../../../view/interaction/InterfaceCommand.js";
|
|
9
9
|
import { InteractionCommand } from "../../../../../view/interaction/InteractionCommand.js";
|
|
10
|
-
import { serializeNodeGraphToJSON } from "../../../../../core/model/node-graph/serializeNodeGraphToJSON.js";
|
|
10
|
+
import { serializeNodeGraphToJSON } from "../../../../../core/model/node-graph/json/serializeNodeGraphToJSON.js";
|
|
11
11
|
import { downloadAsFile } from "../../../../../core/binary/ByteArrayTools.js";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
deserializeNodeGraphFromJSON
|
|
14
|
+
} from "../../../../../core/model/node-graph/json/deserializeNodeGraphFromJSON.js";
|
|
13
15
|
|
|
14
16
|
export class ParticleSpecificationEditorView extends View {
|
|
15
17
|
constructor() {
|
|
@@ -78,7 +80,7 @@ export class ParticleSpecificationEditorView extends View {
|
|
|
78
80
|
command: new InteractionCommand({
|
|
79
81
|
id: 'serialize-json',
|
|
80
82
|
action() {
|
|
81
|
-
const json = serializeNodeGraphToJSON(nodeGraph);
|
|
83
|
+
const json = serializeNodeGraphToJSON({ graph: nodeGraph });
|
|
82
84
|
|
|
83
85
|
|
|
84
86
|
downloadAsFile(JSON.stringify(json, 3, 3), 'graph.json', 'application/json');
|
|
@@ -105,7 +107,7 @@ export class ParticleSpecificationEditorView extends View {
|
|
|
105
107
|
|
|
106
108
|
const json = JSON.parse(fr.result);
|
|
107
109
|
|
|
108
|
-
deserializeNodeGraphFromJSON(nodeGraph, json, nodeRegistry);
|
|
110
|
+
deserializeNodeGraphFromJSON({ graph: nodeGraph, json: json, node_registry: nodeRegistry });
|
|
109
111
|
|
|
110
112
|
visual.layout(nodeGraph);
|
|
111
113
|
};
|
package/src/generation/markers/transform/MarkerNodeTransformerYRotateByFilterGradient.spec.js
CHANGED
|
@@ -78,7 +78,7 @@ test('left to right', () => {
|
|
|
78
78
|
1, 0, 0,
|
|
79
79
|
1, 0, 0,
|
|
80
80
|
1, 0, 0
|
|
81
|
-
])).toBeCloseTo(180);
|
|
81
|
+
])).toBeCloseTo(-180);
|
|
82
82
|
});
|
|
83
83
|
|
|
84
84
|
test('right to left', () => {
|
|
@@ -94,7 +94,7 @@ test('top to bottom', () => {
|
|
|
94
94
|
1, 1, 1,
|
|
95
95
|
0, 0, 0,
|
|
96
96
|
0, 0, 0
|
|
97
|
-
])).toBeCloseTo(
|
|
97
|
+
])).toBeCloseTo(90);
|
|
98
98
|
});
|
|
99
99
|
|
|
100
100
|
test('bottom to top', () => {
|
|
@@ -102,5 +102,5 @@ test('bottom to top', () => {
|
|
|
102
102
|
0, 0, 0,
|
|
103
103
|
0, 0, 0,
|
|
104
104
|
1, 1, 1
|
|
105
|
-
])).toBeCloseTo(90);
|
|
105
|
+
])).toBeCloseTo(-90);
|
|
106
106
|
});
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { assert } from "../../assert.js";
|
|
2
|
-
import { NodeInstance } from "./node/NodeInstance.js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
*
|
|
6
|
-
* @param {NodeGraph} graph
|
|
7
|
-
* @param {{nodes:[], connections:[]}} json
|
|
8
|
-
* @param {NodeRegistry} node_registry
|
|
9
|
-
*/
|
|
10
|
-
export function deserializeNodeGraphFromJSON(graph, json, node_registry) {
|
|
11
|
-
|
|
12
|
-
const nodes = json.nodes;
|
|
13
|
-
const connections = json.connections;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
assert.defined(nodes, 'json.nodes');
|
|
17
|
-
assert.defined(connections, 'json.connections');
|
|
18
|
-
|
|
19
|
-
graph.reset();
|
|
20
|
-
|
|
21
|
-
// parse nodes
|
|
22
|
-
const node_count = nodes.length;
|
|
23
|
-
|
|
24
|
-
for (let i = 0; i < node_count; i++) {
|
|
25
|
-
const jNode = nodes[i];
|
|
26
|
-
|
|
27
|
-
const node_id = jNode.id;
|
|
28
|
-
|
|
29
|
-
assert.isNonNegativeInteger(node_id, 'node.id');
|
|
30
|
-
|
|
31
|
-
const description = jNode.description;
|
|
32
|
-
|
|
33
|
-
const parameters = jNode.parameters;
|
|
34
|
-
|
|
35
|
-
// get node description
|
|
36
|
-
const node_description = node_registry.getNode(description);
|
|
37
|
-
|
|
38
|
-
if (node_description === undefined) {
|
|
39
|
-
throw new Error(`Node ${description} not found in the registry`);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const nodeInstance = new NodeInstance();
|
|
43
|
-
|
|
44
|
-
nodeInstance.id = node_id;
|
|
45
|
-
nodeInstance.setDescription(node_description);
|
|
46
|
-
nodeInstance.setParameters(parameters);
|
|
47
|
-
|
|
48
|
-
graph.addNode(nodeInstance);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// parse connections
|
|
52
|
-
const connection_count = connections.length;
|
|
53
|
-
|
|
54
|
-
for (let i = 0; i < connection_count; i++) {
|
|
55
|
-
const jConnection = connections[i];
|
|
56
|
-
|
|
57
|
-
const jSource = jConnection.source;
|
|
58
|
-
const jTarget = jConnection.target;
|
|
59
|
-
|
|
60
|
-
graph.createConnection(jSource.instance, jSource.port, jTarget.instance, jTarget.port);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* @param {NodeGraph} graph
|
|
4
|
-
*/
|
|
5
|
-
export function serializeNodeGraphToJSON(graph) {
|
|
6
|
-
const nodes = [];
|
|
7
|
-
|
|
8
|
-
graph.traverseNodes(node => {
|
|
9
|
-
|
|
10
|
-
nodes.push({
|
|
11
|
-
id: node.id,
|
|
12
|
-
description: node.description.id,
|
|
13
|
-
parameters: node.parameters
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
const connections = [];
|
|
19
|
-
|
|
20
|
-
graph.traverseConnections(connection => {
|
|
21
|
-
|
|
22
|
-
connections.push({
|
|
23
|
-
source: {
|
|
24
|
-
instance: connection.source.instance.id,
|
|
25
|
-
port: connection.source.port.id
|
|
26
|
-
},
|
|
27
|
-
target: {
|
|
28
|
-
instance: connection.target.instance.id,
|
|
29
|
-
port: connection.target.port.id
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
return {
|
|
36
|
-
nodes,
|
|
37
|
-
connections
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
|