@shaderfrog/core 2.0.0-beta.3 → 3.0.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 (49) hide show
  1. package/README.md +2 -2
  2. package/engine.d.ts +39 -3
  3. package/engine.js +5 -0
  4. package/graph/code-nodes.d.ts +8 -2
  5. package/graph/code-nodes.js +5 -1
  6. package/graph/context.d.ts +8 -6
  7. package/graph/context.js +53 -50
  8. package/graph/data-nodes.d.ts +15 -6
  9. package/graph/data-nodes.js +1 -1
  10. package/graph/evaluate.js +7 -0
  11. package/graph/graph-types.d.ts +26 -6
  12. package/graph/graph-types.js +69 -0
  13. package/graph/graph.d.ts +35 -4
  14. package/graph/graph.js +187 -143
  15. package/graph/graph.test.js +244 -54
  16. package/graph/parsers.d.ts +4 -12
  17. package/graph/parsers.js +32 -18
  18. package/graph/shader-sections.d.ts +31 -14
  19. package/graph/shader-sections.js +93 -19
  20. package/package.json +4 -4
  21. package/plugins/babylon/bablyengine.js +9 -10
  22. package/plugins/playcanvas/playengine.js +9 -10
  23. package/plugins/three/importers.d.ts +1 -0
  24. package/plugins/three/importers.js +49 -1
  25. package/plugins/three/threngine.d.ts +6 -4
  26. package/plugins/three/threngine.js +59 -39
  27. package/plugins/three/threngine.test.js +51 -4
  28. package/strategy/assignmentTo.d.ts +10 -0
  29. package/strategy/assignmentTo.js +35 -0
  30. package/strategy/declarationOf.js +2 -2
  31. package/strategy/hardCode.js +1 -4
  32. package/strategy/index.d.ts +1 -1
  33. package/strategy/index.js +1 -1
  34. package/strategy/inject.js +3 -4
  35. package/strategy/namedAttribute.js +2 -2
  36. package/strategy/strategy.d.ts +30 -5
  37. package/strategy/strategy.js +1 -1
  38. package/strategy/stratgies.test.js +59 -31
  39. package/strategy/texture2D.js +20 -22
  40. package/strategy/uniform.js +54 -56
  41. package/strategy/variable.js +5 -5
  42. package/util/ast.d.ts +9 -4
  43. package/util/ast.js +37 -8
  44. package/util/ast.test.d.ts +1 -0
  45. package/util/ast.test.js +14 -0
  46. package/util/indexByid.d.ts +4 -0
  47. package/util/indexByid.js +18 -0
  48. package/util/whitespace.d.ts +2 -0
  49. package/util/whitespace.js +22 -3
@@ -76,10 +76,11 @@ import { NodeType } from '../../graph/graph-types';
76
76
  import { prepopulatePropertyInputs, mangleMainFn } from '../../graph/graph';
77
77
  import importers from './importers';
78
78
  import { EngineNodeType } from '../../engine';
79
- import { doesLinkThruShader, nodeName } from '../../graph/graph';
79
+ import { doesLinkThruShader } from '../../graph/graph';
80
80
  import { returnGlPosition, returnGlPositionHardCoded, returnGlPositionVec3Right, } from '../../util/ast';
81
81
  import { property, } from '../../graph/code-nodes';
82
82
  import { namedAttributeStrategy, texture2DStrategy, uniformStrategy, } from '../../strategy';
