@mirage-engine/painter 1.0.0 → 1.0.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @mirage-engine/painter
2
2
 
3
+ ## 1.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 11f77b6: update seven craft
8
+
3
9
  ## 1.0.0
4
10
 
5
11
  ### Major Changes
@@ -1,8 +1,8 @@
1
- var I = Object.defineProperty;
2
- var R = (o, e, t) => e in o ? I(o, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : o[e] = t;
3
- var b = (o, e, t) => (R(o, typeof e != "symbol" ? e + "" : e, t), t);
1
+ var R = Object.defineProperty;
2
+ var M = (r, e, n) => e in r ? R(r, e, { enumerable: !0, configurable: !0, writable: !0, value: n }) : r[e] = n;
3
+ var w = (r, e, n) => (M(r, typeof e != "symbol" ? e + "" : e, n), n);
4
4
  import * as d from "three";
5
- class T {
5
+ class I {
6
6
  /**
7
7
  * Calculates or retrieves the exact alphabetic baseline (in pixels) for the given font.
8
8
  * @param font CSS font shorthand string (e.g., "400 16px Inter")
@@ -11,153 +11,153 @@ class T {
11
11
  static getBaseline(e) {
12
12
  if (this.cache.has(e))
13
13
  return this.cache.get(e);
14
- const t = this.calculateBaselineFromDOM(e);
15
- return this.cache.set(e, t), t;
14
+ const n = this.calculateBaselineFromDOM(e);
15
+ return this.cache.set(e, n), n;
16
16
  }
17
17
  static calculateBaselineFromDOM(e) {
18
18
  if (typeof document > "u")
19
19
  return 0;
20
- const t = document.createElement("div"), a = document.createElement("span"), r = document.createElement("img");
21
- t.style.visibility = "hidden", t.style.position = "absolute", t.style.top = "0px", t.style.left = "0px", t.style.font = e, t.style.margin = "0", t.style.padding = "0", t.style.border = "none", a.style.margin = "0", a.style.padding = "0", a.style.border = "none", a.style.lineHeight = "normal", r.width = 1, r.height = 1, r.style.verticalAlign = "baseline", a.appendChild(document.createTextNode("Hidden Text")), t.appendChild(a), t.appendChild(r), document.body.appendChild(t);
22
- const n = r.offsetTop - a.offsetTop;
23
- return document.body.removeChild(t), n;
20
+ const n = document.createElement("div"), a = document.createElement("span"), o = document.createElement("img");
21
+ n.style.visibility = "hidden", n.style.position = "absolute", n.style.top = "0px", n.style.left = "0px", n.style.font = e, n.style.margin = "0", n.style.padding = "0", n.style.border = "none", a.style.margin = "0", a.style.padding = "0", a.style.border = "none", a.style.lineHeight = "normal", o.width = 1, o.height = 1, o.style.verticalAlign = "baseline", a.appendChild(document.createTextNode("Hidden Text")), n.appendChild(a), n.appendChild(o), document.body.appendChild(n);
22
+ const i = o.offsetTop - a.offsetTop;
23
+ return document.body.removeChild(n), i;
24
24
  }
25
25
  }
26
- b(T, "cache", /* @__PURE__ */ new Map());
27
- class A extends d.MeshBasicMaterial {
28
- constructor(t, a, r, n, i = 2) {
26
+ w(I, "cache", /* @__PURE__ */ new Map());
27
+ class k extends d.MeshBasicMaterial {
28
+ constructor(n, a, o, i, t = 2) {
29
29
  super({
30
30
  transparent: !0,
31
31
  side: d.FrontSide,
32
32
  color: 16777215
33
33
  });
34
- b(this, "canvas");
35
- b(this, "ctx");
36
- b(this, "qualityFactor");
34
+ w(this, "canvas");
35
+ w(this, "ctx");
36
+ w(this, "qualityFactor");
37
37
  if (this.canvas = document.createElement("canvas"), this.ctx = this.canvas.getContext("2d"), !this.ctx)
38
38
  throw new Error("[Mirage] Failed to create canvas context");
39
- this.qualityFactor = i, this.map = new d.CanvasTexture(this.canvas), this.map.colorSpace = d.LinearSRGBColorSpace, this.map.minFilter = d.LinearFilter, this.map.magFilter = d.LinearFilter, this.updateText(t, a, r, n);
39
+ this.qualityFactor = t, this.map = new d.CanvasTexture(this.canvas), this.map.colorSpace = d.LinearSRGBColorSpace, this.map.minFilter = d.LinearFilter, this.map.magFilter = d.LinearFilter, this.updateText(n, a, o, i);
40
40
  }
41
- wrapText(t, a) {
42
- const r = t.split(`
43
- `), n = [];
44
- return r.forEach((i) => {
45
- const c = i.match(/[^\s\-]+\-?|\-|\s+/g) || [];
41
+ wrapText(n, a) {
42
+ const o = n.split(`
43
+ `), i = [];
44
+ return o.forEach((t) => {
45
+ const c = t.match(/[^\s\-]+\-?|\-|\s+/g) || [];
46
46
  if (c.length === 0) {
47
- n.push("");
47
+ i.push("");
48
48
  return;
49
49
  }
50
- let l = c[0];
51
- for (let s = 1; s < c.length; s++) {
52
- const u = c[s];
53
- this.ctx.measureText(l + u).width <= a + 2 ? l += u : (l && n.push(l), l = u.trimStart());
50
+ let s = c[0];
51
+ for (let l = 1; l < c.length; l++) {
52
+ const u = c[l];
53
+ this.ctx.measureText(s + u).width <= a + 2 ? s += u : (s && i.push(s), s = u.trimStart());
54
54
  }
55
- l && n.push(l);
56
- }), n;
55
+ s && i.push(s);
56
+ }), i;
57
57
  }
58
- updateText(t, a, r, n, i) {
59
- i !== void 0 && (this.qualityFactor = i);
60
- const l = (window.devicePixelRatio || 1) * this.qualityFactor, s = r * l, u = n * l;
61
- this.canvas.width !== s || this.canvas.height !== u ? (this.canvas.width = s, this.canvas.height = u) : this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height), this.ctx.setTransform(l, 0, 0, l, 0, 0), this.ctx.font = a.font, this.ctx.fillStyle = a.color, this.ctx.textBaseline = "alphabetic", this.ctx.globalAlpha = 1;
62
- const h = this.wrapText(t, r), g = a.lineHeight, p = T.getBaseline(a.font);
63
- h.forEach((f, m) => {
64
- const y = m * g + p;
65
- let x = 0;
66
- a.textAlign === "center" ? x = r / 2 : a.textAlign === "right" && (x = r), this.ctx.textAlign = a.textAlign, this.ctx.fillText(f, x, y);
58
+ updateText(n, a, o, i, t) {
59
+ t !== void 0 && (this.qualityFactor = t);
60
+ const s = (window.devicePixelRatio || 1) * this.qualityFactor, l = o * s, u = i * s;
61
+ this.canvas.width !== l || this.canvas.height !== u ? (this.canvas.width = l, this.canvas.height = u) : this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height), this.ctx.setTransform(s, 0, 0, s, 0, 0), this.ctx.font = a.font, this.ctx.fillStyle = a.color, this.ctx.textBaseline = "alphabetic", this.ctx.globalAlpha = 1;
62
+ const p = this.wrapText(n, o), b = a.lineHeight, v = I.getBaseline(a.font);
63
+ p.forEach((f, m) => {
64
+ const S = m * b + v;
65
+ let C = 0;
66
+ a.textAlign === "center" ? C = o / 2 : a.textAlign === "right" && (C = o), this.ctx.textAlign = a.textAlign, this.ctx.fillText(f, C, S);
67
67
  }), this.map && (this.map.needsUpdate = !0);
68
68
  }
69
69
  dispose() {
70
70
  this.map && this.map.dispose(), super.dispose();
71
71
  }
72
72
  }
73
- function v(o) {
74
- return typeof o == "number" ? o : parseFloat(o) || 0;
73
+ function x(r) {
74
+ return typeof r == "number" ? r : parseFloat(r) || 0;
75
75
  }
76
- function C(o) {
77
- if (!o || o === "transparent")
76
+ function y(r) {
77
+ if (!r || r === "transparent")
78
78
  return { color: new d.Color(16777215), alpha: 0 };
79
- const e = o.match(
79
+ const e = r.match(
80
80
  /rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/
81
81
  );
82
82
  if (e) {
83
- const t = parseInt(e[1], 10), a = parseInt(e[2], 10), r = parseInt(e[3], 10), n = e[4] !== void 0 ? parseFloat(e[4]) : 1;
84
- return { color: new d.Color(`rgb(${t}, ${a}, ${r})`), alpha: n };
83
+ const n = parseInt(e[1], 10), a = parseInt(e[2], 10), o = parseInt(e[3], 10), i = e[4] !== void 0 ? parseFloat(e[4]) : 1;
84
+ return { color: new d.Color(`rgb(${n}, ${a}, ${o})`), alpha: i };
85
85
  }
86
- return { color: new d.Color(o), alpha: 1 };
86
+ return { color: new d.Color(r), alpha: 1 };
87
87
  }
88
- function k(o) {
88
+ function P(r) {
89
89
  const e = [];
90
- let t = "", a = 0;
91
- for (let r = 0; r < o.length; r++) {
92
- const n = o[r];
93
- if (n === "(")
90
+ let n = "", a = 0;
91
+ for (let o = 0; o < r.length; o++) {
92
+ const i = r[o];
93
+ if (i === "(")
94
94
  a++;
95
- else if (n === ")")
95
+ else if (i === ")")
96
96
  a--;
97
- else if (n === "," && a === 0) {
98
- e.push(t.trim()), t = "";
97
+ else if (i === "," && a === 0) {
98
+ e.push(n.trim()), n = "";
99
99
  continue;
100
100
  }
101
- t += n;
101
+ n += i;
102
102
  }
103
- return t && e.push(t.trim()), e;
103
+ return n && e.push(n.trim()), e;
104
104
  }
105
- function M(o) {
106
- if (!o || typeof o != "string" || !o.includes("linear-gradient"))
105
+ function G(r) {
106
+ if (!r || typeof r != "string" || !r.includes("linear-gradient"))
107
107
  return null;
108
- const e = o.match(/linear-gradient\((.*)\)/);
108
+ const e = r.match(/linear-gradient\((.*)\)/);
109
109
  if (!e)
110
110
  return null;
111
- const t = e[1], a = k(t);
112
- let r = Math.PI, n = 0;
113
- const i = a[0].trim();
114
- if (i.startsWith("to "))
115
- i === "to top" ? r = 0 : i === "to right" ? r = Math.PI / 2 : i === "to bottom" ? r = Math.PI : i === "to left" ? r = Math.PI * 1.5 : i === "to top right" || i === "to right top" ? r = Math.PI / 4 : i === "to bottom right" || i === "to right bottom" ? r = Math.PI * 0.75 : i === "to bottom left" || i === "to left bottom" ? r = Math.PI * 1.25 : (i === "to top left" || i === "to left top") && (r = Math.PI * 1.75), n = 1;
116
- else if (i.endsWith("deg") || i.endsWith("rad") || i.endsWith("turn")) {
117
- const l = parseFloat(i);
118
- i.endsWith("deg") ? r = l * (Math.PI / 180) : i.endsWith("rad") ? r = l : i.endsWith("turn") && (r = l * Math.PI * 2), n = 1;
111
+ const n = e[1], a = P(n);
112
+ let o = Math.PI, i = 0;
113
+ const t = a[0].trim();
114
+ if (t.startsWith("to "))
115
+ t === "to top" ? o = 0 : t === "to right" ? o = Math.PI / 2 : t === "to bottom" ? o = Math.PI : t === "to left" ? o = Math.PI * 1.5 : t === "to top right" || t === "to right top" ? o = Math.PI / 4 : t === "to bottom right" || t === "to right bottom" ? o = Math.PI * 0.75 : t === "to bottom left" || t === "to left bottom" ? o = Math.PI * 1.25 : (t === "to top left" || t === "to left top") && (o = Math.PI * 1.75), i = 1;
116
+ else if (t.endsWith("deg") || t.endsWith("rad") || t.endsWith("turn")) {
117
+ const s = parseFloat(t);
118
+ t.endsWith("deg") ? o = s * (Math.PI / 180) : t.endsWith("rad") ? o = s : t.endsWith("turn") && (o = s * Math.PI * 2), i = 1;
119
119
  }
120
120
  const c = [];
121
- for (let l = n; l < a.length && !(c.length >= 8); l++) {
122
- const s = a[l].trim(), u = s.lastIndexOf(" ");
123
- let h = s, g = null;
124
- if (u !== -1 && !s.endsWith(")")) {
125
- const f = s.substring(u + 1);
126
- (f.endsWith("%") || f.endsWith("px") || !isNaN(parseFloat(f))) && (h = s.substring(0, u).trim(), g = f);
121
+ for (let s = i; s < a.length && !(c.length >= 8); s++) {
122
+ const l = a[s].trim(), u = l.lastIndexOf(" ");
123
+ let p = l, b = null;
124
+ if (u !== -1 && !l.endsWith(")")) {
125
+ const f = l.substring(u + 1);
126
+ (f.endsWith("%") || f.endsWith("px") || !isNaN(parseFloat(f))) && (p = l.substring(0, u).trim(), b = f);
127
127
  }
128
- const p = C(h);
128
+ const v = y(p);
129
129
  c.push({
130
- color: p.color,
131
- alpha: p.alpha,
132
- rawStop: g,
130
+ color: v.color,
131
+ alpha: v.alpha,
132
+ rawStop: b,
133
133
  stop: 0
134
134
  });
135
135
  }
136
136
  if (c.length > 0) {
137
- for (let s = 0; s < c.length; s++)
138
- c[s].rawStop !== null && (c[s].stop = parseFloat(c[s].rawStop) / 100);
137
+ for (let l = 0; l < c.length; l++)
138
+ c[l].rawStop !== null && (c[l].stop = parseFloat(c[l].rawStop) / 100);
139
139
  c[0].rawStop === null && (c[0].stop = 0), c.length > 1 && c[c.length - 1].rawStop === null && (c[c.length - 1].stop = 1);
140
- let l = 0;
141
- for (let s = 1; s < c.length; s++)
142
- if (c[s].rawStop !== null || s === c.length - 1) {
143
- const u = s - l;
140
+ let s = 0;
141
+ for (let l = 1; l < c.length; l++)
142
+ if (c[l].rawStop !== null || l === c.length - 1) {
143
+ const u = l - s;
144
144
  if (u > 1) {
145
- const h = c[l].stop, p = (c[s].stop - h) / u;
145
+ const p = c[s].stop, v = (c[l].stop - p) / u;
146
146
  for (let f = 1; f < u; f++)
147
- c[l + f].stop = h + p * f;
147
+ c[s + f].stop = p + v * f;
148
148
  }
149
- l = s;
149
+ s = l;
150
150
  }
151
151
  }
152
- return { angle: r, stops: c };
152
+ return { angle: o, stops: c };
153
153
  }
154
- const P = `varying vec2 vUv;
154
+ const E = `varying vec2 vUv;
155
155
  varying vec4 vScreenPos;
156
156
  void main() {
157
157
  vUv = uv;
158
158
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
159
159
  vScreenPos = gl_Position;
160
- }`, G = `varying vec2 vUv;
160
+ }`, L = `varying vec2 vUv;
161
161
  uniform vec2 uSize;
162
162
  uniform vec4 uBorderRadius;
163
163
  uniform float uBorderWidth;
@@ -286,44 +286,56 @@ void main() {
286
286
 
287
287
  // #include <colorspace_fragment>
288
288
  }
289
- `, E = `uniform sampler2D uTexture;
289
+ `, F = `uniform sampler2D uTexture;
290
290
  varying vec4 vScreenPos;
291
291
  uniform vec2 uTextureRepeat;
292
- uniform vec2 uTextureOffset;`, L = `vec2 screenUv = (vScreenPos.xy / vScreenPos.w) * 0.5 + 0.5;
292
+ uniform vec2 uTextureOffset;`, _ = `vec2 screenUv = (vScreenPos.xy / vScreenPos.w) * 0.5 + 0.5;
293
293
  vec2 resultUv = screenUv;
294
294
 
295
- `, F = `vec4 texColor = texture2D(uTexture, resultUv);
296
- baseColor = blendSrcOver(baseColor, texColor);`, B = {
297
- vertexShader: P,
298
- fragmentShader: G
299
- }, S = {
300
- declChunk: E,
301
- uvChunk: L,
302
- baseColorChunk: F
295
+ `, W = `vec4 texColor = texture2D(uTexture, resultUv);
296
+ baseColor = blendSrcOver(baseColor, texColor);`, O = {
297
+ vertexShader: E,
298
+ fragmentShader: L
299
+ }, B = {
300
+ declChunk: F,
301
+ uvChunk: _,
302
+ baseColorChunk: W
303
303
  };
304
- function _(o, e, t, a = null, r) {
305
- const n = a !== null || !!o.imageSrc, i = n ? S.declChunk : "", c = o.isTraveler ? S.uvChunk : `vec2 resultUv = vUv * uTextureRepeat + uTextureOffset;
306
- `, l = n ? c + ((r == null ? void 0 : r.uvModifier) || "") : "", s = n ? S.baseColorChunk : "", u = (r == null ? void 0 : r.colorModifier) || "", h = B.fragmentShader.replace("#INJECT_DECLARATIONS", i).replace("#INJECT_UV_MODIFIER", l).replace("#INJECT_BASE_COLOR", s).replace("#INJECT_COLOR_MODIFIER", u), g = C(o.backgroundColor), p = C(o.borderColor), f = {
307
- uSize: { value: new d.Vector2(e, t) },
304
+ function U(r, e, n, a = null, o) {
305
+ const i = a !== null || !!r.imageSrc;
306
+ let t = "";
307
+ const c = {};
308
+ if (o != null && o.uniforms)
309
+ for (const [h, g] of Object.entries(o.uniforms))
310
+ typeof g == "number" ? (t += `uniform float ${h};
311
+ `, c[h] = { value: g }) : Array.isArray(g) ? g.length === 2 ? (t += `uniform vec2 ${h};
312
+ `, c[h] = { value: new d.Vector2(...g) }) : g.length === 3 ? (t += `uniform vec3 ${h};
313
+ `, c[h] = { value: new d.Vector3(...g) }) : g.length === 4 && (t += `uniform vec4 ${h};
314
+ `, c[h] = { value: new d.Vector4(...g) }) : (t += `uniform float ${h};
315
+ `, c[h] = { value: g });
316
+ const s = (i ? B.declChunk : "") + `
317
+ ` + t, l = r.isTraveler ? B.uvChunk : `vec2 resultUv = vUv * uTextureRepeat + uTextureOffset;
318
+ `, u = i ? l + ((o == null ? void 0 : o.uvModifier) || "") : "", p = i ? B.baseColorChunk : "", b = (o == null ? void 0 : o.colorModifier) || "", v = O.fragmentShader.replace("#INJECT_DECLARATIONS", s).replace("#INJECT_UV_MODIFIER", u).replace("#INJECT_BASE_COLOR", p).replace("#INJECT_COLOR_MODIFIER", b), f = y(r.backgroundColor), m = y(r.borderColor), S = {
319
+ uSize: { value: new d.Vector2(e, n) },
308
320
  uBgColor: {
309
321
  value: new d.Vector4(
310
- g.color.r,
311
- g.color.g,
312
- g.color.b,
313
- g.alpha
322
+ f.color.r,
323
+ f.color.g,
324
+ f.color.b,
325
+ f.alpha
314
326
  )
315
327
  },
316
328
  uBorderColor: {
317
329
  value: new d.Vector4(
318
- p.color.r,
319
- p.color.g,
320
- p.color.b,
321
- p.alpha
330
+ m.color.r,
331
+ m.color.g,
332
+ m.color.b,
333
+ m.alpha
322
334
  )
323
335
  },
324
336
  uBorderRadius: { value: new d.Vector4(0, 0, 0, 0) },
325
- uBorderWidth: { value: v(o.borderWidth) },
326
- uOpacity: { value: o.opacity ?? 1 },
337
+ uBorderWidth: { value: x(r.borderWidth) },
338
+ uOpacity: { value: r.opacity ?? 1 },
327
339
  uTexture: { value: null },
328
340
  uTextureRepeat: { value: new d.Vector2(1, 1) },
329
341
  uTextureOffset: { value: new d.Vector2(0, 0) },
@@ -334,179 +346,181 @@ function _(o, e, t, a = null, r) {
334
346
  },
335
347
  uGradientStops: { value: new Float32Array(8) }
336
348
  };
337
- O(f.uBorderRadius.value, o.borderRadius), n && (f.uTexture.value = a);
338
- const m = new d.ShaderMaterial({
339
- uniforms: f,
340
- vertexShader: B.vertexShader,
341
- fragmentShader: h,
349
+ A(S.uBorderRadius.value, r.borderRadius), i && (S.uTexture.value = a);
350
+ const C = new d.ShaderMaterial({
351
+ uniforms: { ...S, ...c },
352
+ vertexShader: O.vertexShader,
353
+ fragmentShader: v,
342
354
  transparent: !0,
343
355
  side: d.FrontSide
344
356
  // for better performance
345
357
  });
346
- return o.backgroundImage && w(m, { backgroundImage: o.backgroundImage }), m;
358
+ return r.backgroundImage && T(C, { backgroundImage: r.backgroundImage }), C;
347
359
  }
348
- function W(o, e, t, a, r) {
349
- const n = v(e.borderWidth);
350
- w(o, {
351
- width: t,
360
+ function V(r, e, n, a, o) {
361
+ const i = x(e.borderWidth);
362
+ T(r, {
363
+ width: n,
352
364
  height: a,
353
365
  borderRadius: e.borderRadius,
354
- borderWidth: n,
366
+ borderWidth: i,
355
367
  backgroundColor: e.backgroundColor,
356
368
  borderColor: e.borderColor,
357
369
  opacity: e.opacity,
358
- texture: r,
370
+ texture: o,
359
371
  backgroundImage: e.backgroundImage
360
372
  });
361
373
  }
362
- function w(o, e) {
374
+ function T(r, e) {
363
375
  var a;
364
- if (e.width !== void 0 && e.height !== void 0 && o.uniforms.uSize.value.set(e.width, e.height), e.borderRadius !== void 0 && O(o.uniforms.uBorderRadius.value, e.borderRadius), e.borderWidth !== void 0 && (o.uniforms.uBorderWidth.value = e.borderWidth), e.backgroundColor !== void 0)
376
+ if (e.width !== void 0 && e.height !== void 0 && r.uniforms.uSize.value.set(e.width, e.height), e.borderRadius !== void 0 && A(r.uniforms.uBorderRadius.value, e.borderRadius), e.borderWidth !== void 0 && (r.uniforms.uBorderWidth.value = e.borderWidth), e.backgroundColor !== void 0)
365
377
  if (Array.isArray(e.backgroundColor)) {
366
- const r = o.uniforms.uBgColor.value.w;
367
- o.uniforms.uBgColor.value.set(
378
+ const o = r.uniforms.uBgColor.value.w;
379
+ r.uniforms.uBgColor.value.set(
368
380
  e.backgroundColor[0],
369
381
  e.backgroundColor[1],
370
382
  e.backgroundColor[2],
371
- r
383
+ o
372
384
  );
373
385
  } else if (typeof e.backgroundColor == "string") {
374
- const r = C(e.backgroundColor);
375
- o.uniforms.uBgColor.value.set(
376
- r.color.r,
377
- r.color.g,
378
- r.color.b,
379
- r.alpha
386
+ const o = y(e.backgroundColor);
387
+ r.uniforms.uBgColor.value.set(
388
+ o.color.r,
389
+ o.color.g,
390
+ o.color.b,
391
+ o.alpha
380
392
  );
381
393
  } else {
382
- const r = o.uniforms.uBgColor.value.w;
383
- o.uniforms.uBgColor.value.set(
394
+ const o = r.uniforms.uBgColor.value.w;
395
+ r.uniforms.uBgColor.value.set(
384
396
  e.backgroundColor.r,
385
397
  e.backgroundColor.g,
386
398
  e.backgroundColor.b,
387
- r
399
+ o
388
400
  );
389
401
  }
390
402
  if (e.borderColor !== void 0)
391
403
  if (Array.isArray(e.borderColor)) {
392
- const r = o.uniforms.uBorderColor.value.w;
393
- o.uniforms.uBorderColor.value.set(
404
+ const o = r.uniforms.uBorderColor.value.w;
405
+ r.uniforms.uBorderColor.value.set(
394
406
  e.borderColor[0],
395
407
  e.borderColor[1],
396
408
  e.borderColor[2],
397
- r
409
+ o
398
410
  );
399
411
  } else if (typeof e.borderColor == "string") {
400
- const r = C(e.borderColor);
401
- o.uniforms.uBorderColor.value.set(
402
- r.color.r,
403
- r.color.g,
404
- r.color.b,
405
- r.alpha
412
+ const o = y(e.borderColor);
413
+ r.uniforms.uBorderColor.value.set(
414
+ o.color.r,
415
+ o.color.g,
416
+ o.color.b,
417
+ o.alpha
406
418
  );
407
419
  } else {
408
- const r = o.uniforms.uBorderColor.value.w;
409
- o.uniforms.uBorderColor.value.set(
420
+ const o = r.uniforms.uBorderColor.value.w;
421
+ r.uniforms.uBorderColor.value.set(
410
422
  e.borderColor.r,
411
423
  e.borderColor.g,
412
424
  e.borderColor.b,
413
- r
425
+ o
414
426
  );
415
427
  }
416
- e.opacity !== void 0 && (o.uniforms.uOpacity.value = e.opacity), e.bgOpacity !== void 0 && (o.uniforms.uBgColor.value.w = e.bgOpacity), e.borderOpacity !== void 0 && (o.uniforms.uBorderColor.value.w = e.borderOpacity), o.uniforms.uTexture && e.texture !== void 0 && (o.uniforms.uTexture.value = e.texture);
417
- const t = e.texture !== void 0 ? e.texture : (a = o.uniforms.uTexture) == null ? void 0 : a.value;
418
- if (t && (t.image instanceof ImageBitmap || t.image instanceof HTMLImageElement || t.image instanceof HTMLCanvasElement)) {
419
- const r = t.image.width, n = t.image.height, i = e.width ?? o.uniforms.uSize.value.x, c = e.height ?? o.uniforms.uSize.value.y;
420
- if (r && n && i && c) {
421
- const l = r / n, s = i / c;
422
- if (l > s) {
423
- const u = s / l;
424
- o.uniforms.uTextureRepeat.value.set(u, 1), o.uniforms.uTextureOffset.value.set((1 - u) / 2, 0);
425
- } else {
428
+ e.opacity !== void 0 && (r.uniforms.uOpacity.value = e.opacity), e.bgOpacity !== void 0 && (r.uniforms.uBgColor.value.w = e.bgOpacity), e.borderOpacity !== void 0 && (r.uniforms.uBorderColor.value.w = e.borderOpacity), r.uniforms.uTexture && e.texture !== void 0 && (r.uniforms.uTexture.value = e.texture);
429
+ const n = e.texture !== void 0 ? e.texture : (a = r.uniforms.uTexture) == null ? void 0 : a.value;
430
+ if (n && (n.image instanceof ImageBitmap || n.image instanceof HTMLImageElement || n.image instanceof HTMLCanvasElement)) {
431
+ const o = n.image.width, i = n.image.height, t = e.width ?? r.uniforms.uSize.value.x, c = e.height ?? r.uniforms.uSize.value.y;
432
+ if (o && i && t && c) {
433
+ const s = o / i, l = t / c;
434
+ if (s > l) {
426
435
  const u = l / s;
427
- o.uniforms.uTextureRepeat.value.set(1, u), o.uniforms.uTextureOffset.value.set(0, (1 - u) / 2);
436
+ r.uniforms.uTextureRepeat.value.set(u, 1), r.uniforms.uTextureOffset.value.set((1 - u) / 2, 0);
437
+ } else {
438
+ const u = s / l;
439
+ r.uniforms.uTextureRepeat.value.set(1, u), r.uniforms.uTextureOffset.value.set(0, (1 - u) / 2);
428
440
  }
429
441
  }
430
442
  } else
431
- o.uniforms.uTextureRepeat && (o.uniforms.uTextureRepeat.value.set(1, 1), o.uniforms.uTextureOffset.value.set(0, 0));
443
+ r.uniforms.uTextureRepeat && (r.uniforms.uTextureRepeat.value.set(1, 1), r.uniforms.uTextureOffset.value.set(0, 0));
432
444
  if (e.backgroundImage !== void 0) {
433
- const r = M(e.backgroundImage);
434
- if (r) {
435
- o.uniforms.uGradientCount.value = r.stops.length, o.uniforms.uGradientAngle.value = r.angle;
436
- for (let n = 0; n < 8; n++)
437
- if (n < r.stops.length) {
438
- const i = r.stops[n];
439
- o.uniforms.uGradientColors.value[n].set(
440
- i.color.r,
441
- i.color.g,
442
- i.color.b,
443
- i.alpha
444
- ), console.log(i.color.r, i.color.g, i.color.b), o.uniforms.uGradientStops.value[n] = i.stop;
445
+ const o = G(e.backgroundImage);
446
+ if (o) {
447
+ r.uniforms.uGradientCount.value = o.stops.length, r.uniforms.uGradientAngle.value = o.angle;
448
+ for (let i = 0; i < 8; i++)
449
+ if (i < o.stops.length) {
450
+ const t = o.stops[i];
451
+ r.uniforms.uGradientColors.value[i].set(
452
+ t.color.r,
453
+ t.color.g,
454
+ t.color.b,
455
+ t.alpha
456
+ ), r.uniforms.uGradientStops.value[i] = t.stop;
445
457
  } else
446
- o.uniforms.uGradientColors.value[n].set(0, 0, 0, 0), o.uniforms.uGradientStops.value[n] = 1;
458
+ r.uniforms.uGradientColors.value[i].set(0, 0, 0, 0), r.uniforms.uGradientStops.value[i] = 1;
447
459
  } else
448
- o.uniforms.uGradientCount.value = 0;
460
+ r.uniforms.uGradientCount.value = 0;
449
461
  }
462
+ for (const o of Object.keys(e))
463
+ o !== "width" && o !== "height" && o !== "borderRadius" && o !== "borderWidth" && o !== "backgroundColor" && o !== "borderColor" && o !== "opacity" && o !== "bgOpacity" && o !== "borderOpacity" && o !== "texture" && o !== "backgroundImage" && r.uniforms[o] !== void 0 && (r.uniforms[o].value !== void 0 && r.uniforms[o].value !== null && typeof r.uniforms[o].value.set == "function" ? Array.isArray(e[o]) ? r.uniforms[o].value.set(...e[o]) : e[o] !== void 0 && (e[o].copy ? r.uniforms[o].value.copy(e[o]) : r.uniforms[o].value = e[o]) : r.uniforms[o].value = e[o]);
450
464
  }
451
- function O(o, e) {
465
+ function A(r, e) {
452
466
  if (e == null) {
453
- o.set(0, 0, 0, 0);
467
+ r.set(0, 0, 0, 0);
454
468
  return;
455
469
  }
456
470
  if (typeof e == "number") {
457
- o.set(e, e, e, e);
471
+ r.set(e, e, e, e);
458
472
  return;
459
473
  }
460
474
  if (Array.isArray(e)) {
461
- o.set(e[0], e[1], e[2], e[3]);
475
+ r.set(e[0], e[1], e[2], e[3]);
462
476
  return;
463
477
  }
464
- const t = e.split("/")[0].trim().split(/\s+/), a = v(t[0]), r = v(t[1] ?? t[0]), n = v(t[2] ?? t[0]), i = v(t[3] ?? t[1] ?? t[0]);
465
- o.set(a, r, n, i);
478
+ const n = e.split("/")[0].trim().split(/\s+/), a = x(n[0]), o = x(n[1] ?? n[0]), i = x(n[2] ?? n[0]), t = x(n[3] ?? n[1] ?? n[0]);
479
+ r.set(a, o, i, t);
466
480
  }
467
- const z = {
468
- create(o, e, t, a, r, n = 2, i = null, c) {
469
- return o === "BOX" ? _(
481
+ const N = {
482
+ create(r, e, n, a, o, i = 2, t = null, c) {
483
+ return r === "BOX" ? U(
470
484
  e,
471
485
  a,
472
- r,
473
- i,
486
+ o,
487
+ t,
474
488
  c
475
- ) : o === "TEXT" ? new A(
476
- t || "",
489
+ ) : r === "TEXT" ? new k(
490
+ n || "",
477
491
  e,
478
492
  a,
479
- r,
480
- n
493
+ o,
494
+ i
481
495
  ) : new d.MeshBasicMaterial({ visible: !1 });
482
496
  },
483
- update(o, e, t, a, r, n, i = 2, c) {
484
- e === "BOX" ? W(
485
- o,
486
- t,
497
+ update(r, e, n, a, o, i, t = 2, c) {
498
+ e === "BOX" ? V(
487
499
  r,
488
500
  n,
501
+ o,
502
+ i,
489
503
  c
490
- ) : e === "TEXT" && o.updateText(
504
+ ) : e === "TEXT" && r.updateText(
491
505
  a || "",
492
- t,
493
- r,
494
506
  n,
495
- i
507
+ o,
508
+ i,
509
+ t
496
510
  );
497
511
  },
498
- forceUpdateUniforms(o, e) {
499
- w(o, e);
512
+ forceUpdateUniforms(r, e) {
513
+ T(r, e);
500
514
  }
501
515
  };
502
516
  export {
503
- z as Painter,
504
- A as TextGenerator,
505
- _ as createBoxMaterial,
506
- C as parseColor,
507
- M as parseLinearGradient,
508
- v as parsePixelValue,
509
- w as setBoxUniforms,
510
- k as splitByComma,
511
- W as updateBoxMaterial
517
+ N as Painter,
518
+ k as TextGenerator,
519
+ U as createBoxMaterial,
520
+ y as parseColor,
521
+ G as parseLinearGradient,
522
+ x as parsePixelValue,
523
+ T as setBoxUniforms,
524
+ P as splitByComma,
525
+ V as updateBoxMaterial
512
526
  };
@@ -1,11 +1,11 @@
1
- (function(d,h){typeof exports=="object"&&typeof module<"u"?h(exports,require("three")):typeof define=="function"&&define.amd?define(["exports","three"],h):(d=typeof globalThis<"u"?globalThis:d||self,h(d.MiragePainter={},d.THREE))})(this,function(d,h){"use strict";var V=Object.defineProperty;var D=(d,h,m)=>h in d?V(d,h,{enumerable:!0,configurable:!0,writable:!0,value:m}):d[h]=m;var S=(d,h,m)=>(D(d,typeof h!="symbol"?h+"":h,m),m);function m(o){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(o){for(const t in o)if(t!=="default"){const n=Object.getOwnPropertyDescriptor(o,t);Object.defineProperty(e,t,n.get?n:{enumerable:!0,get:()=>o[t]})}}return e.default=o,Object.freeze(e)}const f=m(h);class y{static getBaseline(e){if(this.cache.has(e))return this.cache.get(e);const t=this.calculateBaselineFromDOM(e);return this.cache.set(e,t),t}static calculateBaselineFromDOM(e){if(typeof document>"u")return 0;const t=document.createElement("div"),n=document.createElement("span"),r=document.createElement("img");t.style.visibility="hidden",t.style.position="absolute",t.style.top="0px",t.style.left="0px",t.style.font=e,t.style.margin="0",t.style.padding="0",t.style.border="none",n.style.margin="0",n.style.padding="0",n.style.border="none",n.style.lineHeight="normal",r.width=1,r.height=1,r.style.verticalAlign="baseline",n.appendChild(document.createTextNode("Hidden Text")),t.appendChild(n),t.appendChild(r),document.body.appendChild(t);const i=r.offsetTop-n.offsetTop;return document.body.removeChild(t),i}}S(y,"cache",new Map);class I extends f.MeshBasicMaterial{constructor(t,n,r,i,a=2){super({transparent:!0,side:f.FrontSide,color:16777215});S(this,"canvas");S(this,"ctx");S(this,"qualityFactor");if(this.canvas=document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),!this.ctx)throw new Error("[Mirage] Failed to create canvas context");this.qualityFactor=a,this.map=new f.CanvasTexture(this.canvas),this.map.colorSpace=f.LinearSRGBColorSpace,this.map.minFilter=f.LinearFilter,this.map.magFilter=f.LinearFilter,this.updateText(t,n,r,i)}wrapText(t,n){const r=t.split(`
2
- `),i=[];return r.forEach(a=>{const c=a.match(/[^\s\-]+\-?|\-|\s+/g)||[];if(c.length===0){i.push("");return}let l=c[0];for(let s=1;s<c.length;s++){const u=c[s];this.ctx.measureText(l+u).width<=n+2?l+=u:(l&&i.push(l),l=u.trimStart())}l&&i.push(l)}),i}updateText(t,n,r,i,a){a!==void 0&&(this.qualityFactor=a);const l=(window.devicePixelRatio||1)*this.qualityFactor,s=r*l,u=i*l;this.canvas.width!==s||this.canvas.height!==u?(this.canvas.width=s,this.canvas.height=u):this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.setTransform(l,0,0,l,0,0),this.ctx.font=n.font,this.ctx.fillStyle=n.color,this.ctx.textBaseline="alphabetic",this.ctx.globalAlpha=1;const b=this.wrapText(t,r),v=n.lineHeight,g=y.getBaseline(n.font);b.forEach((p,B)=>{const z=B*v+g;let O=0;n.textAlign==="center"?O=r/2:n.textAlign==="right"&&(O=r),this.ctx.textAlign=n.textAlign,this.ctx.fillText(p,O,z)}),this.map&&(this.map.needsUpdate=!0)}dispose(){this.map&&this.map.dispose(),super.dispose()}}function C(o){return typeof o=="number"?o:parseFloat(o)||0}function x(o){if(!o||o==="transparent")return{color:new f.Color(16777215),alpha:0};const e=o.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);if(e){const t=parseInt(e[1],10),n=parseInt(e[2],10),r=parseInt(e[3],10),i=e[4]!==void 0?parseFloat(e[4]):1;return{color:new f.Color(`rgb(${t}, ${n}, ${r})`),alpha:i}}return{color:new f.Color(o),alpha:1}}function M(o){const e=[];let t="",n=0;for(let r=0;r<o.length;r++){const i=o[r];if(i==="(")n++;else if(i===")")n--;else if(i===","&&n===0){e.push(t.trim()),t="";continue}t+=i}return t&&e.push(t.trim()),e}function R(o){if(!o||typeof o!="string"||!o.includes("linear-gradient"))return null;const e=o.match(/linear-gradient\((.*)\)/);if(!e)return null;const t=e[1],n=M(t);let r=Math.PI,i=0;const a=n[0].trim();if(a.startsWith("to "))a==="to top"?r=0:a==="to right"?r=Math.PI/2:a==="to bottom"?r=Math.PI:a==="to left"?r=Math.PI*1.5:a==="to top right"||a==="to right top"?r=Math.PI/4:a==="to bottom right"||a==="to right bottom"?r=Math.PI*.75:a==="to bottom left"||a==="to left bottom"?r=Math.PI*1.25:(a==="to top left"||a==="to left top")&&(r=Math.PI*1.75),i=1;else if(a.endsWith("deg")||a.endsWith("rad")||a.endsWith("turn")){const l=parseFloat(a);a.endsWith("deg")?r=l*(Math.PI/180):a.endsWith("rad")?r=l:a.endsWith("turn")&&(r=l*Math.PI*2),i=1}const c=[];for(let l=i;l<n.length&&!(c.length>=8);l++){const s=n[l].trim(),u=s.lastIndexOf(" ");let b=s,v=null;if(u!==-1&&!s.endsWith(")")){const p=s.substring(u+1);(p.endsWith("%")||p.endsWith("px")||!isNaN(parseFloat(p)))&&(b=s.substring(0,u).trim(),v=p)}const g=x(b);c.push({color:g.color,alpha:g.alpha,rawStop:v,stop:0})}if(c.length>0){for(let s=0;s<c.length;s++)c[s].rawStop!==null&&(c[s].stop=parseFloat(c[s].rawStop)/100);c[0].rawStop===null&&(c[0].stop=0),c.length>1&&c[c.length-1].rawStop===null&&(c[c.length-1].stop=1);let l=0;for(let s=1;s<c.length;s++)if(c[s].rawStop!==null||s===c.length-1){const u=s-l;if(u>1){const b=c[l].stop,g=(c[s].stop-b)/u;for(let p=1;p<u;p++)c[l+p].stop=b+g*p}l=s}}return{angle:r,stops:c}}const E=`varying vec2 vUv;
1
+ (function(f,h){typeof exports=="object"&&typeof module<"u"?h(exports,require("three")):typeof define=="function"&&define.amd?define(["exports","three"],h):(f=typeof globalThis<"u"?globalThis:f||self,h(f.MiragePainter={},f.THREE))})(this,function(f,h){"use strict";var N=Object.defineProperty;var q=(f,h,C)=>h in f?N(f,h,{enumerable:!0,configurable:!0,writable:!0,value:C}):f[h]=C;var O=(f,h,C)=>(q(f,typeof h!="symbol"?h+"":h,C),C);function C(r){const o=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const t in r)if(t!=="default"){const i=Object.getOwnPropertyDescriptor(r,t);Object.defineProperty(o,t,i.get?i:{enumerable:!0,get:()=>r[t]})}}return o.default=r,Object.freeze(o)}const u=C(h);class M{static getBaseline(o){if(this.cache.has(o))return this.cache.get(o);const t=this.calculateBaselineFromDOM(o);return this.cache.set(o,t),t}static calculateBaselineFromDOM(o){if(typeof document>"u")return 0;const t=document.createElement("div"),i=document.createElement("span"),e=document.createElement("img");t.style.visibility="hidden",t.style.position="absolute",t.style.top="0px",t.style.left="0px",t.style.font=o,t.style.margin="0",t.style.padding="0",t.style.border="none",i.style.margin="0",i.style.padding="0",i.style.border="none",i.style.lineHeight="normal",e.width=1,e.height=1,e.style.verticalAlign="baseline",i.appendChild(document.createTextNode("Hidden Text")),t.appendChild(i),t.appendChild(e),document.body.appendChild(t);const a=e.offsetTop-i.offsetTop;return document.body.removeChild(t),a}}O(M,"cache",new Map);class R extends u.MeshBasicMaterial{constructor(t,i,e,a,n=2){super({transparent:!0,side:u.FrontSide,color:16777215});O(this,"canvas");O(this,"ctx");O(this,"qualityFactor");if(this.canvas=document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),!this.ctx)throw new Error("[Mirage] Failed to create canvas context");this.qualityFactor=n,this.map=new u.CanvasTexture(this.canvas),this.map.colorSpace=u.LinearSRGBColorSpace,this.map.minFilter=u.LinearFilter,this.map.magFilter=u.LinearFilter,this.updateText(t,i,e,a)}wrapText(t,i){const e=t.split(`
2
+ `),a=[];return e.forEach(n=>{const c=n.match(/[^\s\-]+\-?|\-|\s+/g)||[];if(c.length===0){a.push("");return}let s=c[0];for(let l=1;l<c.length;l++){const d=c[l];this.ctx.measureText(s+d).width<=i+2?s+=d:(s&&a.push(s),s=d.trimStart())}s&&a.push(s)}),a}updateText(t,i,e,a,n){n!==void 0&&(this.qualityFactor=n);const s=(window.devicePixelRatio||1)*this.qualityFactor,l=e*s,d=a*s;this.canvas.width!==l||this.canvas.height!==d?(this.canvas.width=l,this.canvas.height=d):this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.setTransform(s,0,0,s,0,0),this.ctx.font=i.font,this.ctx.fillStyle=i.color,this.ctx.textBaseline="alphabetic",this.ctx.globalAlpha=1;const g=this.wrapText(t,e),y=i.lineHeight,m=M.getBaseline(i.font);g.forEach((p,T)=>{const B=T*y+m;let w=0;i.textAlign==="center"?w=e/2:i.textAlign==="right"&&(w=e),this.ctx.textAlign=i.textAlign,this.ctx.fillText(p,w,B)}),this.map&&(this.map.needsUpdate=!0)}dispose(){this.map&&this.map.dispose(),super.dispose()}}function x(r){return typeof r=="number"?r:parseFloat(r)||0}function S(r){if(!r||r==="transparent")return{color:new u.Color(16777215),alpha:0};const o=r.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);if(o){const t=parseInt(o[1],10),i=parseInt(o[2],10),e=parseInt(o[3],10),a=o[4]!==void 0?parseFloat(o[4]):1;return{color:new u.Color(`rgb(${t}, ${i}, ${e})`),alpha:a}}return{color:new u.Color(r),alpha:1}}function k(r){const o=[];let t="",i=0;for(let e=0;e<r.length;e++){const a=r[e];if(a==="(")i++;else if(a===")")i--;else if(a===","&&i===0){o.push(t.trim()),t="";continue}t+=a}return t&&o.push(t.trim()),o}function P(r){if(!r||typeof r!="string"||!r.includes("linear-gradient"))return null;const o=r.match(/linear-gradient\((.*)\)/);if(!o)return null;const t=o[1],i=k(t);let e=Math.PI,a=0;const n=i[0].trim();if(n.startsWith("to "))n==="to top"?e=0:n==="to right"?e=Math.PI/2:n==="to bottom"?e=Math.PI:n==="to left"?e=Math.PI*1.5:n==="to top right"||n==="to right top"?e=Math.PI/4:n==="to bottom right"||n==="to right bottom"?e=Math.PI*.75:n==="to bottom left"||n==="to left bottom"?e=Math.PI*1.25:(n==="to top left"||n==="to left top")&&(e=Math.PI*1.75),a=1;else if(n.endsWith("deg")||n.endsWith("rad")||n.endsWith("turn")){const s=parseFloat(n);n.endsWith("deg")?e=s*(Math.PI/180):n.endsWith("rad")?e=s:n.endsWith("turn")&&(e=s*Math.PI*2),a=1}const c=[];for(let s=a;s<i.length&&!(c.length>=8);s++){const l=i[s].trim(),d=l.lastIndexOf(" ");let g=l,y=null;if(d!==-1&&!l.endsWith(")")){const p=l.substring(d+1);(p.endsWith("%")||p.endsWith("px")||!isNaN(parseFloat(p)))&&(g=l.substring(0,d).trim(),y=p)}const m=S(g);c.push({color:m.color,alpha:m.alpha,rawStop:y,stop:0})}if(c.length>0){for(let l=0;l<c.length;l++)c[l].rawStop!==null&&(c[l].stop=parseFloat(c[l].rawStop)/100);c[0].rawStop===null&&(c[0].stop=0),c.length>1&&c[c.length-1].rawStop===null&&(c[c.length-1].stop=1);let s=0;for(let l=1;l<c.length;l++)if(c[l].rawStop!==null||l===c.length-1){const d=l-s;if(d>1){const g=c[s].stop,m=(c[l].stop-g)/d;for(let p=1;p<d;p++)c[s+p].stop=g+m*p}s=l}}return{angle:e,stops:c}}const F=`varying vec2 vUv;
3
3
  varying vec4 vScreenPos;
4
4
  void main() {
5
5
  vUv = uv;
6
6
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
7
7
  vScreenPos = gl_Position;
8
- }`,L=`varying vec2 vUv;
8
+ }`,W=`varying vec2 vUv;
9
9
  uniform vec2 uSize;
10
10
  uniform vec4 uBorderRadius;
11
11
  uniform float uBorderWidth;
@@ -134,12 +134,18 @@ void main() {
134
134
 
135
135
  // #include <colorspace_fragment>
136
136
  }
137
- `,_=`uniform sampler2D uTexture;
137
+ `,U=`uniform sampler2D uTexture;
138
138
  varying vec4 vScreenPos;
139
139
  uniform vec2 uTextureRepeat;
140
- uniform vec2 uTextureOffset;`,F=`vec2 screenUv = (vScreenPos.xy / vScreenPos.w) * 0.5 + 0.5;
140
+ uniform vec2 uTextureOffset;`,V=`vec2 screenUv = (vScreenPos.xy / vScreenPos.w) * 0.5 + 0.5;
141
141
  vec2 resultUv = screenUv;
142
142
 
143
- `,W=`vec4 texColor = texture2D(uTexture, resultUv);
144
- baseColor = blendSrcOver(baseColor, texColor);`,k={vertexShader:E,fragmentShader:L},w={declChunk:_,uvChunk:F,baseColorChunk:W};function A(o,e,t,n=null,r){const i=n!==null||!!o.imageSrc,a=i?w.declChunk:"",c=o.isTraveler?w.uvChunk:`vec2 resultUv = vUv * uTextureRepeat + uTextureOffset;
145
- `,l=i?c+((r==null?void 0:r.uvModifier)||""):"",s=i?w.baseColorChunk:"",u=(r==null?void 0:r.colorModifier)||"",b=k.fragmentShader.replace("#INJECT_DECLARATIONS",a).replace("#INJECT_UV_MODIFIER",l).replace("#INJECT_BASE_COLOR",s).replace("#INJECT_COLOR_MODIFIER",u),v=x(o.backgroundColor),g=x(o.borderColor),p={uSize:{value:new f.Vector2(e,t)},uBgColor:{value:new f.Vector4(v.color.r,v.color.g,v.color.b,v.alpha)},uBorderColor:{value:new f.Vector4(g.color.r,g.color.g,g.color.b,g.alpha)},uBorderRadius:{value:new f.Vector4(0,0,0,0)},uBorderWidth:{value:C(o.borderWidth)},uOpacity:{value:o.opacity??1},uTexture:{value:null},uTextureRepeat:{value:new f.Vector2(1,1)},uTextureOffset:{value:new f.Vector2(0,0)},uGradientCount:{value:0},uGradientAngle:{value:0},uGradientColors:{value:Array.from({length:8},()=>new f.Vector4(0,0,0,0))},uGradientStops:{value:new Float32Array(8)}};G(p.uBorderRadius.value,o.borderRadius),i&&(p.uTexture.value=n);const B=new f.ShaderMaterial({uniforms:p,vertexShader:k.vertexShader,fragmentShader:b,transparent:!0,side:f.FrontSide});return o.backgroundImage&&T(B,{backgroundImage:o.backgroundImage}),B}function P(o,e,t,n,r){const i=C(e.borderWidth);T(o,{width:t,height:n,borderRadius:e.borderRadius,borderWidth:i,backgroundColor:e.backgroundColor,borderColor:e.borderColor,opacity:e.opacity,texture:r,backgroundImage:e.backgroundImage})}function T(o,e){var n;if(e.width!==void 0&&e.height!==void 0&&o.uniforms.uSize.value.set(e.width,e.height),e.borderRadius!==void 0&&G(o.uniforms.uBorderRadius.value,e.borderRadius),e.borderWidth!==void 0&&(o.uniforms.uBorderWidth.value=e.borderWidth),e.backgroundColor!==void 0)if(Array.isArray(e.backgroundColor)){const r=o.uniforms.uBgColor.value.w;o.uniforms.uBgColor.value.set(e.backgroundColor[0],e.backgroundColor[1],e.backgroundColor[2],r)}else if(typeof e.backgroundColor=="string"){const r=x(e.backgroundColor);o.uniforms.uBgColor.value.set(r.color.r,r.color.g,r.color.b,r.alpha)}else{const r=o.uniforms.uBgColor.value.w;o.uniforms.uBgColor.value.set(e.backgroundColor.r,e.backgroundColor.g,e.backgroundColor.b,r)}if(e.borderColor!==void 0)if(Array.isArray(e.borderColor)){const r=o.uniforms.uBorderColor.value.w;o.uniforms.uBorderColor.value.set(e.borderColor[0],e.borderColor[1],e.borderColor[2],r)}else if(typeof e.borderColor=="string"){const r=x(e.borderColor);o.uniforms.uBorderColor.value.set(r.color.r,r.color.g,r.color.b,r.alpha)}else{const r=o.uniforms.uBorderColor.value.w;o.uniforms.uBorderColor.value.set(e.borderColor.r,e.borderColor.g,e.borderColor.b,r)}e.opacity!==void 0&&(o.uniforms.uOpacity.value=e.opacity),e.bgOpacity!==void 0&&(o.uniforms.uBgColor.value.w=e.bgOpacity),e.borderOpacity!==void 0&&(o.uniforms.uBorderColor.value.w=e.borderOpacity),o.uniforms.uTexture&&e.texture!==void 0&&(o.uniforms.uTexture.value=e.texture);const t=e.texture!==void 0?e.texture:(n=o.uniforms.uTexture)==null?void 0:n.value;if(t&&(t.image instanceof ImageBitmap||t.image instanceof HTMLImageElement||t.image instanceof HTMLCanvasElement)){const r=t.image.width,i=t.image.height,a=e.width??o.uniforms.uSize.value.x,c=e.height??o.uniforms.uSize.value.y;if(r&&i&&a&&c){const l=r/i,s=a/c;if(l>s){const u=s/l;o.uniforms.uTextureRepeat.value.set(u,1),o.uniforms.uTextureOffset.value.set((1-u)/2,0)}else{const u=l/s;o.uniforms.uTextureRepeat.value.set(1,u),o.uniforms.uTextureOffset.value.set(0,(1-u)/2)}}}else o.uniforms.uTextureRepeat&&(o.uniforms.uTextureRepeat.value.set(1,1),o.uniforms.uTextureOffset.value.set(0,0));if(e.backgroundImage!==void 0){const r=R(e.backgroundImage);if(r){o.uniforms.uGradientCount.value=r.stops.length,o.uniforms.uGradientAngle.value=r.angle;for(let i=0;i<8;i++)if(i<r.stops.length){const a=r.stops[i];o.uniforms.uGradientColors.value[i].set(a.color.r,a.color.g,a.color.b,a.alpha),console.log(a.color.r,a.color.g,a.color.b),o.uniforms.uGradientStops.value[i]=a.stop}else o.uniforms.uGradientColors.value[i].set(0,0,0,0),o.uniforms.uGradientStops.value[i]=1}else o.uniforms.uGradientCount.value=0}}function G(o,e){if(e==null){o.set(0,0,0,0);return}if(typeof e=="number"){o.set(e,e,e,e);return}if(Array.isArray(e)){o.set(e[0],e[1],e[2],e[3]);return}const t=e.split("/")[0].trim().split(/\s+/),n=C(t[0]),r=C(t[1]??t[0]),i=C(t[2]??t[0]),a=C(t[3]??t[1]??t[0]);o.set(n,r,i,a)}const U={create(o,e,t,n,r,i=2,a=null,c){return o==="BOX"?A(e,n,r,a,c):o==="TEXT"?new I(t||"",e,n,r,i):new f.MeshBasicMaterial({visible:!1})},update(o,e,t,n,r,i,a=2,c){e==="BOX"?P(o,t,r,i,c):e==="TEXT"&&o.updateText(n||"",t,r,i,a)},forceUpdateUniforms(o,e){T(o,e)}};d.Painter=U,d.TextGenerator=I,d.createBoxMaterial=A,d.parseColor=x,d.parseLinearGradient=R,d.parsePixelValue=C,d.setBoxUniforms=T,d.splitByComma=M,d.updateBoxMaterial=P,Object.defineProperty(d,Symbol.toStringTag,{value:"Module"})});
143
+ `,z=`vec4 texColor = texture2D(uTexture, resultUv);
144
+ baseColor = blendSrcOver(baseColor, texColor);`,G={vertexShader:F,fragmentShader:W},A={declChunk:U,uvChunk:V,baseColorChunk:z};function E(r,o,t,i=null,e){const a=i!==null||!!r.imageSrc;let n="";const c={};if(e!=null&&e.uniforms)for(const[b,v]of Object.entries(e.uniforms))typeof v=="number"?(n+=`uniform float ${b};
145
+ `,c[b]={value:v}):Array.isArray(v)?v.length===2?(n+=`uniform vec2 ${b};
146
+ `,c[b]={value:new u.Vector2(...v)}):v.length===3?(n+=`uniform vec3 ${b};
147
+ `,c[b]={value:new u.Vector3(...v)}):v.length===4&&(n+=`uniform vec4 ${b};
148
+ `,c[b]={value:new u.Vector4(...v)}):(n+=`uniform float ${b};
149
+ `,c[b]={value:v});const s=(a?A.declChunk:"")+`
150
+ `+n,l=r.isTraveler?A.uvChunk:`vec2 resultUv = vUv * uTextureRepeat + uTextureOffset;
151
+ `,d=a?l+((e==null?void 0:e.uvModifier)||""):"",g=a?A.baseColorChunk:"",y=(e==null?void 0:e.colorModifier)||"",m=G.fragmentShader.replace("#INJECT_DECLARATIONS",s).replace("#INJECT_UV_MODIFIER",d).replace("#INJECT_BASE_COLOR",g).replace("#INJECT_COLOR_MODIFIER",y),p=S(r.backgroundColor),T=S(r.borderColor),B={uSize:{value:new u.Vector2(o,t)},uBgColor:{value:new u.Vector4(p.color.r,p.color.g,p.color.b,p.alpha)},uBorderColor:{value:new u.Vector4(T.color.r,T.color.g,T.color.b,T.alpha)},uBorderRadius:{value:new u.Vector4(0,0,0,0)},uBorderWidth:{value:x(r.borderWidth)},uOpacity:{value:r.opacity??1},uTexture:{value:null},uTextureRepeat:{value:new u.Vector2(1,1)},uTextureOffset:{value:new u.Vector2(0,0)},uGradientCount:{value:0},uGradientAngle:{value:0},uGradientColors:{value:Array.from({length:8},()=>new u.Vector4(0,0,0,0))},uGradientStops:{value:new Float32Array(8)}};_(B.uBorderRadius.value,r.borderRadius),a&&(B.uTexture.value=i);const w=new u.ShaderMaterial({uniforms:{...B,...c},vertexShader:G.vertexShader,fragmentShader:m,transparent:!0,side:u.FrontSide});return r.backgroundImage&&I(w,{backgroundImage:r.backgroundImage}),w}function L(r,o,t,i,e){const a=x(o.borderWidth);I(r,{width:t,height:i,borderRadius:o.borderRadius,borderWidth:a,backgroundColor:o.backgroundColor,borderColor:o.borderColor,opacity:o.opacity,texture:e,backgroundImage:o.backgroundImage})}function I(r,o){var i;if(o.width!==void 0&&o.height!==void 0&&r.uniforms.uSize.value.set(o.width,o.height),o.borderRadius!==void 0&&_(r.uniforms.uBorderRadius.value,o.borderRadius),o.borderWidth!==void 0&&(r.uniforms.uBorderWidth.value=o.borderWidth),o.backgroundColor!==void 0)if(Array.isArray(o.backgroundColor)){const e=r.uniforms.uBgColor.value.w;r.uniforms.uBgColor.value.set(o.backgroundColor[0],o.backgroundColor[1],o.backgroundColor[2],e)}else if(typeof o.backgroundColor=="string"){const e=S(o.backgroundColor);r.uniforms.uBgColor.value.set(e.color.r,e.color.g,e.color.b,e.alpha)}else{const e=r.uniforms.uBgColor.value.w;r.uniforms.uBgColor.value.set(o.backgroundColor.r,o.backgroundColor.g,o.backgroundColor.b,e)}if(o.borderColor!==void 0)if(Array.isArray(o.borderColor)){const e=r.uniforms.uBorderColor.value.w;r.uniforms.uBorderColor.value.set(o.borderColor[0],o.borderColor[1],o.borderColor[2],e)}else if(typeof o.borderColor=="string"){const e=S(o.borderColor);r.uniforms.uBorderColor.value.set(e.color.r,e.color.g,e.color.b,e.alpha)}else{const e=r.uniforms.uBorderColor.value.w;r.uniforms.uBorderColor.value.set(o.borderColor.r,o.borderColor.g,o.borderColor.b,e)}o.opacity!==void 0&&(r.uniforms.uOpacity.value=o.opacity),o.bgOpacity!==void 0&&(r.uniforms.uBgColor.value.w=o.bgOpacity),o.borderOpacity!==void 0&&(r.uniforms.uBorderColor.value.w=o.borderOpacity),r.uniforms.uTexture&&o.texture!==void 0&&(r.uniforms.uTexture.value=o.texture);const t=o.texture!==void 0?o.texture:(i=r.uniforms.uTexture)==null?void 0:i.value;if(t&&(t.image instanceof ImageBitmap||t.image instanceof HTMLImageElement||t.image instanceof HTMLCanvasElement)){const e=t.image.width,a=t.image.height,n=o.width??r.uniforms.uSize.value.x,c=o.height??r.uniforms.uSize.value.y;if(e&&a&&n&&c){const s=e/a,l=n/c;if(s>l){const d=l/s;r.uniforms.uTextureRepeat.value.set(d,1),r.uniforms.uTextureOffset.value.set((1-d)/2,0)}else{const d=s/l;r.uniforms.uTextureRepeat.value.set(1,d),r.uniforms.uTextureOffset.value.set(0,(1-d)/2)}}}else r.uniforms.uTextureRepeat&&(r.uniforms.uTextureRepeat.value.set(1,1),r.uniforms.uTextureOffset.value.set(0,0));if(o.backgroundImage!==void 0){const e=P(o.backgroundImage);if(e){r.uniforms.uGradientCount.value=e.stops.length,r.uniforms.uGradientAngle.value=e.angle;for(let a=0;a<8;a++)if(a<e.stops.length){const n=e.stops[a];r.uniforms.uGradientColors.value[a].set(n.color.r,n.color.g,n.color.b,n.alpha),r.uniforms.uGradientStops.value[a]=n.stop}else r.uniforms.uGradientColors.value[a].set(0,0,0,0),r.uniforms.uGradientStops.value[a]=1}else r.uniforms.uGradientCount.value=0}for(const e of Object.keys(o))e!=="width"&&e!=="height"&&e!=="borderRadius"&&e!=="borderWidth"&&e!=="backgroundColor"&&e!=="borderColor"&&e!=="opacity"&&e!=="bgOpacity"&&e!=="borderOpacity"&&e!=="texture"&&e!=="backgroundImage"&&r.uniforms[e]!==void 0&&(r.uniforms[e].value!==void 0&&r.uniforms[e].value!==null&&typeof r.uniforms[e].value.set=="function"?Array.isArray(o[e])?r.uniforms[e].value.set(...o[e]):o[e]!==void 0&&(o[e].copy?r.uniforms[e].value.copy(o[e]):r.uniforms[e].value=o[e]):r.uniforms[e].value=o[e])}function _(r,o){if(o==null){r.set(0,0,0,0);return}if(typeof o=="number"){r.set(o,o,o,o);return}if(Array.isArray(o)){r.set(o[0],o[1],o[2],o[3]);return}const t=o.split("/")[0].trim().split(/\s+/),i=x(t[0]),e=x(t[1]??t[0]),a=x(t[2]??t[0]),n=x(t[3]??t[1]??t[0]);r.set(i,e,a,n)}const D={create(r,o,t,i,e,a=2,n=null,c){return r==="BOX"?E(o,i,e,n,c):r==="TEXT"?new R(t||"",o,i,e,a):new u.MeshBasicMaterial({visible:!1})},update(r,o,t,i,e,a,n=2,c){o==="BOX"?L(r,t,e,a,c):o==="TEXT"&&r.updateText(i||"",t,e,a,n)},forceUpdateUniforms(r,o){I(r,o)}};f.Painter=D,f.TextGenerator=R,f.createBoxMaterial=E,f.parseColor=S,f.parseLinearGradient=P,f.parsePixelValue=x,f.setBoxUniforms=I,f.splitByComma=k,f.updateBoxMaterial=L,Object.defineProperty(f,Symbol.toStringTag,{value:"Module"})});
@@ -14,5 +14,6 @@ export interface BoxUniformValues {
14
14
  borderOpacity?: number;
15
15
  texture?: THREE.Texture | null;
16
16
  backgroundImage?: string;
17
+ [key: string]: any;
17
18
  }
18
19
  export declare function setBoxUniforms(material: THREE.ShaderMaterial, values: BoxUniformValues): void;
@@ -22,4 +22,5 @@ export interface BoxStyles {
22
22
  export interface ShaderHooks {
23
23
  uvModifier?: string;
24
24
  colorModifier?: string;
25
+ uniforms?: Record<string, any>;
25
26
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mirage-engine/painter",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "main": "src/index.ts",
5
5
  "types": "src/index.ts",
6
6
  "peerDependencies": {
@@ -16,7 +16,33 @@ export function createBoxMaterial(
16
16
  ): THREE.ShaderMaterial {
17
17
  const hasTexture = texture !== null || !!styles.imageSrc;
18
18
 
19
- const declChunk = hasTexture ? BoxChunk.declChunk : "";
19
+ let customUniformsCode = "";
20
+ const customUniforms: any = {};
21
+
22
+ if (hooks?.uniforms) {
23
+ for (const [key, value] of Object.entries(hooks.uniforms)) {
24
+ if (typeof value === "number") {
25
+ customUniformsCode += `uniform float ${key};\n`;
26
+ customUniforms[key] = { value };
27
+ } else if (Array.isArray(value)) {
28
+ if (value.length === 2) {
29
+ customUniformsCode += `uniform vec2 ${key};\n`;
30
+ customUniforms[key] = { value: new THREE.Vector2(...value) };
31
+ } else if (value.length === 3) {
32
+ customUniformsCode += `uniform vec3 ${key};\n`;
33
+ customUniforms[key] = { value: new THREE.Vector3(...value) };
34
+ } else if (value.length === 4) {
35
+ customUniformsCode += `uniform vec4 ${key};\n`;
36
+ customUniforms[key] = { value: new THREE.Vector4(...value) };
37
+ }
38
+ } else {
39
+ customUniformsCode += `uniform float ${key};\n`;
40
+ customUniforms[key] = { value };
41
+ }
42
+ }
43
+ }
44
+
45
+ const declChunk = (hasTexture ? BoxChunk.declChunk : "") + "\n" + customUniformsCode;
20
46
  const baseUvCode = styles.isTraveler ? BoxChunk.uvChunk : "vec2 resultUv = vUv * uTextureRepeat + uTextureOffset;\n";
21
47
  const uvChunk = hasTexture ? baseUvCode + (hooks?.uvModifier || "") : "";
22
48
  const baseColorChunk = hasTexture ? BoxChunk.baseColorChunk : "";
@@ -71,7 +97,7 @@ export function createBoxMaterial(
71
97
  }
72
98
 
73
99
  const material = new THREE.ShaderMaterial({
74
- uniforms: uniforms,
100
+ uniforms: { ...uniforms, ...customUniforms },
75
101
  vertexShader: BoxShader.vertexShader,
76
102
  fragmentShader: fragmentShader,
77
103
  transparent: true,
@@ -119,6 +145,7 @@ export interface BoxUniformValues {
119
145
  borderOpacity?: number;
120
146
  texture?: THREE.Texture | null;
121
147
  backgroundImage?: string;
148
+ [key: string]: any;
122
149
  }
123
150
 
124
151
  export function setBoxUniforms(
@@ -244,7 +271,7 @@ export function setBoxUniforms(
244
271
  s.color.b,
245
272
  s.alpha,
246
273
  );
247
- console.log(s.color.r, s.color.g, s.color.b);
274
+ // console.log(s.color.r, s.color.g, s.color.b);
248
275
  material.uniforms.uGradientStops.value[i] = s.stop;
249
276
  } else {
250
277
  material.uniforms.uGradientColors.value[i].set(0, 0, 0, 0);
@@ -255,6 +282,43 @@ export function setBoxUniforms(
255
282
  material.uniforms.uGradientCount.value = 0;
256
283
  }
257
284
  }
285
+
286
+ // Update dynamic custom uniforms
287
+ for (const key of Object.keys(values)) {
288
+ if (
289
+ key !== "width" &&
290
+ key !== "height" &&
291
+ key !== "borderRadius" &&
292
+ key !== "borderWidth" &&
293
+ key !== "backgroundColor" &&
294
+ key !== "borderColor" &&
295
+ key !== "opacity" &&
296
+ key !== "bgOpacity" &&
297
+ key !== "borderOpacity" &&
298
+ key !== "texture" &&
299
+ key !== "backgroundImage"
300
+ ) {
301
+ if (material.uniforms[key] !== undefined) {
302
+ if (
303
+ material.uniforms[key].value !== undefined &&
304
+ material.uniforms[key].value !== null &&
305
+ typeof material.uniforms[key].value.set === "function"
306
+ ) {
307
+ if (Array.isArray(values[key])) {
308
+ material.uniforms[key].value.set(...values[key]);
309
+ } else if (values[key] !== undefined) {
310
+ if (values[key].copy) {
311
+ material.uniforms[key].value.copy(values[key]);
312
+ } else {
313
+ material.uniforms[key].value = values[key];
314
+ }
315
+ }
316
+ } else {
317
+ material.uniforms[key].value = values[key];
318
+ }
319
+ }
320
+ }
321
+ }
258
322
  }
259
323
 
260
324
  function setBorderRadius(
@@ -25,5 +25,6 @@ export interface BoxStyles {
25
25
  export interface ShaderHooks {
26
26
  uvModifier?: string;
27
27
  colorModifier?: string;
28
+ uniforms?: Record<string, any>;
28
29
  }
29
30