@onerjs/smart-filters 8.31.6 → 8.31.7

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 (57) hide show
  1. package/dist/blockFoundation/customShaderBlock.d.ts +16 -2
  2. package/dist/blockFoundation/customShaderBlock.d.ts.map +1 -1
  3. package/dist/blockFoundation/customShaderBlock.js +69 -5
  4. package/dist/blockFoundation/customShaderBlock.js.map +1 -1
  5. package/dist/blockFoundation/customShaderBlock.serializer.d.ts +22 -0
  6. package/dist/blockFoundation/customShaderBlock.serializer.d.ts.map +1 -0
  7. package/dist/blockFoundation/customShaderBlock.serializer.js +32 -0
  8. package/dist/blockFoundation/customShaderBlock.serializer.js.map +1 -0
  9. package/dist/blockFoundation/disableableShaderBlock.d.ts +5 -0
  10. package/dist/blockFoundation/disableableShaderBlock.d.ts.map +1 -1
  11. package/dist/blockFoundation/disableableShaderBlock.js +18 -11
  12. package/dist/blockFoundation/disableableShaderBlock.js.map +1 -1
  13. package/dist/editorUtils/editableInPropertyPage.d.ts +5 -0
  14. package/dist/editorUtils/editableInPropertyPage.d.ts.map +1 -1
  15. package/dist/editorUtils/editableInPropertyPage.js +11 -2
  16. package/dist/editorUtils/editableInPropertyPage.js.map +1 -1
  17. package/dist/optimization/smartFilterOptimizer.d.ts +11 -0
  18. package/dist/optimization/smartFilterOptimizer.d.ts.map +1 -1
  19. package/dist/optimization/smartFilterOptimizer.js +28 -14
  20. package/dist/optimization/smartFilterOptimizer.js.map +1 -1
  21. package/dist/serialization/importCustomBlockDefinition.js +1 -0
  22. package/dist/serialization/importCustomBlockDefinition.js.map +1 -1
  23. package/dist/serialization/smartFilterSerializer.d.ts.map +1 -1
  24. package/dist/serialization/smartFilterSerializer.js +6 -3
  25. package/dist/serialization/smartFilterSerializer.js.map +1 -1
  26. package/dist/serialization/v1/shaderBlockSerialization.types.d.ts +37 -0
  27. package/dist/serialization/v1/shaderBlockSerialization.types.d.ts.map +1 -1
  28. package/dist/utils/buildTools/shaderCode.types.d.ts +5 -0
  29. package/dist/utils/buildTools/shaderCode.types.d.ts.map +1 -1
  30. package/dist/utils/buildTools/shaderConverter.d.ts +10 -4
  31. package/dist/utils/buildTools/shaderConverter.d.ts.map +1 -1
  32. package/dist/utils/buildTools/shaderConverter.js +58 -2
  33. package/dist/utils/buildTools/shaderConverter.js.map +1 -1
  34. package/dist/utils/index.d.ts +1 -1
  35. package/dist/utils/index.d.ts.map +1 -1
  36. package/dist/utils/index.js +1 -0
  37. package/dist/utils/index.js.map +1 -1
  38. package/dist/utils/shaderCodeUtils.d.ts +6 -0
  39. package/dist/utils/shaderCodeUtils.d.ts.map +1 -1
  40. package/dist/utils/shaderCodeUtils.js +14 -1
  41. package/dist/utils/shaderCodeUtils.js.map +1 -1
  42. package/dist/version.d.ts +1 -1
  43. package/dist/version.js +1 -1
  44. package/package.json +1 -1
  45. package/src/blockFoundation/customShaderBlock.serializer.ts +51 -0
  46. package/src/blockFoundation/customShaderBlock.ts +80 -6
  47. package/src/blockFoundation/disableableShaderBlock.ts +18 -9
  48. package/src/editorUtils/editableInPropertyPage.ts +16 -2
  49. package/src/optimization/smartFilterOptimizer.ts +30 -16
  50. package/src/serialization/importCustomBlockDefinition.ts +1 -0
  51. package/src/serialization/smartFilterSerializer.ts +6 -3
  52. package/src/serialization/v1/shaderBlockSerialization.types.ts +42 -0
  53. package/src/utils/buildTools/shaderCode.types.ts +65 -59
  54. package/src/utils/buildTools/shaderConverter.ts +96 -6
  55. package/src/utils/index.ts +1 -1
  56. package/src/utils/shaderCodeUtils.ts +16 -1
  57. package/src/version.ts +1 -1
