bloody-engine 1.0.1 → 1.0.3
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.
- package/dist/node/index.js +2359 -0
- package/dist/web/index.js +34 -37
- package/dist/web/index.umd.js +7 -7
- package/package.json +1 -1
- package/dist/node/batch-renderer-JqZ4TYcL.js +0 -308
- package/dist/node/browser-resource-loader-D51BD3k_.js +0 -146
- package/dist/node/camera-A8EGrk7U.js +0 -271
- package/dist/node/index-node.js +0 -2117
- package/dist/node/node-resource-loader-MzkD-IGo.js +0 -166
- package/dist/node/resource-loader-factory-DQ-PAVcN.js +0 -93
- package/dist/node/resource-pipeline-Dac9qRso.js +0 -211
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
import * as fs from "fs/promises";
|
|
2
|
-
import * as path from "path";
|
|
3
|
-
class NodeResourceLoader {
|
|
4
|
-
/**
|
|
5
|
-
* Create a new Node.js resource loader
|
|
6
|
-
* @param baseDir Optional base directory for resolving relative paths (defaults to current working directory)
|
|
7
|
-
*/
|
|
8
|
-
constructor(baseDir = process.cwd()) {
|
|
9
|
-
this.baseDir = baseDir;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Resolve a relative path against the base directory
|
|
13
|
-
* @param filePath Relative or absolute file path
|
|
14
|
-
* @returns Resolved absolute file path
|
|
15
|
-
*/
|
|
16
|
-
resolvePath(filePath) {
|
|
17
|
-
if (path.isAbsolute(filePath)) {
|
|
18
|
-
return path.normalize(filePath);
|
|
19
|
-
}
|
|
20
|
-
return path.normalize(path.join(this.baseDir, filePath));
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Load a single resource from a file
|
|
24
|
-
* @param filePath File path (relative or absolute)
|
|
25
|
-
* @param options Optional loading configuration
|
|
26
|
-
* @returns Promise resolving to the file content
|
|
27
|
-
*/
|
|
28
|
-
async load(filePath, options) {
|
|
29
|
-
const resolvedPath = this.resolvePath(filePath);
|
|
30
|
-
const encoding = options?.encoding || "utf-8";
|
|
31
|
-
try {
|
|
32
|
-
const content = await fs.readFile(resolvedPath, encoding);
|
|
33
|
-
return content;
|
|
34
|
-
} catch (error) {
|
|
35
|
-
if (error instanceof Error) {
|
|
36
|
-
const errorCode = error.code;
|
|
37
|
-
if (errorCode === "ENOENT") {
|
|
38
|
-
throw new Error(
|
|
39
|
-
`File not found: ${resolvedPath} (resolved from: ${filePath})`
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
if (errorCode === "EACCES") {
|
|
43
|
-
throw new Error(
|
|
44
|
-
`Permission denied reading file: ${resolvedPath}`
|
|
45
|
-
);
|
|
46
|
-
}
|
|
47
|
-
if (errorCode === "EISDIR") {
|
|
48
|
-
throw new Error(
|
|
49
|
-
`Path is a directory, not a file: ${resolvedPath}`
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
throw new Error(
|
|
53
|
-
`Failed to load resource from ${resolvedPath}: ${error.message}`
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
throw new Error(
|
|
57
|
-
`Failed to load resource from ${resolvedPath}: Unknown error`
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Load multiple resources in parallel
|
|
63
|
-
* @param filePaths Array of file paths
|
|
64
|
-
* @param options Optional loading configuration
|
|
65
|
-
* @returns Promise resolving to array of load results
|
|
66
|
-
*/
|
|
67
|
-
async loadMultiple(filePaths, options) {
|
|
68
|
-
const promises = filePaths.map(async (filePath) => {
|
|
69
|
-
try {
|
|
70
|
-
const data = await this.load(filePath, options);
|
|
71
|
-
return {
|
|
72
|
-
data,
|
|
73
|
-
path: filePath,
|
|
74
|
-
success: true
|
|
75
|
-
};
|
|
76
|
-
} catch (error) {
|
|
77
|
-
return {
|
|
78
|
-
data: "",
|
|
79
|
-
path: filePath,
|
|
80
|
-
success: false,
|
|
81
|
-
error: error instanceof Error ? error.message : String(error)
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
return Promise.all(promises);
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Check if the path is valid for loading in Node.js
|
|
89
|
-
* @param filePath File path to check
|
|
90
|
-
* @returns true if the path can be loaded
|
|
91
|
-
*/
|
|
92
|
-
canLoad(filePath) {
|
|
93
|
-
const validPatterns = [
|
|
94
|
-
/^\//,
|
|
95
|
-
// Unix absolute paths
|
|
96
|
-
/^[a-zA-Z]:/,
|
|
97
|
-
// Windows absolute paths (e.g., C:\)
|
|
98
|
-
/^\.\.?\//,
|
|
99
|
-
// Relative paths starting with ./ or ../
|
|
100
|
-
/^[^/\\]+\//
|
|
101
|
-
// Relative paths without explicit prefix (e.g., "shaders/")
|
|
102
|
-
];
|
|
103
|
-
return validPatterns.some((pattern) => pattern.test(filePath));
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Check if a file exists without loading it
|
|
107
|
-
* @param filePath File path to check
|
|
108
|
-
* @returns Promise resolving to true if file exists
|
|
109
|
-
*/
|
|
110
|
-
async exists(filePath) {
|
|
111
|
-
const resolvedPath = this.resolvePath(filePath);
|
|
112
|
-
try {
|
|
113
|
-
await fs.access(resolvedPath, fs.constants.F_OK);
|
|
114
|
-
return true;
|
|
115
|
-
} catch {
|
|
116
|
-
return false;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Get file statistics (size, modification time, etc.)
|
|
121
|
-
* @param filePath File path to check
|
|
122
|
-
* @returns Promise resolving to file stats
|
|
123
|
-
*/
|
|
124
|
-
async getStats(filePath) {
|
|
125
|
-
const resolvedPath = this.resolvePath(filePath);
|
|
126
|
-
return fs.stat(resolvedPath);
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Set a new base directory for resolving relative paths
|
|
130
|
-
* @param baseDir New base directory
|
|
131
|
-
*/
|
|
132
|
-
setBaseDir(baseDir) {
|
|
133
|
-
this.baseDir = baseDir;
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Get the current base directory
|
|
137
|
-
* @returns Current base directory
|
|
138
|
-
*/
|
|
139
|
-
getBaseDir() {
|
|
140
|
-
return this.baseDir;
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* List all files in a directory
|
|
144
|
-
* @param dirPath Directory path to list
|
|
145
|
-
* @param recursive Whether to recursively list subdirectories (default: false)
|
|
146
|
-
* @returns Promise resolving to array of file paths
|
|
147
|
-
*/
|
|
148
|
-
async listDirectory(dirPath, recursive = false) {
|
|
149
|
-
const resolvedPath = this.resolvePath(dirPath);
|
|
150
|
-
const entries = await fs.readdir(resolvedPath, { withFileTypes: true });
|
|
151
|
-
const files = [];
|
|
152
|
-
for (const entry of entries) {
|
|
153
|
-
const fullPath = path.join(resolvedPath, entry.name);
|
|
154
|
-
if (entry.isDirectory() && recursive) {
|
|
155
|
-
const subFiles = await this.listDirectory(fullPath, true);
|
|
156
|
-
files.push(...subFiles);
|
|
157
|
-
} else if (entry.isFile()) {
|
|
158
|
-
files.push(fullPath);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
return files;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
export {
|
|
165
|
-
NodeResourceLoader
|
|
166
|
-
};
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
var Environment = /* @__PURE__ */ ((Environment2) => {
|
|
2
|
-
Environment2["BROWSER"] = "browser";
|
|
3
|
-
Environment2["NODE"] = "node";
|
|
4
|
-
Environment2["UNKNOWN"] = "unknown";
|
|
5
|
-
return Environment2;
|
|
6
|
-
})(Environment || {});
|
|
7
|
-
class ResourceLoaderFactory {
|
|
8
|
-
/**
|
|
9
|
-
* Detect the current runtime environment
|
|
10
|
-
* @returns The detected environment type
|
|
11
|
-
*/
|
|
12
|
-
static detectEnvironment() {
|
|
13
|
-
if (typeof window !== "undefined" && typeof window.document !== "undefined" && typeof fetch !== "undefined") {
|
|
14
|
-
return "browser";
|
|
15
|
-
}
|
|
16
|
-
if (typeof process !== "undefined" && process.versions != null && process.versions.node != null) {
|
|
17
|
-
return "node";
|
|
18
|
-
}
|
|
19
|
-
return "unknown";
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Check if the current environment is a browser
|
|
23
|
-
* @returns true if running in a browser
|
|
24
|
-
*/
|
|
25
|
-
static isBrowser() {
|
|
26
|
-
return this.detectEnvironment() === "browser";
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Check if the current environment is Node.js
|
|
30
|
-
* @returns true if running in Node.js
|
|
31
|
-
*/
|
|
32
|
-
static isNode() {
|
|
33
|
-
return this.detectEnvironment() === "node";
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Create a resource loader for the current environment
|
|
37
|
-
* @param options Optional factory configuration
|
|
38
|
-
* @returns A resource loader instance appropriate for the current platform
|
|
39
|
-
* @throws Error if the environment is not supported
|
|
40
|
-
*/
|
|
41
|
-
static async create(options) {
|
|
42
|
-
const environment = options?.forceEnvironment || this.detectEnvironment();
|
|
43
|
-
switch (environment) {
|
|
44
|
-
case "browser":
|
|
45
|
-
return await this.createBrowserLoader(options);
|
|
46
|
-
case "node":
|
|
47
|
-
return await this.createNodeLoader(options);
|
|
48
|
-
case "unknown":
|
|
49
|
-
throw new Error(
|
|
50
|
-
"Unsupported environment: Unable to determine runtime environment. Please specify forceEnvironment in options."
|
|
51
|
-
);
|
|
52
|
-
default:
|
|
53
|
-
throw new Error(`Unsupported environment: ${environment}`);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Create a browser resource loader
|
|
58
|
-
* @param options Optional factory configuration
|
|
59
|
-
* @returns A browser resource loader instance
|
|
60
|
-
*/
|
|
61
|
-
static async createBrowserLoader(options) {
|
|
62
|
-
const { BrowserResourceLoader: Loader } = await import("./browser-resource-loader-D51BD3k_.js");
|
|
63
|
-
return new Loader(options?.baseUrl, options?.timeout);
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Create a Node.js resource loader
|
|
67
|
-
* @param options Optional factory configuration
|
|
68
|
-
* @returns A Node.js resource loader instance
|
|
69
|
-
*/
|
|
70
|
-
static async createNodeLoader(options) {
|
|
71
|
-
const { NodeResourceLoader: Loader } = await import("./node-resource-loader-MzkD-IGo.js");
|
|
72
|
-
return new Loader(options?.baseDir);
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Create a resource loader with automatic fallback
|
|
76
|
-
* If the preferred loader is not available, falls back to the available loader
|
|
77
|
-
* @param preferredEnvironment Preferred environment
|
|
78
|
-
* @param options Optional factory configuration
|
|
79
|
-
* @returns A resource loader instance
|
|
80
|
-
*/
|
|
81
|
-
static async createWithFallback(preferredEnvironment, options) {
|
|
82
|
-
try {
|
|
83
|
-
options = { ...options, forceEnvironment: preferredEnvironment };
|
|
84
|
-
return await this.create(options);
|
|
85
|
-
} catch {
|
|
86
|
-
return await this.create({ ...options, forceEnvironment: void 0 });
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
export {
|
|
91
|
-
Environment,
|
|
92
|
-
ResourceLoaderFactory
|
|
93
|
-
};
|
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
class ResourceCache {
|
|
2
|
-
constructor(enabled = true) {
|
|
3
|
-
this.cache = /* @__PURE__ */ new Map();
|
|
4
|
-
this.enabled = enabled;
|
|
5
|
-
}
|
|
6
|
-
get(key) {
|
|
7
|
-
if (!this.enabled) return void 0;
|
|
8
|
-
return this.cache.get(key);
|
|
9
|
-
}
|
|
10
|
-
set(key, value) {
|
|
11
|
-
if (this.enabled) {
|
|
12
|
-
this.cache.set(key, value);
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
has(key) {
|
|
16
|
-
if (!this.enabled) return false;
|
|
17
|
-
return this.cache.has(key);
|
|
18
|
-
}
|
|
19
|
-
clear() {
|
|
20
|
-
this.cache.clear();
|
|
21
|
-
}
|
|
22
|
-
size() {
|
|
23
|
-
return this.cache.size;
|
|
24
|
-
}
|
|
25
|
-
enable() {
|
|
26
|
-
this.enabled = true;
|
|
27
|
-
}
|
|
28
|
-
disable() {
|
|
29
|
-
this.enabled = false;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
class ResourcePipeline {
|
|
33
|
-
/**
|
|
34
|
-
* Create a new resource loading pipeline
|
|
35
|
-
* @param loader Resource loader instance
|
|
36
|
-
* @param options Pipeline configuration options
|
|
37
|
-
*/
|
|
38
|
-
constructor(loader, options) {
|
|
39
|
-
this.loader = loader;
|
|
40
|
-
this.concurrency = options?.concurrency ?? 10;
|
|
41
|
-
this.cache = new ResourceCache(options?.cache ?? true);
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Load a single resource with caching support
|
|
45
|
-
* @param path Resource path or URL
|
|
46
|
-
* @param options Optional loading options
|
|
47
|
-
* @returns Promise resolving to the resource content
|
|
48
|
-
*/
|
|
49
|
-
async load(path, options) {
|
|
50
|
-
const cached = this.cache.get(path);
|
|
51
|
-
if (cached !== void 0) {
|
|
52
|
-
return cached;
|
|
53
|
-
}
|
|
54
|
-
const content = await this.loader.load(path, options);
|
|
55
|
-
this.cache.set(path, content);
|
|
56
|
-
return content;
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Load multiple resources with concurrency control
|
|
60
|
-
* @param paths Array of resource paths
|
|
61
|
-
* @param options Optional loading options
|
|
62
|
-
* @returns Promise resolving to batch load result
|
|
63
|
-
*/
|
|
64
|
-
async loadBatch(paths, options) {
|
|
65
|
-
const succeeded = /* @__PURE__ */ new Map();
|
|
66
|
-
const failed = /* @__PURE__ */ new Map();
|
|
67
|
-
for (let i = 0; i < paths.length; i += this.concurrency) {
|
|
68
|
-
const batch = paths.slice(i, i + this.concurrency);
|
|
69
|
-
const results = await this.loader.loadMultiple(batch, options);
|
|
70
|
-
for (const result of results) {
|
|
71
|
-
if (result.success) {
|
|
72
|
-
succeeded.set(result.path, result.data);
|
|
73
|
-
this.cache.set(result.path, result.data);
|
|
74
|
-
} else {
|
|
75
|
-
failed.set(result.path, result.error || "Unknown error");
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return {
|
|
80
|
-
succeeded,
|
|
81
|
-
failed,
|
|
82
|
-
total: paths.length,
|
|
83
|
-
successCount: succeeded.size,
|
|
84
|
-
failureCount: failed.size
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Load a shader from separate vertex and fragment files
|
|
89
|
-
* @param vertexPath Path to vertex shader file
|
|
90
|
-
* @param fragmentPath Path to fragment shader file
|
|
91
|
-
* @param options Optional loading options
|
|
92
|
-
* @returns Promise resolving to shader source code
|
|
93
|
-
*/
|
|
94
|
-
async loadShader(vertexPath, fragmentPath, options) {
|
|
95
|
-
const [vertex, fragment] = await Promise.all([
|
|
96
|
-
this.load(vertexPath, options),
|
|
97
|
-
this.load(fragmentPath, options)
|
|
98
|
-
]);
|
|
99
|
-
return { vertex, fragment };
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Load multiple shaders
|
|
103
|
-
* @param shaders Array of shader definitions
|
|
104
|
-
* @param options Optional loading options
|
|
105
|
-
* @returns Promise resolving to array of named shader sources
|
|
106
|
-
*/
|
|
107
|
-
async loadShaders(shaders, options) {
|
|
108
|
-
const results = await Promise.all(
|
|
109
|
-
shaders.map(async (shader) => {
|
|
110
|
-
const source = await this.loadShader(
|
|
111
|
-
shader.vertex,
|
|
112
|
-
shader.fragment,
|
|
113
|
-
options
|
|
114
|
-
);
|
|
115
|
-
return {
|
|
116
|
-
name: shader.name,
|
|
117
|
-
...source
|
|
118
|
-
};
|
|
119
|
-
})
|
|
120
|
-
);
|
|
121
|
-
return results;
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Load resources from a manifest file
|
|
125
|
-
* @param manifestPath Path to JSON manifest file
|
|
126
|
-
* @param options Optional loading options
|
|
127
|
-
* @returns Promise resolving to batch load result
|
|
128
|
-
*/
|
|
129
|
-
async loadFromManifest(manifestPath, options) {
|
|
130
|
-
const manifestContent = await this.load(manifestPath, options);
|
|
131
|
-
const manifest = JSON.parse(manifestContent);
|
|
132
|
-
return this.loadBatch(manifest.resources, options);
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Preload resources for faster access later
|
|
136
|
-
* @param paths Array of resource paths to preload
|
|
137
|
-
* @param options Optional loading options
|
|
138
|
-
* @returns Promise resolving when all resources are loaded
|
|
139
|
-
*/
|
|
140
|
-
async preload(paths, options) {
|
|
141
|
-
await this.loadBatch(paths, options);
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Check if a resource is cached
|
|
145
|
-
* @param path Resource path
|
|
146
|
-
* @returns true if the resource is in the cache
|
|
147
|
-
*/
|
|
148
|
-
isCached(path) {
|
|
149
|
-
return this.cache.has(path);
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* Get a resource from cache without loading
|
|
153
|
-
* @param path Resource path
|
|
154
|
-
* @returns Cached content or undefined if not cached
|
|
155
|
-
*/
|
|
156
|
-
getCached(path) {
|
|
157
|
-
return this.cache.get(path);
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Clear the resource cache
|
|
161
|
-
*/
|
|
162
|
-
clearCache() {
|
|
163
|
-
this.cache.clear();
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Get cache statistics
|
|
167
|
-
* @returns Number of cached resources
|
|
168
|
-
*/
|
|
169
|
-
getCacheSize() {
|
|
170
|
-
return this.cache.size();
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* Enable caching
|
|
174
|
-
*/
|
|
175
|
-
enableCache() {
|
|
176
|
-
this.cache.enable();
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Disable caching
|
|
180
|
-
*/
|
|
181
|
-
disableCache() {
|
|
182
|
-
this.cache.disable();
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Set the maximum concurrency for batch operations
|
|
186
|
-
* @param concurrency Maximum concurrent loads
|
|
187
|
-
*/
|
|
188
|
-
setConcurrency(concurrency) {
|
|
189
|
-
this.concurrency = Math.max(1, concurrency);
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Get the underlying resource loader
|
|
193
|
-
* @returns The resource loader instance
|
|
194
|
-
*/
|
|
195
|
-
getLoader() {
|
|
196
|
-
return this.loader;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
async function createResourcePipeline(options) {
|
|
200
|
-
const { ResourceLoaderFactory } = await import("./resource-loader-factory-DQ-PAVcN.js");
|
|
201
|
-
const loader = await ResourceLoaderFactory.create({
|
|
202
|
-
baseUrl: options?.baseUrl,
|
|
203
|
-
baseDir: options?.baseDir,
|
|
204
|
-
timeout: options?.timeout
|
|
205
|
-
});
|
|
206
|
-
return new ResourcePipeline(loader, options);
|
|
207
|
-
}
|
|
208
|
-
export {
|
|
209
|
-
ResourcePipeline,
|
|
210
|
-
createResourcePipeline
|
|
211
|
-
};
|