83
+ import indexById from '../../util/indexByid';
83
84
  var log = function () {
84
85
  var _a;
85
86
  var args = [];
@@ -117,6 +118,8 @@ export var phongNode = function (id, name, position, uniforms, stage) {
117
118
  property('Specular Map', 'specularMap', 'texture', 'filler_specularMap'),
118
119
  property('Displacement Map', 'displacementMap', 'texture', 'filler_displacementMap'),
119
120
  property('Displacement Scale', 'displacementScale', 'number'),
121
+ property('Bump Map', 'bumpMap', 'texture', 'filler_bumpMap'),
122
+ property('Bump Scale', 'bumpScale', 'number'),
120
123
  property('Env Map', 'envMap', 'samplerCube'),
121
124
  ],
122
125
  strategies: [
@@ -167,6 +170,7 @@ export var physicalNode = function (id, name, position, uniforms, stage) {
167
170
  // MeshPhysicalMaterial gets envMap from the scene. MeshStandardMaterial
168
171
  // gets it from the material
169
172
  // property('Env Map', 'envMap', 'samplerCube'),
173
+ property('Env Map Intensity', 'envMapIntensity', 'number', 'uniform_envMapIntensity'),
170
174
  property('Transmission', 'transmission', 'number'),
171
175
  property('Transmission Map', 'transmissionMap', 'texture', 'filler_transmissionMap'),
172
176
  property('Thickness', 'thickness', 'number'),
@@ -176,6 +180,7 @@ export var physicalNode = function (id, name, position, uniforms, stage) {
176
180
  // property('Sheen', 'sheen', 'number'),
177
181
  property('Reflectivity', 'reflectivity', 'number'),
178
182
  property('Clearcoat', 'clearcoat', 'number'),
183
+ property('Clearcoat Roughness', 'clearcoatRoughness', 'number'),
179
184
  property('Iridescence', 'iridescence', 'number'),
180
185
  property('Iridescence IOR', 'iridescenceIOR', 'number'),
181
186
  property('Iridescence Thickness Range', 'iridescenceThicknessRange', 'array', undefined, ['100', '400']),
@@ -213,17 +218,13 @@ var cacher = function (engineContext, graph, node, sibling, newValue) {
213
218
  log('Cache miss', cacheKey);
214
219
  }
215
220
  var materialData = engineContext.runtime.cache.data[cacheKey] || newValue();
221
+ // This is nasty: We mutate the runtime context here, and return the partial
222
+ // nodeContext later. See also the TODO: Refactor in context.ts.
216
223
  engineContext.runtime.cache.data[cacheKey] = materialData;
217
224
  engineContext.runtime.engineMaterial = materialData.material;
218
- // TODO: We mutate the nodes here, can we avoid that later?
219
- node.source =
220
- node.stage === 'fragment' ? materialData.fragment : materialData.vertex;
221
- if (sibling) {
222
- sibling.source =
223
- sibling.stage === 'fragment'
224
- ? materialData.fragment
225
- : materialData.vertex;
226
- }
225
+ return {
226
+ computedSource: node.stage === 'fragment' ? materialData.fragment : materialData.vertex,
227
+ };
227
228
  };
228
229
  var onBeforeCompileMegaShader = function (engineContext, newMat) {
229
230
  log('compiling three megashader!');
@@ -262,7 +263,7 @@ var onBeforeCompileMegaShader = function (engineContext, newMat) {
262
263
  };
263
264
  var megaShaderMainpulateAst = function (engineContext, engine, graph, ast, inputEdges, node, sibling) {
264
265
  var programAst = ast;
265
- var mainName = 'main' || nodeName(node);
266
+ var mainName = 'main'; // || nodeName(node);
266
267
  if (node.stage === 'vertex') {
267
268
  if (doesLinkThruShader(graph, node)) {
268
269
  returnGlPositionHardCoded(mainName, programAst, 'vec3', 'transformed');
@@ -292,6 +293,7 @@ var nodeCacheKey = function (graph, node) {
292
293
  );
293
294
  };
294
295
  var programCacheKey = function (engineContext, graph, node, sibling) {
296
+ var _a, _b;
295
297
  // The megashader source is dependent on scene information, like the number
296
298
  // and type of lights in the scene. This kinda sucks - it's duplicating
297
299
  // three's material cache key, and is coupled to how three builds shaders
@@ -299,7 +301,7 @@ var programCacheKey = function (engineContext, graph, node, sibling) {
299
301
  var lights = [];
300
302
  scene.traverse(function (obj) {
301
303
  if (obj instanceof Light) {
302
- lights.push(obj.type);
304
+ lights.push(obj.uuid);
303
305
  }
304
306
  });
305
307
  return ([node, sibling]
@@ -309,8 +311,10 @@ var programCacheKey = function (engineContext, graph, node, sibling) {
309
311
  .join('-') +
310
312
  '|Lights:' +
311
313
  lights.join(',') +
312
- '|Envtex:' +
313
- scene.environmentTexture);
314
+ '|Bg:' +
315
+ ((_a = scene.background) === null || _a === void 0 ? void 0 : _a.uuid) +
316
+ '|Env:' +
317
+ ((_b = scene.environment) === null || _b === void 0 ? void 0 : _b.uuid));
314
318
  };
315
319
  export var defaultPropertySetting = function (property) {
316
320
  if (property.type === 'texture') {
@@ -328,12 +332,7 @@ export var defaultPropertySetting = function (property) {
328
332
  };
329
333
  var threeMaterialProperties = function (graph, node, sibling) {
330
334
  // Find inputs to this node that are dependent on a property of the material
331
- var propertyInputs = node.inputs
332
- .filter(function (i) { return i.property; })
333
- .reduce(function (acc, input) {
334
- var _a;
335
- return (__assign(__assign({}, acc), (_a = {}, _a[input.id] = input, _a)));
336
- }, {});
335
+ var propertyInputs = indexById(node.inputs.filter(function (i) { return i.property; }));
337
336
  // Then look for any edges into those inputs and set the material property
338
337
  return graph.edges
339
338
  .filter(function (edge) { return edge.to === node.id || edge.to === (sibling === null || sibling === void 0 ? void 0 : sibling.id); })
@@ -349,6 +348,24 @@ var threeMaterialProperties = function (graph, node, sibling) {
349
348
  return acc;
350
349
  }, {});
351
350
  };
351
+ export var stringifyThreeValue = function (input) {
352
+ if (input instanceof Vector2) {
353
+ return "new Vector2(".concat(input.x, ", ").concat(input.y, ")");
354
+ }
355
+ else if (input instanceof Vector3) {
356
+ return "new Vector3(".concat(input.x, ", ").concat(input.y, ", ").concat(input.z, ")");
357
+ }
358
+ else if (input instanceof Vector4) {
359
+ return "new Vector4(".concat(input.x, ", ").concat(input.y, ", ").concat(input.z, ", ").concat(input.w, ")");
360
+ }
361
+ else if (input instanceof Color) {
362
+ return "new Color(".concat(input.r, ", ").concat(input.g, ", ").concat(input.b, ")");
363
+ }
364
+ else if (input instanceof Texture) {
365
+ return "new Texture()";
366
+ }
367
+ return "".concat(input);
368
+ };
352
369
  var evaluateNode = function (node) {
353
370
  if (node.type === 'number') {
354
371
  return parseFloat(node.value);
@@ -395,6 +412,7 @@ export var toonNode = function (id, name, position, uniforms, stage) {
395
412
  property('Displacement Map', 'displacementMap', 'texture', 'filler_displacementMap'),
396
413
  property('Displacement Scale', 'displacementScale', 'number'),
397
414
  property('Env Map', 'envMap', 'samplerCube'),
415
+ property('Env Map Intensity', 'envMapIntensity', 'number'),
398
416
  ],
399
417
  strategies: [
400
418
  uniformStrategy(),
@@ -459,8 +477,9 @@ export var threngine = {
459
477
  'shininess',
460
478
  'opacity',
461
479
  'map',
480
+ 'IncidentLight',
481
+ 'ReflectedLight',
462
482
  'specularTint',
463
- 'time',
464
483
  'normalScale',
465
484
  'normalMap',
466
485
  'envMap',
@@ -502,12 +521,16 @@ export var threngine = {
502
521
  'displacementMap',
503
522
  'displacementScale',
504
523
  'displacementBias',
524
+ // passed by shaderfrog. maybe should have separate names? duplicated across
525
+ // all the engines.
526
+ 'time',
527
+ 'renderResolution',
505
528
  ]),
506
529
  parsers: (_b = {},
507
530
  _b[NodeType.SOURCE] = {
508
531
  manipulateAst: function (engineContext, engine, graph, ast, inputEdges, node, sibling) {
509
532
  var programAst = ast;
510
- var mainName = 'main' || nodeName(node);
533
+ var mainName = 'main'; // || nodeName(node);
511
534
  // This hinges on the vertex shader calling vec3(p)
512
535
  if (node.stage === 'vertex') {
513
536
  if (doesLinkThruShader(graph, node)) {
@@ -523,12 +546,11 @@ export var threngine = {
523
546
  _b[EngineNodeType.phong] = {
524
547
  onBeforeCompile: function (graph, engineContext, node, sibling) { return __awaiter(void 0, void 0, void 0, function () {
525
548
  return __generator(this, function (_a) {
526
- cacher(engineContext, graph, node, sibling, function () {
527
- return onBeforeCompileMegaShader(engineContext, new MeshPhongMaterial(__assign({
528
- // @ts-ignore
529
- isMeshPhongMaterial: true }, threeMaterialProperties(graph, node, sibling))));
530
- });
531
- return [2 /*return*/];
549
+ return [2 /*return*/, cacher(engineContext, graph, node, sibling, function () {
550
+ return onBeforeCompileMegaShader(engineContext, new MeshPhongMaterial(__assign({
551
+ // @ts-ignore
552
+ isMeshPhongMaterial: true }, threeMaterialProperties(graph, node, sibling))));
553
+ })];
532
554
  });
533
555
  }); },
534
556
  manipulateAst: megaShaderMainpulateAst,
@@ -536,10 +558,9 @@ export var threngine = {
536
558
  _b[EngineNodeType.physical] = {
537
559
  onBeforeCompile: function (graph, engineContext, node, sibling) { return __awaiter(void 0, void 0, void 0, function () {
538
560
  return __generator(this, function (_a) {
539
- cacher(engineContext, graph, node, sibling, function () {
540
- return onBeforeCompileMegaShader(engineContext, new MeshPhysicalMaterial(__assign(__assign({}, node.config.hardCodedProperties), threeMaterialProperties(graph, node, sibling))));
541
- });
542
- return [2 /*return*/];
561
+ return [2 /*return*/, cacher(engineContext, graph, node, sibling, function () {
562
+ return onBeforeCompileMegaShader(engineContext, new MeshPhysicalMaterial(__assign(__assign({}, node.config.hardCodedProperties), threeMaterialProperties(graph, node, sibling))));
563
+ })];
543
564
  });
544
565
  }); },
545
566
  manipulateAst: megaShaderMainpulateAst,
@@ -547,12 +568,11 @@ export var threngine = {
547
568
  _b[EngineNodeType.toon] = {
548
569
  onBeforeCompile: function (graph, engineContext, node, sibling) { return __awaiter(void 0, void 0, void 0, function () {
549
570
  return __generator(this, function (_a) {
550
- cacher(engineContext, graph, node, sibling, function () {
551
- return onBeforeCompileMegaShader(engineContext, new MeshToonMaterial(__assign({ gradientMap: new Texture(),
552
- // @ts-ignore
553
- isMeshToonMaterial: true }, threeMaterialProperties(graph, node, sibling))));
554
- });
555
- return [2 /*return*/];
571
+ return [2 /*return*/, cacher(engineContext, graph, node, sibling, function () {
572
+ return onBeforeCompileMegaShader(engineContext, new MeshToonMaterial(__assign({ gradientMap: new Texture(),
573
+ // @ts-ignore
574
+ isMeshToonMaterial: true }, threeMaterialProperties(graph, node, sibling))));
575
+ })];
556
576
  });
557
577
  }); },
558
578
  manipulateAst: megaShaderMainpulateAst,
@@ -561,7 +581,7 @@ export var threngine = {
561
581
  };
562
582
  export var createMaterial = function (compileResult, ctx) {
563
583
  var engineMaterial = ctx.runtime.engineMaterial;
564
- var finalUniforms = __assign(__assign(__assign(__assign({}, ShaderLib.phong.uniforms), ShaderLib.toon.uniforms), ShaderLib.physical.uniforms), { time: { value: 0 }, cameraPosition: { value: new Vector3(1.0) } });
584
+ var finalUniforms = __assign(__assign(__assign(__assign({}, ShaderLib.phong.uniforms), ShaderLib.toon.uniforms), ShaderLib.physical.uniforms), { time: { value: 0 }, cameraPosition: { value: new Vector3(1.0) }, renderResolution: { value: new Vector2(1.0) } });
565
585
  // Also the ThreeComponent's sceneConfig properties modify the material
566
586
  var initialProperties = {
567
587
  name: 'ShaderFrog Material',
@@ -37,15 +37,17 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
37
37
  import { expect, it } from 'vitest';
38
38
  import { outputNode, sourceNode } from '../../graph/graph-node';
39
39
  import { makeEdge } from '../../graph/edge';
40
- import { compileSource } from '../../graph/graph';
41
- import { texture2DStrategy } from '../../strategy';
40
+ import { compileSource, nodeName } from '../../graph/graph';
41
+ import { namedAttributeStrategy, texture2DStrategy } from '../../strategy';
42
42
  import { isError } from '../../graph/context';
43
43
  import { threngine } from './threngine';
44
44
  import { makeId } from '../../util/id';
45
45
  import { fail } from '../../test-util';
46
+ import importers from './importers';
47
+ import { generate, parser } from '@shaderfrog/glsl-parser';
46
48
  var p = { x: 0, y: 0 };
47
49
  var makeSourceNode = function (id, source, stage, strategies) {
48
- if (strategies === void 0) { strategies = [texture2DStrategy()]; }
50
+ if (strategies === void 0) { strategies = [texture2DStrategy(), namedAttributeStrategy('position')]; }
49
51
  return sourceNode(id, "Shader ".concat(id), p, {
50
52
  version: 2,
51
53
  preprocess: false,
@@ -82,8 +84,53 @@ it('threngine compileSource() and manipulateAst()', function () { return __await
82
84
  // Threngine has parsers for vertex shaders, make sure that is set properly
83
85
  expect(result.vertexResult).toContain("vec4 main_Shader_".concat(vertInput.id, "() {\n vec4 frogOut = modelViewMatrix * vec4(position, 1.0);\n return frogOut;\n}"));
84
86
  // Check that it inlned. For fun.
85
- expect(result.vertexResult).toContain("gl_Position = main_Shader_".concat(vertInput.id, "();"));
87
+ expect(result.vertexResult).toContain("gl_Position = ".concat(nodeName(vertInput), "();"));
86
88
  return [2 /*return*/];
87
89
  }
88
90
  });
89
91
  }); });
92
+ it('threngine compileSource() linking through vertex', function () { return __awaiter(void 0, void 0, void 0, function () {
93
+ var outV, outF, vert1, vert2, graph, engineContext, result;
94
+ return __generator(this, function (_a) {
95
+ switch (_a.label) {
96
+ case 0:
97
+ outV = outputNode(makeId(), 'Output v', p, 'vertex');
98
+ outF = outputNode(makeId(), 'Output f', p, 'fragment');
99
+ vert1 = makeSourceNode(makeId(), "void main() {\n gl_Position = modelViewMatrix * vec4(position, 1.0);\n}\n", 'vertex');
100
+ vert2 = makeSourceNode(makeId(), "void main() {\n gl_Position = modelViewMatrix * vec4(position, 1.0);\n}\n", 'vertex');
101
+ graph = {
102
+ nodes: [outV, outF, vert1, vert2],
103
+ edges: [
104
+ makeEdge(makeId(), vert1.id, outV.id, 'out', 'filler_gl_Position', 'vertex'),
105
+ makeEdge(makeId(), vert2.id, vert1.id, 'out', 'filler_position', 'vertex'),
106
+ ],
107
+ };
108
+ engineContext = {
109
+ engine: 'three',
110
+ nodes: {},
111
+ runtime: {},
112
+ debuggingNonsense: {},
113
+ };
114
+ return [4 /*yield*/, compileSource(graph, threngine, engineContext)];
115
+ case 1:
116
+ result = _a.sent();
117
+ if (isError(result)) {
118
+ fail(result);
119
+ }
120
+ // Because vert2 links through vert1, it should be a vec3, not a vec4
121
+ expect(result.vertexResult).toContain("vec3 ".concat(nodeName(vert2), "() {"));
122
+ expect(result.vertexResult).toContain("vec4 ".concat(nodeName(vert1), "() {"));
123
+ return [2 /*return*/];
124
+ }
125
+ });
126
+ }); });
127
+ it('threngine shadertoy import', function () { return __awaiter(void 0, void 0, void 0, function () {
128
+ var testImport, p;
129
+ return __generator(this, function (_a) {
130
+ testImport = "\nvoid mainImage( out vec4 fragColor, in vec2 fragCoord ){\n vec3 rd = normalize(vec3(2.*fragCoord - iResolution.xy, iResolution.y));\n fragColor = vec4(sqrt(clamp(col, 0., 1.)), 1.0 * iTime);\n}\n";
131
+ p = parser.parse(testImport);
132
+ importers.shadertoy.convertAst(p, 'fragment');
133
+ expect(generate(p)).toContain("\nprecision highp float;\nprecision highp int;\n\nuniform vec2 mouse;\nuniform float time;\nuniform vec2 renderResolution;\n\nvoid main() {\n vec3 rd = normalize(vec3(2.*gl_FragCoord.xy - renderResolution.xy, renderResolution.y));\n gl_FragColor = vec4(sqrt(clamp(col, 0., 1.)), 1.0 * time);\n}\n");
134
+ return [2 /*return*/];
135
+ });
136
+ }); });
@@ -0,0 +1,10 @@
1
+ import { BaseStrategy, ApplyStrategy, StrategyType } from '.';
2
+ export interface AssignmentToStrategy extends BaseStrategy {
3
+ type: StrategyType.ASSIGNMENT_TO;
4
+ config: {
5
+ assignTo: string;
6
+ nth?: number;
7
+ };
8
+ }
9
+ export declare const assignemntToStrategy: (assignTo: string, nth?: number) => AssignmentToStrategy;
10
+ export declare const applyAssignmentToStrategy: ApplyStrategy<AssignmentToStrategy>;
@@ -0,0 +1,35 @@
1
+ import { findAssignmentTo } from '../util/ast';
2
+ import { nodeInput } from '../graph/base-node';
3
+ import { StrategyType } from '.';
4
+ // Constructor
5
+ export var assignemntToStrategy = function (assignTo, nth) {
6
+ if (nth === void 0) { nth = 1; }
7
+ return ({
8
+ type: StrategyType.ASSIGNMENT_TO,
9
+ config: { assignTo: assignTo, nth: nth },
10
+ });
11
+ };
12
+ // Apply the strategy
13
+ export var applyAssignmentToStrategy = function (strategy, ast, graphNode, siblingNode) {
14
+ var assignNode = findAssignmentTo(ast, strategy.config.assignTo, strategy.config.nth || 1);
15
+ var name = strategy.config.assignTo;
16
+ return assignNode
17
+ ? [
18
+ [
19
+ nodeInput(name, "filler_".concat(name), 'filler', undefined, // Data type for what plugs into this filler
20
+ ['code', 'data'], false),
21
+ function (filler) {
22
+ var filled = filler();
23
+ if ('expression' in assignNode) {
24
+ assignNode.expression.right =
25
+ filled;
26
+ }
27
+ else {
28
+ assignNode.initializer = filled;
29
+ }
30
+ return ast;
31
+ },
32
+ ],
33
+ ]
34
+ : [];
35
+ };
@@ -13,8 +13,8 @@ export var constApplyDeclarationOf = function (strategy, ast, graphNode, sibling
13
13
  [
14
14
  nodeInput(name, "filler_".concat(name), 'filler', undefined, // Data type for what plugs into this filler
15
15
  ['code', 'data'], false),
16
- function (fillerAst) {
17
- declaration.initializer = fillerAst;
16
+ function (filler) {
17
+ declaration.initializer = filler();
18
18
  return ast;
19
19
  },
20
20
  ],
@@ -12,10 +12,7 @@ export var applyHardCodeStrategy = function (strategy, ast, graphNode, siblingNo
12
12
  // so this awkward branch is to make types line up. But I don't think
13
13
  // this code path would ever get called
14
14
  function (filler) {
15
- if (!filler || Array.isArray(filler)) {
16
- throw new Error('Cannot use void filler');
17
- }
18
- return filler;
15
+ return filler();
19
16
  },
20
17
  ];
21
18
  return ci;
@@ -1,6 +1,6 @@
1
1
  export * from './hardCode';
2
2
  export * from './uniform';
3
- export * from './assignemntTo';
3
+ export * from './assignmentTo';
4
4
  export * from './inject';
5
5
  export * from './declarationOf';
6
6
  export * from './texture2D';
package/strategy/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export * from './hardCode';
2
2
  export * from './uniform';
3
- export * from './assignemntTo';
3
+ export * from './assignmentTo';
4
4
  export * from './inject';
5
5
  export * from './declarationOf';
6
6
  export * from './texture2D';
@@ -62,10 +62,9 @@ export var applyInjectStrategy = function (strategy, ast, graphNode, siblingNode
62
62
  [
63
63
  nodeInput(name, "filler_".concat(name), 'filler', undefined, // Data type for what plugs into this filler
64
64
  ['code', 'data'], false),
65
- function (fillerAst) {
66
- var toInsert = Array.isArray(fillerAst)
67
- ? fillerAst
68
- : [fillerAst];
65
+ function (filler) {
66
+ var result = filler();
67
+ var toInsert = Array.isArray(result) ? result : [result];
69
68
  // Loop backwards through the matches because when we inject code into
70
69
  // parent nodes, it modifies the statement list arrays
71
70
  for (
@@ -28,7 +28,7 @@ export var applyNamedAttributeStrategy = function (strategy, ast, graphNode, sib
28
28
  [
29
29
  nodeInput(attributeName, "filler_".concat(attributeName), 'filler', undefined, // Data type for what plugs into this filler
30
30
  ['code', 'data'], true),
31
- function (fillerAst) {
31
+ function (filler) {
32
32
  Object.entries(program.scopes[0].bindings).forEach(function (_a) {
33
33
  var _b = __read(_a, 2), name = _b[0], binding = _b[1];
34
34
  binding.references.forEach(function (ref) {
@@ -37,7 +37,7 @@ export var applyNamedAttributeStrategy = function (strategy, ast, graphNode, sib
37
37
  if (ref.type === 'identifier' &&
38
38
  ref !== binding.declaration &&
39
39
  ref.identifier === attributeName) {
40
- ref.identifier = generateFiller(fillerAst);
40
+ ref.identifier = generateFiller(filler());
41
41
  }
42
42
  });
43
43
  });
@@ -2,13 +2,38 @@ import { AstNode, Program } from '@shaderfrog/glsl-parser/ast';
2
2
  import { SourceNode } from '../graph/code-nodes';
3
3
  import { HardCodeStrategy } from './hardCode';
4
4
  import { UniformStrategy } from './uniform';
5
- import { AssignemntToStrategy } from './assignemntTo';
5
+ import { AssignmentToStrategy } from './assignmentTo';
6
6
  import { DeclarationOfStrategy } from './declarationOf';
7
7
  import { Texture2DStrategy } from './texture2D';
8
8
  import { NamedAttributeStrategy } from './namedAttribute';
9
9
  import { VariableStrategy } from './variable';
10
10
  import { InjectStrategy } from './inject';
11
- import { ComputedInput } from '../graph/parsers';
11
+ import { NodeInput } from '../graph';
12
+ /**
13
+ * Fillers are generated by *strategies*. Strategies are applied to the AST
14
+ * by applyStrategy() in strategy.ts, which runs strategy functions like
15
+ * applyTexture2DStrategy(), which returns a list of fillers found by each
16
+ * strategy.
17
+ */
18
+ export type Filler = (...args: string[]) => AstNode | AstNode[] | void;
19
+ export type InputFiller = (filler: Filler) => AstNode | Program;
20
+ export type FillerArguments = AstNode[];
21
+ export type FillerStmt = AstNode;
22
+ export type InputFillerGroup = {
23
+ filler: InputFiller;
24
+ fillerArgs?: FillerArguments;
25
+ fillerStmt?: AstNode;
26
+ };
27
+ export type InputFillers = Record<string, InputFillerGroup>;
28
+ /**
29
+ * A computed input is ultimately what the strategy application process returns
30
+ */
31
+ export type ComputedInput = [
32
+ NodeInput,
33
+ InputFiller,
34
+ FillerArguments?,
35
+ FillerStmt?
36
+ ];
12
37
  export declare enum StrategyType {
13
38
  VARIABLE = "Variable Names",
14
39
  ASSIGNMENT_TO = "Assignment To",
@@ -23,6 +48,6 @@ export interface BaseStrategy {
23
48
  type: StrategyType;
24
49
  config: Object;
25
50
  }
26
- export type Strategy = UniformStrategy | AssignemntToStrategy | Texture2DStrategy | NamedAttributeStrategy | VariableStrategy | HardCodeStrategy | InjectStrategy | DeclarationOfStrategy;
27
- export type ApplyStrategy<T> = (strategy: T, ast: AstNode | Program, node: SourceNode, sibling: SourceNode) => ComputedInput[];
28
- export declare const applyStrategy: (strategy: Strategy, ast: AstNode | Program, node: SourceNode, sibling: SourceNode) => ComputedInput[];
51
+ export type Strategy = UniformStrategy | AssignmentToStrategy | Texture2DStrategy | NamedAttributeStrategy | VariableStrategy | HardCodeStrategy | InjectStrategy | DeclarationOfStrategy;
52
+ export type ApplyStrategy<T> = (strategy: T, ast: AstNode | Program, node: SourceNode, sibling?: SourceNode) => ComputedInput[];
53
+ export declare const applyStrategy: (strategy: Strategy, ast: AstNode | Program, node: SourceNode, sibling?: SourceNode) => ComputedInput[];
@@ -1,7 +1,7 @@
1
1
  var _a;
2
2
  import { applyHardCodeStrategy } from './hardCode';
3
3
  import { applyUniformStrategy } from './uniform';
4
- import { applyAssignmentToStrategy, } from './assignemntTo';
4
+ import { applyAssignmentToStrategy, } from './assignmentTo';
5
5
  import { constApplyDeclarationOf as constApplyDeclarationOfStrategy, } from './declarationOf';
6
6
  import { applyTexture2DStrategy } from './texture2D';
7
7
  import { applyNamedAttributeStrategy, } from './namedAttribute';