bloody-engine 1.0.2 → 1.0.4
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 +0 -5
- package/dist/web/batch-renderer.test.d.ts +12 -0
- package/dist/web/batch-renderer.test.d.ts.map +1 -0
- package/dist/web/core/buffer.d.ts +58 -0
- package/dist/web/core/buffer.d.ts.map +1 -0
- package/dist/web/core/grahpic-device.d.ts +66 -0
- package/dist/web/core/grahpic-device.d.ts.map +1 -0
- package/dist/web/core/index.d.ts +8 -0
- package/dist/web/core/index.d.ts.map +1 -0
- package/dist/web/core/resource-loader-factory.d.ts +90 -0
- package/dist/web/core/resource-loader-factory.d.ts.map +1 -0
- package/dist/web/core/resource-loader.d.ts +71 -0
- package/dist/web/core/resource-loader.d.ts.map +1 -0
- package/dist/web/core/resource-pipeline.d.ts +139 -0
- package/dist/web/core/resource-pipeline.d.ts.map +1 -0
- package/dist/web/core/shader.d.ts +62 -0
- package/dist/web/core/shader.d.ts.map +1 -0
- package/dist/web/core/texture.d.ts +69 -0
- package/dist/web/core/texture.d.ts.map +1 -0
- package/dist/web/demo-node.d.ts +2 -0
- package/dist/web/demo-node.d.ts.map +1 -0
- package/dist/web/examples/batch-renderer-demo.d.ts +10 -0
- package/dist/web/examples/batch-renderer-demo.d.ts.map +1 -0
- package/dist/web/examples/projection-examples.d.ts +87 -0
- package/dist/web/examples/projection-examples.d.ts.map +1 -0
- package/dist/web/examples/resource-loader-demo.d.ts +14 -0
- package/dist/web/examples/resource-loader-demo.d.ts.map +1 -0
- package/dist/web/examples/shader-examples.d.ts +92 -0
- package/dist/web/examples/shader-examples.d.ts.map +1 -0
- package/dist/web/examples/sprite-batch-renderer-demo.d.ts +12 -0
- package/dist/web/examples/sprite-batch-renderer-demo.d.ts.map +1 -0
- package/dist/web/index-node-batch.d.ts +10 -0
- package/dist/web/index-node-batch.d.ts.map +1 -0
- package/dist/web/index.d.ts +7 -0
- package/dist/web/index.d.ts.map +1 -0
- package/dist/web/index.js +34 -37
- package/dist/web/index.umd.js +7 -7
- package/dist/web/platforms/browser/browser-context.d.ts +31 -0
- package/dist/web/platforms/browser/browser-context.d.ts.map +1 -0
- package/dist/web/platforms/browser/browser-resource-loader.d.ts +67 -0
- package/dist/web/platforms/browser/browser-resource-loader.d.ts.map +1 -0
- package/dist/web/platforms/node/node-context.d.ts +31 -0
- package/dist/web/platforms/node/node-context.d.ts.map +1 -0
- package/dist/web/platforms/node/node-resource-loader.d.ts +73 -0
- package/dist/web/platforms/node/node-resource-loader.d.ts.map +1 -0
- package/dist/web/platforms/node/sdl-window.d.ts +41 -0
- package/dist/web/platforms/node/sdl-window.d.ts.map +1 -0
- package/dist/web/projection.test.d.ts +5 -0
- package/dist/web/projection.test.d.ts.map +1 -0
- package/dist/web/public-api.d.ts +20 -0
- package/dist/web/public-api.d.ts.map +1 -0
- package/dist/web/rendering/batch-renderer.d.ts +273 -0
- package/dist/web/rendering/batch-renderer.d.ts.map +1 -0
- package/dist/web/rendering/camera.d.ts +153 -0
- package/dist/web/rendering/camera.d.ts.map +1 -0
- package/dist/web/rendering/projection.d.ts +108 -0
- package/dist/web/rendering/projection.d.ts.map +1 -0
- package/dist/web/rendering/rendering-context-factory.d.ts +24 -0
- package/dist/web/rendering/rendering-context-factory.d.ts.map +1 -0
- package/dist/web/rendering/rendering-context.d.ts +77 -0
- package/dist/web/rendering/rendering-context.d.ts.map +1 -0
- package/dist/web/rendering/vertex.d.ts +98 -0
- package/dist/web/rendering/vertex.d.ts.map +1 -0
- package/dist/web/scene/scene.d.ts +139 -0
- package/dist/web/scene/scene.d.ts.map +1 -0
- package/package.json +5 -4
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { ProjectionConfig, GridCoord, ScreenCoord } from '../rendering/projection';
|
|
2
|
+
/**
|
|
3
|
+
* Initialize the projection system with game-specific settings
|
|
4
|
+
*/
|
|
5
|
+
export declare function initializeGameProjection(): ProjectionConfig;
|
|
6
|
+
/**
|
|
7
|
+
* Entity in the game world with position and height
|
|
8
|
+
*/
|
|
9
|
+
interface GameEntity {
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
gridPos: GridCoord;
|
|
13
|
+
screenPos?: ScreenCoord;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Update an entity's screen position based on its grid position
|
|
17
|
+
*/
|
|
18
|
+
export declare function updateEntityScreenPosition(entity: GameEntity, projection: ProjectionConfig): void;
|
|
19
|
+
/**
|
|
20
|
+
* Create a game entity at a grid position
|
|
21
|
+
*/
|
|
22
|
+
export declare function createEntity(id: string, name: string, gridPos: GridCoord, projection: ProjectionConfig): GameEntity;
|
|
23
|
+
/**
|
|
24
|
+
* Handle mouse click event to select a game entity
|
|
25
|
+
* Returns the grid cell that was clicked
|
|
26
|
+
*/
|
|
27
|
+
export declare function handleMouseClick(event: MouseEvent, canvas: HTMLCanvasElement, projection: ProjectionConfig): GridCoord;
|
|
28
|
+
/**
|
|
29
|
+
* Calculate Manhattan distance between two grid positions
|
|
30
|
+
* Ignores height differences (for ground-level pathfinding)
|
|
31
|
+
*/
|
|
32
|
+
export declare function calculateGridDistance(from: GridCoord, to: GridCoord): number;
|
|
33
|
+
/**
|
|
34
|
+
* Calculate 3D Euclidean distance considering height
|
|
35
|
+
* Useful for flying units or elevation-aware costs
|
|
36
|
+
*/
|
|
37
|
+
export declare function calculate3DDistance(from: GridCoord, to: GridCoord): number;
|
|
38
|
+
/**
|
|
39
|
+
* Move an entity towards a target position
|
|
40
|
+
*/
|
|
41
|
+
export declare function moveEntityTowards(entity: GameEntity, target: GridCoord, projection: ProjectionConfig): void;
|
|
42
|
+
/**
|
|
43
|
+
* Calculate render priority based on grid position
|
|
44
|
+
* In isometric view, objects further "back" should render first
|
|
45
|
+
*
|
|
46
|
+
* The render priority is based on the sum of grid coordinates
|
|
47
|
+
* This ensures proper depth sorting for non-overlapping isometric tiles
|
|
48
|
+
*/
|
|
49
|
+
export declare function calculateRenderPriority(gridCoord: GridCoord): number;
|
|
50
|
+
/**
|
|
51
|
+
* Sort entities by render priority
|
|
52
|
+
*/
|
|
53
|
+
export declare function sortEntitiesByDepth(entities: GameEntity[]): GameEntity[];
|
|
54
|
+
/**
|
|
55
|
+
* Simple height map - returns terrain height at a grid position
|
|
56
|
+
*/
|
|
57
|
+
type TerrainHeightMap = (x: number, y: number) => number;
|
|
58
|
+
/**
|
|
59
|
+
* Create a simple height map function
|
|
60
|
+
*/
|
|
61
|
+
export declare function createTerrainHeightMap(): TerrainHeightMap;
|
|
62
|
+
/**
|
|
63
|
+
* Position an entity on terrain (automatically set height)
|
|
64
|
+
*/
|
|
65
|
+
export declare function placeEntityOnTerrain(entity: GameEntity, heightMap: TerrainHeightMap, projection: ProjectionConfig): void;
|
|
66
|
+
/**
|
|
67
|
+
* Game camera with grid-based positioning
|
|
68
|
+
*/
|
|
69
|
+
export interface Camera {
|
|
70
|
+
center: GridCoord;
|
|
71
|
+
viewWidth: number;
|
|
72
|
+
viewHeight: number;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Create a camera centered on a grid position
|
|
76
|
+
*/
|
|
77
|
+
export declare function createCamera(centerGrid: GridCoord, viewWidthPixels: number, viewHeightPixels: number, projection: ProjectionConfig): Camera;
|
|
78
|
+
/**
|
|
79
|
+
* Check if an entity is within camera view
|
|
80
|
+
*/
|
|
81
|
+
export declare function isEntityInView(entity: GameEntity, camera: Camera, projection: ProjectionConfig, margin?: number): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Run a complete example scenario
|
|
84
|
+
*/
|
|
85
|
+
export declare function runExampleScenario(): void;
|
|
86
|
+
export {};
|
|
87
|
+
//# sourceMappingURL=projection-examples.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projection-examples.d.ts","sourceRoot":"","sources":["../../../src/examples/projection-examples.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAKL,gBAAgB,EAEhB,KAAK,SAAS,EACd,KAAK,WAAW,EACjB,MAAM,yBAAyB,CAAC;AAMjC;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,gBAAgB,CAa3D;AAMD;;GAEG;AACH,UAAU,UAAU;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,SAAS,CAAC;IACnB,SAAS,CAAC,EAAE,WAAW,CAAC;CACzB;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,UAAU,EAClB,UAAU,EAAE,gBAAgB,GAC3B,IAAI,CAcN;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,SAAS,EAClB,UAAU,EAAE,gBAAgB,GAC3B,UAAU,CAIZ;AAMD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,iBAAiB,EACzB,UAAU,EAAE,gBAAgB,GAC3B,SAAS,CAkBX;AAMD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,GAAG,MAAM,CAE5E;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,GAAG,MAAM,CAM1E;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,SAAS,EACjB,UAAU,EAAE,gBAAgB,GAC3B,IAAI,CAaN;AAMD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,CAIpE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,CAKxE;AAMD;;GAEG;AACH,KAAK,gBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;AAEzD;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,gBAAgB,CAazD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE,gBAAgB,EAC3B,UAAU,EAAE,gBAAgB,GAC3B,IAAI,CAaN;AAMD;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,MAAM,EAAE,SAAS,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,SAAS,EACrB,eAAe,EAAE,MAAM,EACvB,gBAAgB,EAAE,MAAM,EACxB,UAAU,EAAE,gBAAgB,GAC3B,MAAM,CAMR;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,gBAAgB,EAC5B,MAAM,GAAE,MAAW,GAClB,OAAO,CAYT;AAMD;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAsEzC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource Loader Demo
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates the resource loading system with:
|
|
5
|
+
* - Loading shader source code from external files
|
|
6
|
+
* - Using ResourcePipeline for async resource management
|
|
7
|
+
* - Caching and batch loading
|
|
8
|
+
* - Cross-platform resource loading (Browser/Node.js)
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Browser-based Resource Loader Demo
|
|
12
|
+
*/
|
|
13
|
+
export declare function runBrowserResourceLoaderDemo(): Promise<void>;
|
|
14
|
+
//# sourceMappingURL=resource-loader-demo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-loader-demo.d.ts","sourceRoot":"","sources":["../../../src/examples/resource-loader-demo.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAyCH;;GAEG;AACH,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,IAAI,CAAC,CAyRlE"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shader Examples and Presets
|
|
3
|
+
* Collection of shader implementations for different effects
|
|
4
|
+
*/
|
|
5
|
+
export declare const BASIC_SHADER: {
|
|
6
|
+
vertex: string;
|
|
7
|
+
fragment: string;
|
|
8
|
+
uniforms: string[];
|
|
9
|
+
attributes: string[];
|
|
10
|
+
};
|
|
11
|
+
export declare const GLOW_SHADER: {
|
|
12
|
+
vertex: string;
|
|
13
|
+
fragment: string;
|
|
14
|
+
uniforms: string[];
|
|
15
|
+
attributes: string[];
|
|
16
|
+
};
|
|
17
|
+
export declare const WAVE_SHADER: {
|
|
18
|
+
vertex: string;
|
|
19
|
+
fragment: string;
|
|
20
|
+
uniforms: string[];
|
|
21
|
+
attributes: string[];
|
|
22
|
+
};
|
|
23
|
+
export declare const NEON_SHADER: {
|
|
24
|
+
vertex: string;
|
|
25
|
+
fragment: string;
|
|
26
|
+
uniforms: string[];
|
|
27
|
+
attributes: string[];
|
|
28
|
+
};
|
|
29
|
+
export declare const HOLOGRAM_SHADER: {
|
|
30
|
+
vertex: string;
|
|
31
|
+
fragment: string;
|
|
32
|
+
uniforms: string[];
|
|
33
|
+
attributes: string[];
|
|
34
|
+
};
|
|
35
|
+
export declare const CHROMATIC_SHADER: {
|
|
36
|
+
vertex: string;
|
|
37
|
+
fragment: string;
|
|
38
|
+
uniforms: string[];
|
|
39
|
+
attributes: string[];
|
|
40
|
+
};
|
|
41
|
+
export declare const PSYCHEDELIC_SHADER: {
|
|
42
|
+
vertex: string;
|
|
43
|
+
fragment: string;
|
|
44
|
+
uniforms: string[];
|
|
45
|
+
attributes: string[];
|
|
46
|
+
};
|
|
47
|
+
export declare const SHADER_LIBRARY: {
|
|
48
|
+
BASIC: {
|
|
49
|
+
vertex: string;
|
|
50
|
+
fragment: string;
|
|
51
|
+
uniforms: string[];
|
|
52
|
+
attributes: string[];
|
|
53
|
+
};
|
|
54
|
+
GLOW: {
|
|
55
|
+
vertex: string;
|
|
56
|
+
fragment: string;
|
|
57
|
+
uniforms: string[];
|
|
58
|
+
attributes: string[];
|
|
59
|
+
};
|
|
60
|
+
WAVE: {
|
|
61
|
+
vertex: string;
|
|
62
|
+
fragment: string;
|
|
63
|
+
uniforms: string[];
|
|
64
|
+
attributes: string[];
|
|
65
|
+
};
|
|
66
|
+
NEON: {
|
|
67
|
+
vertex: string;
|
|
68
|
+
fragment: string;
|
|
69
|
+
uniforms: string[];
|
|
70
|
+
attributes: string[];
|
|
71
|
+
};
|
|
72
|
+
HOLOGRAM: {
|
|
73
|
+
vertex: string;
|
|
74
|
+
fragment: string;
|
|
75
|
+
uniforms: string[];
|
|
76
|
+
attributes: string[];
|
|
77
|
+
};
|
|
78
|
+
CHROMATIC: {
|
|
79
|
+
vertex: string;
|
|
80
|
+
fragment: string;
|
|
81
|
+
uniforms: string[];
|
|
82
|
+
attributes: string[];
|
|
83
|
+
};
|
|
84
|
+
PSYCHEDELIC: {
|
|
85
|
+
vertex: string;
|
|
86
|
+
fragment: string;
|
|
87
|
+
uniforms: string[];
|
|
88
|
+
attributes: string[];
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
export type ShaderPreset = keyof typeof SHADER_LIBRARY;
|
|
92
|
+
//# sourceMappingURL=shader-examples.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shader-examples.d.ts","sourceRoot":"","sources":["../../../src/examples/shader-examples.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,eAAO,MAAM,YAAY;;;;;CA0BxB,CAAC;AAKF,eAAO,MAAM,WAAW;;;;;CAkCvB,CAAC;AAKF,eAAO,MAAM,WAAW;;;;;CAiCvB,CAAC;AAKF,eAAO,MAAM,WAAW;;;;;CAuCvB,CAAC;AAKF,eAAO,MAAM,eAAe;;;;;CAmC3B,CAAC;AAKF,eAAO,MAAM,gBAAgB;;;;;CAiC5B,CAAC;AAKF,eAAO,MAAM,kBAAkB;;;;;CAoC9B,CAAC;AAKF,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAQ1B,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,MAAM,OAAO,cAAc,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sprite Batch Renderer Demo - V2
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates the 2.5D sprite batch renderer with:
|
|
5
|
+
* - Full vertex structure (position, texture coords, color tint, texture index)
|
|
6
|
+
* - Z-depth layering for 2.5D positioning
|
|
7
|
+
* - Per-sprite color tinting
|
|
8
|
+
* - Texture atlas support via texture index
|
|
9
|
+
* - UV rect selection for sprite sheets
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=sprite-batch-renderer-demo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sprite-batch-renderer-demo.d.ts","sourceRoot":"","sources":["../../../src/examples/sprite-batch-renderer-demo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Batch Renderer Version of index-node.ts
|
|
3
|
+
*
|
|
4
|
+
* Comparison version using BatchRenderer instead of traditional VertexBuffer
|
|
5
|
+
* Demonstrates the difference between:
|
|
6
|
+
* - Traditional: Create static buffers, render with fixed transforms
|
|
7
|
+
* - Batch: Dynamic buffer, update vertices each frame, batch render
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=index-node-batch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-node-batch.d.ts","sourceRoot":"","sources":["../../src/index-node-batch.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,cAAc,CAAC"}
|
package/dist/web/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import X from "gl";
|
|
2
|
-
import * as
|
|
2
|
+
import * as p from "fs/promises";
|
|
3
3
|
import * as T from "path";
|
|
4
4
|
class Y {
|
|
5
5
|
constructor(e) {
|
|
@@ -495,7 +495,7 @@ const K = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
|
495
495
|
IndexBuffer: j,
|
|
496
496
|
VertexBuffer: Q
|
|
497
497
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
498
|
-
class
|
|
498
|
+
class ue {
|
|
499
499
|
/**
|
|
500
500
|
* Create a new batch renderer (V1)
|
|
501
501
|
* @param gl WebGL rendering context
|
|
@@ -624,7 +624,7 @@ class de {
|
|
|
624
624
|
* @private
|
|
625
625
|
*/
|
|
626
626
|
generateQuadVertices(e) {
|
|
627
|
-
const { x: t, y: r, width: s, height: i, rotation: o } = e, n = s / 2, a = i / 2, h = Math.cos(o), x = Math.sin(o), l = (m,
|
|
627
|
+
const { x: t, y: r, width: s, height: i, rotation: o } = e, n = s / 2, a = i / 2, h = Math.cos(o), x = Math.sin(o), l = (m, w) => [m * h - w * x, m * x + w * h], d = [
|
|
628
628
|
[-n, -a],
|
|
629
629
|
// bottom-left
|
|
630
630
|
[n, -a],
|
|
@@ -652,8 +652,8 @@ class de {
|
|
|
652
652
|
// bottom-left
|
|
653
653
|
], y = [];
|
|
654
654
|
for (let m = 0; m < d.length; m++) {
|
|
655
|
-
const [
|
|
656
|
-
y.push([t + A, r + u, 0,
|
|
655
|
+
const [w, E] = d[m], [A, u] = l(w, E), [v, b] = f[m];
|
|
656
|
+
y.push([t + A, r + u, 0, v, b]);
|
|
657
657
|
}
|
|
658
658
|
return y;
|
|
659
659
|
}
|
|
@@ -664,7 +664,7 @@ class de {
|
|
|
664
664
|
this.vertexBuffer && (this.gl.deleteBuffer(this.vertexBuffer), this.vertexBuffer = null);
|
|
665
665
|
}
|
|
666
666
|
}
|
|
667
|
-
class
|
|
667
|
+
class de {
|
|
668
668
|
/**
|
|
669
669
|
* Create a new sprite batch renderer (V2)
|
|
670
670
|
* @param gl WebGL rendering context
|
|
@@ -837,7 +837,7 @@ class fe {
|
|
|
837
837
|
* @private
|
|
838
838
|
*/
|
|
839
839
|
generateQuadVertices(e) {
|
|
840
|
-
const { x: t, y: r, z: s, width: i, height: o, rotation: n, color: a, uvRect: h, texIndex: x } = e, l = i / 2, d = o / 2, f = Math.cos(n), y = Math.sin(n), m = (u,
|
|
840
|
+
const { x: t, y: r, z: s, width: i, height: o, rotation: n, color: a, uvRect: h, texIndex: x } = e, l = i / 2, d = o / 2, f = Math.cos(n), y = Math.sin(n), m = (u, v) => [u * f - v * y, u * y + v * f], w = [
|
|
841
841
|
[-l, -d],
|
|
842
842
|
// bottom-left
|
|
843
843
|
[l, -d],
|
|
@@ -864,8 +864,8 @@ class fe {
|
|
|
864
864
|
[h.uMin, h.vMin]
|
|
865
865
|
// bottom-left
|
|
866
866
|
], A = [];
|
|
867
|
-
for (let u = 0; u <
|
|
868
|
-
const [
|
|
867
|
+
for (let u = 0; u < w.length; u++) {
|
|
868
|
+
const [v, b] = w[u], [_, D] = m(v, b), [U, g] = E[u];
|
|
869
869
|
A.push({
|
|
870
870
|
x: t + _,
|
|
871
871
|
y: r + D,
|
|
@@ -1012,7 +1012,7 @@ class F {
|
|
|
1012
1012
|
return F.multiply(s, i);
|
|
1013
1013
|
}
|
|
1014
1014
|
}
|
|
1015
|
-
class
|
|
1015
|
+
class fe {
|
|
1016
1016
|
/**
|
|
1017
1017
|
* Create a new camera
|
|
1018
1018
|
* @param x Initial X position (default 0)
|
|
@@ -1275,7 +1275,7 @@ class ee {
|
|
|
1275
1275
|
async load(e, t) {
|
|
1276
1276
|
const r = this.resolvePath(e), s = t?.encoding || "utf-8";
|
|
1277
1277
|
try {
|
|
1278
|
-
return await
|
|
1278
|
+
return await p.readFile(r, s);
|
|
1279
1279
|
} catch (i) {
|
|
1280
1280
|
if (i instanceof Error) {
|
|
1281
1281
|
const o = i.code;
|
|
@@ -1344,7 +1344,7 @@ class ee {
|
|
|
1344
1344
|
async exists(e) {
|
|
1345
1345
|
const t = this.resolvePath(e);
|
|
1346
1346
|
try {
|
|
1347
|
-
return await
|
|
1347
|
+
return await p.access(t, p.constants.F_OK), !0;
|
|
1348
1348
|
} catch {
|
|
1349
1349
|
return !1;
|
|
1350
1350
|
}
|
|
@@ -1356,7 +1356,7 @@ class ee {
|
|
|
1356
1356
|
*/
|
|
1357
1357
|
async getStats(e) {
|
|
1358
1358
|
const t = this.resolvePath(e);
|
|
1359
|
-
return
|
|
1359
|
+
return p.stat(t);
|
|
1360
1360
|
}
|
|
1361
1361
|
/**
|
|
1362
1362
|
* Set a new base directory for resolving relative paths
|
|
@@ -1379,7 +1379,7 @@ class ee {
|
|
|
1379
1379
|
* @returns Promise resolving to array of file paths
|
|
1380
1380
|
*/
|
|
1381
1381
|
async listDirectory(e, t = !1) {
|
|
1382
|
-
const r = this.resolvePath(e), s = await
|
|
1382
|
+
const r = this.resolvePath(e), s = await p.readdir(r, { withFileTypes: !0 }), i = [];
|
|
1383
1383
|
for (const o of s) {
|
|
1384
1384
|
const n = T.join(r, o.name);
|
|
1385
1385
|
if (o.isDirectory() && t) {
|
|
@@ -1738,7 +1738,7 @@ const L = {
|
|
|
1738
1738
|
"resources/shaders/glow.frag"
|
|
1739
1739
|
]
|
|
1740
1740
|
};
|
|
1741
|
-
async function
|
|
1741
|
+
async function ge() {
|
|
1742
1742
|
console.log("🩸 Bloody Engine - Resource Loader Demo"), console.log(`==========================================
|
|
1743
1743
|
`);
|
|
1744
1744
|
const c = N.detectEnvironment();
|
|
@@ -1760,8 +1760,8 @@ async function ae() {
|
|
|
1760
1760
|
if (console.log("✓ Batch loading complete"), console.log(` - Succeeded: ${t.successCount}`), console.log(` - Failed: ${t.failureCount}`), t.failureCount > 0) {
|
|
1761
1761
|
console.log(`
|
|
1762
1762
|
❌ Failed resources:`);
|
|
1763
|
-
for (const [g,
|
|
1764
|
-
console.log(` - ${g}: ${
|
|
1763
|
+
for (const [g, C] of t.failed)
|
|
1764
|
+
console.log(` - ${g}: ${C}`);
|
|
1765
1765
|
console.log(`
|
|
1766
1766
|
⚠️ Falling back to inline shaders...`);
|
|
1767
1767
|
}
|
|
@@ -1776,8 +1776,8 @@ async function ae() {
|
|
|
1776
1776
|
const s = e.getCacheSize();
|
|
1777
1777
|
console.log(`✓ Cache contains ${s} resources`);
|
|
1778
1778
|
for (const g of M.shaders) {
|
|
1779
|
-
const
|
|
1780
|
-
console.log(` - ${g.name}:`), console.log(` Vertex cached: ${
|
|
1779
|
+
const C = e.isCached(g.vertex), $ = e.isCached(g.fragment);
|
|
1780
|
+
console.log(` - ${g.name}:`), console.log(` Vertex cached: ${C}`), console.log(` Fragment cached: ${$}`);
|
|
1781
1781
|
}
|
|
1782
1782
|
console.log(`
|
|
1783
1783
|
5. Initializing Graphics Device...`);
|
|
@@ -1834,7 +1834,7 @@ void main() {
|
|
|
1834
1834
|
);
|
|
1835
1835
|
console.log("✓ Quad buffer created"), console.log(` - Vertices: ${l.getVertexCount()}`), console.log(`
|
|
1836
1836
|
9. Setting up Rendering...`), a.use();
|
|
1837
|
-
const d = a.getAttributeLocation("aPosition"), f = a.getAttributeLocation("aTexCoord"), y = a.getUniformLocation("uTexture"), m = a.getUniformLocation("uMatrix"),
|
|
1837
|
+
const d = a.getAttributeLocation("aPosition"), f = a.getAttributeLocation("aTexCoord"), y = a.getUniformLocation("uTexture"), m = a.getUniformLocation("uMatrix"), w = a.getUniformLocation("uColor"), E = a.getUniformLocation("uGlowIntensity");
|
|
1838
1838
|
l.bind(), o.enableVertexAttribArray(d), o.vertexAttribPointer(d, 3, o.FLOAT, !1, P.quad.stride, 0), o.enableVertexAttribArray(f), o.vertexAttribPointer(
|
|
1839
1839
|
f,
|
|
1840
1840
|
2,
|
|
@@ -1845,8 +1845,8 @@ void main() {
|
|
|
1845
1845
|
), console.log("✓ Vertex attributes configured"), h.bind(0), o.uniform1i(y, 0), console.log("✓ Texture bound to unit 0");
|
|
1846
1846
|
const u = i.getRenderingContext().canvas;
|
|
1847
1847
|
u && (u.style.display = "block", u.style.margin = "0 auto", u.style.border = "2px solid #333", u.style.backgroundColor = "#1a1a1a"), document.body.style.margin = "0", document.body.style.padding = "20px", document.body.style.backgroundColor = "#0a0a0a", document.body.style.fontFamily = "monospace", document.body.style.color = "#aaa";
|
|
1848
|
-
const
|
|
1849
|
-
|
|
1848
|
+
const v = document.createElement("h1");
|
|
1849
|
+
v.textContent = "🩸 Resource Loader Demo", v.style.textAlign = "center", v.style.color = "#fff", u && u.parentNode ? u.parentNode.insertBefore(v, u) : document.body.insertBefore(v, document.body.firstChild);
|
|
1850
1850
|
const b = document.createElement("div");
|
|
1851
1851
|
b.style.textAlign = "center", b.style.marginTop = "10px", b.style.fontSize = "12px", b.innerHTML = `
|
|
1852
1852
|
<div>Environment: <strong>${c}</strong></div>
|
|
@@ -1856,7 +1856,7 @@ void main() {
|
|
|
1856
1856
|
let _ = 0;
|
|
1857
1857
|
const D = Date.now();
|
|
1858
1858
|
function U() {
|
|
1859
|
-
const g = Date.now(),
|
|
1859
|
+
const g = Date.now(), C = (g - D) / 1e3;
|
|
1860
1860
|
i.clear({ r: 0.1, g: 0.1, b: 0.1, a: 1 });
|
|
1861
1861
|
const $ = [
|
|
1862
1862
|
{ x: -0.3, y: 0.3, color: [1, 0.2, 0.2], glow: 1.5 },
|
|
@@ -1865,14 +1865,14 @@ void main() {
|
|
|
1865
1865
|
{ x: 0.3, y: -0.3, color: [1, 1, 0.2], glow: 1.6 }
|
|
1866
1866
|
];
|
|
1867
1867
|
for (const R of $) {
|
|
1868
|
-
const z =
|
|
1869
|
-
if (
|
|
1870
|
-
|
|
1868
|
+
const z = ae();
|
|
1869
|
+
if (ce(z, R.x, R.y, 0), he(z, 0.4, 0.4, 1), m && o.uniformMatrix4fv(m, !1, z), w && o.uniform3f(
|
|
1870
|
+
w,
|
|
1871
1871
|
R.color[0],
|
|
1872
1872
|
R.color[1],
|
|
1873
1873
|
R.color[2]
|
|
1874
1874
|
), E) {
|
|
1875
|
-
const q = R.glow + Math.sin(
|
|
1875
|
+
const q = R.glow + Math.sin(C * 2) * 0.3;
|
|
1876
1876
|
o.uniform1f(E, q);
|
|
1877
1877
|
}
|
|
1878
1878
|
o.drawArrays(o.TRIANGLES, 0, l.getVertexCount());
|
|
@@ -1887,7 +1887,7 @@ void main() {
|
|
|
1887
1887
|
console.log(`
|
|
1888
1888
|
✓ Demo started! Rendering animation...`), U();
|
|
1889
1889
|
}
|
|
1890
|
-
function
|
|
1890
|
+
function ae() {
|
|
1891
1891
|
return new Float32Array([
|
|
1892
1892
|
1,
|
|
1893
1893
|
0,
|
|
@@ -1907,20 +1907,17 @@ function ce() {
|
|
|
1907
1907
|
1
|
|
1908
1908
|
]);
|
|
1909
1909
|
}
|
|
1910
|
-
function
|
|
1910
|
+
function ce(c, e, t, r) {
|
|
1911
1911
|
c[12] += e, c[13] += t, c[14] += r;
|
|
1912
1912
|
}
|
|
1913
|
-
function
|
|
1913
|
+
function he(c, e, t, r) {
|
|
1914
1914
|
c[0] *= e, c[5] *= t, c[10] *= r;
|
|
1915
1915
|
}
|
|
1916
|
-
typeof window < "u" && ae().catch((c) => {
|
|
1917
|
-
console.error("❌ Demo failed:", c);
|
|
1918
|
-
});
|
|
1919
1916
|
export {
|
|
1920
|
-
|
|
1917
|
+
ue as BatchRenderer,
|
|
1921
1918
|
Y as BrowserRenderingContext,
|
|
1922
1919
|
J as BrowserResourceLoader,
|
|
1923
|
-
|
|
1920
|
+
fe as Camera,
|
|
1924
1921
|
I as Environment,
|
|
1925
1922
|
W as GraphicsDevice,
|
|
1926
1923
|
j as IndexBuffer,
|
|
@@ -1931,10 +1928,10 @@ export {
|
|
|
1931
1928
|
N as ResourceLoaderFactory,
|
|
1932
1929
|
oe as ResourcePipeline,
|
|
1933
1930
|
H as Shader,
|
|
1934
|
-
|
|
1931
|
+
de as SpriteBatchRenderer,
|
|
1935
1932
|
B as Texture,
|
|
1936
1933
|
Q as VertexBuffer,
|
|
1937
1934
|
re as createResourceLoader,
|
|
1938
1935
|
ne as createResourcePipeline,
|
|
1939
|
-
|
|
1936
|
+
ge as runBrowserResourceLoaderDemo
|
|
1940
1937
|
};
|
package/dist/web/index.umd.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(function(l,C){typeof exports=="object"&&typeof module<"u"?C(exports,require("gl"),require("fs/promises"),require("path")):typeof define=="function"&&define.amd?define(["exports","gl","fs/promises","path"],C):(l=typeof globalThis<"u"?globalThis:l||self,C(l.BloodyEngine={},l.createGL,l.fs,l.path))})(this,(function(l,C,se
|
|
1
|
+
(function(l,C){typeof exports=="object"&&typeof module<"u"?C(exports,require("gl"),require("fs/promises"),require("path")):typeof define=="function"&&define.amd?define(["exports","gl","fs/promises","path"],C):(l=typeof globalThis<"u"?globalThis:l||self,C(l.BloodyEngine={},l.createGL,l.fs,l.path))})(this,(function(l,C,re,se){"use strict";function q(a){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(a){for(const t in a)if(t!=="default"){const r=Object.getOwnPropertyDescriptor(a,t);Object.defineProperty(e,t,r.get?r:{enumerable:!0,get:()=>a[t]})}}return e.default=a,Object.freeze(e)}const T=q(re),p=q(se);class O{constructor(e){this.isBrowser=!0,e.canvas?this.canvas=e.canvas:(this.canvas=document.createElement("canvas"),document.body.appendChild(this.canvas)),this.width=e.width,this.height=e.height,this.canvas.width=this.width,this.canvas.height=this.height;const t={alpha:!1,...e.contextAttributes},r=this.canvas.getContext("webgl",t);if(!r)throw new Error("Failed to initialize WebGL context in browser");this.glContext=r}resize(e,t){this.width=e,this.height=t,this.canvas.width=e,this.canvas.height=t,this.glContext.viewport(0,0,e,t)}getViewport(){return{width:this.width,height:this.height}}clear(e){e&&this.glContext.clearColor(e.r,e.g,e.b,e.a),this.glContext.clear(this.glContext.COLOR_BUFFER_BIT|this.glContext.DEPTH_BUFFER_BIT)}present(){}dispose(){this.canvas.parentElement&&this.canvas.parentElement.removeChild(this.canvas)}getCanvas(){return this.canvas}}class V{constructor(e){this.isBrowser=!1,this.width=e.width,this.height=e.height;const t=C(this.width,this.height,{preserveDrawingBuffer:e.preserveDrawingBuffer??!0,...e.contextAttributes});if(!t)throw new Error("Failed to initialize WebGL context in Node.js");this.glContext=t}resize(e,t){this.width=e,this.height=t,console.warn("NodeRenderingContext: Resize requested but not supported. Consider recreating context.")}getViewport(){return{width:this.width,height:this.height}}clear(e){e&&this.glContext.clearColor(e.r,e.g,e.b,e.a),this.glContext.clear(this.glContext.COLOR_BUFFER_BIT|this.glContext.DEPTH_BUFFER_BIT)}present(){this.glContext.flush()}dispose(){this.glContext.flush()}readPixels(){const e=new Uint8Array(this.width*this.height*4);return this.glContext.readPixels(0,0,this.width,this.height,this.glContext.RGBA,this.glContext.UNSIGNED_BYTE,e),e}}class X{static isBrowserEnvironment(){return typeof window<"u"&&typeof document<"u"}static createContext(e){return this.isBrowserEnvironment()?new O(e):new V(e)}static createBrowserContext(e){return new O(e)}static createNodeContext(e){return new V(e)}}class k{constructor(e,t,r,s){this.gl=e;const i=this.injectPrecisionHeader(t,s),o=this.injectPrecisionHeader(r,s);this.vertexShader=this.compileShader(i,e.VERTEX_SHADER),this.fragmentShader=this.compileShader(o,e.FRAGMENT_SHADER),this.program=this.linkProgram(this.vertexShader,this.fragmentShader)}injectPrecisionHeader(e,t){return e.includes("#ifdef GL_ES")||e.includes("precision")?e:`#ifdef GL_ES
|
|
2
2
|
precision highp float;
|
|
3
3
|
#endif
|
|
4
4
|
`+e}compileShader(e,t){const r=this.gl.createShader(t);if(!r)throw new Error(`Failed to create shader of type ${t}`);if(this.gl.shaderSource(r,e),this.gl.compileShader(r),!this.gl.getShaderParameter(r,this.gl.COMPILE_STATUS)){const i=this.gl.getShaderInfoLog(r),o=t===this.gl.VERTEX_SHADER?"vertex":"fragment";throw this.gl.deleteShader(r),new Error(`Failed to compile ${o} shader:
|
|
@@ -6,7 +6,7 @@ ${i}
|
|
|
6
6
|
|
|
7
7
|
Source:
|
|
8
8
|
${e}`)}return r}linkProgram(e,t){const r=this.gl.createProgram();if(!r)throw new Error("Failed to create shader program");if(this.gl.attachShader(r,e),this.gl.attachShader(r,t),this.gl.linkProgram(r),!this.gl.getProgramParameter(r,this.gl.LINK_STATUS)){const i=this.gl.getProgramInfoLog(r);throw this.gl.deleteProgram(r),this.gl.deleteShader(e),this.gl.deleteShader(t),new Error(`Failed to link shader program:
|
|
9
|
-
${i}`)}return r}getProgram(){return this.program}getUniformLocation(e){return this.gl.getUniformLocation(this.program,e)}getAttributeLocation(e){return this.gl.getAttribLocation(this.program,e)}use(){this.gl.useProgram(this.program)}dispose(){this.gl.deleteProgram(this.program),this.gl.deleteShader(this.vertexShader),this.gl.deleteShader(this.fragmentShader)}}class H{constructor(e,t){this.context=X.createContext({width:e,height:t,preserveDrawingBuffer:!0})}getGLContext(){return this.context.glContext}getRenderingContext(){return this.context}getWidth(){return this.context.width}getHeight(){return this.context.height}getViewport(){return this.context.getViewport()}isBrowser(){return this.context.isBrowser}resize(e,t){this.context.resize(e,t)}clear(e){this.context.clear(e)}present(){this.context.present()}dispose(){this.context.dispose()}createShader(e,t){return new k(this.context.glContext,e,t,this.context.isBrowser)}}class R{constructor(e,t,r,s){this.gl=e,this.width=t,this.height=r;const i=e.createTexture();if(!i)throw new Error("Failed to create texture");this.texture=i,e.bindTexture(e.TEXTURE_2D,this.texture),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),s?e.texImage2D(e.TEXTURE_2D,0,e.RGBA,t,r,0,e.RGBA,e.UNSIGNED_BYTE,s):e.texImage2D(e.TEXTURE_2D,0,e.RGBA,t,r,0,e.RGBA,e.UNSIGNED_BYTE,null),e.bindTexture(e.TEXTURE_2D,null)}static createSolid(e,t,r,s,i,o,n=255){const c=t*r,h=new Uint8Array(c*4);for(let m=0;m<c;m++){const u=m*4;h[u]=s,h[u+1]=i,h[u+2]=o,h[u+3]=n}return new R(e,t,r,h)}static createCheckerboard(e,t,r,s=32){const i=new Uint8Array(t*r*4);for(let o=0;o<r;o++)for(let n=0;n<t;n++){const c=Math.floor(n/s),h=Math.floor(o/s),m=(c+h)%2===0,u=(o*t+n)*4,f=m?255:0;i[u]=f,i[u+1]=f,i[u+2]=f,i[u+3]=255}return new R(e,t,r,i)}static createGradient(e,t,r){const s=new Uint8Array(t*r*4);for(let i=0;i<r;i++)for(let o=0;o<t;o++){const n=(i*t+o)*4;s[n]=Math.floor(o/t*255),s[n+1]=Math.floor(i/r*255),s[n+2]=128,s[n+3]=255}return new R(e,t,r,s)}bind(e=0){this.gl.activeTexture(this.gl.TEXTURE0+e),this.gl.bindTexture(this.gl.TEXTURE_2D,this.texture)}unbind(){this.gl.bindTexture(this.gl.TEXTURE_2D,null)}getHandle(){return this.texture}getDimensions(){return{width:this.width,height:this.height}}dispose(){this.gl.deleteTexture(this.texture)}}class W{constructor(e,t,r=0){this.gl=e,this.stride=r;const s=r>0?r/4:3;this.vertexCount=t.length/s;const i=e.createBuffer();if(!i)throw new Error("Failed to create vertex buffer");this.buffer=i,e.bindBuffer(e.ARRAY_BUFFER,this.buffer),e.bufferData(e.ARRAY_BUFFER,t,e.STATIC_DRAW),e.bindBuffer(e.ARRAY_BUFFER,null)}bind(){this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.buffer)}unbind(){this.gl.bindBuffer(this.gl.ARRAY_BUFFER,null)}getVertexCount(){return this.vertexCount}getStride(){return this.stride}dispose(){this.gl.deleteBuffer(this.buffer)}}class j{constructor(e,t){this.gl=e,this.indexCount=t.length;const r=e.createBuffer();if(!r)throw new Error("Failed to create index buffer");this.buffer=r,e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.buffer),e.bufferData(e.ELEMENT_ARRAY_BUFFER,t,e.STATIC_DRAW),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,null)}bind(){this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER,this.buffer)}unbind(){this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER,null)}getIndexCount(){return this.indexCount}dispose(){this.gl.deleteBuffer(this.buffer)}}const oe=Object.freeze(Object.defineProperty({__proto__:null,IndexBuffer:j,VertexBuffer:W},Symbol.toStringTag,{value:"Module"}));class ne{constructor(e,t,r=1e3){this.vertexBuffer=null,this.quads=[],this.isDirty=!1,this.verticesPerQuad=6,this.floatsPerVertex=5,this.texture=null,this.gl=e,this.shader=t,this.maxQuads=r;const s=r*this.verticesPerQuad*this.floatsPerVertex;this.vertexData=new Float32Array(s);const i=e.createBuffer();if(!i)throw new Error("Failed to create vertex buffer");this.vertexBuffer=i,e.bindBuffer(e.ARRAY_BUFFER,this.vertexBuffer),e.bufferData(e.ARRAY_BUFFER,this.vertexData.byteLength,e.DYNAMIC_DRAW),e.bindBuffer(e.ARRAY_BUFFER,null)}setTexture(e){this.texture=e}addQuad(e){if(this.quads.length>=this.maxQuads){console.warn(`Batch renderer at max capacity (${this.maxQuads})`);return}this.quads.push(e),this.isDirty=!0}clear(){this.quads=[],this.isDirty=!0}getQuadCount(){return this.quads.length}update(){if(!this.isDirty||this.quads.length===0)return;let e=0;for(const t of this.quads){const r=this.generateQuadVertices(t);for(const s of r)this.vertexData[e++]=s[0],this.vertexData[e++]=s[1],this.vertexData[e++]=s[2],this.vertexData[e++]=s[3],this.vertexData[e++]=s[4]}this.vertexBuffer&&(this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.vertexBuffer),this.gl.bufferSubData(this.gl.ARRAY_BUFFER,0,this.vertexData.subarray(0,e)),this.gl.bindBuffer(this.gl.ARRAY_BUFFER,null)),this.isDirty=!1}render(e){if(this.quads.length!==0&&(this.update(),this.shader.use(),this.vertexBuffer)){this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.vertexBuffer);const t=this.shader.getAttributeLocation("aPosition"),r=this.shader.getAttributeLocation("aTexCoord");if(t!==-1&&(this.gl.enableVertexAttribArray(t),this.gl.vertexAttribPointer(t,3,this.gl.FLOAT,!1,this.floatsPerVertex*4,0)),r!==-1&&(this.gl.enableVertexAttribArray(r),this.gl.vertexAttribPointer(r,2,this.gl.FLOAT,!1,this.floatsPerVertex*4,12)),this.texture){this.texture.bind(0);const o=this.shader.getUniformLocation("uTexture");o!==null&&this.gl.uniform1i(o,0)}const s=this.shader.getUniformLocation("uMatrix");if(s!==null){const o=e?e.getViewMatrix():new Float32Array([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);this.gl.uniformMatrix4fv(s,!1,o)}const i=this.quads.length*this.verticesPerQuad;this.gl.drawArrays(this.gl.TRIANGLES,0,i),this.gl.bindBuffer(this.gl.ARRAY_BUFFER,null)}}generateQuadVertices(e){const{x:t,y:r,width:s,height:i,rotation:o}=e,n=s/2,c=i/2,h=Math.cos(o),m=Math.sin(o),u=(w,b)=>[w*h-b*m,w*m+b*h],f=[[-n,-c],[n,-c],[n,c],[n,c],[-n,c],[-n,-c]],g=[[0,0],[1,0],[1,1],[1,1],[0,1],[0,0]],E=[];for(let w=0;w<f.length;w++){const[b,_]=f[w],[F,d]=u(b,_),[v,y]=g[w];E.push([t+F,r+d,0,v,y])}return E}dispose(){this.vertexBuffer&&(this.gl.deleteBuffer(this.vertexBuffer),this.vertexBuffer=null)}}class ae{constructor(e,t,r=1e3){this.vertexBuffer=null,this.quads=[],this.isDirty=!1,this.verticesPerQuad=6,this.floatsPerVertex=10,this.texture=null,this.depthTestEnabled=!0,this.gl=e,this.shader=t,this.maxQuads=r;const s=r*this.verticesPerQuad*this.floatsPerVertex;this.vertexData=new Float32Array(s);const i=e.createBuffer();if(!i)throw new Error("Failed to create vertex buffer");this.vertexBuffer=i,e.bindBuffer(e.ARRAY_BUFFER,this.vertexBuffer),e.bufferData(e.ARRAY_BUFFER,this.vertexData.byteLength,e.DYNAMIC_DRAW),e.bindBuffer(e.ARRAY_BUFFER,null)}setTexture(e){this.texture=e}addQuad(e){if(this.quads.length>=this.maxQuads){console.warn(`Sprite batch renderer at max capacity (${this.maxQuads})`);return}this.quads.push(e),this.isDirty=!0}clear(){this.quads=[],this.isDirty=!0}getQuadCount(){return this.quads.length}update(){if(!this.isDirty||this.quads.length===0)return;let e=0;for(const t of this.quads){const{x:r,y:s,z:i=0,width:o,height:n,rotation:c,color:h={r:1,g:1,b:1,a:1},uvRect:m={uMin:0,vMin:0,uMax:1,vMax:1},texIndex:u=0}=t,f=this.generateQuadVertices({x:r,y:s,z:i,width:o,height:n,rotation:c,color:h,uvRect:m,texIndex:u});for(const g of f)this.vertexData[e++]=g.x,this.vertexData[e++]=g.y,this.vertexData[e++]=g.z,this.vertexData[e++]=g.u,this.vertexData[e++]=g.v,this.vertexData[e++]=g.r,this.vertexData[e++]=g.g,this.vertexData[e++]=g.b,this.vertexData[e++]=g.a,this.vertexData[e++]=g.texIndex}this.vertexBuffer&&(this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.vertexBuffer),this.gl.bufferSubData(this.gl.ARRAY_BUFFER,0,this.vertexData.subarray(0,e)),this.gl.bindBuffer(this.gl.ARRAY_BUFFER,null)),this.isDirty=!1}setDepthTestEnabled(e){this.depthTestEnabled=e}render(e){if(this.quads.length!==0&&(this.update(),this.shader.use(),this.depthTestEnabled?(this.gl.enable(this.gl.DEPTH_TEST),this.gl.depthFunc(this.gl.LEQUAL)):this.gl.disable(this.gl.DEPTH_TEST),this.vertexBuffer)){this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.vertexBuffer);const t=this.shader.getAttributeLocation("aPosition"),r=this.shader.getAttributeLocation("aTexCoord"),s=this.shader.getAttributeLocation("aColor"),i=this.shader.getAttributeLocation("aTexIndex"),o=this.floatsPerVertex*4;if(t!==-1&&(this.gl.enableVertexAttribArray(t),this.gl.vertexAttribPointer(t,3,this.gl.FLOAT,!1,o,0)),r!==-1&&(this.gl.enableVertexAttribArray(r),this.gl.vertexAttribPointer(r,2,this.gl.FLOAT,!1,o,12)),s!==-1&&(this.gl.enableVertexAttribArray(s),this.gl.vertexAttribPointer(s,4,this.gl.FLOAT,!1,o,20)),i!==-1&&(this.gl.enableVertexAttribArray(i),this.gl.vertexAttribPointer(i,1,this.gl.FLOAT,!1,o,36)),this.texture){this.texture.bind(0);const h=this.shader.getUniformLocation("uTexture");h!==null&&this.gl.uniform1i(h,0)}const n=this.shader.getUniformLocation("uMatrix");if(n!==null){const h=e?e.getViewMatrix():new Float32Array([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);this.gl.uniformMatrix4fv(n,!1,h)}const c=this.quads.length*this.verticesPerQuad;this.gl.drawArrays(this.gl.TRIANGLES,0,c),this.gl.bindBuffer(this.gl.ARRAY_BUFFER,null)}}generateQuadVertices(e){const{x:t,y:r,z:s,width:i,height:o,rotation:n,color:c,uvRect:h,texIndex:m}=e,u=i/2,f=o/2,g=Math.cos(n),E=Math.sin(n),w=(d,v)=>[d*g-v*E,d*E+v*g],b=[[-u,-f],[u,-f],[u,f],[u,f],[-u,f],[-u,-f]],_=[[h.uMin,h.vMin],[h.uMax,h.vMin],[h.uMax,h.vMax],[h.uMax,h.vMax],[h.uMin,h.vMax],[h.uMin,h.vMin]],F=[];for(let d=0;d<b.length;d++){const[v,y]=b[d],[D,I]=w(v,y),[N,x]=_[d];F.push({x:t+D,y:r+I,z:s,u:N,v:x,r:c.r,g:c.g,b:c.b,a:c.a,texIndex:m})}return F}dispose(){this.vertexBuffer&&(this.gl.deleteBuffer(this.vertexBuffer),this.vertexBuffer=null)}}class A{static identity(){return new Float32Array([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1])}static translation(e,t,r=0){return new Float32Array([1,0,0,0,0,1,0,0,0,0,1,0,e,t,r,1])}static scale(e,t,r=1){return new Float32Array([e,0,0,0,0,t,0,0,0,0,r,0,0,0,0,1])}static multiply(e,t){const r=new Float32Array(16);for(let s=0;s<4;s++)for(let i=0;i<4;i++){let o=0;for(let n=0;n<4;n++)o+=e[n*4+i]*t[s*4+n];r[s*4+i]=o}return r}static createViewMatrix(e,t,r){const s=A.translation(-e,-t,0),i=A.scale(r,r,1);return A.multiply(s,i)}}class ce{constructor(e=0,t=0,r=1){this._viewMatrix=null,this._viewMatrixDirty=!0,this._x=e,this._y=t,this._zoom=r}get x(){return this._x}set x(e){this._x=e,this._viewMatrixDirty=!0}get y(){return this._y}set y(e){this._y=e,this._viewMatrixDirty=!0}get zoom(){return this._zoom}set zoom(e){this._zoom=Math.max(.001,e),this._viewMatrixDirty=!0}setPosition(e,t){this._x=e,this._y=t,this._viewMatrixDirty=!0}move(e,t){this._x+=e,this._y+=t,this._viewMatrixDirty=!0}zoomBy(e){this._zoom=Math.max(.001,this._zoom*e),this._viewMatrixDirty=!0}reset(){this._x=0,this._y=0,this._zoom=1,this._viewMatrixDirty=!0}getViewMatrix(){return(this._viewMatrixDirty||this._viewMatrix===null)&&(this._viewMatrix=A.createViewMatrix(this._x,this._y,this._zoom),this._viewMatrixDirty=!1),this._viewMatrix}screenToWorld(e,t,r,s){const i=e-r/2,o=t-s/2,n=i/this._zoom+this._x,c=o/this._zoom+this._y;return{x:n,y:c}}worldToScreen(e,t,r,s){const i=(e-this._x)*this._zoom,o=(t-this._y)*this._zoom,n=i+r/2,c=o+s/2;return{x:n,y:c}}}class Q{constructor(e="",t=1e4){this.baseUrl=e||this.getCurrentOrigin(),this.defaultTimeout=t}getCurrentOrigin(){return typeof window<"u"?window.location.origin:"http://localhost"}resolvePath(e){try{return e.startsWith("http://")||e.startsWith("https://")?e:e.startsWith("//")?window.location.protocol+e:e.startsWith("/")?this.baseUrl+e:`${this.baseUrl}/${e}`}catch{return e}}async load(e,t){const r=this.resolvePath(e);try{const s={credentials:t?.credentials||"same-origin"};t?.headers&&(s.headers=t.headers);const i=new AbortController,o=setTimeout(()=>i.abort(),this.defaultTimeout);s.signal=i.signal;const n=await fetch(r,s);if(clearTimeout(o),!n.ok)throw new Error(`HTTP ${n.status}: ${n.statusText} for URL: ${r}`);return await n.text()}catch(s){throw s instanceof Error?s.name==="AbortError"?new Error(`Request timeout after ${this.defaultTimeout}ms for URL: ${r}`):new Error(`Failed to load resource from ${r}: ${s.message}`):new Error(`Failed to load resource from ${r}: Unknown error`)}}async loadMultiple(e,t){const r=e.map(async s=>{try{return{data:await this.load(s,t),path:s,success:!0}}catch(i){return{data:"",path:s,success:!1,error:i instanceof Error?i.message:String(i)}}});return Promise.all(r)}canLoad(e){const t=[/^https?:\/\//i,/^\/\//,/^\//,/^\.\.?\//],r=/\.[a-z0-9]+$/i.test(e);return t.some(s=>s.test(e))||r}setBaseUrl(e){this.baseUrl=e}getBaseUrl(){return this.baseUrl}setTimeout(e){this.defaultTimeout=e}}const he=Object.freeze(Object.defineProperty({__proto__:null,BrowserResourceLoader:Q},Symbol.toStringTag,{value:"Module"}));class K{constructor(e=process.cwd()){this.baseDir=e}resolvePath(e){return p.isAbsolute(e)?p.normalize(e):p.normalize(p.join(this.baseDir,e))}async load(e,t){const r=this.resolvePath(e),s=t?.encoding||"utf-8";try{return await T.readFile(r,s)}catch(i){if(i instanceof Error){const o=i.code;throw o==="ENOENT"?new Error(`File not found: ${r} (resolved from: ${e})`):o==="EACCES"?new Error(`Permission denied reading file: ${r}`):o==="EISDIR"?new Error(`Path is a directory, not a file: ${r}`):new Error(`Failed to load resource from ${r}: ${i.message}`)}throw new Error(`Failed to load resource from ${r}: Unknown error`)}}async loadMultiple(e,t){const r=e.map(async s=>{try{return{data:await this.load(s,t),path:s,success:!0}}catch(i){return{data:"",path:s,success:!1,error:i instanceof Error?i.message:String(i)}}});return Promise.all(r)}canLoad(e){return[/^\//,/^[a-zA-Z]:/,/^\.\.?\//,/^[^/\\]+\//].some(r=>r.test(e))}async exists(e){const t=this.resolvePath(e);try{return await T.access(t,T.constants.F_OK),!0}catch{return!1}}async getStats(e){const t=this.resolvePath(e);return T.stat(t)}setBaseDir(e){this.baseDir=e}getBaseDir(){return this.baseDir}async listDirectory(e,t=!1){const r=this.resolvePath(e),s=await T.readdir(r,{withFileTypes:!0}),i=[];for(const o of s){const n=p.join(r,o.name);if(o.isDirectory()&&t){const c=await this.listDirectory(n,!0);i.push(...c)}else o.isFile()&&i.push(n)}return i}}const le=Object.freeze(Object.defineProperty({__proto__:null,NodeResourceLoader:K},Symbol.toStringTag,{value:"Module"}));var P=(a=>(a.BROWSER="browser",a.NODE="node",a.UNKNOWN="unknown",a))(P||{});class S{static detectEnvironment(){return typeof window<"u"&&typeof window.document<"u"&&typeof fetch<"u"?"browser":typeof process<"u"&&process.versions!=null&&process.versions.node!=null?"node":"unknown"}static isBrowser(){return this.detectEnvironment()==="browser"}static isNode(){return this.detectEnvironment()==="node"}static async create(e){const t=e?.forceEnvironment||this.detectEnvironment();switch(t){case"browser":return await this.createBrowserLoader(e);case"node":return await this.createNodeLoader(e);case"unknown":throw new Error("Unsupported environment: Unable to determine runtime environment. Please specify forceEnvironment in options.");default:throw new Error(`Unsupported environment: ${t}`)}}static async createBrowserLoader(e){const{BrowserResourceLoader:t}=await Promise.resolve().then(()=>he);return new t(e?.baseUrl,e?.timeout)}static async createNodeLoader(e){const{NodeResourceLoader:t}=await Promise.resolve().then(()=>le);return new t(e?.baseDir)}static async createWithFallback(e,t){try{return t={...t,forceEnvironment:e},await this.create(t)}catch{return await this.create({...t,forceEnvironment:void 0})}}}async function J(a){return await S.create(a)}const ue=Object.freeze(Object.defineProperty({__proto__:null,Environment:P,ResourceLoaderFactory:S,createResourceLoader:J},Symbol.toStringTag,{value:"Module"}));class de{constructor(e=!0){this.cache=new Map,this.enabled=e}get(e){if(this.enabled)return this.cache.get(e)}set(e,t){this.enabled&&this.cache.set(e,t)}has(e){return this.enabled?this.cache.has(e):!1}clear(){this.cache.clear()}size(){return this.cache.size}enable(){this.enabled=!0}disable(){this.enabled=!1}}class Z{constructor(e,t){this.loader=e,this.concurrency=t?.concurrency??10,this.cache=new de(t?.cache??!0)}async load(e,t){const r=this.cache.get(e);if(r!==void 0)return r;const s=await this.loader.load(e,t);return this.cache.set(e,s),s}async loadBatch(e,t){const r=new Map,s=new Map;for(let i=0;i<e.length;i+=this.concurrency){const o=e.slice(i,i+this.concurrency),n=await this.loader.loadMultiple(o,t);for(const c of n)c.success?(r.set(c.path,c.data),this.cache.set(c.path,c.data)):s.set(c.path,c.error||"Unknown error")}return{succeeded:r,failed:s,total:e.length,successCount:r.size,failureCount:s.size}}async loadShader(e,t,r){const[s,i]=await Promise.all([this.load(e,r),this.load(t,r)]);return{vertex:s,fragment:i}}async loadShaders(e,t){return await Promise.all(e.map(async s=>{const i=await this.loadShader(s.vertex,s.fragment,t);return{name:s.name,...i}}))}async loadFromManifest(e,t){const r=await this.load(e,t),s=JSON.parse(r);return this.loadBatch(s.resources,t)}async preload(e,t){await this.loadBatch(e,t)}isCached(e){return this.cache.has(e)}getCached(e){return this.cache.get(e)}clearCache(){this.cache.clear()}getCacheSize(){return this.cache.size()}enableCache(){this.cache.enable()}disableCache(){this.cache.disable()}setConcurrency(e){this.concurrency=Math.max(1,e)}getLoader(){return this.loader}}async function ee(a){const{ResourceLoaderFactory:e}=await Promise.resolve().then(()=>ue),t=await e.create({baseUrl:a?.baseUrl,baseDir:a?.baseDir,timeout:a?.timeout});return new Z(t,a)}const U={width:800,height:600},M={quad:{vertices:new Float32Array([-.5,-.5,0,0,0,.5,-.5,0,1,0,.5,.5,0,1,1,.5,.5,0,1,1,-.5,.5,0,0,1,-.5,-.5,0,0,0]),stride:20}},$={size:256},z={shaders:[{name:"basic",vertex:"resources/shaders/basic.vert",fragment:"resources/shaders/basic.frag"},{name:"glow",vertex:"resources/shaders/glow.vert",fragment:"resources/shaders/glow.frag"}],resources:["resources/shaders/basic.vert","resources/shaders/basic.frag","resources/shaders/glow.vert","resources/shaders/glow.frag"]};async function te(){console.log("🩸 Bloody Engine - Resource Loader Demo"),console.log(`==========================================
|
|
9
|
+
${i}`)}return r}getProgram(){return this.program}getUniformLocation(e){return this.gl.getUniformLocation(this.program,e)}getAttributeLocation(e){return this.gl.getAttribLocation(this.program,e)}use(){this.gl.useProgram(this.program)}dispose(){this.gl.deleteProgram(this.program),this.gl.deleteShader(this.vertexShader),this.gl.deleteShader(this.fragmentShader)}}class H{constructor(e,t){this.context=X.createContext({width:e,height:t,preserveDrawingBuffer:!0})}getGLContext(){return this.context.glContext}getRenderingContext(){return this.context}getWidth(){return this.context.width}getHeight(){return this.context.height}getViewport(){return this.context.getViewport()}isBrowser(){return this.context.isBrowser}resize(e,t){this.context.resize(e,t)}clear(e){this.context.clear(e)}present(){this.context.present()}dispose(){this.context.dispose()}createShader(e,t){return new k(this.context.glContext,e,t,this.context.isBrowser)}}class R{constructor(e,t,r,s){this.gl=e,this.width=t,this.height=r;const i=e.createTexture();if(!i)throw new Error("Failed to create texture");this.texture=i,e.bindTexture(e.TEXTURE_2D,this.texture),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),s?e.texImage2D(e.TEXTURE_2D,0,e.RGBA,t,r,0,e.RGBA,e.UNSIGNED_BYTE,s):e.texImage2D(e.TEXTURE_2D,0,e.RGBA,t,r,0,e.RGBA,e.UNSIGNED_BYTE,null),e.bindTexture(e.TEXTURE_2D,null)}static createSolid(e,t,r,s,i,o,n=255){const c=t*r,h=new Uint8Array(c*4);for(let m=0;m<c;m++){const u=m*4;h[u]=s,h[u+1]=i,h[u+2]=o,h[u+3]=n}return new R(e,t,r,h)}static createCheckerboard(e,t,r,s=32){const i=new Uint8Array(t*r*4);for(let o=0;o<r;o++)for(let n=0;n<t;n++){const c=Math.floor(n/s),h=Math.floor(o/s),m=(c+h)%2===0,u=(o*t+n)*4,f=m?255:0;i[u]=f,i[u+1]=f,i[u+2]=f,i[u+3]=255}return new R(e,t,r,i)}static createGradient(e,t,r){const s=new Uint8Array(t*r*4);for(let i=0;i<r;i++)for(let o=0;o<t;o++){const n=(i*t+o)*4;s[n]=Math.floor(o/t*255),s[n+1]=Math.floor(i/r*255),s[n+2]=128,s[n+3]=255}return new R(e,t,r,s)}bind(e=0){this.gl.activeTexture(this.gl.TEXTURE0+e),this.gl.bindTexture(this.gl.TEXTURE_2D,this.texture)}unbind(){this.gl.bindTexture(this.gl.TEXTURE_2D,null)}getHandle(){return this.texture}getDimensions(){return{width:this.width,height:this.height}}dispose(){this.gl.deleteTexture(this.texture)}}class W{constructor(e,t,r=0){this.gl=e,this.stride=r;const s=r>0?r/4:3;this.vertexCount=t.length/s;const i=e.createBuffer();if(!i)throw new Error("Failed to create vertex buffer");this.buffer=i,e.bindBuffer(e.ARRAY_BUFFER,this.buffer),e.bufferData(e.ARRAY_BUFFER,t,e.STATIC_DRAW),e.bindBuffer(e.ARRAY_BUFFER,null)}bind(){this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.buffer)}unbind(){this.gl.bindBuffer(this.gl.ARRAY_BUFFER,null)}getVertexCount(){return this.vertexCount}getStride(){return this.stride}dispose(){this.gl.deleteBuffer(this.buffer)}}class j{constructor(e,t){this.gl=e,this.indexCount=t.length;const r=e.createBuffer();if(!r)throw new Error("Failed to create index buffer");this.buffer=r,e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.buffer),e.bufferData(e.ELEMENT_ARRAY_BUFFER,t,e.STATIC_DRAW),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,null)}bind(){this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER,this.buffer)}unbind(){this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER,null)}getIndexCount(){return this.indexCount}dispose(){this.gl.deleteBuffer(this.buffer)}}const ie=Object.freeze(Object.defineProperty({__proto__:null,IndexBuffer:j,VertexBuffer:W},Symbol.toStringTag,{value:"Module"}));class oe{constructor(e,t,r=1e3){this.vertexBuffer=null,this.quads=[],this.isDirty=!1,this.verticesPerQuad=6,this.floatsPerVertex=5,this.texture=null,this.gl=e,this.shader=t,this.maxQuads=r;const s=r*this.verticesPerQuad*this.floatsPerVertex;this.vertexData=new Float32Array(s);const i=e.createBuffer();if(!i)throw new Error("Failed to create vertex buffer");this.vertexBuffer=i,e.bindBuffer(e.ARRAY_BUFFER,this.vertexBuffer),e.bufferData(e.ARRAY_BUFFER,this.vertexData.byteLength,e.DYNAMIC_DRAW),e.bindBuffer(e.ARRAY_BUFFER,null)}setTexture(e){this.texture=e}addQuad(e){if(this.quads.length>=this.maxQuads){console.warn(`Batch renderer at max capacity (${this.maxQuads})`);return}this.quads.push(e),this.isDirty=!0}clear(){this.quads=[],this.isDirty=!0}getQuadCount(){return this.quads.length}update(){if(!this.isDirty||this.quads.length===0)return;let e=0;for(const t of this.quads){const r=this.generateQuadVertices(t);for(const s of r)this.vertexData[e++]=s[0],this.vertexData[e++]=s[1],this.vertexData[e++]=s[2],this.vertexData[e++]=s[3],this.vertexData[e++]=s[4]}this.vertexBuffer&&(this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.vertexBuffer),this.gl.bufferSubData(this.gl.ARRAY_BUFFER,0,this.vertexData.subarray(0,e)),this.gl.bindBuffer(this.gl.ARRAY_BUFFER,null)),this.isDirty=!1}render(e){if(this.quads.length!==0&&(this.update(),this.shader.use(),this.vertexBuffer)){this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.vertexBuffer);const t=this.shader.getAttributeLocation("aPosition"),r=this.shader.getAttributeLocation("aTexCoord");if(t!==-1&&(this.gl.enableVertexAttribArray(t),this.gl.vertexAttribPointer(t,3,this.gl.FLOAT,!1,this.floatsPerVertex*4,0)),r!==-1&&(this.gl.enableVertexAttribArray(r),this.gl.vertexAttribPointer(r,2,this.gl.FLOAT,!1,this.floatsPerVertex*4,12)),this.texture){this.texture.bind(0);const o=this.shader.getUniformLocation("uTexture");o!==null&&this.gl.uniform1i(o,0)}const s=this.shader.getUniformLocation("uMatrix");if(s!==null){const o=e?e.getViewMatrix():new Float32Array([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);this.gl.uniformMatrix4fv(s,!1,o)}const i=this.quads.length*this.verticesPerQuad;this.gl.drawArrays(this.gl.TRIANGLES,0,i),this.gl.bindBuffer(this.gl.ARRAY_BUFFER,null)}}generateQuadVertices(e){const{x:t,y:r,width:s,height:i,rotation:o}=e,n=s/2,c=i/2,h=Math.cos(o),m=Math.sin(o),u=(v,b)=>[v*h-b*m,v*m+b*h],f=[[-n,-c],[n,-c],[n,c],[n,c],[-n,c],[-n,-c]],g=[[0,0],[1,0],[1,1],[1,1],[0,1],[0,0]],E=[];for(let v=0;v<f.length;v++){const[b,_]=f[v],[F,d]=u(b,_),[w,y]=g[v];E.push([t+F,r+d,0,w,y])}return E}dispose(){this.vertexBuffer&&(this.gl.deleteBuffer(this.vertexBuffer),this.vertexBuffer=null)}}class ne{constructor(e,t,r=1e3){this.vertexBuffer=null,this.quads=[],this.isDirty=!1,this.verticesPerQuad=6,this.floatsPerVertex=10,this.texture=null,this.depthTestEnabled=!0,this.gl=e,this.shader=t,this.maxQuads=r;const s=r*this.verticesPerQuad*this.floatsPerVertex;this.vertexData=new Float32Array(s);const i=e.createBuffer();if(!i)throw new Error("Failed to create vertex buffer");this.vertexBuffer=i,e.bindBuffer(e.ARRAY_BUFFER,this.vertexBuffer),e.bufferData(e.ARRAY_BUFFER,this.vertexData.byteLength,e.DYNAMIC_DRAW),e.bindBuffer(e.ARRAY_BUFFER,null)}setTexture(e){this.texture=e}addQuad(e){if(this.quads.length>=this.maxQuads){console.warn(`Sprite batch renderer at max capacity (${this.maxQuads})`);return}this.quads.push(e),this.isDirty=!0}clear(){this.quads=[],this.isDirty=!0}getQuadCount(){return this.quads.length}update(){if(!this.isDirty||this.quads.length===0)return;let e=0;for(const t of this.quads){const{x:r,y:s,z:i=0,width:o,height:n,rotation:c,color:h={r:1,g:1,b:1,a:1},uvRect:m={uMin:0,vMin:0,uMax:1,vMax:1},texIndex:u=0}=t,f=this.generateQuadVertices({x:r,y:s,z:i,width:o,height:n,rotation:c,color:h,uvRect:m,texIndex:u});for(const g of f)this.vertexData[e++]=g.x,this.vertexData[e++]=g.y,this.vertexData[e++]=g.z,this.vertexData[e++]=g.u,this.vertexData[e++]=g.v,this.vertexData[e++]=g.r,this.vertexData[e++]=g.g,this.vertexData[e++]=g.b,this.vertexData[e++]=g.a,this.vertexData[e++]=g.texIndex}this.vertexBuffer&&(this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.vertexBuffer),this.gl.bufferSubData(this.gl.ARRAY_BUFFER,0,this.vertexData.subarray(0,e)),this.gl.bindBuffer(this.gl.ARRAY_BUFFER,null)),this.isDirty=!1}setDepthTestEnabled(e){this.depthTestEnabled=e}render(e){if(this.quads.length!==0&&(this.update(),this.shader.use(),this.depthTestEnabled?(this.gl.enable(this.gl.DEPTH_TEST),this.gl.depthFunc(this.gl.LEQUAL)):this.gl.disable(this.gl.DEPTH_TEST),this.vertexBuffer)){this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.vertexBuffer);const t=this.shader.getAttributeLocation("aPosition"),r=this.shader.getAttributeLocation("aTexCoord"),s=this.shader.getAttributeLocation("aColor"),i=this.shader.getAttributeLocation("aTexIndex"),o=this.floatsPerVertex*4;if(t!==-1&&(this.gl.enableVertexAttribArray(t),this.gl.vertexAttribPointer(t,3,this.gl.FLOAT,!1,o,0)),r!==-1&&(this.gl.enableVertexAttribArray(r),this.gl.vertexAttribPointer(r,2,this.gl.FLOAT,!1,o,12)),s!==-1&&(this.gl.enableVertexAttribArray(s),this.gl.vertexAttribPointer(s,4,this.gl.FLOAT,!1,o,20)),i!==-1&&(this.gl.enableVertexAttribArray(i),this.gl.vertexAttribPointer(i,1,this.gl.FLOAT,!1,o,36)),this.texture){this.texture.bind(0);const h=this.shader.getUniformLocation("uTexture");h!==null&&this.gl.uniform1i(h,0)}const n=this.shader.getUniformLocation("uMatrix");if(n!==null){const h=e?e.getViewMatrix():new Float32Array([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);this.gl.uniformMatrix4fv(n,!1,h)}const c=this.quads.length*this.verticesPerQuad;this.gl.drawArrays(this.gl.TRIANGLES,0,c),this.gl.bindBuffer(this.gl.ARRAY_BUFFER,null)}}generateQuadVertices(e){const{x:t,y:r,z:s,width:i,height:o,rotation:n,color:c,uvRect:h,texIndex:m}=e,u=i/2,f=o/2,g=Math.cos(n),E=Math.sin(n),v=(d,w)=>[d*g-w*E,d*E+w*g],b=[[-u,-f],[u,-f],[u,f],[u,f],[-u,f],[-u,-f]],_=[[h.uMin,h.vMin],[h.uMax,h.vMin],[h.uMax,h.vMax],[h.uMax,h.vMax],[h.uMin,h.vMax],[h.uMin,h.vMin]],F=[];for(let d=0;d<b.length;d++){const[w,y]=b[d],[D,I]=v(w,y),[N,x]=_[d];F.push({x:t+D,y:r+I,z:s,u:N,v:x,r:c.r,g:c.g,b:c.b,a:c.a,texIndex:m})}return F}dispose(){this.vertexBuffer&&(this.gl.deleteBuffer(this.vertexBuffer),this.vertexBuffer=null)}}class A{static identity(){return new Float32Array([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1])}static translation(e,t,r=0){return new Float32Array([1,0,0,0,0,1,0,0,0,0,1,0,e,t,r,1])}static scale(e,t,r=1){return new Float32Array([e,0,0,0,0,t,0,0,0,0,r,0,0,0,0,1])}static multiply(e,t){const r=new Float32Array(16);for(let s=0;s<4;s++)for(let i=0;i<4;i++){let o=0;for(let n=0;n<4;n++)o+=e[n*4+i]*t[s*4+n];r[s*4+i]=o}return r}static createViewMatrix(e,t,r){const s=A.translation(-e,-t,0),i=A.scale(r,r,1);return A.multiply(s,i)}}class ae{constructor(e=0,t=0,r=1){this._viewMatrix=null,this._viewMatrixDirty=!0,this._x=e,this._y=t,this._zoom=r}get x(){return this._x}set x(e){this._x=e,this._viewMatrixDirty=!0}get y(){return this._y}set y(e){this._y=e,this._viewMatrixDirty=!0}get zoom(){return this._zoom}set zoom(e){this._zoom=Math.max(.001,e),this._viewMatrixDirty=!0}setPosition(e,t){this._x=e,this._y=t,this._viewMatrixDirty=!0}move(e,t){this._x+=e,this._y+=t,this._viewMatrixDirty=!0}zoomBy(e){this._zoom=Math.max(.001,this._zoom*e),this._viewMatrixDirty=!0}reset(){this._x=0,this._y=0,this._zoom=1,this._viewMatrixDirty=!0}getViewMatrix(){return(this._viewMatrixDirty||this._viewMatrix===null)&&(this._viewMatrix=A.createViewMatrix(this._x,this._y,this._zoom),this._viewMatrixDirty=!1),this._viewMatrix}screenToWorld(e,t,r,s){const i=e-r/2,o=t-s/2,n=i/this._zoom+this._x,c=o/this._zoom+this._y;return{x:n,y:c}}worldToScreen(e,t,r,s){const i=(e-this._x)*this._zoom,o=(t-this._y)*this._zoom,n=i+r/2,c=o+s/2;return{x:n,y:c}}}class Q{constructor(e="",t=1e4){this.baseUrl=e||this.getCurrentOrigin(),this.defaultTimeout=t}getCurrentOrigin(){return typeof window<"u"?window.location.origin:"http://localhost"}resolvePath(e){try{return e.startsWith("http://")||e.startsWith("https://")?e:e.startsWith("//")?window.location.protocol+e:e.startsWith("/")?this.baseUrl+e:`${this.baseUrl}/${e}`}catch{return e}}async load(e,t){const r=this.resolvePath(e);try{const s={credentials:t?.credentials||"same-origin"};t?.headers&&(s.headers=t.headers);const i=new AbortController,o=setTimeout(()=>i.abort(),this.defaultTimeout);s.signal=i.signal;const n=await fetch(r,s);if(clearTimeout(o),!n.ok)throw new Error(`HTTP ${n.status}: ${n.statusText} for URL: ${r}`);return await n.text()}catch(s){throw s instanceof Error?s.name==="AbortError"?new Error(`Request timeout after ${this.defaultTimeout}ms for URL: ${r}`):new Error(`Failed to load resource from ${r}: ${s.message}`):new Error(`Failed to load resource from ${r}: Unknown error`)}}async loadMultiple(e,t){const r=e.map(async s=>{try{return{data:await this.load(s,t),path:s,success:!0}}catch(i){return{data:"",path:s,success:!1,error:i instanceof Error?i.message:String(i)}}});return Promise.all(r)}canLoad(e){const t=[/^https?:\/\//i,/^\/\//,/^\//,/^\.\.?\//],r=/\.[a-z0-9]+$/i.test(e);return t.some(s=>s.test(e))||r}setBaseUrl(e){this.baseUrl=e}getBaseUrl(){return this.baseUrl}setTimeout(e){this.defaultTimeout=e}}const ce=Object.freeze(Object.defineProperty({__proto__:null,BrowserResourceLoader:Q},Symbol.toStringTag,{value:"Module"}));class K{constructor(e=process.cwd()){this.baseDir=e}resolvePath(e){return p.isAbsolute(e)?p.normalize(e):p.normalize(p.join(this.baseDir,e))}async load(e,t){const r=this.resolvePath(e),s=t?.encoding||"utf-8";try{return await T.readFile(r,s)}catch(i){if(i instanceof Error){const o=i.code;throw o==="ENOENT"?new Error(`File not found: ${r} (resolved from: ${e})`):o==="EACCES"?new Error(`Permission denied reading file: ${r}`):o==="EISDIR"?new Error(`Path is a directory, not a file: ${r}`):new Error(`Failed to load resource from ${r}: ${i.message}`)}throw new Error(`Failed to load resource from ${r}: Unknown error`)}}async loadMultiple(e,t){const r=e.map(async s=>{try{return{data:await this.load(s,t),path:s,success:!0}}catch(i){return{data:"",path:s,success:!1,error:i instanceof Error?i.message:String(i)}}});return Promise.all(r)}canLoad(e){return[/^\//,/^[a-zA-Z]:/,/^\.\.?\//,/^[^/\\]+\//].some(r=>r.test(e))}async exists(e){const t=this.resolvePath(e);try{return await T.access(t,T.constants.F_OK),!0}catch{return!1}}async getStats(e){const t=this.resolvePath(e);return T.stat(t)}setBaseDir(e){this.baseDir=e}getBaseDir(){return this.baseDir}async listDirectory(e,t=!1){const r=this.resolvePath(e),s=await T.readdir(r,{withFileTypes:!0}),i=[];for(const o of s){const n=p.join(r,o.name);if(o.isDirectory()&&t){const c=await this.listDirectory(n,!0);i.push(...c)}else o.isFile()&&i.push(n)}return i}}const he=Object.freeze(Object.defineProperty({__proto__:null,NodeResourceLoader:K},Symbol.toStringTag,{value:"Module"}));var P=(a=>(a.BROWSER="browser",a.NODE="node",a.UNKNOWN="unknown",a))(P||{});class S{static detectEnvironment(){return typeof window<"u"&&typeof window.document<"u"&&typeof fetch<"u"?"browser":typeof process<"u"&&process.versions!=null&&process.versions.node!=null?"node":"unknown"}static isBrowser(){return this.detectEnvironment()==="browser"}static isNode(){return this.detectEnvironment()==="node"}static async create(e){const t=e?.forceEnvironment||this.detectEnvironment();switch(t){case"browser":return await this.createBrowserLoader(e);case"node":return await this.createNodeLoader(e);case"unknown":throw new Error("Unsupported environment: Unable to determine runtime environment. Please specify forceEnvironment in options.");default:throw new Error(`Unsupported environment: ${t}`)}}static async createBrowserLoader(e){const{BrowserResourceLoader:t}=await Promise.resolve().then(()=>ce);return new t(e?.baseUrl,e?.timeout)}static async createNodeLoader(e){const{NodeResourceLoader:t}=await Promise.resolve().then(()=>he);return new t(e?.baseDir)}static async createWithFallback(e,t){try{return t={...t,forceEnvironment:e},await this.create(t)}catch{return await this.create({...t,forceEnvironment:void 0})}}}async function J(a){return await S.create(a)}const le=Object.freeze(Object.defineProperty({__proto__:null,Environment:P,ResourceLoaderFactory:S,createResourceLoader:J},Symbol.toStringTag,{value:"Module"}));class ue{constructor(e=!0){this.cache=new Map,this.enabled=e}get(e){if(this.enabled)return this.cache.get(e)}set(e,t){this.enabled&&this.cache.set(e,t)}has(e){return this.enabled?this.cache.has(e):!1}clear(){this.cache.clear()}size(){return this.cache.size}enable(){this.enabled=!0}disable(){this.enabled=!1}}class Z{constructor(e,t){this.loader=e,this.concurrency=t?.concurrency??10,this.cache=new ue(t?.cache??!0)}async load(e,t){const r=this.cache.get(e);if(r!==void 0)return r;const s=await this.loader.load(e,t);return this.cache.set(e,s),s}async loadBatch(e,t){const r=new Map,s=new Map;for(let i=0;i<e.length;i+=this.concurrency){const o=e.slice(i,i+this.concurrency),n=await this.loader.loadMultiple(o,t);for(const c of n)c.success?(r.set(c.path,c.data),this.cache.set(c.path,c.data)):s.set(c.path,c.error||"Unknown error")}return{succeeded:r,failed:s,total:e.length,successCount:r.size,failureCount:s.size}}async loadShader(e,t,r){const[s,i]=await Promise.all([this.load(e,r),this.load(t,r)]);return{vertex:s,fragment:i}}async loadShaders(e,t){return await Promise.all(e.map(async s=>{const i=await this.loadShader(s.vertex,s.fragment,t);return{name:s.name,...i}}))}async loadFromManifest(e,t){const r=await this.load(e,t),s=JSON.parse(r);return this.loadBatch(s.resources,t)}async preload(e,t){await this.loadBatch(e,t)}isCached(e){return this.cache.has(e)}getCached(e){return this.cache.get(e)}clearCache(){this.cache.clear()}getCacheSize(){return this.cache.size()}enableCache(){this.cache.enable()}disableCache(){this.cache.disable()}setConcurrency(e){this.concurrency=Math.max(1,e)}getLoader(){return this.loader}}async function ee(a){const{ResourceLoaderFactory:e}=await Promise.resolve().then(()=>le),t=await e.create({baseUrl:a?.baseUrl,baseDir:a?.baseDir,timeout:a?.timeout});return new Z(t,a)}const U={width:800,height:600},M={quad:{vertices:new Float32Array([-.5,-.5,0,0,0,.5,-.5,0,1,0,.5,.5,0,1,1,.5,.5,0,1,1,-.5,.5,0,0,1,-.5,-.5,0,0,0]),stride:20}},$={size:256},z={shaders:[{name:"basic",vertex:"resources/shaders/basic.vert",fragment:"resources/shaders/basic.frag"},{name:"glow",vertex:"resources/shaders/glow.vert",fragment:"resources/shaders/glow.frag"}],resources:["resources/shaders/basic.vert","resources/shaders/basic.frag","resources/shaders/glow.vert","resources/shaders/glow.frag"]};async function de(){console.log("🩸 Bloody Engine - Resource Loader Demo"),console.log(`==========================================
|
|
10
10
|
`);const a=S.detectEnvironment();if(console.log(`✓ Environment detected: ${a}`),a!==P.BROWSER){console.warn("⚠ This demo is designed for browser environment");return}console.log(`
|
|
11
11
|
1. Creating Resource Pipeline...`);const e=await ee({concurrency:5,cache:!0,timeout:1e4,baseUrl:window.location.origin});console.log("✓ Resource pipeline created"),console.log(" - Concurrency: 5"),console.log(" - Caching: enabled"),console.log(`
|
|
12
12
|
2. Batch Loading Resources...`),console.log(`Loading ${z.resources.length} resources...`);const t=await e.loadBatch(z.resources);if(console.log("✓ Batch loading complete"),console.log(` - Succeeded: ${t.successCount}`),console.log(` - Failed: ${t.failureCount}`),t.failureCount>0){console.log(`
|
|
@@ -44,13 +44,13 @@ void main() {
|
|
|
44
44
|
gl_FragColor = vec4(glowColor, texColor.a);
|
|
45
45
|
}`});const c=i.createShader(n.vertex,n.fragment);console.log("✓ Shader compiled from loaded source code"),console.log(" - Vertex shader: compiled"),console.log(" - Fragment shader: compiled"),console.log(" - Program: linked"),console.log(`
|
|
46
46
|
7. Creating Texture...`);const h=R.createGradient(o,$.size,$.size);console.log("✓ Gradient texture created"),console.log(` - Size: ${$.size}x${$.size}`),console.log(`
|
|
47
|
-
8. Creating Geometry Buffers...`);const{VertexBuffer:m}=await Promise.resolve().then(()=>
|
|
48
|
-
9. Setting up Rendering...`),c.use();const f=c.getAttributeLocation("aPosition"),g=c.getAttributeLocation("aTexCoord"),E=c.getUniformLocation("uTexture"),
|
|
47
|
+
8. Creating Geometry Buffers...`);const{VertexBuffer:m}=await Promise.resolve().then(()=>ie),u=new m(o,M.quad.vertices,M.quad.stride);console.log("✓ Quad buffer created"),console.log(` - Vertices: ${u.getVertexCount()}`),console.log(`
|
|
48
|
+
9. Setting up Rendering...`),c.use();const f=c.getAttributeLocation("aPosition"),g=c.getAttributeLocation("aTexCoord"),E=c.getUniformLocation("uTexture"),v=c.getUniformLocation("uMatrix"),b=c.getUniformLocation("uColor"),_=c.getUniformLocation("uGlowIntensity");u.bind(),o.enableVertexAttribArray(f),o.vertexAttribPointer(f,3,o.FLOAT,!1,M.quad.stride,0),o.enableVertexAttribArray(g),o.vertexAttribPointer(g,2,o.FLOAT,!1,M.quad.stride,12),console.log("✓ Vertex attributes configured"),h.bind(0),o.uniform1i(E,0),console.log("✓ Texture bound to unit 0");const d=i.getRenderingContext().canvas;d&&(d.style.display="block",d.style.margin="0 auto",d.style.border="2px solid #333",d.style.backgroundColor="#1a1a1a"),document.body.style.margin="0",document.body.style.padding="20px",document.body.style.backgroundColor="#0a0a0a",document.body.style.fontFamily="monospace",document.body.style.color="#aaa";const w=document.createElement("h1");w.textContent="🩸 Resource Loader Demo",w.style.textAlign="center",w.style.color="#fff",d&&d.parentNode?d.parentNode.insertBefore(w,d):document.body.insertBefore(w,document.body.firstChild);const y=document.createElement("div");y.style.textAlign="center",y.style.marginTop="10px",y.style.fontSize="12px",y.innerHTML=`
|
|
49
49
|
<div>Environment: <strong>${a}</strong></div>
|
|
50
50
|
<div>Shaders loaded: <strong>${r.length}</strong></div>
|
|
51
51
|
<div>Cached resources: <strong>${s}</strong></div>
|
|
52
|
-
`,document.body.appendChild(y);let D=0;const I=Date.now();function N(){const x=Date.now(),L=(x-I)/1e3;i.clear({r:.1,g:.1,b:.1,a:1});const Y=[{x:-.3,y:.3,color:[1,.2,.2],glow:1.5},{x:.3,y:.3,color:[.2,1,.2],glow:1.8},{x:-.3,y:-.3,color:[.2,.5,1],glow:2},{x:.3,y:-.3,color:[1,1,.2],glow:1.6}];for(const B of Y){const G=fe();if(ge(G,B.x,B.y,0),xe(G,.4,.4,1),
|
|
53
|
-
<div>FPS: <strong>${me.toFixed(1)}</strong> | Frame: <strong>${D}</strong> | Elapsed: <strong>${
|
|
52
|
+
`,document.body.appendChild(y);let D=0;const I=Date.now();function N(){const x=Date.now(),L=(x-I)/1e3;i.clear({r:.1,g:.1,b:.1,a:1});const Y=[{x:-.3,y:.3,color:[1,.2,.2],glow:1.5},{x:.3,y:.3,color:[.2,1,.2],glow:1.8},{x:-.3,y:-.3,color:[.2,.5,1],glow:2},{x:.3,y:-.3,color:[1,1,.2],glow:1.6}];for(const B of Y){const G=fe();if(ge(G,B.x,B.y,0),xe(G,.4,.4,1),v&&o.uniformMatrix4fv(v,!1,G),b&&o.uniform3f(b,B.color[0],B.color[1],B.color[2]),_){const ve=B.glow+Math.sin(L*2)*.3;o.uniform1f(_,ve)}o.drawArrays(o.TRIANGLES,0,u.getVertexCount())}i.present(),D++;const te=(x-I)/1e3,me=D/te;y.innerHTML=`
|
|
53
|
+
<div>FPS: <strong>${me.toFixed(1)}</strong> | Frame: <strong>${D}</strong> | Elapsed: <strong>${te.toFixed(2)}s</strong></div>
|
|
54
54
|
<div>Environment: <strong>${a}</strong> | Shaders loaded: <strong>${r.length}</strong> | Cached: <strong>${s}</strong></div>
|
|
55
55
|
`,requestAnimationFrame(N)}console.log(`
|
|
56
|
-
✓ Demo started! Rendering animation...`),N()}function fe(){return new Float32Array([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1])}function ge(a,e,t,r){a[12]+=e,a[13]+=t,a[14]+=r}function xe(a,e,t,r){a[0]*=e,a[5]*=t,a[10]*=r}
|
|
56
|
+
✓ Demo started! Rendering animation...`),N()}function fe(){return new Float32Array([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1])}function ge(a,e,t,r){a[12]+=e,a[13]+=t,a[14]+=r}function xe(a,e,t,r){a[0]*=e,a[5]*=t,a[10]*=r}l.BatchRenderer=oe,l.BrowserRenderingContext=O,l.BrowserResourceLoader=Q,l.Camera=ae,l.Environment=P,l.GraphicsDevice=H,l.IndexBuffer=j,l.Matrix4=A,l.NodeRenderingContext=V,l.NodeResourceLoader=K,l.RenderingContextFactory=X,l.ResourceLoaderFactory=S,l.ResourcePipeline=Z,l.Shader=k,l.SpriteBatchRenderer=ne,l.Texture=R,l.VertexBuffer=W,l.createResourceLoader=J,l.createResourcePipeline=ee,l.runBrowserResourceLoaderDemo=de,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"})}));
|