@babylonjs/smart-filters 0.2.0-alpha → 0.3.1-alpha

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 (108) hide show
  1. package/dist/blocks/baseBlock.d.ts +1 -1
  2. package/dist/blocks/baseBlock.d.ts.map +1 -1
  3. package/dist/blocks/baseBlock.js +1 -1
  4. package/dist/blocks/baseBlock.js.map +1 -1
  5. package/dist/blocks/copyBlock.d.ts +2 -3
  6. package/dist/blocks/copyBlock.d.ts.map +1 -1
  7. package/dist/blocks/copyBlock.js +4 -24
  8. package/dist/blocks/copyBlock.js.map +1 -1
  9. package/dist/blocks/copyBlock.shader.d.ts +13 -0
  10. package/dist/blocks/copyBlock.shader.d.ts.map +1 -0
  11. package/dist/blocks/copyBlock.shader.js +34 -0
  12. package/dist/blocks/copyBlock.shader.js.map +1 -0
  13. package/dist/blocks/inputBlock.d.ts +41 -5
  14. package/dist/blocks/inputBlock.d.ts.map +1 -1
  15. package/dist/blocks/inputBlock.deserializer.d.ts +14 -0
  16. package/dist/blocks/inputBlock.deserializer.d.ts.map +1 -0
  17. package/dist/blocks/inputBlock.deserializer.js +46 -0
  18. package/dist/blocks/inputBlock.deserializer.js.map +1 -0
  19. package/dist/blocks/inputBlock.js +16 -6
  20. package/dist/blocks/inputBlock.js.map +1 -1
  21. package/dist/blocks/inputBlock.serialization.types.d.ts +74 -0
  22. package/dist/blocks/inputBlock.serialization.types.d.ts.map +1 -0
  23. package/dist/blocks/inputBlock.serialization.types.js +2 -0
  24. package/dist/blocks/inputBlock.serialization.types.js.map +1 -0
  25. package/dist/blocks/inputBlock.serializer.d.ts +6 -0
  26. package/dist/blocks/inputBlock.serializer.d.ts.map +1 -0
  27. package/dist/blocks/inputBlock.serializer.js +115 -0
  28. package/dist/blocks/inputBlock.serializer.js.map +1 -0
  29. package/dist/index.d.ts +2 -1
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +1 -0
  32. package/dist/index.js.map +1 -1
  33. package/dist/serialization/index.d.ts +5 -0
  34. package/dist/serialization/index.d.ts.map +1 -0
  35. package/dist/serialization/index.js +5 -0
  36. package/dist/serialization/index.js.map +1 -0
  37. package/dist/serialization/serializedSmartFilter.d.ts +6 -0
  38. package/dist/serialization/serializedSmartFilter.d.ts.map +1 -0
  39. package/dist/serialization/serializedSmartFilter.js +2 -0
  40. package/dist/serialization/serializedSmartFilter.js.map +1 -0
  41. package/dist/serialization/smartFilterDeserializer.d.ts +25 -0
  42. package/dist/serialization/smartFilterDeserializer.d.ts.map +1 -0
  43. package/dist/serialization/smartFilterDeserializer.js +90 -0
  44. package/dist/serialization/smartFilterDeserializer.js.map +1 -0
  45. package/dist/serialization/smartFilterSerializer.d.ts +23 -0
  46. package/dist/serialization/smartFilterSerializer.d.ts.map +1 -0
  47. package/dist/serialization/smartFilterSerializer.js +91 -0
  48. package/dist/serialization/smartFilterSerializer.js.map +1 -0
  49. package/dist/serialization/v1/defaultBlockSerializer.d.ts +9 -0
  50. package/dist/serialization/v1/defaultBlockSerializer.d.ts.map +1 -0
  51. package/dist/serialization/v1/defaultBlockSerializer.js +16 -0
  52. package/dist/serialization/v1/defaultBlockSerializer.js.map +1 -0
  53. package/dist/serialization/v1/index.d.ts +3 -0
  54. package/dist/serialization/v1/index.d.ts.map +1 -0
  55. package/dist/serialization/v1/index.js +3 -0
  56. package/dist/serialization/v1/index.js.map +1 -0
  57. package/dist/serialization/v1/serialization.types.d.ts +83 -0
  58. package/dist/serialization/v1/serialization.types.d.ts.map +1 -0
  59. package/dist/serialization/v1/serialization.types.js +2 -0
  60. package/dist/serialization/v1/serialization.types.js.map +1 -0
  61. package/dist/smartFilter.d.ts +2 -2
  62. package/dist/smartFilter.d.ts.map +1 -1
  63. package/dist/smartFilter.js +9 -6
  64. package/dist/smartFilter.js.map +1 -1
  65. package/dist/utils/buildTools/determineVersion.d.ts +36 -0
  66. package/dist/utils/buildTools/determineVersion.d.ts.map +1 -0
  67. package/dist/utils/buildTools/determineVersion.js +109 -0
  68. package/dist/utils/buildTools/determineVersion.js.map +1 -0
  69. package/dist/utils/buildTools/shaderConverter.d.ts +2 -0
  70. package/dist/utils/buildTools/shaderConverter.d.ts.map +1 -0
  71. package/dist/utils/buildTools/shaderConverter.js +277 -0
  72. package/dist/utils/buildTools/shaderConverter.js.map +1 -0
  73. package/dist/utils/buildTools/versionUp.d.ts +2 -0
  74. package/dist/utils/buildTools/versionUp.d.ts.map +1 -0
  75. package/dist/utils/buildTools/versionUp.js +45 -0
  76. package/dist/utils/buildTools/versionUp.js.map +1 -0
  77. package/dist/utils/textureLoaders.d.ts +3 -1
  78. package/dist/utils/textureLoaders.d.ts.map +1 -1
  79. package/dist/utils/textureLoaders.js +3 -2
  80. package/dist/utils/textureLoaders.js.map +1 -1
  81. package/dist/utils/uniqueIdGenerator.d.ts +19 -0
  82. package/dist/utils/uniqueIdGenerator.d.ts.map +1 -0
  83. package/dist/utils/uniqueIdGenerator.js +27 -0
  84. package/dist/utils/uniqueIdGenerator.js.map +1 -0
  85. package/package.json +11 -6
  86. package/readme.md +12 -0
  87. package/src/blocks/baseBlock.ts +2 -3
  88. package/src/blocks/copyBlock.fragment.glsl +5 -0
  89. package/src/blocks/copyBlock.shader.ts +36 -0
  90. package/src/blocks/copyBlock.ts +4 -29
  91. package/src/blocks/inputBlock.deserializer.ts +60 -0
  92. package/src/blocks/inputBlock.serialization.types.ts +95 -0
  93. package/src/blocks/inputBlock.serializer.ts +132 -0
  94. package/src/blocks/inputBlock.ts +51 -7
  95. package/src/index.ts +2 -1
  96. package/src/serialization/index.ts +4 -0
  97. package/src/serialization/serializedSmartFilter.ts +6 -0
  98. package/src/serialization/smartFilterDeserializer.ts +127 -0
  99. package/src/serialization/smartFilterSerializer.ts +113 -0
  100. package/src/serialization/v1/defaultBlockSerializer.ts +18 -0
  101. package/src/serialization/v1/index.ts +2 -0
  102. package/src/serialization/v1/serialization.types.ts +108 -0
  103. package/src/smartFilter.ts +10 -8
  104. package/src/utils/buildTools/determineVersion.ts +127 -0
  105. package/src/utils/buildTools/shaderConverter.ts +399 -0
  106. package/src/utils/buildTools/versionUp.ts +52 -0
  107. package/src/utils/textureLoaders.ts +18 -3
  108. package/src/utils/uniqueIdGenerator.ts +28 -0
