@shaderfrog/core 1.2.0 → 1.3.1
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/cjs/package.json +1 -0
- package/esm/engine.d.ts +69 -0
- package/esm/engine.js +209 -0
- package/esm/graph/base-node.d.ts +36 -0
- package/esm/graph/base-node.js +9 -0
- package/esm/graph/code-nodes.d.ts +44 -0
- package/esm/graph/code-nodes.js +18 -0
- package/esm/graph/context.d.ts +37 -0
- package/esm/graph/context.js +243 -0
- package/esm/graph/data-nodes.d.ts +83 -0
- package/esm/graph/data-nodes.js +131 -0
- package/esm/graph/edge.d.ts +13 -0
- package/esm/graph/edge.js +7 -0
- package/esm/graph/evaluate.d.ts +9 -0
- package/esm/graph/evaluate.js +27 -0
- package/esm/graph/graph-node.d.ts +8 -0
- package/esm/graph/graph-node.js +135 -0
- package/esm/graph/graph-types.d.ts +38 -0
- package/esm/graph/graph-types.js +22 -0
- package/esm/graph/graph.d.ts +89 -0
- package/esm/graph/graph.js +506 -0
- package/esm/graph/graph.test.d.ts +1 -0
- package/esm/graph/graph.test.js +168 -0
- package/esm/graph/index.d.ts +11 -0
- package/esm/graph/index.js +11 -0
- package/esm/graph/parsers.d.ts +39 -0
- package/esm/graph/parsers.js +213 -0
- package/esm/graph/shader-sections.d.ts +47 -0
- package/esm/graph/shader-sections.js +256 -0
- package/esm/index.d.ts +3 -0
- package/esm/index.js +3 -0
- package/esm/package.json +1 -0
- package/esm/plugins/babylon/bablyengine.d.ts +28 -0
- package/esm/plugins/babylon/bablyengine.js +589 -0
- package/esm/plugins/babylon/importers.d.ts +3 -0
- package/esm/plugins/babylon/importers.js +64 -0
- package/esm/plugins/babylon/index.d.ts +2 -0
- package/esm/plugins/babylon/index.js +2 -0
- package/esm/plugins/playcanvas/importers.d.ts +3 -0
- package/esm/plugins/playcanvas/importers.js +28 -0
- package/esm/plugins/playcanvas/index.d.ts +2 -0
- package/esm/plugins/playcanvas/index.js +2 -0
- package/esm/plugins/playcanvas/playengine.d.ts +39 -0
- package/esm/plugins/playcanvas/playengine.js +517 -0
- package/esm/plugins/three/importers.d.ts +3 -0
- package/esm/plugins/three/importers.js +15 -0
- package/esm/plugins/three/index.d.ts +2 -0
- package/esm/plugins/three/index.js +2 -0
- package/esm/plugins/three/threngine.d.ts +34 -0
- package/esm/plugins/three/threngine.js +608 -0
- package/esm/strategy/assignemntTo.d.ts +9 -0
- package/esm/strategy/assignemntTo.js +26 -0
- package/esm/strategy/declarationOf.d.ts +9 -0
- package/esm/strategy/declarationOf.js +23 -0
- package/esm/strategy/hardCode.d.ts +15 -0
- package/esm/strategy/hardCode.js +23 -0
- package/esm/strategy/index.d.ts +9 -0
- package/esm/strategy/index.js +9 -0
- package/esm/strategy/inject.d.ts +15 -0
- package/esm/strategy/inject.js +122 -0
- package/esm/strategy/namedAttribute.d.ts +9 -0
- package/esm/strategy/namedAttribute.js +48 -0
- package/esm/strategy/strategy.d.ts +28 -0
- package/esm/strategy/strategy.js +31 -0
- package/esm/strategy/stratgies.test.d.ts +1 -0
- package/esm/strategy/stratgies.test.js +164 -0
- package/esm/strategy/texture2D.d.ts +6 -0
- package/esm/strategy/texture2D.js +83 -0
- package/esm/strategy/uniform.d.ts +6 -0
- package/esm/strategy/uniform.js +190 -0
- package/esm/strategy/variable.d.ts +6 -0
- package/esm/strategy/variable.js +80 -0
- package/esm/util/ast.d.ts +30 -0
- package/esm/util/ast.js +332 -0
- package/esm/util/ensure.d.ts +1 -0
- package/esm/util/ensure.js +7 -0
- package/esm/util/id.d.ts +1 -0
- package/esm/util/id.js +2 -0
- package/package.json +10 -11
- /package/{engine.d.ts → cjs/engine.d.ts} +0 -0
- /package/{engine.js → cjs/engine.js} +0 -0
- /package/{graph → cjs/graph}/base-node.d.ts +0 -0
- /package/{graph → cjs/graph}/base-node.js +0 -0
- /package/{graph → cjs/graph}/code-nodes.d.ts +0 -0
- /package/{graph → cjs/graph}/code-nodes.js +0 -0
- /package/{graph → cjs/graph}/context.d.ts +0 -0
- /package/{graph → cjs/graph}/context.js +0 -0
- /package/{graph → cjs/graph}/data-nodes.d.ts +0 -0
- /package/{graph → cjs/graph}/data-nodes.js +0 -0
- /package/{graph → cjs/graph}/edge.d.ts +0 -0
- /package/{graph → cjs/graph}/edge.js +0 -0
- /package/{graph → cjs/graph}/evaluate.d.ts +0 -0
- /package/{graph → cjs/graph}/evaluate.js +0 -0
- /package/{graph → cjs/graph}/graph-node.d.ts +0 -0
- /package/{graph → cjs/graph}/graph-node.js +0 -0
- /package/{graph → cjs/graph}/graph-types.d.ts +0 -0
- /package/{graph → cjs/graph}/graph-types.js +0 -0
- /package/{graph → cjs/graph}/graph.d.ts +0 -0
- /package/{graph → cjs/graph}/graph.js +0 -0
- /package/{graph → cjs/graph}/graph.test.d.ts +0 -0
- /package/{graph → cjs/graph}/graph.test.js +0 -0
- /package/{graph → cjs/graph}/index.d.ts +0 -0
- /package/{graph → cjs/graph}/index.js +0 -0
- /package/{graph → cjs/graph}/parsers.d.ts +0 -0
- /package/{graph → cjs/graph}/parsers.js +0 -0
- /package/{graph → cjs/graph}/shader-sections.d.ts +0 -0
- /package/{graph → cjs/graph}/shader-sections.js +0 -0
- /package/{index.d.ts → cjs/index.d.ts} +0 -0
- /package/{index.js → cjs/index.js} +0 -0
- /package/{plugins → cjs/plugins}/babylon/bablyengine.d.ts +0 -0
- /package/{plugins → cjs/plugins}/babylon/bablyengine.js +0 -0
- /package/{plugins → cjs/plugins}/babylon/importers.d.ts +0 -0
- /package/{plugins → cjs/plugins}/babylon/importers.js +0 -0
- /package/{plugins → cjs/plugins}/babylon/index.d.ts +0 -0
- /package/{plugins → cjs/plugins}/babylon/index.js +0 -0
- /package/{plugins → cjs/plugins}/playcanvas/importers.d.ts +0 -0
- /package/{plugins → cjs/plugins}/playcanvas/importers.js +0 -0
- /package/{plugins → cjs/plugins}/playcanvas/index.d.ts +0 -0
- /package/{plugins → cjs/plugins}/playcanvas/index.js +0 -0
- /package/{plugins → cjs/plugins}/playcanvas/playengine.d.ts +0 -0
- /package/{plugins → cjs/plugins}/playcanvas/playengine.js +0 -0
- /package/{plugins → cjs/plugins}/three/importers.d.ts +0 -0
- /package/{plugins → cjs/plugins}/three/importers.js +0 -0
- /package/{plugins → cjs/plugins}/three/index.d.ts +0 -0
- /package/{plugins → cjs/plugins}/three/index.js +0 -0
- /package/{plugins → cjs/plugins}/three/threngine.d.ts +0 -0
- /package/{plugins → cjs/plugins}/three/threngine.js +0 -0
- /package/{strategy → cjs/strategy}/assignemntTo.d.ts +0 -0
- /package/{strategy → cjs/strategy}/assignemntTo.js +0 -0
- /package/{strategy → cjs/strategy}/declarationOf.d.ts +0 -0
- /package/{strategy → cjs/strategy}/declarationOf.js +0 -0
- /package/{strategy → cjs/strategy}/hardCode.d.ts +0 -0
- /package/{strategy → cjs/strategy}/hardCode.js +0 -0
- /package/{strategy → cjs/strategy}/index.d.ts +0 -0
- /package/{strategy → cjs/strategy}/index.js +0 -0
- /package/{strategy → cjs/strategy}/inject.d.ts +0 -0
- /package/{strategy → cjs/strategy}/inject.js +0 -0
- /package/{strategy → cjs/strategy}/namedAttribute.d.ts +0 -0
- /package/{strategy → cjs/strategy}/namedAttribute.js +0 -0
- /package/{strategy → cjs/strategy}/strategy.d.ts +0 -0
- /package/{strategy → cjs/strategy}/strategy.js +0 -0
- /package/{strategy → cjs/strategy}/stratgies.test.d.ts +0 -0
- /package/{strategy → cjs/strategy}/stratgies.test.js +0 -0
- /package/{strategy → cjs/strategy}/texture2D.d.ts +0 -0
- /package/{strategy → cjs/strategy}/texture2D.js +0 -0
- /package/{strategy → cjs/strategy}/uniform.d.ts +0 -0
- /package/{strategy → cjs/strategy}/uniform.js +0 -0
- /package/{strategy → cjs/strategy}/variable.d.ts +0 -0
- /package/{strategy → cjs/strategy}/variable.js +0 -0
- /package/{util → cjs/util}/ast.d.ts +0 -0
- /package/{util → cjs/util}/ast.js +0 -0
- /package/{util → cjs/util}/ensure.d.ts +0 -0
- /package/{util → cjs/util}/ensure.js +0 -0
- /package/{util → cjs/util}/id.d.ts +0 -0
- /package/{util → cjs/util}/id.js +0 -0
package/cjs/package.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type": "commonjs"}
|
package/esm/engine.d.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Program } from '@shaderfrog/glsl-parser/ast';
|
|
2
|
+
import { MergeOptions } from './graph/shader-sections';
|
|
3
|
+
import { Graph, ShaderStage } from './graph/graph-types';
|
|
4
|
+
import { NodePosition } from './graph/base-node';
|
|
5
|
+
import { DataNode, UniformDataType } from './graph/data-nodes';
|
|
6
|
+
import { CodeNode, NodeProperty, SourceNode } from './graph/code-nodes';
|
|
7
|
+
import { NodeContext } from './graph/context';
|
|
8
|
+
import { NodeParser } from './graph/parsers';
|
|
9
|
+
export declare enum EngineNodeType {
|
|
10
|
+
toon = "toon",
|
|
11
|
+
phong = "phong",
|
|
12
|
+
physical = "physical",
|
|
13
|
+
shader = "shader",
|
|
14
|
+
binary = "binary"
|
|
15
|
+
}
|
|
16
|
+
export type PhongNodeConstructor = (id: string, name: string, position: NodePosition, uniforms: UniformDataType[], stage: ShaderStage | undefined) => CodeNode;
|
|
17
|
+
export type PhysicalNodeConstructor = (id: string, name: string, position: NodePosition, uniforms: UniformDataType[], stage: ShaderStage | undefined) => CodeNode;
|
|
18
|
+
export type ToonNodeConstructor = (id: string, name: string, position: NodePosition, uniforms: UniformDataType[], stage: ShaderStage | undefined) => CodeNode;
|
|
19
|
+
export interface Engine {
|
|
20
|
+
name: 'three' | 'babylon' | 'playcanvas';
|
|
21
|
+
displayName: string;
|
|
22
|
+
preserve: Set<string>;
|
|
23
|
+
mergeOptions: MergeOptions;
|
|
24
|
+
parsers: Record<string, NodeParser>;
|
|
25
|
+
importers: EngineImporters;
|
|
26
|
+
evaluateNode: (node: DataNode) => any;
|
|
27
|
+
constructors: {
|
|
28
|
+
[EngineNodeType.phong]?: PhongNodeConstructor;
|
|
29
|
+
[EngineNodeType.physical]?: PhysicalNodeConstructor;
|
|
30
|
+
[EngineNodeType.toon]?: ToonNodeConstructor;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export type EngineContext = {
|
|
34
|
+
engine: string;
|
|
35
|
+
nodes: Record<string, NodeContext>;
|
|
36
|
+
runtime: any;
|
|
37
|
+
debuggingNonsense: {
|
|
38
|
+
vertexSource?: string;
|
|
39
|
+
vertexPreprocessed?: string;
|
|
40
|
+
fragmentPreprocessed?: string;
|
|
41
|
+
fragmentSource?: string;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
export type EngineImporter = {
|
|
45
|
+
convertAst(ast: Program, type?: ShaderStage): void;
|
|
46
|
+
nodeInputMap: Partial<Record<EngineNodeType, Record<string, string | null>>>;
|
|
47
|
+
edgeMap: {
|
|
48
|
+
[oldInput: string]: string;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
export type EngineImporters = {
|
|
52
|
+
[engine: string]: EngineImporter;
|
|
53
|
+
};
|
|
54
|
+
export declare const convertNode: (node: SourceNode, converter: EngineImporter) => SourceNode;
|
|
55
|
+
export declare const convertToEngine: (oldEngine: Engine, newEngine: Engine, graph: Graph) => Graph;
|
|
56
|
+
export type DefaultPropertySetter = (p: NodeProperty) => any;
|
|
57
|
+
/**
|
|
58
|
+
* Create the initial engine node properties for a plugin to create its initial
|
|
59
|
+
* material with. This finds all engine nodes in the graph, finds all their
|
|
60
|
+
* properties, evalutes them, and returns an object with initial properties to
|
|
61
|
+
* set on the new plugin material, like a three.RawShaderMaterial().
|
|
62
|
+
*
|
|
63
|
+
* Currently only PlayCanvas uses this. It's at odds with the compileResult.dataInputs
|
|
64
|
+
* code path. That path uses isDataNode() to check for inputs, which excludes
|
|
65
|
+
* baked inputs. PlayCanvas requires (at least diffusesMap?) baked input properties
|
|
66
|
+
* to be set to a pc.Texture() at runtime, otherwise there's an error about
|
|
67
|
+
* vertex_texCoord0.
|
|
68
|
+
*/
|
|
69
|
+
export declare const collectInitialEvaluatedGraphProperties: (engine: Engine, graph: Graph, defaultPropertySetting: DefaultPropertySetter) => Record<string, any>;
|
package/esm/engine.js
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
13
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
14
|
+
if (!m) return o;
|
|
15
|
+
var i = m.call(o), r, ar = [], e;
|
|
16
|
+
try {
|
|
17
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
18
|
+
}
|
|
19
|
+
catch (error) { e = { error: error }; }
|
|
20
|
+
finally {
|
|
21
|
+
try {
|
|
22
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
23
|
+
}
|
|
24
|
+
finally { if (e) throw e.error; }
|
|
25
|
+
}
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
29
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
30
|
+
if (ar || !(i in from)) {
|
|
31
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
32
|
+
ar[i] = from[i];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
36
|
+
};
|
|
37
|
+
import preprocess from '@shaderfrog/glsl-parser/preprocessor';
|
|
38
|
+
import { generate, parser } from '@shaderfrog/glsl-parser';
|
|
39
|
+
import { NodeType } from './graph/graph-types';
|
|
40
|
+
import groupBy from 'lodash.groupby';
|
|
41
|
+
import { collectNodeProperties } from './graph/graph';
|
|
42
|
+
import { evaluateNode } from './graph/evaluate';
|
|
43
|
+
var log = function () {
|
|
44
|
+
var _a;
|
|
45
|
+
var args = [];
|
|
46
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
47
|
+
args[_i] = arguments[_i];
|
|
48
|
+
}
|
|
49
|
+
return (_a = console.log).call.apply(_a, __spreadArray([console, '\x1b[32m(core)\x1b[0m'], __read(args), false));
|
|
50
|
+
};
|
|
51
|
+
export var EngineNodeType;
|
|
52
|
+
(function (EngineNodeType) {
|
|
53
|
+
EngineNodeType["toon"] = "toon";
|
|
54
|
+
EngineNodeType["phong"] = "phong";
|
|
55
|
+
EngineNodeType["physical"] = "physical";
|
|
56
|
+
EngineNodeType["shader"] = "shader";
|
|
57
|
+
EngineNodeType["binary"] = "binary";
|
|
58
|
+
})(EngineNodeType || (EngineNodeType = {}));
|
|
59
|
+
// type EdgeUpdates = { [edgeId: string]: { oldInput: string; newInput: string } };
|
|
60
|
+
export var convertNode = function (node, converter) {
|
|
61
|
+
log("Converting ".concat(node.name, " (").concat(node.id, ")"));
|
|
62
|
+
var preprocessed = preprocess(node.source, {
|
|
63
|
+
preserveComments: true,
|
|
64
|
+
preserve: {
|
|
65
|
+
version: function () { return true; },
|
|
66
|
+
define: function () { return true; },
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
var ast = parser.parse(preprocessed);
|
|
70
|
+
converter.convertAst(ast, node.stage);
|
|
71
|
+
var source = generate(ast);
|
|
72
|
+
return __assign(__assign({}, node), { source: source });
|
|
73
|
+
};
|
|
74
|
+
export var convertToEngine = function (oldEngine, newEngine, graph) {
|
|
75
|
+
var converter = newEngine.importers[oldEngine.name];
|
|
76
|
+
if (!converter) {
|
|
77
|
+
throw new Error("The engine ".concat(newEngine.name, " has no importer for ").concat(oldEngine.name));
|
|
78
|
+
}
|
|
79
|
+
log("Attempting to convert from ".concat(newEngine.name, " to ").concat(oldEngine.name));
|
|
80
|
+
// const edgeUpdates: EdgeUpdates = {};
|
|
81
|
+
var edgesByNodeId = groupBy(graph.edges, 'to');
|
|
82
|
+
var edgeUpdates = {};
|
|
83
|
+
var nodeUpdates = {};
|
|
84
|
+
graph.nodes.forEach(function (node) {
|
|
85
|
+
// Convert engine nodes
|
|
86
|
+
if (node.type in EngineNodeType) {
|
|
87
|
+
if (node.type in newEngine.constructors) {
|
|
88
|
+
var source = node;
|
|
89
|
+
nodeUpdates[source.id] = // @ts-ignore
|
|
90
|
+
newEngine.constructors[source.type](source.id, source.name, source.position, source.config.uniforms, source.stage);
|
|
91
|
+
// Bail if no conversion
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
throw new Error("Can't convert ".concat(oldEngine.name, " to ").concat(newEngine.name, " because ").concat(newEngine.name, " does not have a \"").concat(node.type, "\" constructor"));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
else if (NodeType.SOURCE === node.type) {
|
|
98
|
+
nodeUpdates[node.id] = convertNode(node, converter);
|
|
99
|
+
}
|
|
100
|
+
// Then update input edges. We only care about engine nodes
|
|
101
|
+
if (node.type in converter.nodeInputMap) {
|
|
102
|
+
var map_1 = converter.nodeInputMap[node.type];
|
|
103
|
+
(edgesByNodeId[node.id] || []).forEach(function (edge) {
|
|
104
|
+
if (edge.input in map_1) {
|
|
105
|
+
var mapped = map_1[edge.input];
|
|
106
|
+
log('Converting edge', edge.input, 'to', map_1[edge.input]);
|
|
107
|
+
edgeUpdates[edge.id] = __assign(__assign({}, edge), { input: mapped });
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
log('Discarding', edge.input, 'as there is no edge mapping in the', newEngine.name, 'importer');
|
|
111
|
+
edgeUpdates[edge.id] = null;
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
graph.edges = graph.edges.reduce(function (edges, edge) {
|
|
117
|
+
if (edge.id in edgeUpdates) {
|
|
118
|
+
var res = edgeUpdates[edge.id];
|
|
119
|
+
if (res === null) {
|
|
120
|
+
return edges;
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
return __spreadArray(__spreadArray([], __read(edges), false), [res], false);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return __spreadArray(__spreadArray([], __read(edges), false), [edge], false);
|
|
127
|
+
}, []);
|
|
128
|
+
graph.nodes = graph.nodes.reduce(function (nodes, node) {
|
|
129
|
+
if (node.id in nodeUpdates) {
|
|
130
|
+
var res = nodeUpdates[node.id];
|
|
131
|
+
if (res === null) {
|
|
132
|
+
return nodes;
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
return __spreadArray(__spreadArray([], __read(nodes), false), [res], false);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return __spreadArray(__spreadArray([], __read(nodes), false), [node], false);
|
|
139
|
+
}, []);
|
|
140
|
+
log('Created converted graph', graph);
|
|
141
|
+
return graph;
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* Create the initial engine node properties for a plugin to create its initial
|
|
145
|
+
* material with. This finds all engine nodes in the graph, finds all their
|
|
146
|
+
* properties, evalutes them, and returns an object with initial properties to
|
|
147
|
+
* set on the new plugin material, like a three.RawShaderMaterial().
|
|
148
|
+
*
|
|
149
|
+
* Currently only PlayCanvas uses this. It's at odds with the compileResult.dataInputs
|
|
150
|
+
* code path. That path uses isDataNode() to check for inputs, which excludes
|
|
151
|
+
* baked inputs. PlayCanvas requires (at least diffusesMap?) baked input properties
|
|
152
|
+
* to be set to a pc.Texture() at runtime, otherwise there's an error about
|
|
153
|
+
* vertex_texCoord0.
|
|
154
|
+
*/
|
|
155
|
+
export var collectInitialEvaluatedGraphProperties = function (engine, graph, defaultPropertySetting) {
|
|
156
|
+
var graphProperties = {};
|
|
157
|
+
// Get all the nodes with properties, meaning engine nodes, and the inputs
|
|
158
|
+
// for each property (property is like "diffuseMap").
|
|
159
|
+
var _a = collectNodeProperties(graph), nodes = _a.nodes, inputs = _a.inputs;
|
|
160
|
+
Object.entries(inputs).forEach(function (_a) {
|
|
161
|
+
var _b = __read(_a, 2), nodeId = _b[0], nodeInputs = _b[1];
|
|
162
|
+
// For every node with properties... There might be mulitple if there are
|
|
163
|
+
// uniforms plugged into both frag and vertex engine nodes, which
|
|
164
|
+
var node = nodes[nodeId];
|
|
165
|
+
nodeInputs.forEach(function (i) {
|
|
166
|
+
// Cast this to an input with a property specified on it, which the
|
|
167
|
+
// predicate search enforces
|
|
168
|
+
var input = i;
|
|
169
|
+
var edge = graph.edges.find(function (_a) {
|
|
170
|
+
var to = _a.to, i = _a.input;
|
|
171
|
+
return to === node.id && i === input.id;
|
|
172
|
+
});
|
|
173
|
+
// In the case where a node has been deleted from the graph,
|
|
174
|
+
// dataInputs won't have been udpated until a recompile completes
|
|
175
|
+
var fromNode = edge && graph.nodes.find(function (_a) {
|
|
176
|
+
var id = _a.id;
|
|
177
|
+
return id === edge.from;
|
|
178
|
+
});
|
|
179
|
+
if (fromNode) {
|
|
180
|
+
// If this is a baked input, we need to set the engine property to force
|
|
181
|
+
// whatever we're baking to generate.
|
|
182
|
+
if (input.baked) {
|
|
183
|
+
// Find the corresponding property on the node and get the default
|
|
184
|
+
// setting
|
|
185
|
+
var property = (node.config.properties || []).find(function (p) { return p.property === input.property; });
|
|
186
|
+
if (property) {
|
|
187
|
+
graphProperties[input.property] = defaultPropertySetting(property);
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
console.error('Property not found on input node', node, input);
|
|
191
|
+
throw new Error('Property not found on input node');
|
|
192
|
+
}
|
|
193
|
+
// Other inputs should(?) be data if not baked
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
try {
|
|
197
|
+
graphProperties[input.property] = evaluateNode(engine, graph, fromNode);
|
|
198
|
+
}
|
|
199
|
+
catch (err) {
|
|
200
|
+
console.error('Tried to evaluate a non-data node!', {
|
|
201
|
+
err: err,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
return graphProperties;
|
|
209
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base node stuff, used across all nodes
|
|
3
|
+
*/
|
|
4
|
+
import { GraphDataType } from './data-nodes';
|
|
5
|
+
export type InputCategory = 'data' | 'code';
|
|
6
|
+
export type InputType = 'uniform' | 'property' | 'filler';
|
|
7
|
+
export interface NodeInput {
|
|
8
|
+
displayName: string;
|
|
9
|
+
id: string;
|
|
10
|
+
type: InputType;
|
|
11
|
+
dataType?: GraphDataType;
|
|
12
|
+
accepts: InputCategory[];
|
|
13
|
+
baked?: boolean;
|
|
14
|
+
bakeable: boolean;
|
|
15
|
+
property?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare const nodeInput: (displayName: string, id: string, type: InputType, dataType: GraphDataType | undefined, accepts: InputCategory[], bakeable: boolean, property?: string) => NodeInput;
|
|
18
|
+
export interface NodeOutput {
|
|
19
|
+
name: string;
|
|
20
|
+
id: string;
|
|
21
|
+
dataType?: GraphDataType;
|
|
22
|
+
category: InputCategory;
|
|
23
|
+
}
|
|
24
|
+
export type NodePosition = {
|
|
25
|
+
x: number;
|
|
26
|
+
y: number;
|
|
27
|
+
};
|
|
28
|
+
export interface BaseNode {
|
|
29
|
+
id: string;
|
|
30
|
+
parentId?: string;
|
|
31
|
+
name: string;
|
|
32
|
+
type: string;
|
|
33
|
+
inputs: NodeInput[];
|
|
34
|
+
outputs: NodeOutput[];
|
|
35
|
+
position: NodePosition;
|
|
36
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ShaderStage } from './graph-types';
|
|
2
|
+
import { Strategy } from '../strategy';
|
|
3
|
+
import { GraphDataType, UniformDataType } from './data-nodes';
|
|
4
|
+
import { BaseNode, NodeInput } from './base-node';
|
|
5
|
+
export declare const mapInputName: (node: CodeNode, { id, displayName }: NodeInput) => string;
|
|
6
|
+
export type InputMapping = {
|
|
7
|
+
[original: string]: string;
|
|
8
|
+
};
|
|
9
|
+
export type NodeConfig = {
|
|
10
|
+
version: 2 | 3;
|
|
11
|
+
mangle?: boolean;
|
|
12
|
+
preprocess: boolean;
|
|
13
|
+
inputMapping?: InputMapping;
|
|
14
|
+
strategies: Strategy[];
|
|
15
|
+
uniforms: UniformDataType[];
|
|
16
|
+
properties?: NodeProperty[];
|
|
17
|
+
hardCodedProperties?: Record<string, any>;
|
|
18
|
+
};
|
|
19
|
+
export interface NodeProperty {
|
|
20
|
+
displayName: string;
|
|
21
|
+
type: GraphDataType;
|
|
22
|
+
property: string;
|
|
23
|
+
fillerName?: string;
|
|
24
|
+
defaultValue?: any;
|
|
25
|
+
}
|
|
26
|
+
export declare const property: (displayName: string, property: string, type: GraphDataType, fillerName?: string, defaultValue?: any) => NodeProperty;
|
|
27
|
+
export declare enum SourceType {
|
|
28
|
+
SHADER_PROGRAM = "Shader Program",
|
|
29
|
+
EXPRESSION = "Expression",
|
|
30
|
+
FN_BODY_FRAGMENT = "Function Body Fragment"
|
|
31
|
+
}
|
|
32
|
+
export interface CodeNode extends BaseNode {
|
|
33
|
+
config: NodeConfig;
|
|
34
|
+
engine: boolean;
|
|
35
|
+
source: string;
|
|
36
|
+
sourceType?: SourceType;
|
|
37
|
+
stage?: ShaderStage;
|
|
38
|
+
biStage?: boolean;
|
|
39
|
+
originalEngine?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface BinaryNode extends CodeNode {
|
|
42
|
+
operator: string;
|
|
43
|
+
}
|
|
44
|
+
export type SourceNode = BinaryNode | CodeNode;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export var mapInputName = function (node, _a) {
|
|
2
|
+
var _b, _c;
|
|
3
|
+
var id = _a.id, displayName = _a.displayName;
|
|
4
|
+
return ((_c = (_b = node.config) === null || _b === void 0 ? void 0 : _b.inputMapping) === null || _c === void 0 ? void 0 : _c[id]) || displayName;
|
|
5
|
+
};
|
|
6
|
+
export var property = function (displayName, property, type, fillerName, defaultValue) { return ({
|
|
7
|
+
displayName: displayName,
|
|
8
|
+
type: type,
|
|
9
|
+
property: property,
|
|
10
|
+
fillerName: fillerName,
|
|
11
|
+
defaultValue: defaultValue,
|
|
12
|
+
}); };
|
|
13
|
+
export var SourceType;
|
|
14
|
+
(function (SourceType) {
|
|
15
|
+
SourceType["SHADER_PROGRAM"] = "Shader Program";
|
|
16
|
+
SourceType["EXPRESSION"] = "Expression";
|
|
17
|
+
SourceType["FN_BODY_FRAGMENT"] = "Function Body Fragment";
|
|
18
|
+
})(SourceType || (SourceType = {}));
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { GlslSyntaxError } from '@shaderfrog/glsl-parser';
|
|
2
|
+
import { AstNode, Program } from '@shaderfrog/glsl-parser/ast';
|
|
3
|
+
import { Engine, EngineContext } from '../engine';
|
|
4
|
+
import { NodeInput } from './base-node';
|
|
5
|
+
import { Graph, GraphNode } from './graph-types';
|
|
6
|
+
import { InputFillers } from './parsers';
|
|
7
|
+
/**
|
|
8
|
+
* A node's context is the runtime / in-memory computed data associated with a
|
|
9
|
+
* graph node. It includes the parsed AST representation of the node, as well as
|
|
10
|
+
* the inputs found in that AST. It's not currently saved to the database.
|
|
11
|
+
*/
|
|
12
|
+
export type NodeContext = {
|
|
13
|
+
id?: string;
|
|
14
|
+
name?: string;
|
|
15
|
+
source?: string;
|
|
16
|
+
ast: AstNode | Program;
|
|
17
|
+
inputs?: NodeInput[];
|
|
18
|
+
inputFillers: InputFillers;
|
|
19
|
+
errors?: NodeErrors;
|
|
20
|
+
};
|
|
21
|
+
export type NodeErrors = {
|
|
22
|
+
type: 'errors';
|
|
23
|
+
nodeId: string;
|
|
24
|
+
errors: (GlslSyntaxError | string)[];
|
|
25
|
+
};
|
|
26
|
+
export declare const isError: (test: any) => test is NodeErrors;
|
|
27
|
+
export declare const computeContextForNodes: (engineContext: EngineContext, engine: Engine, graph: Graph, nodes: GraphNode[]) => Promise<NodeErrors | Record<string, NodeContext>>;
|
|
28
|
+
/**
|
|
29
|
+
* Compute the context for every node in the graph, done on initial graph load
|
|
30
|
+
* to compute the inputs/outputs for every node
|
|
31
|
+
*/
|
|
32
|
+
export declare const computeAllContexts: (engineContext: EngineContext, engine: Engine, graph: Graph) => Promise<NodeErrors>;
|
|
33
|
+
/**
|
|
34
|
+
* Compute the contexts for nodes starting from the outputs, working backwards.
|
|
35
|
+
* Used to only (re)-compute context for any actively used nodes
|
|
36
|
+
*/
|
|
37
|
+
export declare const computeGraphContext: (engineContext: EngineContext, engine: Engine, graph: Graph) => Promise<NodeErrors>;
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
13
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
14
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
15
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
16
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
17
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
18
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
22
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
23
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
24
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
25
|
+
function step(op) {
|
|
26
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
27
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
28
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
29
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
30
|
+
switch (op[0]) {
|
|
31
|
+
case 0: case 1: t = op; break;
|
|
32
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
33
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
34
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
35
|
+
default:
|
|
36
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
37
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
38
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
39
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
40
|
+
if (t[2]) _.ops.pop();
|
|
41
|
+
_.trys.pop(); continue;
|
|
42
|
+
}
|
|
43
|
+
op = body.call(thisArg, _);
|
|
44
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
45
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
49
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
50
|
+
if (!m) return o;
|
|
51
|
+
var i = m.call(o), r, ar = [], e;
|
|
52
|
+
try {
|
|
53
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
54
|
+
}
|
|
55
|
+
catch (error) { e = { error: error }; }
|
|
56
|
+
finally {
|
|
57
|
+
try {
|
|
58
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
59
|
+
}
|
|
60
|
+
finally { if (e) throw e.error; }
|
|
61
|
+
}
|
|
62
|
+
return ar;
|
|
63
|
+
};
|
|
64
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
65
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
66
|
+
if (ar || !(i in from)) {
|
|
67
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
68
|
+
ar[i] = from[i];
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
72
|
+
};
|
|
73
|
+
import groupBy from 'lodash.groupby';
|
|
74
|
+
import { mapInputName, SourceType } from './code-nodes';
|
|
75
|
+
import { NodeType } from './graph-types';
|
|
76
|
+
import { collectConnectedNodes, filterGraphFromNode, findLinkedNode, findLinkedVertexNodes, isSourceNode, mangleEntireProgram, } from './graph';
|
|
77
|
+
import { coreParsers } from './parsers';
|
|
78
|
+
var makeError = function (nodeId) {
|
|
79
|
+
var errors = [];
|
|
80
|
+
for (var _i = 1; _i < arguments.length; _i++) {
|
|
81
|
+
errors[_i - 1] = arguments[_i];
|
|
82
|
+
}
|
|
83
|
+
return ({
|
|
84
|
+
type: 'errors',
|
|
85
|
+
nodeId: nodeId,
|
|
86
|
+
errors: errors,
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
export var isError = function (test) {
|
|
90
|
+
return (test === null || test === void 0 ? void 0 : test.type) === 'errors';
|
|
91
|
+
};
|
|
92
|
+
// Merge existing node inputs, and inputs based on properties, with new ones
|
|
93
|
+
// found from the source code, using the *id* as the uniqueness key. Any filler input gets
|
|
94
|
+
// merged into property inputs with the same id. This preserves the
|
|
95
|
+
// "baked" property on node inputs which is toggle-able in the graph
|
|
96
|
+
var collapseNodeInputs = function (node, updatedInputs) {
|
|
97
|
+
return Object.values(groupBy(__spreadArray(__spreadArray([], __read(updatedInputs), false), __read(node.inputs), false), function (i) { return i.id; })).map(function (dupes) { return dupes.reduce(function (node, dupe) { return (__assign(__assign({}, node), dupe)); }); });
|
|
98
|
+
};
|
|
99
|
+
var computeNodeContext = function (engineContext, engine, graph, node) { return __awaiter(void 0, void 0, void 0, function () {
|
|
100
|
+
var parser, sibling, onBeforeCompile, manipulateAst, inputEdges, ast, dataInputs, computedInputs, nodeContext;
|
|
101
|
+
return __generator(this, function (_a) {
|
|
102
|
+
switch (_a.label) {
|
|
103
|
+
case 0:
|
|
104
|
+
parser = __assign(__assign({}, (coreParsers[node.type] || coreParsers[NodeType.SOURCE])), (engine.parsers[node.type] || {}));
|
|
105
|
+
sibling = findLinkedNode(graph, node.id);
|
|
106
|
+
onBeforeCompile = parser.onBeforeCompile, manipulateAst = parser.manipulateAst;
|
|
107
|
+
if (!onBeforeCompile) return [3 /*break*/, 2];
|
|
108
|
+
return [4 /*yield*/, onBeforeCompile(graph, engineContext, node, sibling)];
|
|
109
|
+
case 1:
|
|
110
|
+
_a.sent();
|
|
111
|
+
_a.label = 2;
|
|
112
|
+
case 2:
|
|
113
|
+
inputEdges = graph.edges.filter(function (edge) { return edge.to === node.id; });
|
|
114
|
+
try {
|
|
115
|
+
ast = parser.produceAst(engineContext, engine, graph, node, inputEdges);
|
|
116
|
+
if (manipulateAst) {
|
|
117
|
+
ast = manipulateAst(engineContext, engine, graph, ast, inputEdges, node, sibling);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
console.error('Error parsing source code!', { error: error, node: node });
|
|
122
|
+
return [2 /*return*/, makeError(node.id, error)];
|
|
123
|
+
}
|
|
124
|
+
dataInputs = groupBy(filterGraphFromNode(graph, node, {
|
|
125
|
+
input: function (input, b, c, fromNode) {
|
|
126
|
+
return input.bakeable && (fromNode === null || fromNode === void 0 ? void 0 : fromNode.type) === 'source';
|
|
127
|
+
},
|
|
128
|
+
}, 1).inputs[node.id] || [], 'id');
|
|
129
|
+
computedInputs = parser.findInputs(engineContext, ast, inputEdges, node, sibling);
|
|
130
|
+
node.inputs = collapseNodeInputs(node, computedInputs.map(function (_a) {
|
|
131
|
+
var _b = __read(_a, 1), i = _b[0];
|
|
132
|
+
return (__assign(__assign({}, i), { displayName: mapInputName(node, i) }));
|
|
133
|
+
})).map(function (input) { return (__assign(__assign({}, input), (input.id in dataInputs ? { baked: true } : {}))); });
|
|
134
|
+
nodeContext = {
|
|
135
|
+
ast: ast,
|
|
136
|
+
id: node.id,
|
|
137
|
+
inputFillers: computedInputs.reduce(function (acc, _a) {
|
|
138
|
+
var _b;
|
|
139
|
+
var _c = __read(_a, 3), input = _c[0], filler = _c[1], args = _c[2];
|
|
140
|
+
return (__assign(__assign({}, acc), (_b = {}, _b[input.id] = {
|
|
141
|
+
filler: filler,
|
|
142
|
+
args: args,
|
|
143
|
+
}, _b)));
|
|
144
|
+
}, {}),
|
|
145
|
+
};
|
|
146
|
+
// Skip mangling if the node tells us to, which probably means it's an engine
|
|
147
|
+
// node where we don't care about renaming all the variables, or if it's
|
|
148
|
+
// an expression, where we want to be in the context of other variables
|
|
149
|
+
// TODO: Use global undefined engine variables here?
|
|
150
|
+
if (node.config.mangle !== false &&
|
|
151
|
+
node.sourceType !== SourceType.EXPRESSION &&
|
|
152
|
+
node.sourceType !== SourceType.FN_BODY_FRAGMENT) {
|
|
153
|
+
mangleEntireProgram(engine, ast, node, findLinkedNode(graph, node.id));
|
|
154
|
+
}
|
|
155
|
+
return [2 /*return*/, nodeContext];
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
}); };
|
|
159
|
+
export var computeContextForNodes = function (engineContext, engine, graph, nodes) { return __awaiter(void 0, void 0, void 0, function () {
|
|
160
|
+
return __generator(this, function (_a) {
|
|
161
|
+
return [2 /*return*/, nodes
|
|
162
|
+
.filter(isSourceNode)
|
|
163
|
+
.reduce(function (ctx, node) { return __awaiter(void 0, void 0, void 0, function () {
|
|
164
|
+
var context, nodeContextOrError;
|
|
165
|
+
return __generator(this, function (_a) {
|
|
166
|
+
switch (_a.label) {
|
|
167
|
+
case 0: return [4 /*yield*/, ctx];
|
|
168
|
+
case 1:
|
|
169
|
+
context = _a.sent();
|
|
170
|
+
if (isError(context)) {
|
|
171
|
+
return [2 /*return*/, context];
|
|
172
|
+
}
|
|
173
|
+
return [4 /*yield*/, computeNodeContext(engineContext, engine, graph, node)];
|
|
174
|
+
case 2:
|
|
175
|
+
nodeContextOrError = _a.sent();
|
|
176
|
+
if (isError(nodeContextOrError)) {
|
|
177
|
+
return [2 /*return*/, nodeContextOrError];
|
|
178
|
+
}
|
|
179
|
+
context[node.id] = __assign(__assign({}, (context[node.id] || {})), nodeContextOrError);
|
|
180
|
+
return [2 /*return*/, context];
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}); }, Promise.resolve(engineContext.nodes))];
|
|
184
|
+
});
|
|
185
|
+
}); };
|
|
186
|
+
/**
|
|
187
|
+
* Compute the context for every node in the graph, done on initial graph load
|
|
188
|
+
* to compute the inputs/outputs for every node
|
|
189
|
+
*/
|
|
190
|
+
export var computeAllContexts = function (engineContext, engine, graph) { return __awaiter(void 0, void 0, void 0, function () {
|
|
191
|
+
var result;
|
|
192
|
+
return __generator(this, function (_a) {
|
|
193
|
+
switch (_a.label) {
|
|
194
|
+
case 0: return [4 /*yield*/, computeContextForNodes(engineContext, engine, graph, graph.nodes)];
|
|
195
|
+
case 1:
|
|
196
|
+
result = _a.sent();
|
|
197
|
+
if (isError(result)) {
|
|
198
|
+
return [2 /*return*/, result];
|
|
199
|
+
}
|
|
200
|
+
return [2 /*return*/];
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
}); };
|
|
204
|
+
/**
|
|
205
|
+
* Compute the contexts for nodes starting from the outputs, working backwards.
|
|
206
|
+
* Used to only (re)-compute context for any actively used nodes
|
|
207
|
+
*/
|
|
208
|
+
export var computeGraphContext = function (engineContext, engine, graph) { return __awaiter(void 0, void 0, void 0, function () {
|
|
209
|
+
var outputFrag, outputVert, vertexIds, fragmentIds, unlinkedNodes, vertNodesOrError, fragNodesOrError;
|
|
210
|
+
return __generator(this, function (_a) {
|
|
211
|
+
switch (_a.label) {
|
|
212
|
+
case 0:
|
|
213
|
+
outputFrag = graph.nodes.find(function (node) { return node.type === 'output' && node.stage === 'fragment'; });
|
|
214
|
+
if (!outputFrag) {
|
|
215
|
+
throw new Error('No fragment output in graph');
|
|
216
|
+
}
|
|
217
|
+
outputVert = graph.nodes.find(function (node) { return node.type === 'output' && node.stage === 'vertex'; });
|
|
218
|
+
if (!outputVert) {
|
|
219
|
+
throw new Error('No vertex output in graph');
|
|
220
|
+
}
|
|
221
|
+
vertexIds = collectConnectedNodes(graph, outputVert);
|
|
222
|
+
fragmentIds = collectConnectedNodes(graph, outputFrag);
|
|
223
|
+
unlinkedNodes = findLinkedVertexNodes(graph, vertexIds);
|
|
224
|
+
return [4 /*yield*/, computeContextForNodes(engineContext, engine, graph, __spreadArray(__spreadArray([
|
|
225
|
+
outputVert
|
|
226
|
+
], __read(Object.values(vertexIds).filter(function (node) { return node.id !== outputVert.id; })), false), __read(unlinkedNodes), false))];
|
|
227
|
+
case 1:
|
|
228
|
+
vertNodesOrError = _a.sent();
|
|
229
|
+
if (isError(vertNodesOrError)) {
|
|
230
|
+
return [2 /*return*/, vertNodesOrError];
|
|
231
|
+
}
|
|
232
|
+
return [4 /*yield*/, computeContextForNodes(engineContext, engine, graph, __spreadArray([
|
|
233
|
+
outputFrag
|
|
234
|
+
], __read(Object.values(fragmentIds).filter(function (node) { return node.id !== outputFrag.id; })), false))];
|
|
235
|
+
case 2:
|
|
236
|
+
fragNodesOrError = _a.sent();
|
|
237
|
+
if (isError(fragNodesOrError)) {
|
|
238
|
+
return [2 /*return*/, fragNodesOrError];
|
|
239
|
+
}
|
|
240
|
+
return [2 /*return*/];
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
}); };
|