@shaderfrog/core 1.0.10 → 1.1.0

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.
Files changed (45) hide show
  1. package/README.md +7 -0
  2. package/dist/engine.d.ts +8 -5
  3. package/dist/engine.js +1 -1
  4. package/dist/graph/base-node.d.ts +5 -3
  5. package/dist/graph/code-nodes.d.ts +6 -8
  6. package/dist/graph/code-nodes.js +1 -1
  7. package/dist/graph/context.d.ts +7 -5
  8. package/dist/graph/context.js +44 -31
  9. package/dist/graph/data-nodes.d.ts +22 -22
  10. package/dist/graph/data-nodes.js +9 -1
  11. package/dist/graph/edge.d.ts +3 -2
  12. package/dist/graph/edge.js +6 -0
  13. package/dist/graph/{engine-node.d.ts → graph-node.d.ts} +1 -8
  14. package/dist/graph/{engine-node.js → graph-node.js} +11 -65
  15. package/dist/graph/graph-types.d.ts +13 -0
  16. package/dist/graph/graph-types.js +15 -0
  17. package/dist/graph/graph.d.ts +22 -12
  18. package/dist/graph/graph.js +107 -50
  19. package/dist/graph/graph.test.js +3 -2
  20. package/dist/graph/index.d.ts +1 -1
  21. package/dist/graph/index.js +1 -1
  22. package/dist/graph/parsers.d.ts +2 -2
  23. package/dist/graph/parsers.js +7 -7
  24. package/dist/plugins/babylon/bablyengine.d.ts +2 -2
  25. package/dist/plugins/babylon/bablyengine.js +23 -16
  26. package/dist/plugins/playcanvas/playengine.d.ts +2 -2
  27. package/dist/plugins/playcanvas/playengine.js +32 -25
  28. package/dist/plugins/three/threngine.d.ts +5 -5
  29. package/dist/plugins/three/threngine.js +103 -38
  30. package/dist/strategy/assignemntTo.js +2 -2
  31. package/dist/strategy/declarationOf.js +2 -2
  32. package/dist/strategy/hardCode.js +1 -1
  33. package/dist/strategy/index.d.ts +1 -0
  34. package/dist/strategy/index.js +1 -0
  35. package/dist/strategy/inject.js +2 -2
  36. package/dist/strategy/namedAttribute.js +2 -2
  37. package/dist/strategy/strategy.d.ts +2 -2
  38. package/dist/strategy/strategy.js +1 -1
  39. package/dist/strategy/stratgies.test.js +7 -7
  40. package/dist/strategy/texture2D.js +2 -2
  41. package/dist/strategy/uniform.js +3 -3
  42. package/dist/strategy/variable.js +2 -2
  43. package/dist/util/ast.js +0 -1
  44. package/dist/util/id.js +1 -1
  45. package/package.json +4 -5
@@ -1,25 +1,19 @@
1
- import { EngineNodeType } from '../engine';
2
- import { prepopulatePropertyInputs } from './graph';
3
1
  import { NodeType } from './graph-types';