@@ -0,0 +1,399 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+
4
+ const TYPE_IMPORT_PATH = "@TYPE_IMPORT_PATH@";
5
+ const VERTEX_SHADER = "@VERTEX_SHADER@";
6
+ const UNIFORMS = "@UNIFORMS@";
7
+ const CONSTS_VALUE = "@CONSTS@";
8
+ const CONSTS_PROPERTY = "@CONSTS_PROPERTY@";
9
+ const MAIN_INPUT_NAME = "@MAIN_INPUT_NAME@";
10
+ const MAIN_FUNCTION_NAME = "@MAIN_FUNCTION_NAME@";
11
+ const FUNCTIONS = "@FUNCTIONS@";
12
+ const FUNCTION_NAME = "@FUNCTION_NAME@";
13
+ const FUNCTION_CODE = "@FUNCTION_CODE@";
14
+ const UNIFORM_NAMES = "@UNIFORM_NAMES@";
15
+
16
+ const ConstsTemplate = `
17
+ const: \`${CONSTS_VALUE}\`,`;
18
+
19
+ const FunctionTemplate = `
20
+ {
21
+ name: "${FUNCTION_NAME}",
22
+ code: \`
23
+ ${FUNCTION_CODE}
24
+ \`,
25
+ },`;
26
+
27
+ const CodeLinePrefix = " ";
28
+ const UniformLinePrefix = " ";
29
+ const ConstLinePrefix = " ";
30
+
31
+ const ShaderTemplate = `import type { ShaderProgram } from "${TYPE_IMPORT_PATH}";
32
+
33
+ /**
34
+ * The shader program for the block.
35
+ */
36
+ export const shaderProgram: ShaderProgram = {
37
+ vertex: ${VERTEX_SHADER},
38
+ fragment: {
39
+ uniform: \`${UNIFORMS}
40
+ uniform bool _disabled_;\`,${CONSTS_PROPERTY}
41
+ mainInputTexture: "${MAIN_INPUT_NAME}",
42
+ mainFunctionName: "${MAIN_FUNCTION_NAME}",
43
+ functions: [${FUNCTIONS}
44
+ ],
45
+ },
46
+ };
47
+
48
+ /**
49
+ * The uniform names for this shader, to be used in the shader binding so
50
+ * that the names are always in sync.
51
+ */
52
+ export const uniforms = {
53
+ ${UNIFORM_NAMES}
54
+ };
55
+ `;
56
+
57
+ const UniformNameLinePrefix = " ";
58
+
59
+ const GetFunctionNamesRegEx = /\S*\w+\s+(\w+)\s*\(/g;
60
+
61
+ /**
62
+ * Converts a single shader
63
+ * @param fragmentShaderPath - The path to the fragment file for the shader
64
+ * @param importPath - The path to import the ShaderProgram type from
65
+ */
66
+ function convertShader(fragmentShaderPath: string, importPath: string): void {
67
+ console.log(`Processing fragment shader: ${fragmentShaderPath}`);
68
+
69
+ // See if there is a corresponding vertex shader
70
+ let vertexShader: string | undefined = undefined;
71
+ const vertexShaderPath = fragmentShaderPath.replace(".fragment.glsl", ".vertex.glsl");
72
+ if (fs.existsSync(vertexShaderPath)) {
73
+ vertexShader = fs.readFileSync(vertexShaderPath, "utf8");
74
+ }
75
+ if (vertexShader) {
76
+ console.log("Found vertex shader");
77
+ }
78
+
79
+ // Read the fragment shader
80
+ const fragmentShader = fs.readFileSync(fragmentShaderPath, "utf8");
81
+
82
+ // Version check
83
+ const versionsFound = [...fragmentShader.matchAll(/\/\/\s+\[Smart Filter Shader Version\]\s*=\s*(\d+)/g)].map(
84
+ (match) => match[1]
85
+ );
86
+ let version: number = 1;
87
+ if (versionsFound.length === 1 && versionsFound[0]) {
88
+ version = parseInt(versionsFound[0]);
89
+ }
90
+ console.log(`Shader version: ${version}`);
91
+
92
+ let fragmentShaderInfo: FragmentShaderInfo;
93
+
94
+ switch (version) {
95
+ case 1:
96
+ {
97
+ fragmentShaderInfo = processFragmentShaderV1(fragmentShader);
98
+ }
99
+ break;
100
+ default: {
101
+ throw new Error(`Unsupported shader version: ${version}`);
102
+ }
103
+ }
104
+
105
+ // Write the shader TS file
106
+ const shaderFile = fragmentShaderPath.replace(".fragment.glsl", ".shader.ts");
107
+ const finalContents = ShaderTemplate.replace(VERTEX_SHADER, vertexShader ? `\`${vertexShader}\`` : "undefined")
108
+ .replace(TYPE_IMPORT_PATH, importPath)
109
+ .replace(UNIFORMS, "\n" + addLinePrefixes(fragmentShaderInfo.finalUniforms.join("\n"), UniformLinePrefix))
110
+ .replace(MAIN_FUNCTION_NAME, fragmentShaderInfo.mainFunctionName)
111
+ .replace(MAIN_INPUT_NAME, fragmentShaderInfo.mainInputName)
112
+ .replace(
113
+ CONSTS_PROPERTY,
114
+ fragmentShaderInfo.finalConsts.length > 0
115
+ ? ConstsTemplate.replace(
116
+ CONSTS_VALUE,
117
+ addLinePrefixes(fragmentShaderInfo.finalConsts.join("\n"), ConstLinePrefix)
118
+ )
119
+ : ""
120
+ )
121
+ .replace(FUNCTIONS, fragmentShaderInfo.extractedFunctions.join(""))
122
+ .replace(UNIFORM_NAMES, addLinePrefixes(fragmentShaderInfo.uniformNames.join("\n"), UniformNameLinePrefix));
123
+
124
+ fs.writeFileSync(shaderFile, finalContents);
125
+ }
126
+
127
+ /**
128
+ * Information about a fragment shader
129
+ */
130
+ type FragmentShaderInfo = {
131
+ /**
132
+ * The lines of code which declare the uniforms
133
+ */
134
+ finalUniforms: (string | undefined)[];
135
+
136
+ /**
137
+ * The main function name
138
+ */
139
+ mainFunctionName: string;
140
+
141
+ /**
142
+ * The main input name
143
+ */
144
+ mainInputName: string;
145
+
146
+ /**
147
+ * The lines of code which declare the consts
148
+ */
149
+ finalConsts: (string | undefined)[];
150
+
151
+ /**
152
+ * The lines of code which declare the functions
153
+ */
154
+ extractedFunctions: string[];
155
+
156
+ /**
157
+ * The lines of code which declare the uniform names
158
+ */
159
+ uniformNames: string[];
160
+ };
161
+
162
+ /**
163
+ * Processes a fragment shader
164
+ * @param fragmentShader - The fragment shader to process
165
+ * @returns The processed fragment shader
166
+ */
167
+ function processFragmentShaderV1(fragmentShader: string): FragmentShaderInfo {
168
+ const fragmentShaderWithNoFunctionBodies = removeFunctionBodies(fragmentShader);
169
+
170
+ // Collect uniform, const, and function names which need to be decorated
171
+ // eslint-disable-next-line prettier/prettier
172
+ const uniforms = [...fragmentShader.matchAll(/\S*uniform.*\s(\w*);/g)].map((match) => match[1]);
173
+ console.log(`Uniforms found: ${JSON.stringify(uniforms)}`);
174
+ const consts = [...fragmentShader.matchAll(/\S*const\s+\w*\s+(\w*)\s*=.*;/g)].map((match) => match[1]);
175
+ console.log(`Consts found: ${JSON.stringify(consts)}`);
176
+ const functionNames = [...fragmentShaderWithNoFunctionBodies.matchAll(GetFunctionNamesRegEx)].map(
177
+ (match) => match[1]
178
+ );
179
+ console.log(`Functions found: ${JSON.stringify(functionNames)}`);
180
+
181
+ // Decorate the uniforms, consts, and functions
182
+ const symbolsToDecorate = [...uniforms, ...consts, ...functionNames];
183
+ let fragmentShaderWithRenamedSymbols = fragmentShader;
184
+ for (const symbol of symbolsToDecorate) {
185
+ const regex = new RegExp(`(\\S*(?:\\s|;|,|\\)|\\()+)${symbol}((\\s|;|,|\\)|\\()+)`, "gs");
186
+ fragmentShaderWithRenamedSymbols = fragmentShaderWithRenamedSymbols.replace(regex, `$1_${symbol}_$2`);
187
+ }
188
+ console.log(`${symbolsToDecorate.length} symbol(s) renamed`);
189
+ const uniformNames = uniforms.map((uniform) => `${uniform}: "${uniform}",`);
190
+
191
+ // Extract all the uniforms
192
+ const finalUniforms = [...fragmentShaderWithRenamedSymbols.matchAll(/^\s*(uniform\s.*)/gm)].map(
193
+ (match) => match[1]
194
+ );
195
+
196
+ // Extract all the consts
197
+ const finalConsts = [...fragmentShaderWithRenamedSymbols.matchAll(/^\s*(const\s.*)/gm)].map((match) => match[1]);
198
+
199
+ // Find the main input
200
+ const mainInputs = [...fragmentShaderWithRenamedSymbols.matchAll(/\S*uniform.*\s(\w*);\s*\/\/\s*main/gm)].map(
201
+ (match) => match[1]
202
+ );
203
+ if (mainInputs.length !== 1 || !mainInputs[0]) {
204
+ throw new Error("Exactly one main input must be defined in the shader");
205
+ }
206
+ const mainInputName = mainInputs[0];
207
+
208
+ // Extract all the functions
209
+ const { extractedFunctions, mainFunctionName } = extractFunctions(fragmentShaderWithRenamedSymbols, mainInputName);
210
+
211
+ return {
212
+ finalUniforms,
213
+ mainFunctionName,
214
+ mainInputName,
215
+ finalConsts,
216
+ extractedFunctions,
217
+ uniformNames,
218
+ };
219
+ }
220
+
221
+ /**
222
+ * Prefixes each line in the input
223
+ * @param input - The input string
224
+ * @param prefix - The prefix to add to each line
225
+ * @returns The input with each line prefixed
226
+ */
227
+ function addLinePrefixes(input: string, prefix: string): string {
228
+ return input
229
+ .split("\n")
230
+ .map((line) => prefix + line)
231
+ .join("\n");
232
+ }
233
+
234
+ /**
235
+ * Extracts all the functions from the shader
236
+ * @param fragment - The shader code to process
237
+ * @param mainInputName - The name of the main input
238
+ * @returns A list of functions
239
+ */
240
+ function extractFunctions(
241
+ fragment: string,
242
+ mainInputName: string
243
+ ): {
244
+ /**
245
+ * The extracted functions
246
+ */
247
+ extractedFunctions: string[];
248
+
249
+ /**
250
+ * The name of the main function
251
+ */
252
+ mainFunctionName: string;
253
+ } {
254
+ const lines = fragment.split("\n");
255
+ const extractedFunctions: string[] = [];
256
+ let mainFunctionName: string | undefined;
257
+ let inFunction = false;
258
+ let depth = 0;
259
+ let currentFunction = "";
260
+
261
+ for (const line of lines) {
262
+ if (!inFunction && line.includes("{")) {
263
+ inFunction = true;
264
+ }
265
+ if (inFunction) {
266
+ currentFunction += line + "\n";
267
+ }
268
+ for (let pos = 0; pos < line.length; pos++) {
269
+ if (line[pos] === "{") {
270
+ depth++;
271
+ } else if (line[pos] === "}") {
272
+ depth--;
273
+ }
274
+ }
275
+ if (inFunction && depth === 0) {
276
+ inFunction = false;
277
+ const { functionBody, functionName, isMainFunction } = processFunctionBody(currentFunction);
278
+
279
+ let body = functionBody;
280
+ if (isMainFunction) {
281
+ body = functionBody.replace("{", `{\n if (_disabled_) return texture2D(${mainInputName}, vUV);\n`);
282
+ }
283
+
284
+ extractedFunctions.push(
285
+ FunctionTemplate.replace(FUNCTION_NAME, functionName).replace(
286
+ FUNCTION_CODE,
287
+ addLinePrefixes(body, CodeLinePrefix)
288
+ )
289
+ );
290
+ if (isMainFunction) {
291
+ if (mainFunctionName) {
292
+ throw new Error("Multiple main functions found in shader code");
293
+ }
294
+ mainFunctionName = functionName;
295
+ }
296
+ currentFunction = "";
297
+ }
298
+ }
299
+
300
+ if (!mainFunctionName) {
301
+ throw new Error("No main function found in shader code");
302
+ }
303
+
304
+ return { extractedFunctions, mainFunctionName };
305
+ }
306
+
307
+ /**
308
+ * Creates code for a ShaderFunction instance from the body of a function
309
+ * @param functionBody - The body of the function
310
+ * @returns The body, name, and whether the function is the main function
311
+ */
312
+ function processFunctionBody(functionBody: string): {
313
+ /**
314
+ * The body of the function
315
+ */
316
+ functionBody: string;
317
+
318
+ /**
319
+ * The name of the function
320
+ */
321
+ functionName: string;
322
+
323
+ /**
324
+ * Whether the function is the main function
325
+ */
326
+ isMainFunction: boolean;
327
+ } {
328
+ // Extract the function name
329
+ const functionNamesFound = [...functionBody.matchAll(GetFunctionNamesRegEx)].map((match) => match[1]);
330
+ const functionName = functionNamesFound[0];
331
+ if (!functionName) {
332
+ throw new Error("No function name found in shader code");
333
+ }
334
+
335
+ const isMainFunction = functionBody.includes("// main");
336
+
337
+ return { functionBody, functionName, isMainFunction };
338
+ }
339
+
340
+ /**
341
+ * Removes all function bodies from the shader code, leaving just curly braces behind at the top level
342
+ * @param input - The shader code to process
343
+ * @returns The shader code with all function bodies removed
344
+ */
345
+ function removeFunctionBodies(input: string): string {
346
+ let output: string = "";
347
+ let depth: number = 0;
348
+
349
+ for (let pos = 0; pos < input.length; pos++) {
350
+ if (input[pos] === "{") {
351
+ depth++;
352
+ // Special case - if we just hit the first { then include it
353
+ if (depth === 1) {
354
+ output += "{";
355
+ }
356
+ } else if (input[pos] === "}") {
357
+ depth--;
358
+ // Special case - if we just hit the last } then include it
359
+ if (depth === 0) {
360
+ output += "}";
361
+ }
362
+ } else if (depth === 0) {
363
+ output += input[pos];
364
+ }
365
+ }
366
+
367
+ if (depth !== 0) {
368
+ console.error("Unbalanced curly braces in shader code");
369
+ }
370
+
371
+ return output;
372
+ }
373
+
374
+ /**
375
+ * Converts .fragment.glsl and vertex.glsl file pairs into .shader.ts files which export a ShaderProgram object.
376
+ * @param shaderPath - The path to the .glsl files to convert.
377
+ * @param importPath - The path to import the ShaderProgram type from.
378
+ */
379
+ function convertShaders(shaderPath: string, importPath: string) {
380
+ // Get all files in the path
381
+ const allFiles = fs.readdirSync(shaderPath, { withFileTypes: true, recursive: true });
382
+
383
+ // Find all fragment shaders (excluding the template)
384
+ const fragmentShaderFiles = allFiles.filter(
385
+ (file) => file.isFile() && file.name.endsWith(".fragment.glsl") && !file.name.endsWith("template.fragment.glsl")
386
+ );
387
+
388
+ // Convert all shaders
389
+ for (const fragmentShaderFile of fragmentShaderFiles) {
390
+ convertShader(path.join(fragmentShaderFile.path, fragmentShaderFile.name), importPath);
391
+ }
392
+ }
393
+
394
+ const externalArguments = process.argv.slice(2);
395
+ if (externalArguments.length >= 2 && externalArguments[0] && externalArguments[1]) {
396
+ convertShaders(externalArguments[0], externalArguments[1]);
397
+ }
398
+
399
+ // TODO: simple copy from shader file to .ts, get it to build (including import trick)
@@ -0,0 +1,52 @@
1
+ import * as fs from "fs";
2
+ import { exec, type ExecException } from "child_process";
3
+ import { compareVersions, determineVersion, getNpmVersion, type VersionType } from "./determineVersion.js";
4
+ import type { Nullable } from "@babylonjs/core/types.js";
5
+
6
+ const alpha = process.argv.includes("--alpha");
7
+ const packageText = fs.readFileSync("package.json");
8
+ const packageJSON = JSON.parse(packageText.toString());
9
+
10
+ const packageName = packageJSON.name;
11
+ console.log("Processing package:", packageName);
12
+ console.log("Alpha flag:", alpha);
13
+ console.log("Current package.json version:", packageJSON.version);
14
+
15
+ /**
16
+ * Queries the NPM registry for the specified version type
17
+ * @param versionType - The type of version to query
18
+ * @param callback - The callback to call with the NPM version
19
+ */
20
+ function queryNpmFeed(versionType: VersionType, callback: (npmVersion: Nullable<string>) => void) {
21
+ exec(`npm view ${packageName} dist-tags.${versionType}`, (err: Nullable<ExecException>, stdout) => {
22
+ let npmVersion = getNpmVersion(versionType, err, stdout);
23
+ if (npmVersion !== null) {
24
+ npmVersion = npmVersion.trim();
25
+ console.log(`NPM Registry ${versionType} version:`, npmVersion);
26
+ }
27
+ callback(npmVersion);
28
+ });
29
+ }
30
+
31
+ queryNpmFeed("preview", (npmPreviewVersion) => {
32
+ queryNpmFeed("latest", (npmLatestVersion) => {
33
+ let highestNpmVersion: Nullable<string> = npmLatestVersion;
34
+ if (npmPreviewVersion && (!highestNpmVersion || compareVersions(npmPreviewVersion, highestNpmVersion) === 1)) {
35
+ highestNpmVersion = npmPreviewVersion;
36
+ }
37
+
38
+ console.log("Highest NPM Registry version:", highestNpmVersion);
39
+
40
+ const versionToUse = determineVersion(highestNpmVersion, packageJSON.version, alpha);
41
+
42
+ console.log("Version to use:", versionToUse);
43
+
44
+ if (packageJSON.version !== versionToUse) {
45
+ packageJSON.version = versionToUse;
46
+ fs.writeFileSync("package.json", JSON.stringify(packageJSON, null, 4));
47
+ console.log("Version updated in package.json");
48
+ } else {
49
+ console.log("No need to update package.json");
50
+ }
51
+ });
52
+ });
@@ -1,5 +1,6 @@
1
1
  import { ThinTexture } from "@babylonjs/core/Materials/Textures/thinTexture.js";
2
2
  import { type ThinEngine } from "@babylonjs/core/Engines/thinEngine.js";
3
+ import type { Nullable } from "@babylonjs/core/types";
3
4
 
4
5
  /**
5
6
  * Helper that takes in a URL to an image and returns a ThinTexture
@@ -9,15 +10,29 @@ import { type ThinEngine } from "@babylonjs/core/Engines/thinEngine.js";
9
10
  * * A base64 string of in-line texture data, e.g. 'data:image/jpg;base64,/...'
10
11
  * @param flipY - Indicates if the Y axis should be flipped
11
12
  * @param samplingMode - The sampling mode to use
13
+ * @param forcedExtension - defines the extension to use to pick the right loader
12
14
  * @returns A ThinTexture of the image
13
15
  */
14
16
  export function createImageTexture(
15
17
  engine: ThinEngine,
16
18
  url: string,
17
- flipY: boolean = true,
18
- samplingMode: number | undefined = undefined
19
+ flipY: Nullable<boolean> = null,
20
+ samplingMode: number | undefined = undefined,
21
+ forcedExtension: string | null = null
19
22
  ): ThinTexture {
20
- const internalTexture = engine.createTexture(url, true, flipY, null, samplingMode);
23
+ const internalTexture = engine.createTexture(
24
+ url,
25
+ true,
26
+ flipY ?? true,
27
+ null,
28
+ samplingMode,
29
+ null,
30
+ null,
31
+ null,
32
+ null,
33
+ null,
34
+ forcedExtension
35
+ );
21
36
  return new ThinTexture(internalTexture);
22
37
  }
23
38
 
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Helper class used to generate IDs unique to the current session
3
+ */
4
+ export class UniqueIdGenerator {
5
+ /**
6
+ * The next unique ID to be returned
7
+ */
8
+ public static _NextUniqueId = 1;
9
+
10
+ /**
11
+ * Gets a unique (relatively to the current session) Id
12
+ */
13
+ public static get UniqueId() {
14
+ const result = this._NextUniqueId;
15
+ this._NextUniqueId++;
16
+ return result;
17
+ }
18
+
19
+ /**
20
+ * Ensures future generated IDs are greater than the specified value
21
+ * @param minimum - The minimum value that future generated IDs should be greater than
22
+ */
23
+ public static EnsureIdsGreaterThan(minimum: number): void {
24
+ if (this._NextUniqueId <= minimum) {
25
+ this._NextUniqueId = minimum + 1;
26
+ }
27
+ }
28
+ }