bloody-engine 1.0.2 → 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.
@@ -2335,11 +2335,6 @@ function scaleMatrix(mat, x, y, z) {
2335
2335
  mat[5] *= y;
2336
2336
  mat[10] *= z;
2337
2337
  }
2338
- if (typeof window !== "undefined") {
2339
- runBrowserResourceLoaderDemo().catch((error) => {
2340
- console.error("❌ Demo failed:", error);
2341
- });
2342
- }
2343
2338
  export {
2344
2339
  BatchRenderer,
2345
2340
  BrowserRenderingContext,
package/dist/web/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import X from "gl";
2
- import * as C from "fs/promises";
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 de {
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, v) => [m * h - v * x, m * x + v * h], d = [
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 [v, E] = d[m], [A, u] = l(v, E), [w, b] = f[m];
656
- y.push([t + A, r + u, 0, w, b]);
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 fe {
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, w) => [u * f - w * y, u * y + w * f], v = [
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 < v.length; u++) {
868
- const [w, b] = v[u], [_, D] = m(w, b), [U, g] = E[u];
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 ge {
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 C.readFile(r, s);
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 C.access(t, C.constants.F_OK), !0;
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 C.stat(t);
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 C.readdir(r, { withFileTypes: !0 }), i = [];
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 ae() {
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, p] of t.failed)
1764
- console.log(` - ${g}: ${p}`);
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 p = e.isCached(g.vertex), $ = e.isCached(g.fragment);
1780
- console.log(` - ${g.name}:`), console.log(` Vertex cached: ${p}`), console.log(` Fragment 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"), v = a.getUniformLocation("uColor"), E = a.getUniformLocation("uGlowIntensity");
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 w = document.createElement("h1");
1849
- w.textContent = "🩸 Resource Loader Demo", w.style.textAlign = "center", w.style.color = "#fff", u && u.parentNode ? u.parentNode.insertBefore(w, u) : document.body.insertBefore(w, document.body.firstChild);
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(), p = (g - D) / 1e3;
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 = ce();
1869
- if (he(z, R.x, R.y, 0), le(z, 0.4, 0.4, 1), m && o.uniformMatrix4fv(m, !1, z), v && o.uniform3f(
1870
- v,
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(p * 2) * 0.3;
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 ce() {
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 he(c, e, t, r) {
1910
+ function ce(c, e, t, r) {
1911
1911
  c[12] += e, c[13] += t, c[14] += r;
1912
1912
  }
1913
- function le(c, e, t, r) {
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
- de as BatchRenderer,
1917
+ ue as BatchRenderer,
1921
1918
  Y as BrowserRenderingContext,
1922
1919
  J as BrowserResourceLoader,
1923
- ge as Camera,
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
- fe as SpriteBatchRenderer,
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
- ae as runBrowserResourceLoaderDemo
1936
+ ge as runBrowserResourceLoaderDemo
1940
1937
  };
@@ -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,ie){"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(se),p=q(ie);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
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(()=>oe),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"),w=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 v=document.createElement("h1");v.textContent="🩸 Resource Loader Demo",v.style.textAlign="center",v.style.color="#fff",d&&d.parentNode?d.parentNode.insertBefore(v,d):document.body.insertBefore(v,document.body.firstChild);const y=document.createElement("div");y.style.textAlign="center",y.style.marginTop="10px",y.style.fontSize="12px",y.innerHTML=`
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),w&&o.uniformMatrix4fv(w,!1,G),b&&o.uniform3f(b,B.color[0],B.color[1],B.color[2]),_){const we=B.glow+Math.sin(L*2)*.3;o.uniform1f(_,we)}o.drawArrays(o.TRIANGLES,0,u.getVertexCount())}i.present(),D++;const re=(x-I)/1e3,me=D/re;y.innerHTML=`
53
- <div>FPS: <strong>${me.toFixed(1)}</strong> | Frame: <strong>${D}</strong> | Elapsed: <strong>${re.toFixed(2)}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),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}typeof window<"u"&&te().catch(a=>{console.error("❌ Demo failed:",a)}),l.BatchRenderer=ne,l.BrowserRenderingContext=O,l.BrowserResourceLoader=Q,l.Camera=ce,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=ae,l.Texture=R,l.VertexBuffer=W,l.createResourceLoader=J,l.createResourcePipeline=ee,l.runBrowserResourceLoaderDemo=te,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"})}));
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"})}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bloody-engine",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "A WebGL-based 2.5D graphics engine for isometric rendering",
5
5
  "license": "MIT",
6
6
  "type": "module",