@@ -3,6 +3,8 @@ import { Logger } from "core/Misc/logger.js";
3
3
  import type { ShaderCode, ShaderFunction } from "./shaderCode.types.js";
4
4
  import { ConnectionPointType } from "../../connection/connectionPointType.js";
5
5
  import { BlockDisableStrategy } from "../../blockFoundation/disableableShaderBlock.js";
6
+ import type { ConstPropertyMetadata } from "../../serialization/v1/shaderBlockSerialization.types.js";
7
+ import { DecorateSymbol } from "../shaderCodeUtils.js";
6
8
 
7
9
  // Note: creating a global RegExp object is risky, because it holds state (e.g. lastIndex) that has to be
8
10
  // cleared at the right time to ensure correctness, which is easy to forget to do.
@@ -20,9 +22,9 @@ const GetDefineRegExOptions = "gm";
20
22
  const ReservedSymbols = ["main"];
21
23
 
22
24
  /**
23
- * Describes the supported metadata properties for a uniform
25
+ * Describes the supported metadata annotation for a uniform
24
26
  */
25
- export type UniformMetadataProperties = {
27
+ type UniformMetadataAnnotation = {
26
28
  /**
27
29
  * If supplied, the default value to use for the corresponding input connection point
28
30
  */
@@ -38,7 +40,7 @@ export type UniformMetadataProperties = {
38
40
  /**
39
41
  * Describes a uniform in a shader
40
42
  */
41
- export type UniformMetadata = {
43
+ type UniformMetadata = {
42
44
  /**
43
45
  * The original name of the uniform (not renamed)
44
46
  */
@@ -52,9 +54,24 @@ export type UniformMetadata = {
52
54
  /**
53
55
  * Optional properties of the uniform
54
56
  */
55
- properties?: UniformMetadataProperties;
57
+ properties?: UniformMetadataAnnotation;
56
58
  };
57
59
 
60
+ /**
61
+ * Describes the supported metadata annotation for a const
62
+ */
63
+ type ConstMetadataAnnotation = {
64
+ /**
65
+ * If supplied, the const will be treated as a property which can be set before creating a runtime.
66
+ * Note: in this case, the const will be unique to each instance of this block.
67
+ */
68
+ property?: {
69
+ options?: ConstMetadataAnnotationFloatOptions;
70
+ };
71
+ };
72
+
73
+ type ConstMetadataAnnotationFloatOptions = { [key: string]: number };
74
+
58
75
  /**
59
76
  * Information about a fragment shader
60
77
  */
@@ -88,6 +105,11 @@ export type FragmentShaderInfo = {
88
105
  * The set of uniforms
89
106
  */
90
107
  uniforms: UniformMetadata[];
108
+
109
+ /**
110
+ * The set of fragment const values to be exposed as properties
111
+ */
112
+ fragmentConstProperties: ConstPropertyMetadata[];
91
113
  };
92
114
 
93
115
  /**
@@ -164,6 +186,67 @@ export function ParseFragmentShader(fragmentShader: string): FragmentShaderInfo
164
186
  }
165
187
  }
166
188
 
189
+ // Read the property consts (consts to be exposed as properties)
190
+ const fragmentConstProperties: ConstPropertyMetadata[] = [];
191
+ const constRegExp = new RegExp(/(\/\/\s*\{.*\}\s*(?:\r\n|\r|\n)+)?(const .*)/gm);
192
+ const constGroups = fragmentShader.matchAll(constRegExp);
193
+ for (const matches of constGroups) {
194
+ const annotationJSON = matches[1];
195
+
196
+ // If it doesn't have any annotation, treat it as a regular const
197
+ if (!annotationJSON) {
198
+ continue;
199
+ }
200
+
201
+ const annotation = JSON.parse(annotationJSON.replace("//", "").trim()) as ConstMetadataAnnotation;
202
+
203
+ // If the annotation doesn't have a "property" field, treat it as a regular const
204
+ if (!annotation.property) {
205
+ continue;
206
+ }
207
+
208
+ const constLine = matches[2];
209
+
210
+ if (!constLine) {
211
+ throw new Error("Const line not found");
212
+ }
213
+
214
+ const constLineMatches = new RegExp(/^const\s+(\w+)\s+(\w+)\s*=\s*([^\s;]+)\s*;?\s*$/gm).exec(constLine);
215
+ if (!constLineMatches || constLineMatches.length < 4) {
216
+ throw new Error(`Consts must have a name, type, and a default value: '${constLine}'`);
217
+ }
218
+ const type = constLineMatches[1];
219
+ const friendlyName = constLineMatches[2];
220
+ const defaultValue = constLineMatches[3];
221
+
222
+ if (!friendlyName) {
223
+ throw new Error(`Consts must have a name: '${constLine}'`);
224
+ }
225
+ if (defaultValue === null) {
226
+ throw new Error(`Consts must have a value: '${constLine}'`);
227
+ }
228
+
229
+ const constProperty: Nullable<ConstPropertyMetadata> =
230
+ type === "float"
231
+ ? {
232
+ name: DecorateSymbol(friendlyName),
233
+ friendlyName,
234
+ type,
235
+ defaultValue: parseFloat(defaultValue),
236
+ options: annotation.property.options as ConstMetadataAnnotationFloatOptions | undefined,
237
+ }
238
+ : null;
239
+
240
+ if (!constProperty) {
241
+ throw new Error(`Unsupported const property type: '${type}'`);
242
+ }
243
+ fragmentConstProperties.push(constProperty);
244
+
245
+ // Strip out the definition from the code - it will be added back in when creating the runtime by the CustomShaderBlock
246
+ fragmentShader = fragmentShader.replace(annotationJSON, "");
247
+ fragmentShader = fragmentShader.replace(constLine, "");
248
+ }
249
+
167
250
  const fragmentShaderWithNoFunctionBodies = RemoveFunctionBodies(fragmentShader);
168
251
 
169
252
  // Collect uniform, const, and function names which need to be decorated
@@ -172,13 +255,15 @@ export function ParseFragmentShader(fragmentShader: string): FragmentShaderInfo
172
255
  Logger.Log(`Uniforms found: ${JSON.stringify(uniforms)}`);
173
256
  const consts = [...fragmentShader.matchAll(/\S*const\s+\w*\s+(\w*)\s*=.*;/g)].map((match) => match[1]);
174
257
  Logger.Log(`Consts found: ${JSON.stringify(consts)}`);
258
+ const constPropertyFriendlyNames = fragmentConstProperties.map((c) => c.friendlyName);
259
+ Logger.Log(`Const properties found: ${JSON.stringify(constPropertyFriendlyNames)}`);
175
260
  const defineNames = [...fragmentShader.matchAll(new RegExp(GetDefineRegExString, GetDefineRegExOptions))].map((match) => match[1]);
176
261
  Logger.Log(`Defines found: ${JSON.stringify(defineNames)}`);
177
262
  const functionNames = [...fragmentShaderWithNoFunctionBodies.matchAll(new RegExp(GetFunctionHeaderRegExString, GetFunctionHeaderRegExOptions))].map((match) => match[1]);
178
263
  Logger.Log(`Functions found: ${JSON.stringify(functionNames)}`);
179
264
 
180
265
  // Decorate the uniforms, consts, defines, and functions
181
- const symbolsToDecorate = [...uniformNames, ...consts, ...defineNames, ...functionNames];
266
+ const symbolsToDecorate = [...uniformNames, ...consts, ...constPropertyFriendlyNames, ...defineNames, ...functionNames];
182
267
  let fragmentShaderWithRenamedSymbols = fragmentShader;
183
268
  for (const symbol of symbolsToDecorate) {
184
269
  if (!symbol) {
@@ -188,7 +273,7 @@ export function ParseFragmentShader(fragmentShader: string): FragmentShaderInfo
188
273
  throw new Error(`Symbol "${symbol}" is reserved and cannot be used`);
189
274
  }
190
275
  const regex = new RegExp(`(?<=\\W+)${symbol}(?=\\W+)`, "gs");
191
- fragmentShaderWithRenamedSymbols = fragmentShaderWithRenamedSymbols.replace(regex, `_${symbol}_`);
276
+ fragmentShaderWithRenamedSymbols = fragmentShaderWithRenamedSymbols.replace(regex, DecorateSymbol(symbol));
192
277
  }
193
278
  Logger.Log(`${symbolsToDecorate.length} symbol(s) renamed`);
194
279
 
@@ -223,11 +308,16 @@ export function ParseFragmentShader(fragmentShader: string): FragmentShaderInfo
223
308
  shaderCode.const = finalConsts.join("\n");
224
309
  }
225
310
 
311
+ if (fragmentConstProperties.length > 0) {
312
+ shaderCode.constPerInstance = fragmentConstProperties.map((property) => `const ${property.type} ${property.name} = ${property.defaultValue};`).join("\n");
313
+ }
314
+
226
315
  return {
227
316
  blockType,
228
317
  namespace,
229
318
  shaderCode,
230
319
  uniforms,
320
+ fragmentConstProperties,
231
321
  disableOptimization: !!header?.disableOptimization,
232
322
  blockDisableStrategy: header?.blockDisableStrategy,
233
323
  };
@@ -1,4 +1,4 @@
1
1
  export * from "./textureLoaders.js";
2
2
  // Back compat for when camelCase was used
3
3
  export { CreateImageTexture as createImageTexture } from "./textureLoaders.js";
4
- export { type ShaderProgram } from "./shaderCodeUtils.js";
4
+ export { type ShaderProgram, CloneShaderProgram } from "./shaderCodeUtils.js";
@@ -22,6 +22,20 @@ export type ShaderProgram = {
22
22
  fragment: ShaderCode;
23
23
  };
24
24
 
25
+ /**
26
+ * Creates a copy of a ShaderProgram so it can be modified without other instances being affected.
27
+ * @param shaderProgram - The shader program to clone
28
+ * @returns A new ShaderProgram instance
29
+ */
30
+ export function CloneShaderProgram(shaderProgram: ShaderProgram): ShaderProgram {
31
+ return {
32
+ vertex: shaderProgram.vertex,
33
+ fragment: {
34
+ ...shaderProgram.fragment,
35
+ },
36
+ };
37
+ }
38
+
25
39
  /**
26
40
  * The list of options required to create a shader block.
27
41
  * It mainly contains the shader code to execute and its associated parameters.
@@ -103,7 +117,8 @@ export function InjectAutoSampleDisableCode(shaderProgram: ShaderProgram) {
103
117
  export function GetShaderFragmentCode(shaderProgram: ShaderProgram, mainCodeOnly = false): string {
104
118
  const shaderFragment = shaderProgram.fragment;
105
119
 
106
- const declarations = (shaderFragment.const ?? "") + "\n" + shaderFragment.uniform + "\n" + (shaderFragment.uniformSingle ?? "") + "\n";
120
+ const declarations =
121
+ (shaderFragment.const ?? "") + "\n" + (shaderFragment.constPerInstance ?? "") + "\n" + shaderFragment.uniform + "\n" + (shaderFragment.uniformSingle ?? "") + "\n";
107
122
 
108
123
  let mainFunctionCode = "";
109
124
  let otherFunctionsCode = "";
package/src/version.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  /**
2
2
  * The version of the SmartFilter core. During publish, this file is overwritten by recordVersionNumber.ts with the same version that is used for the NPM publish.
3
3
  */
4
- export const SmartFilterCoreVersion = "8.31.6";
4
+ export const SmartFilterCoreVersion = "8.31.7";