4
- import { assignemntToStrategy, namedAttributeStrategy, texture2DStrategy, uniformStrategy, variableStrategy, } from '../strategy';
5
- import { SourceType, property, } from './code-nodes';
6
- /**
7
- * TODO: These definitions should live outside of core since I'm trying to
8
- * refactor out this core folder to only know about nodes with config config,
9
- * where nodes like output/phong/physical are all configured at the
10
- * implementation level. "phong" shouldn't be in the core
11
- */
12
- export var sourceNode = function (id, name, position, config, source, stage, originalEngine, nextStageNodeId) { return ({
2
+ import { assignemntToStrategy, variableStrategy } from '../strategy';
3
+ import { SourceType } from './code-nodes';
4
+ export var sourceNode = function (id, name, position, config, source, stage, originalEngine) { return ({
13
5
  id: id,
14
6
  name: name,
15
- groupId: undefined,
16
7
  type: NodeType.SOURCE,
8
+ sourceType: SourceType.SHADER_PROGRAM,
9
+ engine: false,
17
10
  config: config,
18
11
  position: position,
19
12
  inputs: [],
20
13
  outputs: [
21
14
  {
22
15
  name: 'vector4',
16
+ dataType: 'vector4',
23
17
  category: 'data',
24
18
  id: '1',
25
19
  },
@@ -27,14 +21,14 @@ export var sourceNode = function (id, name, position, config, source, stage, ori
27
21
  source: source,
28
22
  stage: stage,
29
23
  originalEngine: originalEngine,
30
- nextStageNodeId: nextStageNodeId,
31
24
  }); };
32
25
  export var outputNode = function (id, name, position, stage) { return ({
33
26
  id: id,
34
27
  name: name,
35
28
  position: position,
36
- groupId: undefined,
37
29
  type: NodeType.OUTPUT,
30
+ sourceType: SourceType.SHADER_PROGRAM,
31
+ engine: false,
38
32
  config: {
39
33
  version: 3,
40
34
  mangle: false,
@@ -65,8 +59,8 @@ export var expressionNode = function (id, name, position, source) { return ({
65
59
  name: name,
66
60
  position: position,
67
61
  type: NodeType.SOURCE,
62
+ engine: false,
68
63
  sourceType: SourceType.EXPRESSION,
69
- groupId: undefined,
70
64
  stage: undefined,
71
65
  config: {
72
66
  uniforms: [],
@@ -85,60 +79,12 @@ export var expressionNode = function (id, name, position, source) { return ({
85
79
  ],
86
80
  source: source,
87
81
  }); };
88
- export var phongNode = function (id, name, groupId, position, stage, nextStageNodeId) {
89
- return prepopulatePropertyInputs({
90
- id: id,
91
- name: name,
92
- groupId: groupId,
93
- position: position,
94
- type: EngineNodeType.phong,
95
- config: {
96
- version: 3,
97
- uniforms: [],
98
- preprocess: true,
99
- mangle: false,
100
- properties: [
101
- property('Color', 'color', 'rgb', 'uniform_diffuse'),
102
- property('Emissive', 'emissive', 'rgb', 'uniform_emissive'),
103
- property('Emissive Map', 'emissiveMap', 'texture', 'filler_emissiveMap'),
104
- property('Emissive Intensity', 'emissiveIntensity', 'number', 'uniform_emissive'),
105
- property('Texture', 'map', 'texture', 'filler_map'),
106
- property('Normal Map', 'normalMap', 'texture', 'filler_normalMap'),
107
- property('Normal Scale', 'normalScale', 'vector2'),
108
- property('Shininess', 'shininess', 'number'),
109
- property('Reflectivity', 'reflectivity', 'number'),
110
- property('Refraction Ratio', 'refractionRatio', 'number'),
111
- property('Specular', 'specular', 'rgb', 'uniform_specular'),
112
- property('Specular Map', 'specularMap', 'texture', 'filler_specularMap'),
113
- property('Displacement Map', 'displacementMap', 'texture'),
114
- property('Env Map', 'envMap', 'samplerCube'),
115
- ],
116
- strategies: [
117
- uniformStrategy(),
118
- stage === 'fragment'
119
- ? texture2DStrategy()
120
- : namedAttributeStrategy('position'),
121
- ],
122
- },
123
- inputs: [],
124
- outputs: [
125
- {
126
- name: 'vector4',
127
- category: 'data',
128
- id: '1',
129
- },
130
- ],
131
- source: '',
132
- stage: stage,
133
- nextStageNodeId: nextStageNodeId,
134
- });
135
- };
136
82
  export var addNode = function (id, position) { return ({
137
83
  id: id,
138
84
  name: 'add',
139
85
  position: position,
140
86
  type: NodeType.BINARY,
141
- groupId: undefined,
87
+ engine: false,
142
88
  stage: undefined,
143
89
  config: {
144
90
  mangle: false,
@@ -164,7 +110,7 @@ export var multiplyNode = function (id, position) { return ({
164
110
  id: id,
165
111
  name: 'multiply',
166
112
  type: NodeType.BINARY,
167
- groupId: undefined,
113
+ engine: false,
168
114
  stage: undefined,
169
115
  position: position,
170
116
  config: {
@@ -12,6 +12,19 @@ import { SourceNode } from './code-nodes';
12
12
  * by then.
13
13
  */
14
14
  export type ShaderStage = 'fragment' | 'vertex';
15
+ /**
16
+ * The type applied to the edge representing a link between node stages
17
+ */
18
+ export declare enum EdgeLink {
19
+ NEXT_STAGE = "next_stage"
20
+ }
21
+ /**
22
+ * The handle types for links. These become <Handle /> ids
23
+ */
24
+ export declare enum LinkHandle {
25
+ NEXT_STAGE = "next_stage",
26
+ PREVIOUS_STAGE = "previous_stage"
27
+ }
15
28
  export declare enum NodeType {
16
29
  OUTPUT = "output",
17
30
  BINARY = "binary",
@@ -1,3 +1,18 @@
1
+ /**
2
+ * The type applied to the edge representing a link between node stages
3
+ */
4
+ export var EdgeLink;
5
+ (function (EdgeLink) {
6
+ EdgeLink["NEXT_STAGE"] = "next_stage";
7
+ })(EdgeLink || (EdgeLink = {}));
8
+ /**
9
+ * The handle types for links. These become <Handle /> ids
10
+ */
11
+ export var LinkHandle;
12
+ (function (LinkHandle) {
13
+ LinkHandle["NEXT_STAGE"] = "next_stage";
14
+ LinkHandle["PREVIOUS_STAGE"] = "previous_stage";
15
+ })(LinkHandle || (LinkHandle = {}));
1
16
  export var NodeType;
2
17
  (function (NodeType) {
3
18
  NodeType["OUTPUT"] = "output";
@@ -1,5 +1,6 @@
1
1
  import { Program } from '@shaderfrog/glsl-parser/ast';
2
2
  import { Engine, EngineContext } from '../engine';
3
+ import { NodeErrors } from './context';
3
4
  import { ShaderSections } from './shader-sections';
4
5
  import { DataNode } from './data-nodes';
5
6
  import { Edge } from './edge';
@@ -12,18 +13,29 @@ export declare const isSourceNode: (node: GraphNode) => node is SourceNode;
12
13
  export declare const findNode: (graph: Graph, id: string) => GraphNode;
13
14
  export declare const doesLinkThruShader: (graph: Graph, node: GraphNode) => boolean;
14
15
  export declare const nodeName: (node: GraphNode) => string;
15
- export declare const mangleName: (name: string, node: GraphNode) => string;
16
- export declare const mangleVar: (name: string, engine: Engine, node: GraphNode) => string;
17
- export declare const mangleEntireProgram: (ast: Program, node: SourceNode, engine: Engine) => void;
18
- export declare const mangleMainFn: (ast: Program, node: SourceNode) => void;
19
- type Predicates = {
20
- node?: (node: GraphNode, inputEdges: Edge[]) => boolean;
21
- input?: (input: NodeInput, node: GraphNode, inputEdge: Edge | undefined, fromNode: GraphNode | undefined) => boolean;
16
+ export declare const mangleName: (name: string, node: GraphNode, nextSibling?: GraphNode) => string;
17
+ export declare const mangleVar: (name: string, engine: Engine, node: GraphNode, sibling?: GraphNode) => string;
18
+ export declare const mangleEntireProgram: (engine: Engine, ast: Program, node: GraphNode, sibling?: GraphNode) => void;
19
+ export declare const mangleMainFn: (ast: Program, node: GraphNode, sibling?: GraphNode) => void;
20
+ export declare const ensureFromNode: (graph: Graph, inputEdge: Edge) => GraphNode;
21
+ export declare const resetGraphIds: (graph: Graph) => Graph;
22
+ export declare const findLinkedNode: (graph: Graph, id: string) => GraphNode;
23
+ /**
24
+ * Find any unconnected vertex nodes linked to collected fragment nodes
25
+ */
26
+ export declare const findLinkedVertexNodes: (graph: Graph, existingIds?: NodeIds) => GraphNode[];
27
+ export type Predicates = {
28
+ node?: (node: GraphNode, inputEdges: Edge[], lastResult: SearchResult) => boolean;
29
+ edge?: (input: NodeInput | undefined, node: GraphNode, inputEdge: Edge | undefined, fromNode: GraphNode | undefined, lastResult: SearchResult) => boolean;
30
+ input?: (input: NodeInput, node: GraphNode, inputEdge: Edge | undefined, fromNode: GraphNode | undefined, lastResult: SearchResult) => boolean;
22
31
  };
23
32
  export type SearchResult = {
24
33
  nodes: Record<string, GraphNode>;
25
34
  inputs: Record<string, NodeInput[]>;
35
+ edges: Edge[];
26
36
  };
37
+ export declare const consSearchResult: () => SearchResult;
38
+ export declare const mergeSearchResults: (a: SearchResult, b: SearchResult) => SearchResult;
27
39
  /**
28
40
  * Create the inputs on a node from the properties. This used to be done at
29
41
  * context time. Doing it at node creation time lets us auto-bake edges into
@@ -32,14 +44,12 @@ export type SearchResult = {
32
44
  export declare const prepopulatePropertyInputs: (node: CodeNode) => CodeNode;
33
45
  /**
34
46
  * Recursively filter the graph, starting from a specific node, looking for
35
- * nodes and edges that match predicates. This function returns the inputs for
36
- * matched edges, not the edges themselves, as a convenience for the only
37
- * consumer of this function, which is finding input names to use as uniforms.
47
+ * nodes and edges that match predicates.
38
48
  *
39
49
  * Inputs can only be filtered if the graph context has been computed, since
40
50
  * inputs aren't created until then.
41
51
  */
42
- export declare const filterGraphFromNode: (graph: Graph, node: GraphNode, predicates: Predicates, depth?: number) => SearchResult;
52
+ export declare const filterGraphFromNode: (graph: Graph, node: GraphNode, predicates: Predicates, depth?: number, lastResult?: SearchResult) => SearchResult;
43
53
  export declare const collectConnectedNodes: (graph: Graph, node: GraphNode) => NodeIds;
44
54
  export declare const filterGraphNodes: (graph: Graph, nodes: GraphNode[], filter: Predicates, depth?: number) => SearchResult;
45
55
  type NodeIds = Record<string, GraphNode>;
@@ -75,5 +85,5 @@ export type CompileResult = {
75
85
  dataNodes: Record<string, GraphNode>;
76
86
  dataInputs: IndexedDataInputs;
77
87
  };
78
- export declare const compileSource: (graph: Graph, engine: Engine, ctx: EngineContext) => Promise<CompileResult>;
88
+ export declare const compileSource: (graph: Graph, engine: Engine, ctx: EngineContext) => Promise<CompileResult | NodeErrors>;
79
89
  export {};
@@ -71,7 +71,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
71
71
  return to.concat(ar || Array.prototype.slice.call(from));
72
72
  };
73
73
  import { renameBindings, renameFunctions, } from '@shaderfrog/glsl-parser/parser/utils';
74
- import { computeGraphContext } from './context';
74
+ import { computeGraphContext, isError, } from './context';
75
75
  import { emptyShaderSections, findShaderSections, mergeShaderSections, shaderSectionsToProgram, } from './shader-sections';
76
76
  import { makeExpression } from '../util/ast';
77
77
  import { ensure } from '../util/ensure';
@@ -80,7 +80,7 @@ import { nodeInput } from './base-node';
80
80
  import { makeId } from '../util/id';
81
81
  import { coreParsers } from './parsers';
82
82
  import { toGlsl } from './evaluate';
83
- import { MAGIC_OUTPUT_STMTS, NodeType } from './graph-types';
83
+ import { EdgeLink, MAGIC_OUTPUT_STMTS, NodeType, } from './graph-types';
84
84
  import { generate } from '@shaderfrog/glsl-parser';
85
85
  var log = function () {
86
86
  var _a;
@@ -100,7 +100,7 @@ export var findNode = function (graph, id) {
100
100
  return ensure(graph.nodes.find(function (node) { return node.id === id; }));
101
101
  };
102
102
  export var doesLinkThruShader = function (graph, node) {
103
- var edges = graph.edges.filter(function (edge) { return edge.from === node.id; });
103
+ var edges = graph.edges.filter(function (edge) { return edge.type !== EdgeLink.NEXT_STAGE && edge.from === node.id; });
104
104
  if (edges.length === 0) {
105
105
  return false;
106
106
  }
@@ -120,72 +120,128 @@ export var doesLinkThruShader = function (graph, node) {
120
120
  export var nodeName = function (node) {
121
121
  return 'main_' + node.name.replace(/[^a-zA-Z0-9]/g, ' ').replace(/ +/g, '_');
122
122
  };
123
- export var mangleName = function (name, node) {
124
- // Mangle names by using the next stage id, if present
125
- var id = ('nextStageNodeId' in node && node.nextStageNodeId) || node.id;
123
+ export var mangleName = function (name, node, nextSibling) {
124
+ // Mangle a name to its next stage node, so the vertex suffix becomes the
125
+ // fragment id, but not the other way around.
126
+ var id = (nextSibling === null || nextSibling === void 0 ? void 0 : nextSibling.stage) === 'fragment'
127
+ ? nextSibling === null || nextSibling === void 0 ? void 0 : nextSibling.id
128
+ : node.id;
126
129
  return "".concat(name, "_").concat(id);
127
130
  };
128
- export var mangleVar = function (name, engine, node) {
129
- return engine.preserve.has(name) ? name : mangleName(name, node);
130
- };
131
- export var mangleEntireProgram = function (ast, node, engine) {
131
+ export var mangleVar = function (name, engine, node, sibling) { return (engine.preserve.has(name) ? name : mangleName(name, node, sibling)); };
132
+ export var mangleEntireProgram = function (engine, ast, node, sibling) {
132
133
  renameBindings(ast.scopes[0], function (name, n) {
133
- return n.doNotDescope ? name : mangleVar(name, engine, node);
134
+ return n.doNotDescope ? name : mangleVar(name, engine, node, sibling);
134
135
  });
135
- mangleMainFn(ast, node);
136
+ mangleMainFn(ast, node, sibling);
136
137
  };
137
- export var mangleMainFn = function (ast, node) {
138
+ export var mangleMainFn = function (ast, node, sibling) {
138
139
  renameFunctions(ast.scopes[0], function (name) {
139
- return name === 'main' ? nodeName(node) : mangleName(name, node);
140
+ return name === 'main' ? nodeName(node) : mangleName(name, node, sibling);
140
141
  });
141
142
  };
143
+ export var ensureFromNode = function (graph, inputEdge) {
144
+ return ensure(graph.nodes.find(function (_a) {
145
+ var id = _a.id;
146
+ return id === inputEdge.from;
147
+ }), "Orphaned edge! There is an edge fro \"".concat(inputEdge.from, "\" to \"").concat(inputEdge.to, "\", but from node ").concat(inputEdge.from, " does not exist in the graph."));
148
+ };
149
+ export var resetGraphIds = function (graph) {
150
+ var idMap = {};
151
+ var map = function (id) {
152
+ idMap[id] = idMap[id] || makeId();
153
+ return idMap[id];
154
+ };
155
+ return {
156
+ nodes: graph.nodes.map(function (n) { return (__assign(__assign(__assign({}, n), { id: map(n.id) }), (n.parentId ? { parentId: map(n.parentId) } : {}))); }),
157
+ edges: graph.edges.map(function (e) { return (__assign(__assign({}, e), { id: map(e.id), from: map(e.from), to: map(e.to) })); }),
158
+ };
159
+ };
160
+ export var findLinkedNode = function (graph, id) {
161
+ var edgeLink = graph.edges.find(function (e) { return e.type === EdgeLink.NEXT_STAGE && (e.from === id || e.to === id); });
162
+ var otherId = (edgeLink === null || edgeLink === void 0 ? void 0 : edgeLink.from) === id ? edgeLink === null || edgeLink === void 0 ? void 0 : edgeLink.to : edgeLink === null || edgeLink === void 0 ? void 0 : edgeLink.from;
163
+ return graph.nodes.find(function (node) { return node.id === otherId; });
164
+ };
165
+ /**
166
+ * Find any unconnected vertex nodes linked to collected fragment nodes
167
+ */
168
+ export var findLinkedVertexNodes = function (graph, existingIds) {
169
+ if (existingIds === void 0) { existingIds = {}; }
170
+ // Group edges by where they point
171
+ var edgeLinks = graph.edges
172
+ .filter(function (e) { return e.type === EdgeLink.NEXT_STAGE; })
173
+ .reduce(function (edges, edge) {
174
+ var _a;
175
+ return (__assign(__assign({}, edges), (_a = {}, _a[edge.to] = edge, _a[edge.from] = edge, _a)));
176
+ }, {});
177
+ return graph.nodes.filter(function (node) {
178
+ // If this is a vertex node
179
+ return isSourceNode(node) &&
180
+ node.stage === 'vertex' &&
181
+ // That's linked
182
+ node.id in edgeLinks &&
183
+ // And not already captured (this should probably just be a set)
184
+ !existingIds[node.id];
185
+ });
186
+ };
187
+ export var consSearchResult = function () { return ({
188
+ nodes: {},
189
+ inputs: {},
190
+ edges: [],
191
+ }); };
192
+ export var mergeSearchResults = function (a, b) { return ({
193
+ nodes: __assign(__assign({}, a.nodes), b.nodes),
194
+ inputs: __assign(__assign({}, a.inputs), b.inputs),
195
+ edges: __spreadArray(__spreadArray([], __read(a.edges), false), __read(b.edges), false),
196
+ }); };
142
197
  /**
143
198
  * Create the inputs on a node from the properties. This used to be done at
144
199
  * context time. Doing it at node creation time lets us auto-bake edges into
145
200
  * the node at initial graph creation time.
146
201
  */
147
202
  export var prepopulatePropertyInputs = function (node) { return (__assign(__assign({}, node), { inputs: __spreadArray(__spreadArray([], __read(node.inputs), false), __read((node.config.properties || []).map(function (property) {
148
- return nodeInput(property.displayName, "property_".concat(property.property), 'property', property.type, new Set(['data']), !!property.fillerName, // bakeable
203
+ return nodeInput(property.displayName, "property_".concat(property.property), 'property', property.type, ['data'], !!property.fillerName, // bakeable
149
204
  property.property);
150
205
  })), false) })); };
151
206
  /**
152
207
  * Recursively filter the graph, starting from a specific node, looking for
153
- * nodes and edges that match predicates. This function returns the inputs for
154
- * matched edges, not the edges themselves, as a convenience for the only
155
- * consumer of this function, which is finding input names to use as uniforms.
208
+ * nodes and edges that match predicates.
156
209
  *
157
210
  * Inputs can only be filtered if the graph context has been computed, since
158
211
  * inputs aren't created until then.
159
212
  */
160
- export var filterGraphFromNode = function (graph, node, predicates, depth) {
213
+ export var filterGraphFromNode = function (graph, node, predicates, depth, lastResult) {
161
214
  var _a;
162
215
  if (depth === void 0) { depth = Infinity; }
216
+ if (lastResult === void 0) { lastResult = consSearchResult(); }
163
217
  var inputs = node.inputs;
164
218
  var inputEdges = graph.edges.filter(function (edge) { return edge.to === node.id; });
165
- var nodeAcc = __assign({}, (predicates.node && predicates.node(node, inputEdges)
219
+ var nodeAcc = __assign({}, (predicates.node && predicates.node(node, inputEdges, lastResult)
166
220
  ? (_a = {}, _a[node.id] = node, _a) : {}));
221
+ var accumulatedResult = __assign(__assign({}, lastResult), { nodes: __assign(__assign({}, lastResult.nodes), nodeAcc) });
167
222
  return inputEdges.reduce(function (acc, inputEdge) {
168
223
  var _a;
169
224
  var input = inputs.find(function (i) { return i.id === inputEdge.input; });
170
- var fromNode = inputEdge
171
- ? ensure(graph.nodes.find(function (_a) {
172
- var id = _a.id;
173
- return id === inputEdge.from;
174
- }))
175
- : undefined;
225
+ var fromNode = inputEdge ? ensureFromNode(graph, inputEdge) : undefined;
176
226
  var inputAcc = __assign(__assign({}, acc.inputs), (input &&
177
227
  predicates.input &&
178
- predicates.input(input, node, inputEdge, fromNode)
228
+ predicates.input(input, node, inputEdge, fromNode, lastResult)
179
229
  ? (_a = {}, _a[node.id] = __spreadArray(__spreadArray([], __read((acc.inputs[node.id] || [])), false), [input], false), _a) : {}));
230
+ var edgeAcc = __spreadArray(__spreadArray([], __read(acc.edges), false), __read((predicates.edge &&
231
+ predicates.edge(input, node, inputEdge, fromNode, lastResult)
232
+ ? [inputEdge]
233
+ : [])), false);
234
+ // Add in the latest result of edges and inputs so that when we recurse into
235
+ // the next node, it has the latest accumulator
236
+ var intermediateAcc = __assign(__assign({}, acc), { inputs: inputAcc, edges: edgeAcc });
180
237
  if (inputEdge && fromNode && depth > 1) {
181
- var result = filterGraphFromNode(graph, fromNode, predicates, depth - 1);
182
- return {
183
- nodes: __assign(__assign({}, acc.nodes), result.nodes),
184
- inputs: __assign(__assign(__assign({}, acc.inputs), inputAcc), result.inputs),
185
- };
238
+ var result = filterGraphFromNode(graph, fromNode, predicates, depth - 1, intermediateAcc);
239
+ return mergeSearchResults(intermediateAcc, result);
240
+ }
241
+ else {
242
+ return intermediateAcc;
186
243
  }
187
- return __assign(__assign({}, acc), { inputs: __assign(__assign({}, acc.inputs), inputAcc) });
188
- }, { inputs: {}, nodes: nodeAcc });
244
+ }, accumulatedResult);
189
245
  };
190
246
  export var collectConnectedNodes = function (graph, node) {
191
247
  return filterGraphFromNode(graph, node, { node: function () { return true; } }).nodes;
@@ -197,11 +253,9 @@ export var filterGraphNodes = function (graph, nodes, filter, depth) {
197
253
  return {
198
254
  nodes: __assign(__assign({}, acc.nodes), result.nodes),
199
255
  inputs: __assign(__assign({}, acc.inputs), result.inputs),
256
+ edges: __assign(__assign({}, acc.edges), result.edges),
200
257
  };
201
- }, {
202
- nodes: {},
203
- inputs: {},
204
- });
258
+ }, consSearchResult());
205
259
  };
206
260
  // before data inputs were known by the input.category being node or data. I
207
261
  // tried updating inputs to have acepts: [code|data] and "baked" now is there a
@@ -231,16 +285,19 @@ export var compileNode = function (engine, graph, edges, engineContext, node, ac
231
285
  if (inputEdges.length) {
232
286
  var continuation_1 = emptyShaderSections();
233
287
  inputEdges
288
+ .filter(function (edge) { return edge.type !== EdgeLink.NEXT_STAGE; })
234
289
  .map(function (edge) { return ({
235
290
  edge: edge,
236
291
  fromNode: ensure(graph.nodes.find(function (node) { return edge.from === node.id; }), "GraphNode for edge ".concat(edge.from, " not found")),
237
292
  input: ensure(inputs.find(function (_a) {
238
293
  var id = _a.id;
239
294
  return id == edge.input;
240
- }), "GraphNode \"".concat(node.name, "\" has no input ").concat(edge.input, "!\nAvailable:").concat(inputs.map(function (_a) {
295
+ }), "GraphNode \"".concat(node.name, "\"").concat(node.stage ? " (".concat(node.stage, ")") : '', " has no input ").concat(edge.input, "!\nAvailable:").concat(inputs
296
+ .map(function (_a) {
241
297
  var id = _a.id;
242
298
  return id;
243
- }).join(', '))),
299
+ })
300
+ .join(', '))),
244
301
  }); })
245
302
  .filter(function (_a) {
246
303
  var input = _a.input;
@@ -272,7 +329,9 @@ export var compileNode = function (engine, graph, edges, engineContext, node, ac
272
329
  inputFillers: inputFillers,
273
330
  fillerName: fillerName,
274
331
  });
275
- throw new Error("Node \"".concat(node.name, "\" has no filler for input \"").concat(input.displayName, "\" named ").concat(fillerName));
332
+ throw new Error("Node \"".concat(node.name, "\"").concat(node.stage
333
+ ? " (".concat(node.stage, ")")
334
+ : '', " has no filler for input \"").concat(input.displayName, "\" named ").concat(fillerName));
276
335
  }
277
336
  /**
278
337
  * +------+ +------+
@@ -363,13 +422,7 @@ export var compileGraph = function (engineContext, engine, graph) {
363
422
  // given edges in the graph. Build invisible edges from these vertex nodes to
364
423
  // the hidden "mainStmts" input on the output node, which inlines the function
365
424
  // calls to those vertex main() statements and includes them in the output
366
- var orphanNodes = graph.nodes.filter(function (node) {
367
- return isSourceNode(node) &&
368
- node.stage === 'vertex' &&
369
- node.nextStageNodeId &&
370
- fragmentIds[node.nextStageNodeId] &&
371
- !vertexIds[node.id];
372
- });
425
+ var orphanNodes = findLinkedVertexNodes(graph, vertexIds);
373
426
  var orphanEdges = orphanNodes.map(function (node) { return ({
374
427
  id: makeId(),
375
428
  from: node.id,
@@ -415,15 +468,19 @@ export var collectNodeProperties = function (graph) {
415
468
  return {
416
469
  nodes: __assign(__assign({}, fragProperties.nodes), vertProperties.nodes),
417
470
  inputs: __assign(__assign({}, fragProperties.inputs), vertProperties.inputs),
471
+ edges: __assign(__assign({}, fragProperties.edges), vertProperties.edges),
418
472
  };
419
473
  };
420
474
  export var compileSource = function (graph, engine, ctx) { return __awaiter(void 0, void 0, void 0, function () {
421
- var compileResult, fragmentResult, vertexResult, dataInputs, dataNodes;
475
+ var result, compileResult, fragmentResult, vertexResult, dataInputs, dataNodes;
422
476
  return __generator(this, function (_a) {
423
477
  switch (_a.label) {
424
478
  case 0: return [4 /*yield*/, computeGraphContext(ctx, engine, graph)];
425
479
  case 1:
426
- _a.sent();
480
+ result = _a.sent();
481
+ if (isError(result)) {
482
+ return [2 /*return*/, result];
483
+ }
427
484
  compileResult = compileGraph(ctx, engine, graph);
428
485
  fragmentResult = generate(shaderSectionsToProgram(compileResult.fragment, engine.mergeOptions).program);
429
486
  vertexResult = generate(shaderSectionsToProgram(compileResult.vertex, engine.mergeOptions).program);
@@ -1,7 +1,7 @@
1
1
  import util from 'util';
2
2
  import { parser } from '@shaderfrog/glsl-parser';
3
3
  import { generate } from '@shaderfrog/glsl-parser';
4
- import { addNode } from './engine-node';
4
+ import { addNode } from './graph-node';
5
5
  import { shaderSectionsToProgram, mergeShaderSections, findShaderSections, } from './shader-sections';
6
6
  import { numberNode } from './data-nodes';
7
7
  import { makeEdge } from './edge';
@@ -36,16 +36,17 @@ var constructor = function () { return ({
36
36
  },
37
37
  id: '1',
38
38
  name: '1',
39
+ engine: true,
39
40
  type: '',
40
41
  inputs: [],
41
42
  outputs: [],
42
43
  position: { x: 0, y: 0 },
43
44
  source: '',
44
45
  stage: undefined,
45
- groupId: null,
46
46
  }); };
47
47
  var engine = {
48
48
  name: 'three',
49
+ displayName: 'Three.js',
49
50
  evaluateNode: function (node) {
50
51
  if (node.type === 'number') {
51
52
  return parseFloat(node.value);
@@ -1,6 +1,6 @@
1
1
  export * from './base-node';
2
2
  export * from './data-nodes';
3
- export * from './engine-node';
3
+ export * from './graph-node';
4
4
  export * from './code-nodes';
5
5
  export * from './edge';
6
6
  export * from './parsers';
@@ -1,6 +1,6 @@
1
1
  export * from './base-node';
2
2
  export * from './data-nodes';
3
- export * from './engine-node';
3
+ export * from './graph-node';
4
4
  export * from './code-nodes';
5
5
  export * from './edge';
6
6
  export * from './parsers';
@@ -17,14 +17,14 @@ type FillerArguments = AstNode[];
17
17
  export type ComputedInput = [NodeInput, InputFiller, FillerArguments?];
18
18
  export type ProduceAst = (engineContext: EngineContext, engine: Engine, graph: Graph, node: SourceNode, inputEdges: Edge[]) => AstNode | Program;
19
19
  export type OnBeforeCompile = (graph: Graph, engineContext: EngineContext, node: SourceNode, sibling?: SourceNode) => Promise<void>;
20
- export type ManipulateAst = (engineContext: EngineContext, engine: Engine, graph: Graph, node: SourceNode, ast: AstNode | Program, inputEdges: Edge[]) => AstNode | Program;
20
+ export type ManipulateAst = (engineContext: EngineContext, engine: Engine, graph: Graph, ast: AstNode | Program, inputEdges: Edge[], node: SourceNode, sibling: SourceNode) => AstNode | Program;
21
21
  export type NodeParser = {
22
22
  onBeforeCompile?: OnBeforeCompile;
23
23
  manipulateAst?: ManipulateAst;
24
24
  findInputs?: FindInputs;
25
25
  produceFiller?: ProduceNodeFiller;
26
26
  };
27
- export type FindInputs = (engineContext: EngineContext, node: SourceNode, ast: Program | AstNode, inputEdges: Edge[]) => ComputedInput[];
27
+ export type FindInputs = (engineContext: EngineContext, ast: Program | AstNode, inputEdges: Edge[], node: SourceNode, sibling: SourceNode) => ComputedInput[];
28
28
  export type ProduceNodeFiller = (node: SourceNode, ast: Program | AstNode) => Filler;
29
29
  type CoreNodeParser = {
30
30
  produceAst: ProduceAst;
@@ -98,10 +98,10 @@ export var coreParsers = (_a = {},
98
98
  }
99
99
  return ast;
100
100
  },
101
- findInputs: function (engineContext, node, ast) {
101
+ findInputs: function (engineContext, ast, edges, node, sibling) {
102
102
  var seen = new Set();
103
103
  return node.config.strategies
104
- .flatMap(function (strategy) { return applyStrategy(strategy, node, ast); })
104
+ .flatMap(function (strategy) { return applyStrategy(strategy, ast, node, sibling); })
105
105
  .filter(function (_a) {
106
106
  var _b = __read(_a, 2), input = _b[0], _ = _b[1];
107
107
  if (!seen.has(input.id)) {
@@ -125,12 +125,12 @@ export var coreParsers = (_a = {},
125
125
  produceAst: function (engineContext, engine, graph, node, inputEdges) {
126
126
  return parser.parse(node.source);
127
127
  },
128
- findInputs: function (engineContext, node, ast) {
128
+ findInputs: function (engineContext, ast, edges, node, sibling) {
129
129
  return __spreadArray(__spreadArray([], __read(node.config.strategies.flatMap(function (strategy) {
130
- return applyStrategy(strategy, node, ast);
130
+ return applyStrategy(strategy, ast, node, sibling);
131
131
  })), false), [
132
132
  [
133
- nodeInput(MAGIC_OUTPUT_STMTS, "filler_".concat(MAGIC_OUTPUT_STMTS), 'filler', 'rgba', new Set(['code']), false),
133
+ nodeInput(MAGIC_OUTPUT_STMTS, "filler_".concat(MAGIC_OUTPUT_STMTS), 'filler', 'rgba', ['code'], false),
134
134
  function (fillerAst) {
135
135
  var fn = ast.program.find(function (stmt) { return stmt.type === 'function'; });
136
136
  fn === null || fn === void 0 ? void 0 : fn.body.statements.unshift(makeFnStatement(generateFiller(fillerAst)));
@@ -154,13 +154,13 @@ export var coreParsers = (_a = {},
154
154
  : "a ".concat(node.operator, " b")) +
155
155
  ')');
156
156
  },
157
- findInputs: function (engineContext, node, ast, inputEdges) {
157
+ findInputs: function (engineContext, ast, inputEdges, node, sibling) {
158
158
  return new Array(Math.max(inputEdges.length + 1, 2))
159
159
  .fill(0)
160
160
  .map(function (_, index) {
161
161
  var letter = alphabet.charAt(index);
162
162
  return [
163
- nodeInput(letter, letter, 'filler', undefined, new Set(['data', 'code']), false),
163
+ nodeInput(letter, letter, 'filler', undefined, ['data', 'code'], false),
164
164
  function (fillerAst) {
165
165
  var foundPath;
166
166
  var visitors = {
@@ -5,7 +5,7 @@ import { CodeNode } from '../../graph/code-nodes';
5
5
  import { NodePosition } from '../../graph/base-node';
6
6
  import { UniformDataType } from '../../graph/data-nodes';
7
7
  export declare const physicalDefaultProperties: Partial<Record<keyof PBRMaterial, any>>;
8
- export declare const physicalNode: (id: string, name: string, groupId: string | null | undefined, position: NodePosition, uniforms: UniformDataType[], stage: ShaderStage | undefined, nextStageNodeId?: string) => CodeNode;
8
+ export declare const physicalNode: (id: string, name: string, position: NodePosition, uniforms: UniformDataType[], stage: ShaderStage | undefined) => CodeNode;
9
9
  export type RuntimeContext = {
10
10
  scene: Scene;
11
11
  camera: Camera;
@@ -23,6 +23,6 @@ export type RuntimeContext = {
23
23
  };
24
24
  };
25
25
  };
26
- export declare const toonNode: (id: string, name: string, groupId: string | null | undefined, position: NodePosition, uniforms: UniformDataType[], stage: ShaderStage | undefined, nextStageNodeId?: string) => CodeNode;
26
+ export declare const toonNode: (id: string, name: string, position: NodePosition, uniforms: UniformDataType[], stage: ShaderStage | undefined) => CodeNode;
27
27
  export declare let mIdx: number;
28
28
  export declare const babylengine: Engine;