From ec4c19ea6c4ef33b949c67870f1bed1d89d55376 Mon Sep 17 00:00:00 2001 From: "Alex C. Huber" <91097647+alexchuber@users.noreply.github.com> Date: Wed, 28 Aug 2024 18:07:06 -0400 Subject: [PATCH] Add watch support for GLSL files (#22) Monitor for new GLSL files and changes to existing ones so that their corresponding shader programs can be re-generated --- packages/core/package.json | 6 ++- .../core/src/utils/buildTools/buildShaders.ts | 13 ++++++ .../src/utils/buildTools/shaderConverter.ts | 9 +---- .../core/src/utils/buildTools/watchShaders.ts | 40 +++++++++++++++++++ packages/demo/package.json | 7 +++- 5 files changed, 64 insertions(+), 11 deletions(-) create mode 100644 packages/core/src/utils/buildTools/buildShaders.ts create mode 100644 packages/core/src/utils/buildTools/watchShaders.ts diff --git a/packages/core/package.json b/packages/core/package.json index 05c867cd..48518401 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -43,8 +43,10 @@ "build": "npm run build:buildTools && npm run build:runTools && npm run build:core", "build:core": "tsc -p ./tsconfig.build.json", "build:buildTools": "tsc -p ./tsconfig.buildTools.build.json", - "build:runTools": "node buildTools/shaderConverter.js ./src/blocks ../utils/shaderCodeUtils", - "watch": "tsc -p ./tsconfig.build.json --watch", + "build:runTools": "node buildTools/buildShaders.js ./src/blocks ../utils/shaderCodeUtils", + "watch": "concurrently \"npm run watch:core\" \"npm run watch:shaders\"", + "watch:core": "tsc -p ./tsconfig.build.json --watch", + "watch:shaders": "node buildTools/watchShaders.js ./src/blocks ../utils/shaderCodeUtils", "test": "echo \"Error: run test from the root of the monorepo\" && exit 1" }, "peerDependencies": { diff --git a/packages/core/src/utils/buildTools/buildShaders.ts b/packages/core/src/utils/buildTools/buildShaders.ts new file mode 100644 index 00000000..a035796b --- /dev/null +++ b/packages/core/src/utils/buildTools/buildShaders.ts @@ -0,0 +1,13 @@ +/** + * Builds all .glsl files under . + * @param shaderPath - The path to the shaders to watch + * @param importPath - The path to import the converted shaders + * @example node buildShaders.js + */ + +import { convertShaders } from "./shaderConverter.js"; + +const externalArguments = process.argv.slice(2); +if (externalArguments.length >= 2 && externalArguments[0] && externalArguments[1]) { + convertShaders(externalArguments[0], externalArguments[1]); +} diff --git a/packages/core/src/utils/buildTools/shaderConverter.ts b/packages/core/src/utils/buildTools/shaderConverter.ts index c9c1af15..cf309701 100644 --- a/packages/core/src/utils/buildTools/shaderConverter.ts +++ b/packages/core/src/utils/buildTools/shaderConverter.ts @@ -63,7 +63,7 @@ const GetFunctionNamesRegEx = /\S*\w+\s+(\w+)\s*\(/g; * @param fragmentShaderPath - The path to the fragment file for the shader * @param importPath - The path to import the ShaderProgram type from */ -function convertShader(fragmentShaderPath: string, importPath: string): void { +export function convertShader(fragmentShaderPath: string, importPath: string): void { console.log(`Processing fragment shader: ${fragmentShaderPath}`); // See if there is a corresponding vertex shader @@ -376,7 +376,7 @@ function removeFunctionBodies(input: string): string { * @param shaderPath - The path to the .glsl files to convert. * @param importPath - The path to import the ShaderProgram type from. */ -function convertShaders(shaderPath: string, importPath: string) { +export function convertShaders(shaderPath: string, importPath: string) { // Get all files in the path const allFiles = fs.readdirSync(shaderPath, { withFileTypes: true, recursive: true }); @@ -391,9 +391,4 @@ function convertShaders(shaderPath: string, importPath: string) { } } -const externalArguments = process.argv.slice(2); -if (externalArguments.length >= 2 && externalArguments[0] && externalArguments[1]) { - convertShaders(externalArguments[0], externalArguments[1]); -} - // TODO: simple copy from shader file to .ts, get it to build (including import trick) diff --git a/packages/core/src/utils/buildTools/watchShaders.ts b/packages/core/src/utils/buildTools/watchShaders.ts new file mode 100644 index 00000000..a669f972 --- /dev/null +++ b/packages/core/src/utils/buildTools/watchShaders.ts @@ -0,0 +1,40 @@ +/* eslint-disable no-console */ +/** + * Watches all .glsl files under and rebuilds them when changed. + * @param shaderPath - The path to the shaders to watch + * @param importPath - The path to import the converted shaders + * @example node watchShaders.js + */ + +import { convertShader } from "./shaderConverter.js"; +import { watch } from "chokidar"; +import { extname } from "path"; + +const externalArguments = process.argv.slice(2); +if (externalArguments.length >= 2 && externalArguments[0] && externalArguments[1]) { + const shaderPath = externalArguments[0]; + const importPath = externalArguments[1]; + + watch(shaderPath).on("all", (event, file) => { + // Only process file changes and added files + if (event !== "change" && event !== "add") { + return; + } + + // Only process .glsl files + if (extname(file) !== ".glsl") { + return; + } + + // Wrap in try-catch to prevent the watcher from crashing + // if the new shader changes are invalid + try { + convertShader(file, importPath); + console.log(`Successfully updated shader ${file}`); + } catch (error) { + console.error(`Failed to convert shader ${file}: ${error}`); + } + }); + + console.log(`Watching for shader changes in ${shaderPath}`); +} diff --git a/packages/demo/package.json b/packages/demo/package.json index 108db6b1..0cd5c1e2 100644 --- a/packages/demo/package.json +++ b/packages/demo/package.json @@ -21,9 +21,12 @@ "license": "MIT", "scripts": { "build": "npm run build:runTools && webpack --env=prod", - "build:runTools": "node ../../node_modules/@babylonjs/smart-filters/dist/utils/buildTools/shaderConverter.js ./src/configuration/blocks @babylonjs/smart-filters", + "build:runTools": "node ../../node_modules/@babylonjs/smart-filters/dist/utils/buildTools/buildShaders.js ./src/configuration/blocks @babylonjs/smart-filters", + "watch": "concurrently \"npm run watch:demo\" \"npm run watch:shaders\" \"npm run watch:shaders -w @babylonjs/smart-filters\"", + "watch:demo": "npx webpack-dev-server", + "watch:shaders": "node ../../node_modules/@babylonjs/smart-filters/dist/utils/buildTools/watchShaders.js ./src/configuration/blocks @babylonjs/smart-filters", "clean": "rimraf .temp && rimraf www/scripts", - "start": "npx webpack-dev-server", + "start": "npm run watch", "analyze": "webpack --profile --json > www/scripts/stats.json && npx webpack-bundle-analyzer www/scripts/stats.json" }, "devDependencies": {