@bian-womp/spark-graph 0.1.8 → 0.1.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/lib/cjs/index.cjs +303 -115
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/cjs/src/builder/Registry.d.ts +18 -2
- package/lib/cjs/src/builder/Registry.d.ts.map +1 -1
- package/lib/cjs/src/examples/shared.d.ts +0 -1
- package/lib/cjs/src/examples/shared.d.ts.map +1 -1
- package/lib/cjs/src/examples/simple.d.ts +2 -1
- package/lib/cjs/src/examples/simple.d.ts.map +1 -1
- package/lib/esm/index.js +303 -115
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/src/builder/Registry.d.ts +18 -2
- package/lib/esm/src/builder/Registry.d.ts.map +1 -1
- package/lib/esm/src/examples/shared.d.ts +0 -1
- package/lib/esm/src/examples/shared.d.ts.map +1 -1
- package/lib/esm/src/examples/simple.d.ts +2 -1
- package/lib/esm/src/examples/simple.d.ts.map +1 -1
- package/package.json +2 -2
package/lib/cjs/index.cjs
CHANGED
|
@@ -24,9 +24,12 @@ class Registry {
|
|
|
24
24
|
this.serializers = new Map();
|
|
25
25
|
this.coercions = new Map();
|
|
26
26
|
this.asyncCoercions = new Map();
|
|
27
|
+
this.resolvedCache = new Map();
|
|
27
28
|
}
|
|
28
29
|
registerType(desc, opts) {
|
|
29
30
|
this.types.set(desc.id, desc);
|
|
31
|
+
// Any structural change invalidates resolution cache
|
|
32
|
+
this.resolvedCache.clear();
|
|
30
33
|
if (!this.serializers.has(desc.id)) {
|
|
31
34
|
this.registerSerializer(desc.id, {
|
|
32
35
|
serialize: (v) => v,
|
|
@@ -83,46 +86,231 @@ class Registry {
|
|
|
83
86
|
return this;
|
|
84
87
|
}
|
|
85
88
|
// Register a type coercion from one type id to another
|
|
86
|
-
registerCoercion(fromTypeId, toTypeId, convert) {
|
|
87
|
-
this.coercions.set(`${fromTypeId}->${toTypeId}`,
|
|
89
|
+
registerCoercion(fromTypeId, toTypeId, convert, opts) {
|
|
90
|
+
this.coercions.set(`${fromTypeId}->${toTypeId}`, {
|
|
91
|
+
convert,
|
|
92
|
+
nonTransitive: !!opts?.nonTransitive,
|
|
93
|
+
});
|
|
94
|
+
// If both source and target have array variants, add derived array->array coercion
|
|
95
|
+
const fromArr = `${fromTypeId}[]`;
|
|
96
|
+
const toArr = `${toTypeId}[]`;
|
|
97
|
+
const arrKey = `${fromArr}->${toArr}`;
|
|
98
|
+
if (this.types.has(fromArr) && this.types.has(toArr)) {
|
|
99
|
+
if (!this.coercions.has(arrKey) && !this.asyncCoercions.has(arrKey)) {
|
|
100
|
+
this.coercions.set(arrKey, {
|
|
101
|
+
convert: (value) => {
|
|
102
|
+
if (Array.isArray(value))
|
|
103
|
+
return value.map((v) => convert(v));
|
|
104
|
+
// Best-effort: coerce single to array-of-single
|
|
105
|
+
return [convert(value)];
|
|
106
|
+
},
|
|
107
|
+
nonTransitive: !!opts?.nonTransitive,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
this.resolvedCache.clear();
|
|
88
112
|
return this;
|
|
89
113
|
}
|
|
90
114
|
// Register an async type coercion from one type id to another
|
|
91
|
-
registerAsyncCoercion(fromTypeId, toTypeId, convertAsync) {
|
|
92
|
-
this.asyncCoercions.set(`${fromTypeId}->${toTypeId}`,
|
|
115
|
+
registerAsyncCoercion(fromTypeId, toTypeId, convertAsync, opts) {
|
|
116
|
+
this.asyncCoercions.set(`${fromTypeId}->${toTypeId}`, {
|
|
117
|
+
convertAsync,
|
|
118
|
+
nonTransitive: !!opts?.nonTransitive,
|
|
119
|
+
});
|
|
120
|
+
// If both source and target have array variants, add derived array->array async coercion
|
|
121
|
+
const fromArr = `${fromTypeId}[]`;
|
|
122
|
+
const toArr = `${toTypeId}[]`;
|
|
123
|
+
const arrKey = `${fromArr}->${toArr}`;
|
|
124
|
+
if (this.types.has(fromArr) && this.types.has(toArr)) {
|
|
125
|
+
if (!this.coercions.has(arrKey) && !this.asyncCoercions.has(arrKey)) {
|
|
126
|
+
this.asyncCoercions.set(arrKey, {
|
|
127
|
+
convertAsync: async (value, signal) => {
|
|
128
|
+
if (Array.isArray(value)) {
|
|
129
|
+
const out = [];
|
|
130
|
+
for (let i = 0; i < value.length; i++) {
|
|
131
|
+
if (signal?.aborted)
|
|
132
|
+
throw signal.reason ?? new Error("aborted");
|
|
133
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
134
|
+
out.push(await convertAsync(value[i], signal));
|
|
135
|
+
}
|
|
136
|
+
return out;
|
|
137
|
+
}
|
|
138
|
+
return [await convertAsync(value, signal)];
|
|
139
|
+
},
|
|
140
|
+
nonTransitive: !!opts?.nonTransitive,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
this.resolvedCache.clear();
|
|
93
145
|
return this;
|
|
94
146
|
}
|
|
95
147
|
canCoerce(fromTypeId, toTypeId) {
|
|
96
148
|
if (!fromTypeId || !toTypeId)
|
|
97
149
|
return false;
|
|
98
|
-
|
|
99
|
-
return true;
|
|
100
|
-
const key = `${fromTypeId}->${toTypeId}`;
|
|
101
|
-
return this.coercions.has(key) || this.asyncCoercions.has(key);
|
|
150
|
+
return !!this.resolveCoercion(fromTypeId, toTypeId);
|
|
102
151
|
}
|
|
103
152
|
getCoercion(fromTypeId, toTypeId) {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
153
|
+
const resolved = this.resolveCoercion(fromTypeId, toTypeId);
|
|
154
|
+
if (!resolved)
|
|
155
|
+
return undefined;
|
|
156
|
+
if (resolved.kind === "sync")
|
|
157
|
+
return resolved.convert;
|
|
158
|
+
return undefined;
|
|
107
159
|
}
|
|
108
160
|
getAsyncCoercion(fromTypeId, toTypeId) {
|
|
109
|
-
|
|
161
|
+
const resolved = this.resolveCoercion(fromTypeId, toTypeId);
|
|
162
|
+
if (!resolved)
|
|
110
163
|
return undefined;
|
|
111
|
-
|
|
164
|
+
if (resolved.kind === "async")
|
|
165
|
+
return resolved.convertAsync;
|
|
166
|
+
return undefined;
|
|
112
167
|
}
|
|
113
168
|
// Introspection for dynamic discovery
|
|
114
169
|
listCoercions() {
|
|
115
170
|
const out = [];
|
|
116
|
-
for (const key of this.coercions.
|
|
171
|
+
for (const [key, rec] of this.coercions.entries()) {
|
|
117
172
|
const [from, to] = key.split("->");
|
|
118
|
-
out.push({
|
|
173
|
+
out.push({
|
|
174
|
+
from,
|
|
175
|
+
to,
|
|
176
|
+
async: false,
|
|
177
|
+
nonTransitive: rec.nonTransitive,
|
|
178
|
+
});
|
|
119
179
|
}
|
|
120
|
-
for (const key of this.asyncCoercions.
|
|
180
|
+
for (const [key, rec] of this.asyncCoercions.entries()) {
|
|
121
181
|
const [from, to] = key.split("->");
|
|
122
|
-
out.push({ from, to, async: true });
|
|
182
|
+
out.push({ from, to, async: true, nonTransitive: rec.nonTransitive });
|
|
123
183
|
}
|
|
124
184
|
return out;
|
|
125
185
|
}
|
|
186
|
+
resolveCoercion(fromTypeId, toTypeId) {
|
|
187
|
+
const cacheKey = `${fromTypeId}->${toTypeId}`;
|
|
188
|
+
const cached = this.resolvedCache.get(cacheKey);
|
|
189
|
+
if (cached)
|
|
190
|
+
return cached;
|
|
191
|
+
if (fromTypeId === toTypeId) {
|
|
192
|
+
const res = { kind: "sync", convert: (v) => v };
|
|
193
|
+
this.resolvedCache.set(cacheKey, res);
|
|
194
|
+
return res;
|
|
195
|
+
}
|
|
196
|
+
// Direct edges (regardless of nonTransitive)
|
|
197
|
+
const directSync = this.coercions.get(cacheKey);
|
|
198
|
+
if (directSync) {
|
|
199
|
+
const res = {
|
|
200
|
+
kind: "sync",
|
|
201
|
+
convert: directSync.convert,
|
|
202
|
+
};
|
|
203
|
+
this.resolvedCache.set(cacheKey, res);
|
|
204
|
+
return res;
|
|
205
|
+
}
|
|
206
|
+
const directAsync = this.asyncCoercions.get(cacheKey);
|
|
207
|
+
if (directAsync) {
|
|
208
|
+
const res = {
|
|
209
|
+
kind: "async",
|
|
210
|
+
convertAsync: directAsync.convertAsync,
|
|
211
|
+
};
|
|
212
|
+
this.resolvedCache.set(cacheKey, res);
|
|
213
|
+
return res;
|
|
214
|
+
}
|
|
215
|
+
// Build adjacency from transitive-allowed edges only
|
|
216
|
+
const getNeighbors = (from) => {
|
|
217
|
+
const out = [];
|
|
218
|
+
for (const [key, rec] of this.coercions.entries()) {
|
|
219
|
+
if (rec.nonTransitive)
|
|
220
|
+
continue;
|
|
221
|
+
const [src, dst] = key.split("->");
|
|
222
|
+
if (src === from)
|
|
223
|
+
out.push({ from: src, to: dst, kind: "sync", convert: rec.convert });
|
|
224
|
+
}
|
|
225
|
+
for (const [key, rec] of this.asyncCoercions.entries()) {
|
|
226
|
+
if (rec.nonTransitive)
|
|
227
|
+
continue;
|
|
228
|
+
const [src, dst] = key.split("->");
|
|
229
|
+
if (src === from)
|
|
230
|
+
out.push({
|
|
231
|
+
from: src,
|
|
232
|
+
to: dst,
|
|
233
|
+
kind: "async",
|
|
234
|
+
convertAsync: rec.convertAsync,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
return out;
|
|
238
|
+
};
|
|
239
|
+
const betterOf = (a, b) => {
|
|
240
|
+
if (!a)
|
|
241
|
+
return true;
|
|
242
|
+
if (b.edges !== a.edges)
|
|
243
|
+
return b.edges < a.edges;
|
|
244
|
+
return b.async < a.async;
|
|
245
|
+
};
|
|
246
|
+
const best = new Map();
|
|
247
|
+
const queue = [];
|
|
248
|
+
const push = (e) => {
|
|
249
|
+
// simple insertion to keep queue roughly ordered by cost
|
|
250
|
+
let i = 0;
|
|
251
|
+
while (i < queue.length) {
|
|
252
|
+
const q = queue[i];
|
|
253
|
+
if (e.cost.edges < q.cost.edges ||
|
|
254
|
+
(e.cost.edges === q.cost.edges && e.cost.async < q.cost.async)) {
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
i++;
|
|
258
|
+
}
|
|
259
|
+
queue.splice(i, 0, e);
|
|
260
|
+
};
|
|
261
|
+
push({ node: fromTypeId, cost: { edges: 0, async: 0 }, path: [] });
|
|
262
|
+
best.set(fromTypeId, { edges: 0, async: 0 });
|
|
263
|
+
while (queue.length > 0) {
|
|
264
|
+
const cur = queue.shift();
|
|
265
|
+
if (cur.node === toTypeId) {
|
|
266
|
+
// Compose
|
|
267
|
+
const hasAsync = cur.path.some((s) => s.kind === "async");
|
|
268
|
+
if (!hasAsync) {
|
|
269
|
+
const convert = (value) => {
|
|
270
|
+
let acc = value;
|
|
271
|
+
for (const step of cur.path) {
|
|
272
|
+
// all sync by construction
|
|
273
|
+
acc = step.convert(acc);
|
|
274
|
+
}
|
|
275
|
+
return acc;
|
|
276
|
+
};
|
|
277
|
+
const res = { kind: "sync", convert };
|
|
278
|
+
this.resolvedCache.set(cacheKey, res);
|
|
279
|
+
return res;
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
const convertAsync = async (value, signal) => {
|
|
283
|
+
let acc = value;
|
|
284
|
+
for (const step of cur.path) {
|
|
285
|
+
if (step.kind === "sync") {
|
|
286
|
+
acc = step.convert(acc);
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
acc = await step.convertAsync(acc, signal);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return acc;
|
|
293
|
+
};
|
|
294
|
+
const res = { kind: "async", convertAsync };
|
|
295
|
+
this.resolvedCache.set(cacheKey, res);
|
|
296
|
+
return res;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
// expand neighbors
|
|
300
|
+
for (const step of getNeighbors(cur.node)) {
|
|
301
|
+
const nextCost = {
|
|
302
|
+
edges: cur.cost.edges + 1,
|
|
303
|
+
async: cur.cost.async + (step.kind === "async" ? 1 : 0),
|
|
304
|
+
};
|
|
305
|
+
const prev = best.get(step.to);
|
|
306
|
+
if (betterOf(prev, nextCost)) {
|
|
307
|
+
best.set(step.to, nextCost);
|
|
308
|
+
push({ node: step.to, cost: nextCost, path: [...cur.path, step] });
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return undefined;
|
|
313
|
+
}
|
|
126
314
|
// Enum support
|
|
127
315
|
registerEnum(desc) {
|
|
128
316
|
const { id, displayName, options, opts } = desc;
|
|
@@ -1331,79 +1519,89 @@ const CompositeCategory = (registry) => ({
|
|
|
1331
1519
|
policy: { mode: "hybrid" },
|
|
1332
1520
|
});
|
|
1333
1521
|
|
|
1522
|
+
// Helpers
|
|
1523
|
+
const asArray = (v) => Array.isArray(v) ? v : [Number(v)];
|
|
1524
|
+
const broadcast = (a, b) => {
|
|
1525
|
+
const aa = asArray(a);
|
|
1526
|
+
const bb = asArray(b);
|
|
1527
|
+
if (aa.length === bb.length)
|
|
1528
|
+
return [aa, bb];
|
|
1529
|
+
if (aa.length === 1)
|
|
1530
|
+
return [new Array(bb.length).fill(aa[0]), bb];
|
|
1531
|
+
if (bb.length === 1)
|
|
1532
|
+
return [aa, new Array(aa.length).fill(bb[0])];
|
|
1533
|
+
const len = Math.max(aa.length, bb.length);
|
|
1534
|
+
return [new Array(len).fill(aa[0] ?? 0), new Array(len).fill(bb[0] ?? 0)];
|
|
1535
|
+
};
|
|
1536
|
+
const clamp = (x, min, max) => Math.min(max, Math.max(min, x));
|
|
1537
|
+
const lerp = (a, b, t) => a + (b - a) * t;
|
|
1538
|
+
const lcg = (seed) => {
|
|
1539
|
+
let s = seed >>> 0 || 1;
|
|
1540
|
+
return () => (s = (s * 1664525 + 1013904223) >>> 0) / 0xffffffff;
|
|
1541
|
+
};
|
|
1334
1542
|
function setupBasicGraphRegistry() {
|
|
1335
1543
|
const registry = new Registry();
|
|
1336
1544
|
registry.categories.register(ComputeCategory);
|
|
1337
|
-
|
|
1545
|
+
registry.registerType({
|
|
1338
1546
|
id: "base.float",
|
|
1339
1547
|
validate: (v) => typeof v === "number" && !Number.isNaN(v),
|
|
1340
|
-
};
|
|
1341
|
-
registry.registerType(
|
|
1342
|
-
registry.registerSerializer("base.float", {
|
|
1343
|
-
serialize: (v) => v,
|
|
1344
|
-
deserialize: (d) => Number(d),
|
|
1345
|
-
});
|
|
1346
|
-
const boolType = {
|
|
1548
|
+
}, { withArray: true, arrayPickFirstDefined: true });
|
|
1549
|
+
registry.registerType({
|
|
1347
1550
|
id: "base.bool",
|
|
1348
1551
|
validate: (v) => typeof v === "boolean",
|
|
1349
|
-
};
|
|
1350
|
-
|
|
1552
|
+
}, { withArray: true, arrayPickFirstDefined: true });
|
|
1553
|
+
registry.registerType({
|
|
1351
1554
|
id: "base.string",
|
|
1352
1555
|
validate: (v) => typeof v === "string",
|
|
1353
|
-
};
|
|
1354
|
-
|
|
1556
|
+
}, { withArray: true, arrayPickFirstDefined: true });
|
|
1557
|
+
registry.registerType({
|
|
1355
1558
|
id: "base.vec3",
|
|
1356
1559
|
validate: (v) => Array.isArray(v) &&
|
|
1357
1560
|
v.length === 3 &&
|
|
1358
1561
|
v.every((x) => typeof x === "number"),
|
|
1359
|
-
};
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
serialize: (v) => v,
|
|
1364
|
-
deserialize: (d) => d,
|
|
1365
|
-
});
|
|
1562
|
+
}, { withArray: true, arrayPickFirstDefined: true });
|
|
1563
|
+
// float -> vec3 : map x to [x,0,0]
|
|
1564
|
+
registry.registerCoercion("base.float", "base.vec3", (v) => {
|
|
1565
|
+
return [Number(v) || 0, 0, 0];
|
|
1366
1566
|
});
|
|
1367
|
-
//
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
const
|
|
1372
|
-
|
|
1567
|
+
// Async coercion variant for vec3 -> float (chunked + abortable)
|
|
1568
|
+
registry.registerAsyncCoercion("base.vec3", "base.float", async (value, signal) => {
|
|
1569
|
+
if (signal.aborted)
|
|
1570
|
+
throw new DOMException("Aborted", "AbortError");
|
|
1571
|
+
const v = value;
|
|
1572
|
+
await new Promise((r) => setTimeout(r, 1000));
|
|
1573
|
+
return Math.hypot(Number(v[0] ?? 0), Number(v[1] ?? 0), Number(v[2] ?? 0));
|
|
1373
1574
|
});
|
|
1374
|
-
|
|
1375
|
-
registry.
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1575
|
+
registry.registerCoercion("base.bool", "base.float", (v) => (v ? 1 : 0));
|
|
1576
|
+
registry.registerCoercion("base.float", "base.bool", (v) => !!v);
|
|
1577
|
+
registry.registerCoercion("base.float", "base.string", (v) => String(v));
|
|
1578
|
+
registry.registerCoercion("base.string", "base.float", (v) => Number(v));
|
|
1579
|
+
// Enums: Math Operation
|
|
1580
|
+
registry.registerEnum({
|
|
1581
|
+
id: "base.enum:math.operation",
|
|
1582
|
+
options: [
|
|
1583
|
+
{ value: 0, label: "Add" },
|
|
1584
|
+
{ value: 1, label: "Subtract" },
|
|
1585
|
+
{ value: 2, label: "Multiply" },
|
|
1586
|
+
{ value: 3, label: "Divide" },
|
|
1587
|
+
{ value: 4, label: "Min" },
|
|
1588
|
+
{ value: 5, label: "Max" },
|
|
1589
|
+
{ value: 6, label: "Modulo" },
|
|
1590
|
+
{ value: 7, label: "Power" },
|
|
1591
|
+
],
|
|
1592
|
+
});
|
|
1593
|
+
// Enums: Compare Operation
|
|
1594
|
+
registry.registerEnum({
|
|
1595
|
+
id: "base.enum:compare.operation",
|
|
1596
|
+
options: [
|
|
1597
|
+
{ value: 0, label: "LessThan" },
|
|
1598
|
+
{ value: 1, label: "LessThanOrEqual" },
|
|
1599
|
+
{ value: 2, label: "GreaterThan" },
|
|
1600
|
+
{ value: 3, label: "GreaterThanOrEqual" },
|
|
1601
|
+
{ value: 4, label: "Equal" },
|
|
1602
|
+
{ value: 5, label: "NotEqual" },
|
|
1603
|
+
],
|
|
1388
1604
|
});
|
|
1389
|
-
const broadcast = (a, b) => {
|
|
1390
|
-
const aa = asArray(a);
|
|
1391
|
-
const bb = asArray(b);
|
|
1392
|
-
if (aa.length === bb.length)
|
|
1393
|
-
return [aa, bb];
|
|
1394
|
-
if (aa.length === 1)
|
|
1395
|
-
return [new Array(bb.length).fill(aa[0]), bb];
|
|
1396
|
-
if (bb.length === 1)
|
|
1397
|
-
return [aa, new Array(aa.length).fill(bb[0])];
|
|
1398
|
-
const len = Math.max(aa.length, bb.length);
|
|
1399
|
-
return [new Array(len).fill(aa[0] ?? 0), new Array(len).fill(bb[0] ?? 0)];
|
|
1400
|
-
};
|
|
1401
|
-
const clamp = (x, min, max) => Math.min(max, Math.max(min, x));
|
|
1402
|
-
const lerp = (a, b, t) => a + (b - a) * t;
|
|
1403
|
-
const lcg = (seed) => {
|
|
1404
|
-
let s = seed >>> 0 || 1;
|
|
1405
|
-
return () => (s = (s * 1664525 + 1013904223) >>> 0) / 0xffffffff;
|
|
1406
|
-
};
|
|
1407
1605
|
// Number
|
|
1408
1606
|
registry.registerNode({
|
|
1409
1607
|
id: "base.number",
|
|
@@ -1430,32 +1628,6 @@ function setupBasicGraphRegistry() {
|
|
|
1430
1628
|
outputs: { Text: "base.string" },
|
|
1431
1629
|
impl: (ins) => ({ Text: String(ins.Value) }),
|
|
1432
1630
|
});
|
|
1433
|
-
// Enums: Math Operation
|
|
1434
|
-
registry.registerEnum({
|
|
1435
|
-
id: "base.enum:math.operation",
|
|
1436
|
-
options: [
|
|
1437
|
-
{ value: 0, label: "Add" },
|
|
1438
|
-
{ value: 1, label: "Subtract" },
|
|
1439
|
-
{ value: 2, label: "Multiply" },
|
|
1440
|
-
{ value: 3, label: "Divide" },
|
|
1441
|
-
{ value: 4, label: "Min" },
|
|
1442
|
-
{ value: 5, label: "Max" },
|
|
1443
|
-
{ value: 6, label: "Modulo" },
|
|
1444
|
-
{ value: 7, label: "Power" },
|
|
1445
|
-
],
|
|
1446
|
-
});
|
|
1447
|
-
// Enums: Compare Operation
|
|
1448
|
-
registry.registerEnum({
|
|
1449
|
-
id: "base.enum:compare.operation",
|
|
1450
|
-
options: [
|
|
1451
|
-
{ value: 0, label: "LessThan" },
|
|
1452
|
-
{ value: 1, label: "LessThanOrEqual" },
|
|
1453
|
-
{ value: 2, label: "GreaterThan" },
|
|
1454
|
-
{ value: 3, label: "GreaterThanOrEqual" },
|
|
1455
|
-
{ value: 4, label: "Equal" },
|
|
1456
|
-
{ value: 5, label: "NotEqual" },
|
|
1457
|
-
],
|
|
1458
|
-
});
|
|
1459
1631
|
// Clamp
|
|
1460
1632
|
registry.registerNode({
|
|
1461
1633
|
id: "base.clamp",
|
|
@@ -1667,21 +1839,6 @@ function setupBasicGraphRegistry() {
|
|
|
1667
1839
|
});
|
|
1668
1840
|
return registry;
|
|
1669
1841
|
}
|
|
1670
|
-
function makeBasicGraphDefinition() {
|
|
1671
|
-
return {
|
|
1672
|
-
nodes: [
|
|
1673
|
-
{ nodeId: "n1", typeId: "base.math" },
|
|
1674
|
-
{ nodeId: "n2", typeId: "base.math" },
|
|
1675
|
-
],
|
|
1676
|
-
edges: [
|
|
1677
|
-
{
|
|
1678
|
-
id: "e1",
|
|
1679
|
-
source: { nodeId: "n1", handle: "Result" },
|
|
1680
|
-
target: { nodeId: "n2", handle: "A" },
|
|
1681
|
-
},
|
|
1682
|
-
],
|
|
1683
|
-
};
|
|
1684
|
-
}
|
|
1685
1842
|
function registerDelayNode(registry) {
|
|
1686
1843
|
registry.registerNode({
|
|
1687
1844
|
id: "async.delay",
|
|
@@ -1755,6 +1912,37 @@ function registerProgressNodes(registry) {
|
|
|
1755
1912
|
});
|
|
1756
1913
|
}
|
|
1757
1914
|
|
|
1915
|
+
function makeBasicGraphDefinition() {
|
|
1916
|
+
return {
|
|
1917
|
+
nodes: [
|
|
1918
|
+
{ nodeId: "n1", typeId: "base.math" },
|
|
1919
|
+
{ nodeId: "n2", typeId: "base.math" },
|
|
1920
|
+
// Transitivity demo nodes
|
|
1921
|
+
{ nodeId: "n3", typeId: "base.compare" },
|
|
1922
|
+
{ nodeId: "n4", typeId: "base.randomXYZs" },
|
|
1923
|
+
],
|
|
1924
|
+
edges: [
|
|
1925
|
+
{
|
|
1926
|
+
id: "e1",
|
|
1927
|
+
source: { nodeId: "n1", handle: "Result" },
|
|
1928
|
+
target: { nodeId: "n2", handle: "A" },
|
|
1929
|
+
},
|
|
1930
|
+
// Feed n2 result to comparer A
|
|
1931
|
+
{
|
|
1932
|
+
id: "e2",
|
|
1933
|
+
source: { nodeId: "n2", handle: "Result" },
|
|
1934
|
+
target: { nodeId: "n3", handle: "A" },
|
|
1935
|
+
},
|
|
1936
|
+
// Transitive coercion edge: bool[] (n3.Result) -> vec3 (n4.Min)
|
|
1937
|
+
// Path: bool[] -> float[] -> vec3[] -> vec3
|
|
1938
|
+
{
|
|
1939
|
+
id: "e3",
|
|
1940
|
+
source: { nodeId: "n3", handle: "Result" },
|
|
1941
|
+
target: { nodeId: "n4", handle: "Min" },
|
|
1942
|
+
},
|
|
1943
|
+
],
|
|
1944
|
+
};
|
|
1945
|
+
}
|
|
1758
1946
|
function createSimpleGraphDef() {
|
|
1759
1947
|
return makeBasicGraphDefinition();
|
|
1760
1948
|
}
|