@stevejtrettel/shader-sandbox 0.1.1 → 0.1.2
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.
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* Called by the generated loader
|
|
4
4
|
*/
|
|
5
5
|
import { ShadertoyProject, ShadertoyConfig } from './types';
|
|
6
|
-
export declare function loadDemo(
|
|
6
|
+
export declare function loadDemo(demoPath: string, glslFiles: Record<string, () => Promise<string>>, jsonFiles: Record<string, () => Promise<ShadertoyConfig>>, imageFiles: Record<string, () => Promise<string>>): Promise<ShadertoyProject>;
|
|
7
7
|
//# sourceMappingURL=loaderHelper.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loaderHelper.d.ts","sourceRoot":"","sources":["../../src/project/loaderHelper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,gBAAgB,EAChB,eAAe,EAIhB,MAAM,SAAS,CAAC;AA8CjB,wBAAsB,QAAQ,CAC5B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC,EAChD,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,CAAC,EACzD,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC,GAChD,OAAO,CAAC,gBAAgB,CAAC,
|
|
1
|
+
{"version":3,"file":"loaderHelper.d.ts","sourceRoot":"","sources":["../../src/project/loaderHelper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,gBAAgB,EAChB,eAAe,EAIhB,MAAM,SAAS,CAAC;AA8CjB,wBAAsB,QAAQ,CAC5B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC,EAChD,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,CAAC,EACzD,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC,GAChD,OAAO,CAAC,gBAAgB,CAAC,CAoB3B"}
|
|
@@ -40,38 +40,42 @@ function parseChannelValue(value) {
|
|
|
40
40
|
}
|
|
41
41
|
return value;
|
|
42
42
|
}
|
|
43
|
-
export async function loadDemo(
|
|
44
|
-
|
|
43
|
+
export async function loadDemo(demoPath, glslFiles, jsonFiles, imageFiles) {
|
|
44
|
+
// Normalize path - handle both "./shaders/name" and "shaders/name" formats
|
|
45
|
+
const normalizedPath = demoPath.startsWith('./') ? demoPath : `./${demoPath}`;
|
|
46
|
+
const configPath = `${normalizedPath}/config.json`;
|
|
45
47
|
const hasConfig = configPath in jsonFiles;
|
|
46
48
|
if (hasConfig) {
|
|
47
49
|
const config = await jsonFiles[configPath]();
|
|
48
50
|
const hasPassConfigs = config.Image || config.BufferA || config.BufferB ||
|
|
49
51
|
config.BufferC || config.BufferD;
|
|
50
52
|
if (hasPassConfigs) {
|
|
51
|
-
return loadWithConfig(
|
|
53
|
+
return loadWithConfig(normalizedPath, config, glslFiles, imageFiles);
|
|
52
54
|
}
|
|
53
55
|
else {
|
|
54
56
|
// Config with only settings (layout, controls, etc.) but no passes
|
|
55
|
-
return loadSinglePass(
|
|
57
|
+
return loadSinglePass(normalizedPath, glslFiles, config);
|
|
56
58
|
}
|
|
57
59
|
}
|
|
58
60
|
else {
|
|
59
|
-
return loadSinglePass(
|
|
61
|
+
return loadSinglePass(normalizedPath, glslFiles);
|
|
60
62
|
}
|
|
61
63
|
}
|
|
62
|
-
async function loadSinglePass(
|
|
63
|
-
const imagePath =
|
|
64
|
+
async function loadSinglePass(demoPath, glslFiles, configOverrides) {
|
|
65
|
+
const imagePath = `${demoPath}/image.glsl`;
|
|
64
66
|
const actualImagePath = findFileCaseInsensitive(glslFiles, imagePath);
|
|
65
67
|
if (!actualImagePath) {
|
|
66
|
-
throw new Error(`Demo '${
|
|
68
|
+
throw new Error(`Demo '${demoPath}' not found. Expected ${imagePath}`);
|
|
67
69
|
}
|
|
68
70
|
const imageSource = await glslFiles[actualImagePath]();
|
|
69
71
|
const layout = configOverrides?.layout || 'tabbed';
|
|
70
72
|
const controls = configOverrides?.controls ?? true;
|
|
73
|
+
// Extract name from path for title (e.g., "./shaders/example-gradient" -> "example-gradient")
|
|
74
|
+
const demoName = demoPath.split('/').pop() || demoPath;
|
|
71
75
|
const title = configOverrides?.title ||
|
|
72
76
|
demoName.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');
|
|
73
77
|
return {
|
|
74
|
-
root:
|
|
78
|
+
root: demoPath,
|
|
75
79
|
meta: {
|
|
76
80
|
title,
|
|
77
81
|
author: configOverrides?.author || null,
|
|
@@ -95,7 +99,7 @@ async function loadSinglePass(demoName, glslFiles, configOverrides) {
|
|
|
95
99
|
textures: [],
|
|
96
100
|
};
|
|
97
101
|
}
|
|
98
|
-
async function loadWithConfig(
|
|
102
|
+
async function loadWithConfig(demoPath, config, glslFiles, imageFiles) {
|
|
99
103
|
// Extract pass configs from top level
|
|
100
104
|
const passConfigs = {
|
|
101
105
|
Image: config.Image,
|
|
@@ -107,14 +111,14 @@ async function loadWithConfig(demoName, config, glslFiles, imageFiles) {
|
|
|
107
111
|
// Load common source
|
|
108
112
|
let commonSource = null;
|
|
109
113
|
if (config.common) {
|
|
110
|
-
const commonPath =
|
|
114
|
+
const commonPath = `${demoPath}/${config.common}`;
|
|
111
115
|
const actualCommonPath = findFileCaseInsensitive(glslFiles, commonPath);
|
|
112
116
|
if (actualCommonPath) {
|
|
113
117
|
commonSource = await glslFiles[actualCommonPath]();
|
|
114
118
|
}
|
|
115
119
|
}
|
|
116
120
|
else {
|
|
117
|
-
const defaultCommonPath =
|
|
121
|
+
const defaultCommonPath = `${demoPath}/common.glsl`;
|
|
118
122
|
const actualCommonPath = findFileCaseInsensitive(glslFiles, defaultCommonPath);
|
|
119
123
|
if (actualCommonPath) {
|
|
120
124
|
commonSource = await glslFiles[actualCommonPath]();
|
|
@@ -141,7 +145,7 @@ async function loadWithConfig(demoName, config, glslFiles, imageFiles) {
|
|
|
141
145
|
const textures = [];
|
|
142
146
|
const texturePathToName = new Map();
|
|
143
147
|
for (const texturePath of texturePathsSet) {
|
|
144
|
-
const fullPath =
|
|
148
|
+
const fullPath = `${demoPath}/${texturePath.replace(/^\.\//, '')}`;
|
|
145
149
|
const actualPath = findFileCaseInsensitive(imageFiles, fullPath);
|
|
146
150
|
if (!actualPath) {
|
|
147
151
|
throw new Error(`Texture not found: ${texturePath} (expected at ${fullPath})`);
|
|
@@ -172,7 +176,7 @@ async function loadWithConfig(demoName, config, glslFiles, imageFiles) {
|
|
|
172
176
|
BufferD: 'bufferD.glsl',
|
|
173
177
|
};
|
|
174
178
|
const sourceFile = passConfig.source || defaultNames[passName];
|
|
175
|
-
const sourcePath =
|
|
179
|
+
const sourcePath = `${demoPath}/${sourceFile}`;
|
|
176
180
|
const actualSourcePath = findFileCaseInsensitive(glslFiles, sourcePath);
|
|
177
181
|
if (!actualSourcePath) {
|
|
178
182
|
throw new Error(`Missing shader file: ${sourcePath}`);
|
|
@@ -191,8 +195,10 @@ async function loadWithConfig(demoName, config, glslFiles, imageFiles) {
|
|
|
191
195
|
};
|
|
192
196
|
}
|
|
193
197
|
if (!passes.Image) {
|
|
194
|
-
throw new Error(`Demo '${
|
|
198
|
+
throw new Error(`Demo '${demoPath}' must have an Image pass`);
|
|
195
199
|
}
|
|
200
|
+
// Extract name from path for title (e.g., "./shaders/example-gradient" -> "example-gradient")
|
|
201
|
+
const demoName = demoPath.split('/').pop() || demoPath;
|
|
196
202
|
const title = config.title ||
|
|
197
203
|
demoName.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');
|
|
198
204
|
const author = config.author || null;
|
|
@@ -200,7 +206,7 @@ async function loadWithConfig(demoName, config, glslFiles, imageFiles) {
|
|
|
200
206
|
const layout = config.layout || 'tabbed';
|
|
201
207
|
const controls = config.controls ?? true;
|
|
202
208
|
return {
|
|
203
|
-
root:
|
|
209
|
+
root: demoPath,
|
|
204
210
|
meta: { title, author, description },
|
|
205
211
|
layout,
|
|
206
212
|
controls,
|
package/package.json
CHANGED
|
@@ -56,12 +56,14 @@ function parseChannelValue(value: ChannelValue): ChannelJSONObject | null {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
export async function loadDemo(
|
|
59
|
-
|
|
59
|
+
demoPath: string,
|
|
60
60
|
glslFiles: Record<string, () => Promise<string>>,
|
|
61
61
|
jsonFiles: Record<string, () => Promise<ShadertoyConfig>>,
|
|
62
62
|
imageFiles: Record<string, () => Promise<string>>
|
|
63
63
|
): Promise<ShadertoyProject> {
|
|
64
|
-
|
|
64
|
+
// Normalize path - handle both "./shaders/name" and "shaders/name" formats
|
|
65
|
+
const normalizedPath = demoPath.startsWith('./') ? demoPath : `./${demoPath}`;
|
|
66
|
+
const configPath = `${normalizedPath}/config.json`;
|
|
65
67
|
const hasConfig = configPath in jsonFiles;
|
|
66
68
|
|
|
67
69
|
if (hasConfig) {
|
|
@@ -70,37 +72,39 @@ export async function loadDemo(
|
|
|
70
72
|
config.BufferC || config.BufferD;
|
|
71
73
|
|
|
72
74
|
if (hasPassConfigs) {
|
|
73
|
-
return loadWithConfig(
|
|
75
|
+
return loadWithConfig(normalizedPath, config, glslFiles, imageFiles);
|
|
74
76
|
} else {
|
|
75
77
|
// Config with only settings (layout, controls, etc.) but no passes
|
|
76
|
-
return loadSinglePass(
|
|
78
|
+
return loadSinglePass(normalizedPath, glslFiles, config);
|
|
77
79
|
}
|
|
78
80
|
} else {
|
|
79
|
-
return loadSinglePass(
|
|
81
|
+
return loadSinglePass(normalizedPath, glslFiles);
|
|
80
82
|
}
|
|
81
83
|
}
|
|
82
84
|
|
|
83
85
|
async function loadSinglePass(
|
|
84
|
-
|
|
86
|
+
demoPath: string,
|
|
85
87
|
glslFiles: Record<string, () => Promise<string>>,
|
|
86
88
|
configOverrides?: Partial<ShadertoyConfig>
|
|
87
89
|
): Promise<ShadertoyProject> {
|
|
88
|
-
const imagePath =
|
|
90
|
+
const imagePath = `${demoPath}/image.glsl`;
|
|
89
91
|
const actualImagePath = findFileCaseInsensitive(glslFiles, imagePath);
|
|
90
92
|
|
|
91
93
|
if (!actualImagePath) {
|
|
92
|
-
throw new Error(`Demo '${
|
|
94
|
+
throw new Error(`Demo '${demoPath}' not found. Expected ${imagePath}`);
|
|
93
95
|
}
|
|
94
96
|
|
|
95
97
|
const imageSource = await glslFiles[actualImagePath]();
|
|
96
98
|
|
|
97
99
|
const layout = configOverrides?.layout || 'tabbed';
|
|
98
100
|
const controls = configOverrides?.controls ?? true;
|
|
101
|
+
// Extract name from path for title (e.g., "./shaders/example-gradient" -> "example-gradient")
|
|
102
|
+
const demoName = demoPath.split('/').pop() || demoPath;
|
|
99
103
|
const title = configOverrides?.title ||
|
|
100
104
|
demoName.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');
|
|
101
105
|
|
|
102
106
|
return {
|
|
103
|
-
root:
|
|
107
|
+
root: demoPath,
|
|
104
108
|
meta: {
|
|
105
109
|
title,
|
|
106
110
|
author: configOverrides?.author || null,
|
|
@@ -126,7 +130,7 @@ async function loadSinglePass(
|
|
|
126
130
|
}
|
|
127
131
|
|
|
128
132
|
async function loadWithConfig(
|
|
129
|
-
|
|
133
|
+
demoPath: string,
|
|
130
134
|
config: ShadertoyConfig,
|
|
131
135
|
glslFiles: Record<string, () => Promise<string>>,
|
|
132
136
|
imageFiles: Record<string, () => Promise<string>>
|
|
@@ -144,13 +148,13 @@ async function loadWithConfig(
|
|
|
144
148
|
// Load common source
|
|
145
149
|
let commonSource: string | null = null;
|
|
146
150
|
if (config.common) {
|
|
147
|
-
const commonPath =
|
|
151
|
+
const commonPath = `${demoPath}/${config.common}`;
|
|
148
152
|
const actualCommonPath = findFileCaseInsensitive(glslFiles, commonPath);
|
|
149
153
|
if (actualCommonPath) {
|
|
150
154
|
commonSource = await glslFiles[actualCommonPath]();
|
|
151
155
|
}
|
|
152
156
|
} else {
|
|
153
|
-
const defaultCommonPath =
|
|
157
|
+
const defaultCommonPath = `${demoPath}/common.glsl`;
|
|
154
158
|
const actualCommonPath = findFileCaseInsensitive(glslFiles, defaultCommonPath);
|
|
155
159
|
if (actualCommonPath) {
|
|
156
160
|
commonSource = await glslFiles[actualCommonPath]();
|
|
@@ -181,7 +185,7 @@ async function loadWithConfig(
|
|
|
181
185
|
const texturePathToName = new Map<string, string>();
|
|
182
186
|
|
|
183
187
|
for (const texturePath of texturePathsSet) {
|
|
184
|
-
const fullPath =
|
|
188
|
+
const fullPath = `${demoPath}/${texturePath.replace(/^\.\//, '')}`;
|
|
185
189
|
const actualPath = findFileCaseInsensitive(imageFiles, fullPath);
|
|
186
190
|
|
|
187
191
|
if (!actualPath) {
|
|
@@ -219,7 +223,7 @@ async function loadWithConfig(
|
|
|
219
223
|
};
|
|
220
224
|
|
|
221
225
|
const sourceFile = passConfig.source || defaultNames[passName];
|
|
222
|
-
const sourcePath =
|
|
226
|
+
const sourcePath = `${demoPath}/${sourceFile}`;
|
|
223
227
|
const actualSourcePath = findFileCaseInsensitive(glslFiles, sourcePath);
|
|
224
228
|
|
|
225
229
|
if (!actualSourcePath) {
|
|
@@ -243,9 +247,11 @@ async function loadWithConfig(
|
|
|
243
247
|
}
|
|
244
248
|
|
|
245
249
|
if (!passes.Image) {
|
|
246
|
-
throw new Error(`Demo '${
|
|
250
|
+
throw new Error(`Demo '${demoPath}' must have an Image pass`);
|
|
247
251
|
}
|
|
248
252
|
|
|
253
|
+
// Extract name from path for title (e.g., "./shaders/example-gradient" -> "example-gradient")
|
|
254
|
+
const demoName = demoPath.split('/').pop() || demoPath;
|
|
249
255
|
const title = config.title ||
|
|
250
256
|
demoName.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');
|
|
251
257
|
const author = config.author || null;
|
|
@@ -254,7 +260,7 @@ async function loadWithConfig(
|
|
|
254
260
|
const controls = config.controls ?? true;
|
|
255
261
|
|
|
256
262
|
return {
|
|
257
|
-
root:
|
|
263
|
+
root: demoPath,
|
|
258
264
|
meta: { title, author, description },
|
|
259
265
|
layout,
|
|
260
266
|
controls,
|