fuxi-topology 0.2.6 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/fuxi-topology.js +1934 -1933
- package/dist/fuxi-topology.umd.cjs +151 -151
- package/dist/scene/scene.d.ts +4 -2
- package/dist/topology.d.ts +0 -3
- package/package.json +1 -1
package/dist/fuxi-topology.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EventEmitter as le, Graphics as L, Sprite as gn, Texture as ne, Rectangle as Lt, Container as R, Point as Vr, MeshRope as Xr, TilingSprite as mn, TextStyle as qr, Text as vn, Assets as gi,
|
|
1
|
+
import { EventEmitter as le, Graphics as L, Sprite as gn, Texture as ne, Rectangle as Lt, Container as R, Point as Vr, MeshRope as Xr, TilingSprite as mn, TextStyle as qr, Text as vn, Assets as gi, BlurFilter as Jr, Filter as G, GlProgram as U, UniformGroup as H, ColorMatrixFilter as mi, Application as Kr } from "pixi.js";
|
|
2
2
|
import dt from "pathfinding";
|
|
3
3
|
import { zoom as Zr, ZoomTransform as Ut, zoomTransform as Qr, zoomIdentity as es } from "d3-zoom";
|
|
4
4
|
import { ZoomTransform as md } from "d3-zoom";
|
|
@@ -3027,712 +3027,710 @@ class Ja extends le {
|
|
|
3027
3027
|
this._looseGraphics.clear(), this._rootOrder = [], this.removeAllListeners();
|
|
3028
3028
|
}
|
|
3029
3029
|
}
|
|
3030
|
-
function
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
}
|
|
3041
|
-
|
|
3042
|
-
return typeof t.toDataURL == "function" ? t.toDataURL("image/png") : "";
|
|
3030
|
+
function bf(t, e) {
|
|
3031
|
+
const i = e?.strength ?? 4, n = e?.quality ?? 4;
|
|
3032
|
+
return {
|
|
3033
|
+
postProcessId: t,
|
|
3034
|
+
createFilter() {
|
|
3035
|
+
return new Jr({ strength: i, quality: n });
|
|
3036
|
+
},
|
|
3037
|
+
setOptions(r, s) {
|
|
3038
|
+
const o = r;
|
|
3039
|
+
s.strength !== void 0 && (o.strength = s.strength), s.quality !== void 0 && (o.quality = s.quality);
|
|
3040
|
+
}
|
|
3041
|
+
};
|
|
3043
3042
|
}
|
|
3044
|
-
|
|
3045
|
-
|
|
3043
|
+
const Ka = (
|
|
3044
|
+
/* glsl */
|
|
3045
|
+
`
|
|
3046
|
+
in vec2 aPosition;
|
|
3047
|
+
out vec2 vTextureCoord;
|
|
3048
|
+
|
|
3049
|
+
uniform vec4 uInputSize;
|
|
3050
|
+
uniform vec4 uOutputFrame;
|
|
3051
|
+
uniform vec4 uOutputTexture;
|
|
3052
|
+
|
|
3053
|
+
vec4 filterVertexPosition(void)
|
|
3054
|
+
{
|
|
3055
|
+
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
|
|
3056
|
+
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
|
|
3057
|
+
position.y = position.y * (2.0 * uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
|
|
3058
|
+
return vec4(position, 0.0, 1.0);
|
|
3046
3059
|
}
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3060
|
+
|
|
3061
|
+
vec2 filterTextureCoord(void)
|
|
3062
|
+
{
|
|
3063
|
+
return aPosition * (uOutputFrame.zw * uInputSize.zw);
|
|
3050
3064
|
}
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3065
|
+
|
|
3066
|
+
void main(void)
|
|
3067
|
+
{
|
|
3068
|
+
gl_Position = filterVertexPosition();
|
|
3069
|
+
vTextureCoord = filterTextureCoord();
|
|
3056
3070
|
}
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3071
|
+
`
|
|
3072
|
+
);
|
|
3073
|
+
function Za(t) {
|
|
3074
|
+
return (
|
|
3075
|
+
/* glsl */
|
|
3076
|
+
`
|
|
3077
|
+
precision highp float;
|
|
3078
|
+
|
|
3079
|
+
in vec2 vTextureCoord;
|
|
3080
|
+
out vec4 finalColor;
|
|
3081
|
+
|
|
3082
|
+
uniform sampler2D uTexture;
|
|
3083
|
+
uniform vec4 uInputSize;
|
|
3084
|
+
uniform float uThreshold;
|
|
3085
|
+
uniform float uIntensity;
|
|
3086
|
+
uniform float uRadius;
|
|
3087
|
+
|
|
3088
|
+
const int SAMPLES = ${t};
|
|
3089
|
+
const float FSAMPLES = ${t}.0;
|
|
3090
|
+
|
|
3091
|
+
void main(void)
|
|
3092
|
+
{
|
|
3093
|
+
vec4 original = texture(uTexture, vTextureCoord);
|
|
3094
|
+
|
|
3095
|
+
/* ---- 提取高亮区域并模糊 ---- */
|
|
3096
|
+
vec3 bloom = vec3(0.0);
|
|
3097
|
+
float totalWeight = 0.0;
|
|
3098
|
+
|
|
3099
|
+
for (int i = -SAMPLES; i <= SAMPLES; i++) {
|
|
3100
|
+
for (int j = -SAMPLES; j <= SAMPLES; j++) {
|
|
3101
|
+
vec2 offset = vec2(float(i), float(j)) * uRadius * uInputSize.zw;
|
|
3102
|
+
vec4 samp = texture(uTexture, vTextureCoord + offset);
|
|
3103
|
+
|
|
3104
|
+
// 亮度提取(Luminance)
|
|
3105
|
+
float lum = dot(samp.rgb, vec3(0.2126, 0.7152, 0.0722));
|
|
3106
|
+
float bright = max(0.0, lum - uThreshold);
|
|
3107
|
+
|
|
3108
|
+
// 高斯权重近似
|
|
3109
|
+
float dist = length(vec2(float(i), float(j)));
|
|
3110
|
+
float weight = exp(-dist * dist / (2.0 * FSAMPLES));
|
|
3111
|
+
|
|
3112
|
+
bloom += samp.rgb * bright * weight;
|
|
3113
|
+
totalWeight += weight;
|
|
3114
|
+
}
|
|
3067
3115
|
}
|
|
3068
|
-
|
|
3116
|
+
|
|
3117
|
+
bloom /= totalWeight;
|
|
3118
|
+
|
|
3119
|
+
/* ---- 叠加 ---- */
|
|
3120
|
+
vec3 result = original.rgb + bloom * uIntensity;
|
|
3121
|
+
|
|
3122
|
+
finalColor = vec4(result, original.a);
|
|
3069
3123
|
}
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3124
|
+
`
|
|
3125
|
+
);
|
|
3126
|
+
}
|
|
3127
|
+
class Qa extends G {
|
|
3128
|
+
constructor(e = {}) {
|
|
3129
|
+
const i = e.threshold ?? 0.5, n = e.intensity ?? 1, r = e.radius ?? 2, s = e.samples ?? 3, o = U.from({
|
|
3130
|
+
vertex: Ka,
|
|
3131
|
+
fragment: Za(s),
|
|
3132
|
+
name: "bloom-filter"
|
|
3133
|
+
});
|
|
3134
|
+
super({
|
|
3135
|
+
glProgram: o,
|
|
3136
|
+
resources: {
|
|
3137
|
+
bloomUniforms: new H({
|
|
3138
|
+
uThreshold: { value: i, type: "f32" },
|
|
3139
|
+
uIntensity: { value: n, type: "f32" },
|
|
3140
|
+
uRadius: { value: r, type: "f32" }
|
|
3141
|
+
})
|
|
3080
3142
|
}
|
|
3143
|
+
});
|
|
3081
3144
|
}
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
const { background: i = !0 } = e ?? {}, n = t.projectionContainer, r = n.skew.x, s = n.skew.y, o = n.scale.x, a = n.position.x, c = n.position.y, l = Math.ceil(t.app.screen.width), h = Math.ceil(t.app.screen.height), u = o * Math.cos(s), f = o * Math.sin(s), d = o * Math.sin(r), p = o * Math.cos(r), m = Math.cos(s), v = Math.sin(s), _ = Math.sin(r), x = Math.cos(r), w = m * x - v * _, S = x / w, b = -v / w, E = -_ / w, N = m / w, j = u * p - f * d, ee = [
|
|
3086
|
-
{ x: 0, y: 0 },
|
|
3087
|
-
{ x: l, y: 0 },
|
|
3088
|
-
{ x: 0, y: h },
|
|
3089
|
-
{ x: l, y: h }
|
|
3090
|
-
];
|
|
3091
|
-
let V = 1 / 0, X = 1 / 0, ue = -1 / 0, fe = -1 / 0;
|
|
3092
|
-
for (const { x: I, y: te } of ee) {
|
|
3093
|
-
const pe = I - a, ge = te - c, me = (p * pe - d * ge) / j, ve = (-f * pe + u * ge) / j;
|
|
3094
|
-
V = Math.min(V, me), X = Math.min(X, ve), ue = Math.max(ue, me), fe = Math.max(fe, ve);
|
|
3145
|
+
/* ---------- 便捷存取器 ---------- */
|
|
3146
|
+
get threshold() {
|
|
3147
|
+
return this.resources.bloomUniforms.uniforms.uThreshold;
|
|
3095
3148
|
}
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
y: Math.floor((X - q) / g) * g,
|
|
3099
|
-
width: Math.ceil((ue - V + q * 2) / g) * g,
|
|
3100
|
-
height: Math.ceil((fe - X + q * 2) / g) * g
|
|
3101
|
-
}, $ = await tc(t), O = [];
|
|
3102
|
-
O.push(
|
|
3103
|
-
'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"',
|
|
3104
|
-
` width="${l}" height="${h}" viewBox="0 0 ${l} ${h}">`
|
|
3105
|
-
), O.push(" <defs>");
|
|
3106
|
-
for (const [I, te] of $)
|
|
3107
|
-
te && O.push(
|
|
3108
|
-
` <symbol id="icon-${Ct(I)}" viewBox="0 0 100 100">`,
|
|
3109
|
-
` <image href="${te}" width="100" height="100" />`,
|
|
3110
|
-
" </symbol>"
|
|
3111
|
-
);
|
|
3112
|
-
if (O.push(" </defs>"), i) {
|
|
3113
|
-
const I = t.grid.options, te = Ze(I.bgColor ?? 0);
|
|
3114
|
-
O.push(` <rect width="${l}" height="${h}" fill="${te}" />`);
|
|
3149
|
+
set threshold(e) {
|
|
3150
|
+
this.resources.bloomUniforms.uniforms.uThreshold = e;
|
|
3115
3151
|
}
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
const I = await nc(t, de);
|
|
3119
|
-
I && O.push(I);
|
|
3152
|
+
get intensity() {
|
|
3153
|
+
return this.resources.bloomUniforms.uniforms.uIntensity;
|
|
3120
3154
|
}
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
for (const I of t.lines.getAll())
|
|
3124
|
-
O.push(sc(I));
|
|
3125
|
-
for (const I of t.nodes.getAll())
|
|
3126
|
-
O.push(oc(I.options, $, S, b, E, N));
|
|
3127
|
-
for (const I of t.texts.getAll())
|
|
3128
|
-
O.push(ac(I.options, S, b, E, N));
|
|
3129
|
-
return O.push(" </g>"), O.push("</svg>"), O.join(`
|
|
3130
|
-
`);
|
|
3131
|
-
}
|
|
3132
|
-
async function nc(t, e) {
|
|
3133
|
-
const n = t.grid.getGraphics().children[0];
|
|
3134
|
-
if (!n) return "";
|
|
3135
|
-
const r = t.grid.options.tileSize ?? 100, s = n.x, o = n.y, a = n.width, c = n.height, l = n.tilePosition?.x ?? 0, h = n.tilePosition?.y ?? 0;
|
|
3136
|
-
try {
|
|
3137
|
-
n.x = 0, n.y = 0, n.width = e.width, n.height = e.height, n.tilePosition && n.tilePosition.set(
|
|
3138
|
-
-e.x - r / 2,
|
|
3139
|
-
-e.y - r / 2
|
|
3140
|
-
);
|
|
3141
|
-
const u = n.parent;
|
|
3142
|
-
u && u.removeChild(n);
|
|
3143
|
-
const f = await t.app.renderer.extract.base64({
|
|
3144
|
-
target: n,
|
|
3145
|
-
format: "png"
|
|
3146
|
-
});
|
|
3147
|
-
return u && u.addChild(n), ` <image href="${f}" x="${e.x}" y="${e.y}" width="${e.width}" height="${e.height}" />`;
|
|
3148
|
-
} catch {
|
|
3149
|
-
return "";
|
|
3150
|
-
} finally {
|
|
3151
|
-
n.x = s, n.y = o, n.width = a, n.height = c, n.tilePosition && n.tilePosition.set(l, h);
|
|
3155
|
+
set intensity(e) {
|
|
3156
|
+
this.resources.bloomUniforms.uniforms.uIntensity = e;
|
|
3152
3157
|
}
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
const e = t.x * g - g / 2, i = t.y * g - g / 2, n = (t.width ?? 1) * g, r = (t.height ?? 1) * g, s = Ze(t.bgColor ?? 3447003), o = t.bgOpacity ?? 0.8, a = Ze(t.borderColor ?? 16777215), c = t.borderWidth ?? 2, l = t.borderOpacity ?? 1, h = t.borderRadius ?? 0, u = h > 0 ? ` rx="${h}" ry="${h}"` : "";
|
|
3156
|
-
return ` <rect x="${e}" y="${i}" width="${n}" height="${r}"${u} fill="${s}" fill-opacity="${o}" stroke="${a}" stroke-width="${c}" stroke-opacity="${l}" />`;
|
|
3157
|
-
}
|
|
3158
|
-
function sc(t) {
|
|
3159
|
-
const e = t.options, i = Ze(e.color ?? 4473958), n = e.width ?? 6, r = t.getPoints();
|
|
3160
|
-
let s;
|
|
3161
|
-
if (r && r.length >= 2)
|
|
3162
|
-
s = r.map((a) => `${a.x},${a.y}`).join(" ");
|
|
3163
|
-
else {
|
|
3164
|
-
const a = [];
|
|
3165
|
-
for (const c of e.anchor) {
|
|
3166
|
-
const l = t.resolveAnchorPosition(c);
|
|
3167
|
-
l && a.push({ x: l.x * g, y: l.y * g });
|
|
3168
|
-
}
|
|
3169
|
-
if (a.length < 2) return "";
|
|
3170
|
-
s = a.map((c) => `${c.x},${c.y}`).join(" ");
|
|
3158
|
+
get radius() {
|
|
3159
|
+
return this.resources.bloomUniforms.uniforms.uRadius;
|
|
3171
3160
|
}
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
}
|
|
3175
|
-
function oc(t, e, i, n, r, s) {
|
|
3176
|
-
const o = t.x * g, a = t.y * g, c = t.scale ?? 1, l = t.isFlat ?? !1, h = l ? 1 : t.scaleY ?? 1, u = t.offsetY ?? 0, f = t.icon;
|
|
3177
|
-
if (!(e.has(f) && e.get(f) !== "")) return "";
|
|
3178
|
-
const p = 100, m = -p / 2 * h + cr / 2 + u, v = [];
|
|
3179
|
-
if (l) {
|
|
3180
|
-
const _ = p * c, x = p * c, w = o - _ / 2, S = a + c * (m - p / 2);
|
|
3181
|
-
v.push(
|
|
3182
|
-
` <use href="#icon-${Ct(f)}" x="${w}" y="${S}" width="${_}" height="${x}" />`
|
|
3183
|
-
);
|
|
3184
|
-
} else {
|
|
3185
|
-
const _ = p * c, x = p * c * h, w = -_ / 2, S = c * h * m - x / 2, b = `matrix(${i},${n},${r},${s},0,0)`;
|
|
3186
|
-
v.push(` <g transform="translate(${o},${a})">`), v.push(` <g transform="${b}">`), v.push(
|
|
3187
|
-
` <use href="#icon-${Ct(f)}" x="${w}" y="${S}" width="${_}" height="${x}" />`
|
|
3188
|
-
), v.push(" </g>"), v.push(" </g>");
|
|
3161
|
+
set radius(e) {
|
|
3162
|
+
this.resources.bloomUniforms.uniforms.uRadius = e;
|
|
3189
3163
|
}
|
|
3190
|
-
return v.join(`
|
|
3191
|
-
`);
|
|
3192
|
-
}
|
|
3193
|
-
function ac(t, e, i, n, r) {
|
|
3194
|
-
const s = t.x * g, o = t.y * g, a = t.fontSize ?? 16, c = Ze(t.color ?? 16777215), l = t.fontWeight ?? "normal", h = t.fontFamily ?? "Arial", u = t.align ?? "center", f = t.position ?? "x", d = u === "left" ? "start" : u === "right" ? "end" : "middle", p = Ct(t.text), m = `text-anchor="${d}" fill="${c}" font-size="${a}" font-weight="${l}" font-family="${h}"`;
|
|
3195
|
-
if (f === "screen") {
|
|
3196
|
-
const v = `matrix(${e},${i},${n},${r},0,0)`;
|
|
3197
|
-
return [
|
|
3198
|
-
` <g transform="translate(${s},${o})">`,
|
|
3199
|
-
` <text transform="${v}" ${m}>${p}</text>`,
|
|
3200
|
-
" </g>"
|
|
3201
|
-
].join(`
|
|
3202
|
-
`);
|
|
3203
|
-
} else return f === "y" ? ` <text x="${s}" y="${o}" transform="rotate(-90,${s},${o})" ${m}>${p}</text>` : ` <text x="${s}" y="${o}" ${m}>${p}</text>`;
|
|
3204
3164
|
}
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
return
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3165
|
+
function Cf(t, e) {
|
|
3166
|
+
const i = e?.threshold ?? 0.5, n = e?.intensity ?? 1, r = e?.radius ?? 2, s = e?.samples ?? 3;
|
|
3167
|
+
return {
|
|
3168
|
+
postProcessId: t,
|
|
3169
|
+
createFilter() {
|
|
3170
|
+
return new Qa({ threshold: i, intensity: n, radius: r, samples: s });
|
|
3171
|
+
},
|
|
3172
|
+
setOptions(o, a) {
|
|
3173
|
+
const c = o;
|
|
3174
|
+
a.threshold !== void 0 && (c.threshold = a.threshold), a.intensity !== void 0 && (c.intensity = a.intensity), a.radius !== void 0 && (c.radius = a.radius);
|
|
3175
|
+
}
|
|
3176
|
+
};
|
|
3177
|
+
}
|
|
3178
|
+
function Ki(t, e) {
|
|
3179
|
+
const i = e.brightness ?? 1, n = e.contrast ?? 0, r = e.saturate ?? 0, s = e.hue ?? 0;
|
|
3180
|
+
t.reset(), i !== 1 && t.brightness(i, !0), n !== 0 && t.contrast(n, !0), r !== 0 && t.saturate(r, !0), s !== 0 && t.hue(s, !0);
|
|
3181
|
+
}
|
|
3182
|
+
function If(t, e) {
|
|
3183
|
+
const i = {
|
|
3184
|
+
brightness: e?.brightness ?? 1,
|
|
3185
|
+
contrast: e?.contrast ?? 0,
|
|
3186
|
+
saturate: e?.saturate ?? 0,
|
|
3187
|
+
hue: e?.hue ?? 0
|
|
3188
|
+
};
|
|
3189
|
+
return {
|
|
3190
|
+
postProcessId: t,
|
|
3191
|
+
createFilter() {
|
|
3192
|
+
const n = new mi();
|
|
3193
|
+
return Ki(n, i), n;
|
|
3194
|
+
},
|
|
3195
|
+
setOptions(n, r) {
|
|
3196
|
+
Object.assign(i, r), Ki(n, i);
|
|
3197
|
+
}
|
|
3198
|
+
};
|
|
3199
|
+
}
|
|
3200
|
+
const ec = (
|
|
3201
|
+
/* glsl */
|
|
3202
|
+
`
|
|
3203
|
+
in vec2 aPosition;
|
|
3204
|
+
out vec2 vTextureCoord;
|
|
3205
|
+
|
|
3206
|
+
uniform vec4 uInputSize;
|
|
3207
|
+
uniform vec4 uOutputFrame;
|
|
3208
|
+
uniform vec4 uOutputTexture;
|
|
3209
|
+
|
|
3210
|
+
vec4 filterVertexPosition(void)
|
|
3211
|
+
{
|
|
3212
|
+
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
|
|
3213
|
+
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
|
|
3214
|
+
position.y = position.y * (2.0 * uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
|
|
3215
|
+
return vec4(position, 0.0, 1.0);
|
|
3216
|
+
}
|
|
3217
|
+
|
|
3218
|
+
vec2 filterTextureCoord(void)
|
|
3219
|
+
{
|
|
3220
|
+
return aPosition * (uOutputFrame.zw * uInputSize.zw);
|
|
3221
|
+
}
|
|
3222
|
+
|
|
3223
|
+
void main(void)
|
|
3224
|
+
{
|
|
3225
|
+
gl_Position = filterVertexPosition();
|
|
3226
|
+
vTextureCoord = filterTextureCoord();
|
|
3227
|
+
}
|
|
3228
|
+
`
|
|
3229
|
+
), tc = (
|
|
3230
|
+
/* glsl */
|
|
3231
|
+
`
|
|
3232
|
+
precision highp float;
|
|
3233
|
+
|
|
3234
|
+
in vec2 vTextureCoord;
|
|
3235
|
+
out vec4 finalColor;
|
|
3236
|
+
|
|
3237
|
+
uniform sampler2D uTexture;
|
|
3238
|
+
uniform vec4 uInputSize;
|
|
3239
|
+
uniform vec4 uOutputFrame;
|
|
3240
|
+
uniform float uRadius;
|
|
3241
|
+
uniform float uSoftness;
|
|
3242
|
+
uniform float uIntensity;
|
|
3243
|
+
uniform vec3 uColor;
|
|
3244
|
+
|
|
3245
|
+
void main(void)
|
|
3246
|
+
{
|
|
3247
|
+
vec4 original = texture(uTexture, vTextureCoord);
|
|
3248
|
+
|
|
3249
|
+
// 将归一化 0.5 中心映射到实际纹理坐标空间
|
|
3250
|
+
vec2 texCenter = vec2(0.5) * (uOutputFrame.zw * uInputSize.zw);
|
|
3251
|
+
// 从中心到边缘的距离(归一化回 0~1 空间)
|
|
3252
|
+
vec2 center = (vTextureCoord - texCenter) / (uOutputFrame.zw * uInputSize.zw);
|
|
3253
|
+
float dist = length(center) * 2.0;
|
|
3254
|
+
|
|
3255
|
+
// smoothstep 在 radius 和 radius+softness 之间平滑过渡
|
|
3256
|
+
float vignetteFactor = smoothstep(uRadius, uRadius + uSoftness, dist) * uIntensity;
|
|
3257
|
+
|
|
3258
|
+
// 将边缘像素向暗角颜色混合
|
|
3259
|
+
finalColor = vec4(mix(original.rgb, uColor, vignetteFactor), original.a);
|
|
3260
|
+
}
|
|
3261
|
+
`
|
|
3262
|
+
);
|
|
3263
|
+
class ic extends G {
|
|
3264
|
+
constructor(e = {}) {
|
|
3265
|
+
const i = e.radius ?? 0.3, n = e.softness ?? 0.5, r = e.intensity ?? 0.8, s = e.color ?? [0, 0, 0], o = U.from({
|
|
3266
|
+
vertex: ec,
|
|
3267
|
+
fragment: tc,
|
|
3268
|
+
name: "vignette-filter"
|
|
3269
|
+
});
|
|
3270
|
+
super({
|
|
3271
|
+
glProgram: o,
|
|
3272
|
+
resources: {
|
|
3273
|
+
vignetteUniforms: new H({
|
|
3274
|
+
uRadius: { value: i, type: "f32" },
|
|
3275
|
+
uSoftness: { value: n, type: "f32" },
|
|
3276
|
+
uIntensity: { value: r, type: "f32" },
|
|
3277
|
+
uColor: { value: new Float32Array(s), type: "vec3<f32>" }
|
|
3278
|
+
})
|
|
3279
|
+
}
|
|
3280
|
+
});
|
|
3265
3281
|
}
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
* @param options 导出选项(padding / pixelRatio)
|
|
3270
|
-
* @returns PNG Blob
|
|
3271
|
-
*/
|
|
3272
|
-
async exportPNG(e) {
|
|
3273
|
-
return Qa(this, e);
|
|
3282
|
+
/* ---------- 便捷存取器 ---------- */
|
|
3283
|
+
get radius() {
|
|
3284
|
+
return this.resources.vignetteUniforms.uniforms.uRadius;
|
|
3274
3285
|
}
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
* @param options 导出选项(padding / background)
|
|
3278
|
-
* @returns SVG 文档字符串
|
|
3279
|
-
*/
|
|
3280
|
-
async exportSVG(e) {
|
|
3281
|
-
return ic(this, e);
|
|
3286
|
+
set radius(e) {
|
|
3287
|
+
this.resources.vignetteUniforms.uniforms.uRadius = e;
|
|
3282
3288
|
}
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
* @param filename 文件名,默认为 `{sceneId}.png`
|
|
3286
|
-
* @param options 导出选项
|
|
3287
|
-
*/
|
|
3288
|
-
async downloadPNG(e, i) {
|
|
3289
|
-
const n = await this.exportPNG(i);
|
|
3290
|
-
It(n, e ?? `${this.id}.png`);
|
|
3289
|
+
get softness() {
|
|
3290
|
+
return this.resources.vignetteUniforms.uniforms.uSoftness;
|
|
3291
3291
|
}
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
* @param filename 文件名,默认为 `{sceneId}.svg`
|
|
3295
|
-
* @param options 导出选项
|
|
3296
|
-
*/
|
|
3297
|
-
async downloadSVG(e, i) {
|
|
3298
|
-
const n = await this.exportSVG(i);
|
|
3299
|
-
It(n, e ?? `${this.id}.svg`);
|
|
3292
|
+
set softness(e) {
|
|
3293
|
+
this.resources.vignetteUniforms.uniforms.uSoftness = e;
|
|
3300
3294
|
}
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
* 注册外部相机处理器(通常由 ViewportPlugin 调用)。
|
|
3304
|
-
* 注册后,`setCamera` 将委托给该处理器而非直接更新 projectionContainer,
|
|
3305
|
-
* 从而允许插件实现动画过渡等特性。
|
|
3306
|
-
*
|
|
3307
|
-
* @param handler 处理函数,传 `undefined` 可清除
|
|
3308
|
-
*/
|
|
3309
|
-
setCameraHandler(e) {
|
|
3310
|
-
this._cameraHandler = e;
|
|
3295
|
+
get intensity() {
|
|
3296
|
+
return this.resources.vignetteUniforms.uniforms.uIntensity;
|
|
3311
3297
|
}
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
*/
|
|
3315
|
-
getCamera() {
|
|
3316
|
-
const e = this.projectionContainer;
|
|
3317
|
-
return { zoom: e.scale.x, x: e.position.x, y: e.position.y };
|
|
3298
|
+
set intensity(e) {
|
|
3299
|
+
this.resources.vignetteUniforms.uniforms.uIntensity = e;
|
|
3318
3300
|
}
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
* - 否则,直接更新 projectionContainer。
|
|
3323
|
-
*
|
|
3324
|
-
* 返回 Promise,在有动画过渡时可 `await` 等待完成。
|
|
3325
|
-
*
|
|
3326
|
-
* @param camera 部分相机参数,未传的字段保留当前值
|
|
3327
|
-
*/
|
|
3328
|
-
setCamera(e) {
|
|
3329
|
-
const i = this.projectionContainer, n = {
|
|
3330
|
-
zoom: e.zoom ?? i.scale.x,
|
|
3331
|
-
x: e.x ?? i.position.x,
|
|
3332
|
-
y: e.y ?? i.position.y
|
|
3333
|
-
};
|
|
3334
|
-
return this._cameraHandler ? Promise.resolve(this._cameraHandler(n)) : (this.applyCamera(n), Promise.resolve());
|
|
3301
|
+
get color() {
|
|
3302
|
+
const e = this.resources.vignetteUniforms.uniforms.uColor;
|
|
3303
|
+
return [e[0], e[1], e[2]];
|
|
3335
3304
|
}
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
* 也可被外部直接调用以跳过插件处理。
|
|
3340
|
-
*/
|
|
3341
|
-
applyCamera(e) {
|
|
3342
|
-
const i = this.projectionContainer, n = this.lastCameraState, r = e.x !== n.x || e.y !== n.y, s = e.zoom !== n.scale;
|
|
3343
|
-
i.scale.set(e.zoom), i.position.set(e.x, e.y), this._isActive && (this.lastCameraState = { x: i.x, y: i.y, scale: i.scale.x }, this.notifyCameraChange(r, s));
|
|
3305
|
+
set color(e) {
|
|
3306
|
+
const i = this.resources.vignetteUniforms.uniforms.uColor;
|
|
3307
|
+
i[0] = e[0], i[1] = e[1], i[2] = e[2];
|
|
3344
3308
|
}
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3309
|
+
}
|
|
3310
|
+
function Af(t, e) {
|
|
3311
|
+
const i = e?.radius ?? 0.3, n = e?.softness ?? 0.5, r = e?.intensity ?? 0.8, s = e?.color ?? [0, 0, 0];
|
|
3312
|
+
return {
|
|
3313
|
+
postProcessId: t,
|
|
3314
|
+
createFilter() {
|
|
3315
|
+
return new ic({ radius: i, softness: n, intensity: r, color: s });
|
|
3316
|
+
},
|
|
3317
|
+
setOptions(o, a) {
|
|
3318
|
+
const c = o;
|
|
3319
|
+
a.radius !== void 0 && (c.radius = a.radius), a.softness !== void 0 && (c.softness = a.softness), a.intensity !== void 0 && (c.intensity = a.intensity), a.color !== void 0 && (c.color = a.color);
|
|
3320
|
+
}
|
|
3321
|
+
};
|
|
3322
|
+
}
|
|
3323
|
+
const nc = (
|
|
3324
|
+
/* glsl */
|
|
3325
|
+
`
|
|
3326
|
+
in vec2 aPosition;
|
|
3327
|
+
out vec2 vTextureCoord;
|
|
3328
|
+
|
|
3329
|
+
uniform vec4 uInputSize;
|
|
3330
|
+
uniform vec4 uOutputFrame;
|
|
3331
|
+
uniform vec4 uOutputTexture;
|
|
3332
|
+
|
|
3333
|
+
vec4 filterVertexPosition(void)
|
|
3334
|
+
{
|
|
3335
|
+
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
|
|
3336
|
+
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
|
|
3337
|
+
position.y = position.y * (2.0 * uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
|
|
3338
|
+
return vec4(position, 0.0, 1.0);
|
|
3339
|
+
}
|
|
3340
|
+
|
|
3341
|
+
vec2 filterTextureCoord(void)
|
|
3342
|
+
{
|
|
3343
|
+
return aPosition * (uOutputFrame.zw * uInputSize.zw);
|
|
3344
|
+
}
|
|
3345
|
+
|
|
3346
|
+
void main(void)
|
|
3347
|
+
{
|
|
3348
|
+
gl_Position = filterVertexPosition();
|
|
3349
|
+
vTextureCoord = filterTextureCoord();
|
|
3350
|
+
}
|
|
3351
|
+
`
|
|
3352
|
+
), rc = (
|
|
3353
|
+
/* glsl */
|
|
3354
|
+
`
|
|
3355
|
+
precision highp float;
|
|
3356
|
+
|
|
3357
|
+
in vec2 vTextureCoord;
|
|
3358
|
+
out vec4 finalColor;
|
|
3359
|
+
|
|
3360
|
+
uniform sampler2D uTexture;
|
|
3361
|
+
uniform vec4 uInputSize;
|
|
3362
|
+
uniform float uPixelSize;
|
|
3363
|
+
|
|
3364
|
+
void main(void)
|
|
3365
|
+
{
|
|
3366
|
+
// 将纹理坐标对齐到像素块中心
|
|
3367
|
+
vec2 pixelCoord = vTextureCoord * uInputSize.xy;
|
|
3368
|
+
vec2 snapped = floor(pixelCoord / uPixelSize) * uPixelSize + uPixelSize * 0.5;
|
|
3369
|
+
vec2 uv = snapped * uInputSize.zw;
|
|
3370
|
+
|
|
3371
|
+
finalColor = texture(uTexture, uv);
|
|
3372
|
+
}
|
|
3373
|
+
`
|
|
3374
|
+
);
|
|
3375
|
+
class sc extends G {
|
|
3376
|
+
constructor(e = {}) {
|
|
3377
|
+
const i = e.pixelSize ?? 8, n = U.from({
|
|
3378
|
+
vertex: nc,
|
|
3379
|
+
fragment: rc,
|
|
3380
|
+
name: "pixelate-filter"
|
|
3381
|
+
});
|
|
3382
|
+
super({
|
|
3383
|
+
glProgram: n,
|
|
3384
|
+
resources: {
|
|
3385
|
+
pixelateUniforms: new H({
|
|
3386
|
+
uPixelSize: { value: i, type: "f32" }
|
|
3387
|
+
})
|
|
3388
|
+
}
|
|
3389
|
+
});
|
|
3354
3390
|
}
|
|
3355
|
-
|
|
3356
|
-
get
|
|
3357
|
-
return this.
|
|
3391
|
+
/* ---------- 便捷存取器 ---------- */
|
|
3392
|
+
get pixelSize() {
|
|
3393
|
+
return this.resources.pixelateUniforms.uniforms.uPixelSize;
|
|
3358
3394
|
}
|
|
3359
|
-
|
|
3360
|
-
this.
|
|
3395
|
+
set pixelSize(e) {
|
|
3396
|
+
this.resources.pixelateUniforms.uniforms.uPixelSize = e;
|
|
3361
3397
|
}
|
|
3362
|
-
|
|
3363
|
-
|
|
3398
|
+
}
|
|
3399
|
+
function Tf(t, e) {
|
|
3400
|
+
const i = e?.pixelSize ?? 8;
|
|
3401
|
+
return {
|
|
3402
|
+
postProcessId: t,
|
|
3403
|
+
createFilter() {
|
|
3404
|
+
return new sc({ pixelSize: i });
|
|
3405
|
+
},
|
|
3406
|
+
setOptions(n, r) {
|
|
3407
|
+
const s = n;
|
|
3408
|
+
r.pixelSize !== void 0 && (s.pixelSize = r.pixelSize);
|
|
3409
|
+
}
|
|
3410
|
+
};
|
|
3411
|
+
}
|
|
3412
|
+
const oc = (
|
|
3413
|
+
/* glsl */
|
|
3414
|
+
`
|
|
3415
|
+
in vec2 aPosition;
|
|
3416
|
+
out vec2 vTextureCoord;
|
|
3417
|
+
|
|
3418
|
+
uniform vec4 uInputSize;
|
|
3419
|
+
uniform vec4 uOutputFrame;
|
|
3420
|
+
uniform vec4 uOutputTexture;
|
|
3421
|
+
|
|
3422
|
+
vec4 filterVertexPosition(void)
|
|
3423
|
+
{
|
|
3424
|
+
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
|
|
3425
|
+
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
|
|
3426
|
+
position.y = position.y * (2.0 * uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
|
|
3427
|
+
return vec4(position, 0.0, 1.0);
|
|
3428
|
+
}
|
|
3429
|
+
|
|
3430
|
+
vec2 filterTextureCoord(void)
|
|
3431
|
+
{
|
|
3432
|
+
return aPosition * (uOutputFrame.zw * uInputSize.zw);
|
|
3433
|
+
}
|
|
3434
|
+
|
|
3435
|
+
void main(void)
|
|
3436
|
+
{
|
|
3437
|
+
gl_Position = filterVertexPosition();
|
|
3438
|
+
vTextureCoord = filterTextureCoord();
|
|
3439
|
+
}
|
|
3440
|
+
`
|
|
3441
|
+
), ac = (
|
|
3442
|
+
/* glsl */
|
|
3443
|
+
`
|
|
3444
|
+
precision highp float;
|
|
3445
|
+
|
|
3446
|
+
in vec2 vTextureCoord;
|
|
3447
|
+
out vec4 finalColor;
|
|
3448
|
+
|
|
3449
|
+
uniform sampler2D uTexture;
|
|
3450
|
+
uniform float uIntensity;
|
|
3451
|
+
uniform float uSeed;
|
|
3452
|
+
|
|
3453
|
+
// 伪随机噪声生成
|
|
3454
|
+
float random(vec2 co)
|
|
3455
|
+
{
|
|
3456
|
+
return fract(sin(dot(co, vec2(12.9898, 78.233))) * 43758.5453);
|
|
3457
|
+
}
|
|
3458
|
+
|
|
3459
|
+
void main(void)
|
|
3460
|
+
{
|
|
3461
|
+
vec4 original = texture(uTexture, vTextureCoord);
|
|
3462
|
+
|
|
3463
|
+
// 用坐标和种子生成噪声
|
|
3464
|
+
float noise = random(vTextureCoord + uSeed) * 2.0 - 1.0;
|
|
3465
|
+
|
|
3466
|
+
// 叠加噪声到 RGB 通道
|
|
3467
|
+
vec3 result = original.rgb + noise * uIntensity;
|
|
3468
|
+
|
|
3469
|
+
finalColor = vec4(clamp(result, 0.0, 1.0), original.a);
|
|
3470
|
+
}
|
|
3471
|
+
`
|
|
3472
|
+
);
|
|
3473
|
+
class cc extends G {
|
|
3474
|
+
constructor(e = {}) {
|
|
3475
|
+
const i = e.intensity ?? 0.15, n = e.seed ?? 0, r = U.from({
|
|
3476
|
+
vertex: oc,
|
|
3477
|
+
fragment: ac,
|
|
3478
|
+
name: "noise-filter"
|
|
3479
|
+
});
|
|
3480
|
+
super({
|
|
3481
|
+
glProgram: r,
|
|
3482
|
+
resources: {
|
|
3483
|
+
noiseUniforms: new H({
|
|
3484
|
+
uIntensity: { value: i, type: "f32" },
|
|
3485
|
+
uSeed: { value: n, type: "f32" }
|
|
3486
|
+
})
|
|
3487
|
+
}
|
|
3488
|
+
});
|
|
3364
3489
|
}
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
this.
|
|
3490
|
+
/* ---------- 便捷存取器 ---------- */
|
|
3491
|
+
get intensity() {
|
|
3492
|
+
return this.resources.noiseUniforms.uniforms.uIntensity;
|
|
3368
3493
|
}
|
|
3369
|
-
|
|
3370
|
-
this.
|
|
3494
|
+
set intensity(e) {
|
|
3495
|
+
this.resources.noiseUniforms.uniforms.uIntensity = e;
|
|
3371
3496
|
}
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
for (const a of this.sceneItems)
|
|
3375
|
-
a.onRender(e), a.tickStates(e);
|
|
3376
|
-
this.postprocess.update(e);
|
|
3377
|
-
const { x: i, y: n } = this.projectionContainer.position, r = this.projectionContainer.scale.x, s = i !== this.lastCameraState.x || n !== this.lastCameraState.y, o = r !== this.lastCameraState.scale;
|
|
3378
|
-
(s || o) && (this.lastCameraState = { x: i, y: n, scale: r }, this.notifyCameraChange(s, o));
|
|
3379
|
-
};
|
|
3380
|
-
/**
|
|
3381
|
-
* 通知所有 SceneItem 相机已变化,并向外发射相机事件。
|
|
3382
|
-
*
|
|
3383
|
-
* @param positionChanged 位置(x/y)是否改变;传 `false` 时不发射 `camera:move` 事件
|
|
3384
|
-
* @param zoomChanged 缩放是否改变;传 `false` 时不发射 `camera:zoom` 事件
|
|
3385
|
-
*
|
|
3386
|
-
* 两者均为 `false` 时仅通知 SceneItem(用于场景初始化),不发射任何相机事件。
|
|
3387
|
-
*/
|
|
3388
|
-
notifyCameraChange(e = !0, i = !0) {
|
|
3389
|
-
const n = this.getViewRect(), r = this.projectionContainer.scale.x;
|
|
3390
|
-
for (const o of this.sceneItems) o.onCameraChange(n, r);
|
|
3391
|
-
if (!e && !i) return;
|
|
3392
|
-
const s = {
|
|
3393
|
-
...this.getCamera(),
|
|
3394
|
-
positionChanged: e,
|
|
3395
|
-
zoomChanged: i
|
|
3396
|
-
};
|
|
3397
|
-
this.emit("camera:change", s), e && this.emit("camera:move", s), i && this.emit("camera:zoom", s);
|
|
3497
|
+
get seed() {
|
|
3498
|
+
return this.resources.noiseUniforms.uniforms.uSeed;
|
|
3398
3499
|
}
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
const q = ue - f, de = fe - d;
|
|
3402
|
-
return { x: m * q + _ * de, y: v * q + x * de };
|
|
3403
|
-
}, S = w(0, 0), b = w(e, 0), E = w(0, i), N = w(e, i), j = Math.min(S.x, b.x, E.x, N.x), ee = Math.min(S.y, b.y, E.y, N.y), V = Math.max(S.x, b.x, E.x, N.x), X = Math.max(S.y, b.y, E.y, N.y);
|
|
3404
|
-
return { x: j, y: ee, width: V - j, height: X - ee };
|
|
3500
|
+
set seed(e) {
|
|
3501
|
+
this.resources.noiseUniforms.uniforms.uSeed = e;
|
|
3405
3502
|
}
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
}
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3503
|
+
}
|
|
3504
|
+
function Of(t, e) {
|
|
3505
|
+
const i = e?.intensity ?? 0.15;
|
|
3506
|
+
let n = e?.animated ?? !0;
|
|
3507
|
+
return {
|
|
3508
|
+
postProcessId: t,
|
|
3509
|
+
createFilter() {
|
|
3510
|
+
return new cc({ intensity: i });
|
|
3511
|
+
},
|
|
3512
|
+
onUpdate(r, s) {
|
|
3513
|
+
n && (r.seed = Math.random());
|
|
3514
|
+
},
|
|
3515
|
+
setOptions(r, s) {
|
|
3516
|
+
const o = r;
|
|
3517
|
+
s.intensity !== void 0 && (o.intensity = s.intensity), s.animated !== void 0 && (n = s.animated);
|
|
3420
3518
|
}
|
|
3421
|
-
|
|
3422
|
-
a(c.options.x * 100, c.options.y * 100);
|
|
3423
|
-
for (const c of this.lines.getAll())
|
|
3424
|
-
for (const l of c.options.anchor) {
|
|
3425
|
-
const h = c.resolveAnchorPosition(l);
|
|
3426
|
-
h && a(h.x * 100, h.y * 100);
|
|
3427
|
-
}
|
|
3428
|
-
for (const c of this.fences.getAll()) {
|
|
3429
|
-
const l = c.options.x * 100, h = c.options.y * 100, u = c.options.direction ?? "+x", f = (c.options.length ?? 4) * 100;
|
|
3430
|
-
switch (a(l, h), u) {
|
|
3431
|
-
case "x":
|
|
3432
|
-
case "+x":
|
|
3433
|
-
a(l + f, h);
|
|
3434
|
-
break;
|
|
3435
|
-
case "-x":
|
|
3436
|
-
a(l - f, h);
|
|
3437
|
-
break;
|
|
3438
|
-
case "y":
|
|
3439
|
-
case "+y":
|
|
3440
|
-
a(l, h + f);
|
|
3441
|
-
break;
|
|
3442
|
-
case "-y":
|
|
3443
|
-
a(l, h - f);
|
|
3444
|
-
break;
|
|
3445
|
-
}
|
|
3446
|
-
}
|
|
3447
|
-
for (const c of this.waves.getAll()) {
|
|
3448
|
-
const l = (c.options.width ?? 4) * 100, h = (c.options.height ?? 4) * 100;
|
|
3449
|
-
a(c.options.x * 100 - l / 2, c.options.y * 100 - h / 2), a(c.options.x * 100 + l / 2, c.options.y * 100 + h / 2);
|
|
3450
|
-
}
|
|
3451
|
-
for (const c of this.images.getAll())
|
|
3452
|
-
a(c.options.x * 100, c.options.y * 100);
|
|
3453
|
-
return o ? { x: i, y: n, width: r - i, height: s - n } : null;
|
|
3454
|
-
}
|
|
3519
|
+
};
|
|
3455
3520
|
}
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3521
|
+
const lc = (
|
|
3522
|
+
/* glsl */
|
|
3523
|
+
`
|
|
3524
|
+
in vec2 aPosition;
|
|
3525
|
+
out vec2 vTextureCoord;
|
|
3526
|
+
|
|
3527
|
+
uniform vec4 uInputSize;
|
|
3528
|
+
uniform vec4 uOutputFrame;
|
|
3529
|
+
uniform vec4 uOutputTexture;
|
|
3530
|
+
|
|
3531
|
+
vec4 filterVertexPosition(void)
|
|
3532
|
+
{
|
|
3533
|
+
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
|
|
3534
|
+
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
|
|
3535
|
+
position.y = position.y * (2.0 * uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
|
|
3536
|
+
return vec4(position, 0.0, 1.0);
|
|
3537
|
+
}
|
|
3538
|
+
|
|
3539
|
+
vec2 filterTextureCoord(void)
|
|
3540
|
+
{
|
|
3541
|
+
return aPosition * (uOutputFrame.zw * uInputSize.zw);
|
|
3542
|
+
}
|
|
3543
|
+
|
|
3544
|
+
void main(void)
|
|
3545
|
+
{
|
|
3546
|
+
gl_Position = filterVertexPosition();
|
|
3547
|
+
vTextureCoord = filterTextureCoord();
|
|
3548
|
+
}
|
|
3549
|
+
`
|
|
3550
|
+
), hc = (
|
|
3551
|
+
/* glsl */
|
|
3552
|
+
`
|
|
3553
|
+
precision highp float;
|
|
3554
|
+
|
|
3555
|
+
in vec2 vTextureCoord;
|
|
3556
|
+
out vec4 finalColor;
|
|
3557
|
+
|
|
3558
|
+
uniform sampler2D uTexture;
|
|
3559
|
+
uniform vec4 uInputSize;
|
|
3560
|
+
uniform vec4 uOutputFrame;
|
|
3561
|
+
uniform float uOffset;
|
|
3562
|
+
uniform vec2 uDirection;
|
|
3563
|
+
|
|
3564
|
+
void main(void)
|
|
3565
|
+
{
|
|
3566
|
+
// 将归一化 0.5 中心映射到实际纹理坐标空间
|
|
3567
|
+
vec2 texCenter = vec2(0.5) * (uOutputFrame.zw * uInputSize.zw);
|
|
3568
|
+
// 从中心到当前像素的方向
|
|
3569
|
+
vec2 center = vTextureCoord - texCenter;
|
|
3570
|
+
vec2 dir = normalize(center) * uOffset * 0.01;
|
|
3571
|
+
|
|
3572
|
+
// 沿径向偏移采样 RGB 三通道
|
|
3573
|
+
float r = texture(uTexture, vTextureCoord + dir).r;
|
|
3574
|
+
float g = texture(uTexture, vTextureCoord).g;
|
|
3575
|
+
float b = texture(uTexture, vTextureCoord - dir).b;
|
|
3576
|
+
float a = texture(uTexture, vTextureCoord).a;
|
|
3577
|
+
|
|
3578
|
+
finalColor = vec4(r, g, b, a);
|
|
3579
|
+
}
|
|
3580
|
+
`
|
|
3581
|
+
);
|
|
3582
|
+
class uc extends G {
|
|
3583
|
+
constructor(e = {}) {
|
|
3584
|
+
const i = e.offset ?? 3, n = U.from({
|
|
3585
|
+
vertex: lc,
|
|
3586
|
+
fragment: hc,
|
|
3587
|
+
name: "chromatic-aberration-filter"
|
|
3588
|
+
});
|
|
3589
|
+
super({
|
|
3590
|
+
glProgram: n,
|
|
3591
|
+
resources: {
|
|
3592
|
+
chromaticUniforms: new H({
|
|
3593
|
+
uOffset: { value: i, type: "f32" },
|
|
3594
|
+
uDirection: { value: new Float32Array([1, 1]), type: "vec2<f32>" }
|
|
3595
|
+
})
|
|
3596
|
+
}
|
|
3597
|
+
});
|
|
3495
3598
|
}
|
|
3496
|
-
|
|
3599
|
+
/* ---------- 便捷存取器 ---------- */
|
|
3600
|
+
get offset() {
|
|
3601
|
+
return this.resources.chromaticUniforms.uniforms.uOffset;
|
|
3497
3602
|
}
|
|
3498
|
-
|
|
3603
|
+
set offset(e) {
|
|
3604
|
+
this.resources.chromaticUniforms.uniforms.uOffset = e;
|
|
3499
3605
|
}
|
|
3500
3606
|
}
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3607
|
+
function Pf(t, e) {
|
|
3608
|
+
const i = e?.offset ?? 3;
|
|
3609
|
+
return {
|
|
3610
|
+
postProcessId: t,
|
|
3611
|
+
createFilter() {
|
|
3612
|
+
return new uc({ offset: i });
|
|
3613
|
+
},
|
|
3614
|
+
setOptions(n, r) {
|
|
3615
|
+
const s = n;
|
|
3616
|
+
r.offset !== void 0 && (s.offset = r.offset);
|
|
3617
|
+
}
|
|
3618
|
+
};
|
|
3619
|
+
}
|
|
3620
|
+
const fc = (
|
|
3621
|
+
/* glsl */
|
|
3622
|
+
`
|
|
3623
|
+
in vec2 aPosition;
|
|
3624
|
+
out vec2 vTextureCoord;
|
|
3625
|
+
|
|
3626
|
+
uniform vec4 uInputSize;
|
|
3627
|
+
uniform vec4 uOutputFrame;
|
|
3628
|
+
uniform vec4 uOutputTexture;
|
|
3629
|
+
|
|
3630
|
+
vec4 filterVertexPosition(void)
|
|
3631
|
+
{
|
|
3632
|
+
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
|
|
3633
|
+
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
|
|
3634
|
+
position.y = position.y * (2.0 * uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
|
|
3635
|
+
return vec4(position, 0.0, 1.0);
|
|
3636
|
+
}
|
|
3637
|
+
|
|
3638
|
+
vec2 filterTextureCoord(void)
|
|
3639
|
+
{
|
|
3640
|
+
return aPosition * (uOutputFrame.zw * uInputSize.zw);
|
|
3641
|
+
}
|
|
3642
|
+
|
|
3643
|
+
void main(void)
|
|
3644
|
+
{
|
|
3645
|
+
gl_Position = filterVertexPosition();
|
|
3646
|
+
vTextureCoord = filterTextureCoord();
|
|
3647
|
+
}
|
|
3648
|
+
`
|
|
3649
|
+
), dc = (
|
|
3650
|
+
/* glsl */
|
|
3651
|
+
`
|
|
3652
|
+
precision highp float;
|
|
3653
|
+
|
|
3654
|
+
in vec2 vTextureCoord;
|
|
3655
|
+
out vec4 finalColor;
|
|
3656
|
+
|
|
3657
|
+
uniform sampler2D uTexture;
|
|
3658
|
+
uniform vec4 uInputSize;
|
|
3659
|
+
uniform float uLineWidth;
|
|
3660
|
+
uniform float uIntensity;
|
|
3661
|
+
uniform float uOffset;
|
|
3662
|
+
|
|
3663
|
+
void main(void)
|
|
3664
|
+
{
|
|
3665
|
+
vec4 original = texture(uTexture, vTextureCoord);
|
|
3666
|
+
|
|
3667
|
+
// 按像素行计算扫描线
|
|
3668
|
+
float y = vTextureCoord.y * uInputSize.y + uOffset;
|
|
3669
|
+
float scanline = step(0.5, fract(y / uLineWidth));
|
|
3670
|
+
|
|
3671
|
+
// 暗行降低亮度
|
|
3672
|
+
float factor = 1.0 - scanline * uIntensity;
|
|
3673
|
+
|
|
3674
|
+
finalColor = vec4(original.rgb * factor, original.a);
|
|
3675
|
+
}
|
|
3676
|
+
`
|
|
3677
|
+
);
|
|
3678
|
+
class pc extends G {
|
|
3679
|
+
constructor(e = {}) {
|
|
3680
|
+
const i = e.lineWidth ?? 2, n = e.intensity ?? 0.3, r = e.offset ?? 0, s = U.from({
|
|
3681
|
+
vertex: fc,
|
|
3682
|
+
fragment: dc,
|
|
3683
|
+
name: "scanlines-filter"
|
|
3684
|
+
});
|
|
3685
|
+
super({
|
|
3686
|
+
glProgram: s,
|
|
3687
|
+
resources: {
|
|
3688
|
+
scanlinesUniforms: new H({
|
|
3689
|
+
uLineWidth: { value: i, type: "f32" },
|
|
3690
|
+
uIntensity: { value: n, type: "f32" },
|
|
3691
|
+
uOffset: { value: r, type: "f32" }
|
|
3692
|
+
})
|
|
3693
|
+
}
|
|
3694
|
+
});
|
|
3504
3695
|
}
|
|
3505
|
-
|
|
3506
|
-
|
|
3696
|
+
/* ---------- 便捷存取器 ---------- */
|
|
3697
|
+
get lineWidth() {
|
|
3698
|
+
return this.resources.scanlinesUniforms.uniforms.uLineWidth;
|
|
3507
3699
|
}
|
|
3508
|
-
|
|
3509
|
-
this.
|
|
3700
|
+
set lineWidth(e) {
|
|
3701
|
+
this.resources.scanlinesUniforms.uniforms.uLineWidth = e;
|
|
3510
3702
|
}
|
|
3511
|
-
|
|
3512
|
-
|
|
3703
|
+
get intensity() {
|
|
3704
|
+
return this.resources.scanlinesUniforms.uniforms.uIntensity;
|
|
3513
3705
|
}
|
|
3514
|
-
|
|
3515
|
-
this.
|
|
3706
|
+
set intensity(e) {
|
|
3707
|
+
this.resources.scanlinesUniforms.uniforms.uIntensity = e;
|
|
3516
3708
|
}
|
|
3517
|
-
|
|
3518
|
-
|
|
3709
|
+
get offset() {
|
|
3710
|
+
return this.resources.scanlinesUniforms.uniforms.uOffset;
|
|
3519
3711
|
}
|
|
3520
|
-
|
|
3521
|
-
this.
|
|
3712
|
+
set offset(e) {
|
|
3713
|
+
this.resources.scanlinesUniforms.uniforms.uOffset = e;
|
|
3522
3714
|
}
|
|
3523
3715
|
}
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
_hoveredItemId = null;
|
|
3528
|
-
_hoveredItemType = null;
|
|
3529
|
-
get enabled() {
|
|
3530
|
-
return this._enabled;
|
|
3531
|
-
}
|
|
3532
|
-
set enabled(e) {
|
|
3533
|
-
this._enabled = e;
|
|
3534
|
-
}
|
|
3535
|
-
_handlers;
|
|
3536
|
-
onBindActiveScene(e) {
|
|
3537
|
-
const i = this.topology, n = i.app.stage, r = (c) => {
|
|
3538
|
-
let l = c.target;
|
|
3539
|
-
for (; l && l !== n; ) {
|
|
3540
|
-
const h = Ta(l);
|
|
3541
|
-
if (h) {
|
|
3542
|
-
const { itemType: u, itemId: f } = h;
|
|
3543
|
-
return { itemType: u, itemId: f };
|
|
3544
|
-
}
|
|
3545
|
-
l = l.parent;
|
|
3546
|
-
}
|
|
3547
|
-
return { itemType: null, itemId: null };
|
|
3548
|
-
}, s = (c) => {
|
|
3549
|
-
if (!this._enabled) return;
|
|
3550
|
-
const { itemType: l, itemId: h } = r(c);
|
|
3551
|
-
i.emit("item:pointerdown", { itemType: l, itemId: h, sceneId: e.id, event: c });
|
|
3552
|
-
}, o = (c) => {
|
|
3553
|
-
if (!this._enabled) return;
|
|
3554
|
-
const { itemType: l, itemId: h } = r(c);
|
|
3555
|
-
i.emit("item:pointerup", { itemType: l, itemId: h, sceneId: e.id, event: c });
|
|
3556
|
-
}, a = (c) => {
|
|
3557
|
-
if (!this._enabled) return;
|
|
3558
|
-
const { itemType: l, itemId: h } = r(c);
|
|
3559
|
-
(this._hoveredItemId !== h || this._hoveredItemType !== l) && (this._hoveredItemId !== null && this._hoveredItemType !== null && i.emit("item:pointerout", {
|
|
3560
|
-
itemType: this._hoveredItemType,
|
|
3561
|
-
itemId: this._hoveredItemId,
|
|
3562
|
-
sceneId: e.id,
|
|
3563
|
-
event: c
|
|
3564
|
-
}), h !== null && l !== null && i.emit("item:pointerover", { itemType: l, itemId: h, sceneId: e.id, event: c }), this._hoveredItemId = h, this._hoveredItemType = l);
|
|
3565
|
-
};
|
|
3566
|
-
n.on("pointerdown", s), n.on("pointerup", o), n.on("pointermove", a), this._handlers = { onPointerDown: s, onPointerUp: o, onPointerMove: a };
|
|
3567
|
-
}
|
|
3568
|
-
onUnbindActiveScene() {
|
|
3569
|
-
if (!this._handlers) return;
|
|
3570
|
-
const e = this.topology?.app.stage;
|
|
3571
|
-
e && (e.off("pointerdown", this._handlers.onPointerDown), e.off("pointerup", this._handlers.onPointerUp), e.off("pointermove", this._handlers.onPointerMove)), this._handlers = void 0, this._hoveredItemId = null, this._hoveredItemType = null;
|
|
3572
|
-
}
|
|
3573
|
-
}
|
|
3574
|
-
class lc extends le {
|
|
3575
|
-
icons = /* @__PURE__ */ new Map();
|
|
3576
|
-
textureCache = /* @__PURE__ */ new Map();
|
|
3577
|
-
loading = /* @__PURE__ */ new Map();
|
|
3578
|
-
/** 添加或批量添加图标 */
|
|
3579
|
-
add(e) {
|
|
3580
|
-
for (const i of Array.isArray(e) ? e : [e]) {
|
|
3581
|
-
const { id: n } = i, r = this.icons.has(n);
|
|
3582
|
-
this.icons.set(n, i), r ? (this.textureCache.delete(n), this.loading.delete(n), this.emit("icon:updated", i)) : this.emit("icon:added", i);
|
|
3583
|
-
}
|
|
3584
|
-
return this;
|
|
3585
|
-
}
|
|
3586
|
-
/** 删除图标(按 id) */
|
|
3587
|
-
remove(e) {
|
|
3588
|
-
return this.icons.delete(e) ? (this.textureCache.delete(e), this.loading.delete(e), this.emit("icon:removed", { id: e }), !0) : !1;
|
|
3589
|
-
}
|
|
3590
|
-
/** 获取图标 URL(按 id) */
|
|
3591
|
-
getUrl(e) {
|
|
3592
|
-
return this.icons.get(e)?.url;
|
|
3593
|
-
}
|
|
3594
|
-
/** 获取图标完整信息(按 id) */
|
|
3595
|
-
get(e) {
|
|
3596
|
-
return this.icons.get(e);
|
|
3597
|
-
}
|
|
3598
|
-
/** 是否已注册(按 id) */
|
|
3599
|
-
has(e) {
|
|
3600
|
-
return this.icons.has(e);
|
|
3601
|
-
}
|
|
3602
|
-
/** 获取所有图标 */
|
|
3603
|
-
getAll() {
|
|
3604
|
-
return [...this.icons.values()];
|
|
3605
|
-
}
|
|
3606
|
-
/**
|
|
3607
|
-
* 加载图标纹理,自动缓存。
|
|
3608
|
-
* 参数为图标 id;若 id 未注册则当作 URL 直接加载。
|
|
3609
|
-
*/
|
|
3610
|
-
async loadTexture(e) {
|
|
3611
|
-
const i = this.textureCache.get(e);
|
|
3612
|
-
if (i) return i;
|
|
3613
|
-
const n = this.loading.get(e);
|
|
3614
|
-
if (n) return n;
|
|
3615
|
-
const r = this.icons.get(e)?.url ?? e, s = gi.load(r).then((o) => (this.textureCache.set(e, o), this.loading.delete(e), o));
|
|
3616
|
-
return this.loading.set(e, s), s;
|
|
3617
|
-
}
|
|
3618
|
-
/** 清空所有图标和缓存 */
|
|
3619
|
-
clear() {
|
|
3620
|
-
this.icons.clear(), this.textureCache.clear(), this.loading.clear(), this.emit("icons:cleared");
|
|
3621
|
-
}
|
|
3622
|
-
/** 序列化 */
|
|
3623
|
-
toJSON() {
|
|
3624
|
-
return this.getAll();
|
|
3625
|
-
}
|
|
3626
|
-
/** 反序列化(追加模式) */
|
|
3627
|
-
fromJSON(e) {
|
|
3628
|
-
this.add(e);
|
|
3629
|
-
}
|
|
3630
|
-
/** 序列化为 YAML 字符串 */
|
|
3631
|
-
toYAML() {
|
|
3632
|
-
return be(this.toJSON());
|
|
3633
|
-
}
|
|
3634
|
-
/** 从 YAML 字符串反序列化(追加模式) */
|
|
3635
|
-
fromYAML(e) {
|
|
3636
|
-
this.fromJSON(Ce(e));
|
|
3637
|
-
}
|
|
3638
|
-
destroy() {
|
|
3639
|
-
this.clear(), this.removeAllListeners();
|
|
3640
|
-
}
|
|
3641
|
-
}
|
|
3642
|
-
const Wt = /* @__PURE__ */ new WeakMap();
|
|
3643
|
-
function bf(t, e, i) {
|
|
3644
|
-
const n = i?.frequency ?? 2, r = i?.minAlpha ?? 0.2, s = i?.maxAlpha ?? 1;
|
|
3645
|
-
return {
|
|
3646
|
-
stateId: t,
|
|
3647
|
-
type: e,
|
|
3648
|
-
onEnter(o) {
|
|
3649
|
-
Wt.set(o, { elapsed: 0 });
|
|
3650
|
-
},
|
|
3651
|
-
onLeave(o) {
|
|
3652
|
-
Wt.delete(o), o.getGraphics().alpha = 1;
|
|
3653
|
-
},
|
|
3654
|
-
onUpdate(o, a) {
|
|
3655
|
-
const c = Wt.get(o);
|
|
3656
|
-
if (!c) return;
|
|
3657
|
-
c.elapsed += a;
|
|
3658
|
-
const l = (Math.sin(c.elapsed * n * Math.PI * 2 / 1e3) + 1) / 2;
|
|
3659
|
-
o.getGraphics().alpha = r + l * (s - r);
|
|
3660
|
-
}
|
|
3661
|
-
};
|
|
3662
|
-
}
|
|
3663
|
-
const ot = /* @__PURE__ */ new WeakMap();
|
|
3664
|
-
function Cf(t, e, i) {
|
|
3665
|
-
const n = i?.frequency ?? 2, r = i?.height ?? 12;
|
|
3666
|
-
return {
|
|
3667
|
-
stateId: t,
|
|
3668
|
-
type: e,
|
|
3669
|
-
onEnter(s) {
|
|
3670
|
-
const o = s.getGraphics();
|
|
3671
|
-
ot.set(s, { elapsed: 0, origY: o.position.y, origX: o.position.x });
|
|
3672
|
-
},
|
|
3673
|
-
onLeave(s) {
|
|
3674
|
-
const o = ot.get(s);
|
|
3675
|
-
o && (s.getGraphics().position.y = o.origY, s.getGraphics().position.x = o.origX, ot.delete(s));
|
|
3676
|
-
},
|
|
3677
|
-
onUpdate(s, o) {
|
|
3678
|
-
const a = ot.get(s);
|
|
3679
|
-
if (!a) return;
|
|
3680
|
-
a.elapsed += o;
|
|
3681
|
-
const c = Math.abs(Math.sin(a.elapsed * n * Math.PI / 1e3));
|
|
3682
|
-
s.getGraphics().position.y = a.origY - r * c, s.getGraphics().position.x = a.origX - r * c;
|
|
3683
|
-
}
|
|
3684
|
-
};
|
|
3685
|
-
}
|
|
3686
|
-
const Ve = /* @__PURE__ */ new WeakMap();
|
|
3687
|
-
function Rt(t) {
|
|
3688
|
-
const e = t.getGraphics(), i = (Ve.get(e) ?? 0) + 1;
|
|
3689
|
-
if (Ve.set(e, i), i > 1) return;
|
|
3690
|
-
const n = e.getLocalBounds(), r = 100, s = 80, o = Math.min(n.x, -r) - s, a = Math.min(n.y, -r) - s, c = Math.max(n.x + n.width, r) + s, l = Math.max(n.y + n.height, r) + s;
|
|
3691
|
-
e.filterArea = new Lt(o, a, c - o, l - a);
|
|
3692
|
-
}
|
|
3693
|
-
function Dt(t) {
|
|
3694
|
-
const e = t.getGraphics(), i = (Ve.get(e) ?? 1) - 1;
|
|
3695
|
-
i <= 0 ? (Ve.delete(e), e.filterArea = void 0) : Ve.set(e, i);
|
|
3696
|
-
}
|
|
3697
|
-
const jt = /* @__PURE__ */ new WeakMap();
|
|
3698
|
-
function If(t, e, i) {
|
|
3699
|
-
const n = i?.brightness ?? 1.5;
|
|
3716
|
+
function Mf(t, e) {
|
|
3717
|
+
const i = e?.lineWidth ?? 2, n = e?.intensity ?? 0.3;
|
|
3718
|
+
let r = e?.animated ?? !1, s = e?.speed ?? 0.5, o = 0;
|
|
3700
3719
|
return {
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
const s = r.getGraphics(), o = new mi();
|
|
3705
|
-
o.brightness(n, !1), jt.set(r, o), Rt(r), s.filters = [...s.filters ?? [], o];
|
|
3720
|
+
postProcessId: t,
|
|
3721
|
+
createFilter() {
|
|
3722
|
+
return new pc({ lineWidth: i, intensity: n, offset: 0 });
|
|
3706
3723
|
},
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
if (s) {
|
|
3710
|
-
const o = r.getGraphics();
|
|
3711
|
-
o.filters = (o.filters ?? []).filter((a) => a !== s), Dt(r), jt.delete(r);
|
|
3712
|
-
}
|
|
3713
|
-
}
|
|
3714
|
-
};
|
|
3715
|
-
}
|
|
3716
|
-
const Vt = /* @__PURE__ */ new WeakMap();
|
|
3717
|
-
function Af(t, e, i) {
|
|
3718
|
-
const n = Math.max(0, Math.min(1, i?.brightness ?? 0.5));
|
|
3719
|
-
return {
|
|
3720
|
-
stateId: t,
|
|
3721
|
-
type: e,
|
|
3722
|
-
onEnter(r) {
|
|
3723
|
-
const s = r.getGraphics(), o = new mi();
|
|
3724
|
-
o.brightness(n, !1), Vt.set(r, o), Rt(r), s.filters = [...s.filters ?? [], o];
|
|
3724
|
+
onUpdate(a, c) {
|
|
3725
|
+
r && (o += s * c, a.offset = o);
|
|
3725
3726
|
},
|
|
3726
|
-
|
|
3727
|
-
const
|
|
3728
|
-
|
|
3729
|
-
const o = r.getGraphics();
|
|
3730
|
-
o.filters = (o.filters ?? []).filter((a) => a !== s), Dt(r), Vt.delete(r);
|
|
3731
|
-
}
|
|
3727
|
+
setOptions(a, c) {
|
|
3728
|
+
const l = a;
|
|
3729
|
+
c.lineWidth !== void 0 && (l.lineWidth = c.lineWidth), c.intensity !== void 0 && (l.intensity = c.intensity), c.animated !== void 0 && (r = c.animated), c.speed !== void 0 && (s = c.speed);
|
|
3732
3730
|
}
|
|
3733
3731
|
};
|
|
3734
3732
|
}
|
|
3735
|
-
const
|
|
3733
|
+
const gc = (
|
|
3736
3734
|
/* glsl */
|
|
3737
3735
|
`
|
|
3738
3736
|
in vec2 aPosition;
|
|
@@ -3761,12 +3759,9 @@ void main(void)
|
|
|
3761
3759
|
vTextureCoord = filterTextureCoord();
|
|
3762
3760
|
}
|
|
3763
3761
|
`
|
|
3764
|
-
)
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
return (
|
|
3768
|
-
/* glsl */
|
|
3769
|
-
`
|
|
3762
|
+
), mc = (
|
|
3763
|
+
/* glsl */
|
|
3764
|
+
`
|
|
3770
3765
|
precision highp float;
|
|
3771
3766
|
|
|
3772
3767
|
in vec2 vTextureCoord;
|
|
@@ -3774,150 +3769,110 @@ out vec4 finalColor;
|
|
|
3774
3769
|
|
|
3775
3770
|
uniform sampler2D uTexture;
|
|
3776
3771
|
uniform vec4 uInputSize;
|
|
3777
|
-
uniform
|
|
3778
|
-
uniform
|
|
3779
|
-
uniform
|
|
3772
|
+
uniform vec4 uOutputFrame;
|
|
3773
|
+
uniform vec2 uCenter;
|
|
3774
|
+
uniform float uIntensity;
|
|
3775
|
+
uniform float uDecay;
|
|
3776
|
+
uniform float uDensity;
|
|
3777
|
+
uniform float uWeight;
|
|
3780
3778
|
|
|
3781
|
-
const int
|
|
3782
|
-
const int DIST_STEPS = ${i};
|
|
3783
|
-
const float TOTAL = ${n}.0;
|
|
3784
|
-
const float PI2 = 6.28318530718;
|
|
3779
|
+
const int NUM_SAMPLES = 30;
|
|
3785
3780
|
|
|
3786
3781
|
void main(void)
|
|
3787
3782
|
{
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3783
|
+
vec2 texCoord = vTextureCoord;
|
|
3784
|
+
// 将归一化 0~1 的光源中心映射到实际纹理坐标空间
|
|
3785
|
+
vec2 center = uCenter * (uOutputFrame.zw * uInputSize.zw);
|
|
3786
|
+
vec2 deltaTexCoord = (texCoord - center) * (1.0 / float(NUM_SAMPLES)) * uDensity;
|
|
3792
3787
|
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
vec2 dir = vec2(cos(angle), sin(angle));
|
|
3788
|
+
vec4 color = texture(uTexture, texCoord);
|
|
3789
|
+
float illuminationDecay = 1.0;
|
|
3796
3790
|
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3791
|
+
for (int i = 0; i < NUM_SAMPLES; i++) {
|
|
3792
|
+
texCoord -= deltaTexCoord;
|
|
3793
|
+
vec4 samp = texture(uTexture, texCoord);
|
|
3794
|
+
samp *= illuminationDecay * uWeight;
|
|
3795
|
+
color += samp;
|
|
3796
|
+
illuminationDecay *= uDecay;
|
|
3802
3797
|
}
|
|
3803
3798
|
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
/* ---- 外发光:仅在原始像素透明处显示 ---- */
|
|
3807
|
-
float glowAlpha = clamp(totalAlpha * uOuterStrength * (1.0 - original.a), 0.0, 1.0);
|
|
3808
|
-
|
|
3809
|
-
/* ---- premultiplied-alpha 合成:original 在上,glow 在下 ---- */
|
|
3810
|
-
vec4 glow = vec4(uColor * glowAlpha, glowAlpha);
|
|
3811
|
-
finalColor = original + glow * (1.0 - original.a);
|
|
3799
|
+
vec4 original = texture(uTexture, vTextureCoord);
|
|
3800
|
+
finalColor = mix(original, color * uIntensity / float(NUM_SAMPLES), uIntensity);
|
|
3812
3801
|
}
|
|
3813
3802
|
`
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
class fc extends G {
|
|
3803
|
+
);
|
|
3804
|
+
class vc extends G {
|
|
3817
3805
|
constructor(e = {}) {
|
|
3818
|
-
const i = e.
|
|
3819
|
-
vertex:
|
|
3820
|
-
fragment:
|
|
3821
|
-
name: "
|
|
3806
|
+
const i = e.centerX ?? 0.5, n = e.centerY ?? 0.5, r = e.intensity ?? 0.3, s = e.decay ?? 0.96, o = e.density ?? 1, a = e.weight ?? 0.5, c = U.from({
|
|
3807
|
+
vertex: gc,
|
|
3808
|
+
fragment: mc,
|
|
3809
|
+
name: "god-rays-filter"
|
|
3822
3810
|
});
|
|
3823
3811
|
super({
|
|
3824
|
-
glProgram:
|
|
3812
|
+
glProgram: c,
|
|
3825
3813
|
resources: {
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
}
|
|
3814
|
+
godRaysUniforms: new H({
|
|
3815
|
+
uCenter: { value: new Float32Array([i, n]), type: "vec2<f32>" },
|
|
3816
|
+
uIntensity: { value: r, type: "f32" },
|
|
3817
|
+
uDecay: { value: s, type: "f32" },
|
|
3818
|
+
uDensity: { value: o, type: "f32" },
|
|
3819
|
+
uWeight: { value: a, type: "f32" }
|
|
3833
3820
|
})
|
|
3834
|
-
}
|
|
3835
|
-
padding: n + 5
|
|
3821
|
+
}
|
|
3836
3822
|
});
|
|
3837
3823
|
}
|
|
3838
3824
|
/* ---------- 便捷存取器 ---------- */
|
|
3839
|
-
get
|
|
3840
|
-
return this.resources.
|
|
3825
|
+
get centerX() {
|
|
3826
|
+
return this.resources.godRaysUniforms.uniforms.uCenter[0];
|
|
3841
3827
|
}
|
|
3842
|
-
set
|
|
3843
|
-
this.resources.
|
|
3828
|
+
set centerX(e) {
|
|
3829
|
+
this.resources.godRaysUniforms.uniforms.uCenter[0] = e;
|
|
3844
3830
|
}
|
|
3845
|
-
get
|
|
3846
|
-
return this.resources.
|
|
3831
|
+
get centerY() {
|
|
3832
|
+
return this.resources.godRaysUniforms.uniforms.uCenter[1];
|
|
3847
3833
|
}
|
|
3848
|
-
set
|
|
3849
|
-
this.resources.
|
|
3834
|
+
set centerY(e) {
|
|
3835
|
+
this.resources.godRaysUniforms.uniforms.uCenter[1] = e;
|
|
3850
3836
|
}
|
|
3851
|
-
get
|
|
3852
|
-
return this.resources.
|
|
3837
|
+
get intensity() {
|
|
3838
|
+
return this.resources.godRaysUniforms.uniforms.uIntensity;
|
|
3853
3839
|
}
|
|
3854
|
-
set
|
|
3855
|
-
|
|
3856
|
-
|
|
3840
|
+
set intensity(e) {
|
|
3841
|
+
this.resources.godRaysUniforms.uniforms.uIntensity = e;
|
|
3842
|
+
}
|
|
3843
|
+
get decay() {
|
|
3844
|
+
return this.resources.godRaysUniforms.uniforms.uDecay;
|
|
3845
|
+
}
|
|
3846
|
+
set decay(e) {
|
|
3847
|
+
this.resources.godRaysUniforms.uniforms.uDecay = e;
|
|
3848
|
+
}
|
|
3849
|
+
get density() {
|
|
3850
|
+
return this.resources.godRaysUniforms.uniforms.uDensity;
|
|
3851
|
+
}
|
|
3852
|
+
set density(e) {
|
|
3853
|
+
this.resources.godRaysUniforms.uniforms.uDensity = e;
|
|
3854
|
+
}
|
|
3855
|
+
get weight() {
|
|
3856
|
+
return this.resources.godRaysUniforms.uniforms.uWeight;
|
|
3857
|
+
}
|
|
3858
|
+
set weight(e) {
|
|
3859
|
+
this.resources.godRaysUniforms.uniforms.uWeight = e;
|
|
3857
3860
|
}
|
|
3858
3861
|
}
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
return [
|
|
3862
|
-
(t >> 16 & 255) / 255,
|
|
3863
|
-
(t >> 8 & 255) / 255,
|
|
3864
|
-
(t & 255) / 255
|
|
3865
|
-
];
|
|
3866
|
-
}
|
|
3867
|
-
function Tf(t, e, i) {
|
|
3868
|
-
const n = i?.color ?? 16776960, r = i?.distance ?? 10, [s, o] = i?.strength ?? [2, 6], a = i?.frequency ?? 1.5, c = i?.quality ?? 4, l = dc(n);
|
|
3869
|
-
return {
|
|
3870
|
-
stateId: t,
|
|
3871
|
-
type: e,
|
|
3872
|
-
onEnter(h) {
|
|
3873
|
-
const u = h.getGraphics(), f = new fc({
|
|
3874
|
-
color: l,
|
|
3875
|
-
distance: r,
|
|
3876
|
-
outerStrength: s,
|
|
3877
|
-
quality: c
|
|
3878
|
-
});
|
|
3879
|
-
at.set(h, { elapsed: 0, filter: f }), Rt(h), u.filters = [...u.filters ?? [], f];
|
|
3880
|
-
},
|
|
3881
|
-
onLeave(h) {
|
|
3882
|
-
const u = at.get(h);
|
|
3883
|
-
if (u) {
|
|
3884
|
-
const f = h.getGraphics();
|
|
3885
|
-
f.filters = (f.filters ?? []).filter((d) => d !== u.filter), Dt(h), at.delete(h);
|
|
3886
|
-
}
|
|
3887
|
-
},
|
|
3888
|
-
onUpdate(h, u) {
|
|
3889
|
-
const f = at.get(h);
|
|
3890
|
-
if (!f) return;
|
|
3891
|
-
f.elapsed += u;
|
|
3892
|
-
const d = (Math.sin(f.elapsed * a * Math.PI * 2 / 1e3) + 1) / 2;
|
|
3893
|
-
f.filter.outerStrength = s + d * (o - s);
|
|
3894
|
-
}
|
|
3895
|
-
};
|
|
3896
|
-
}
|
|
3897
|
-
const ct = /* @__PURE__ */ new WeakMap();
|
|
3898
|
-
function Of(t, e, i) {
|
|
3899
|
-
const n = i?.frequency ?? 1.2, r = i?.minScale ?? 0.92, s = i?.maxScale ?? 1.08;
|
|
3862
|
+
function Ef(t, e) {
|
|
3863
|
+
const i = e?.centerX ?? 0.5, n = e?.centerY ?? 0.5, r = e?.intensity ?? 0.3, s = e?.decay ?? 0.96, o = e?.density ?? 1, a = e?.weight ?? 0.5;
|
|
3900
3864
|
return {
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
const a = o.getGraphics();
|
|
3905
|
-
ct.set(o, { elapsed: 0, origScaleX: a.scale.x, origScaleY: a.scale.y });
|
|
3906
|
-
},
|
|
3907
|
-
onLeave(o) {
|
|
3908
|
-
const a = ct.get(o);
|
|
3909
|
-
a && (o.getGraphics().scale.set(a.origScaleX, a.origScaleY), ct.delete(o));
|
|
3865
|
+
postProcessId: t,
|
|
3866
|
+
createFilter() {
|
|
3867
|
+
return new vc({ centerX: i, centerY: n, intensity: r, decay: s, density: o, weight: a });
|
|
3910
3868
|
},
|
|
3911
|
-
|
|
3912
|
-
const
|
|
3913
|
-
|
|
3914
|
-
c.elapsed += a;
|
|
3915
|
-
const l = c.elapsed * n / 1e3 % 1, h = Math.pow(Math.abs(Math.sin(l * Math.PI)), 0.6), u = r + h * (s - r);
|
|
3916
|
-
o.getGraphics().scale.set(c.origScaleX * u, c.origScaleY * u);
|
|
3869
|
+
setOptions(c, l) {
|
|
3870
|
+
const h = c;
|
|
3871
|
+
l.centerX !== void 0 && (h.centerX = l.centerX), l.centerY !== void 0 && (h.centerY = l.centerY), l.intensity !== void 0 && (h.intensity = l.intensity), l.decay !== void 0 && (h.decay = l.decay), l.density !== void 0 && (h.density = l.density), l.weight !== void 0 && (h.weight = l.weight);
|
|
3917
3872
|
}
|
|
3918
3873
|
};
|
|
3919
3874
|
}
|
|
3920
|
-
const
|
|
3875
|
+
const xc = (
|
|
3921
3876
|
/* glsl */
|
|
3922
3877
|
`
|
|
3923
3878
|
in vec2 aPosition;
|
|
@@ -3946,7 +3901,7 @@ void main(void)
|
|
|
3946
3901
|
vTextureCoord = filterTextureCoord();
|
|
3947
3902
|
}
|
|
3948
3903
|
`
|
|
3949
|
-
),
|
|
3904
|
+
), yc = (
|
|
3950
3905
|
/* glsl */
|
|
3951
3906
|
`
|
|
3952
3907
|
precision highp float;
|
|
@@ -3955,224 +3910,76 @@ in vec2 vTextureCoord;
|
|
|
3955
3910
|
out vec4 finalColor;
|
|
3956
3911
|
|
|
3957
3912
|
uniform sampler2D uTexture;
|
|
3958
|
-
uniform float
|
|
3959
|
-
uniform float uWidth; // 光带宽度(投影轴空间)
|
|
3960
|
-
uniform float uIntensity; // 白光峰值强度 0-1
|
|
3961
|
-
uniform float uCosA; // cos(angle)
|
|
3962
|
-
uniform float uSinA; // sin(angle)
|
|
3913
|
+
uniform float uAmount;
|
|
3963
3914
|
|
|
3964
3915
|
void main(void)
|
|
3965
3916
|
{
|
|
3966
3917
|
vec4 original = texture(uTexture, vTextureCoord);
|
|
3967
3918
|
|
|
3968
|
-
//
|
|
3969
|
-
float
|
|
3970
|
-
|
|
3971
|
-
// 计算到光带中心的距离,smooth 衰减
|
|
3972
|
-
float dist = abs(pos - uPhase);
|
|
3973
|
-
float halfW = uWidth * 0.5;
|
|
3974
|
-
float t = 1.0 - smoothstep(0.0, halfW, dist);
|
|
3919
|
+
// Rec.709 亮度系数
|
|
3920
|
+
float lum = dot(original.rgb, vec3(0.2126, 0.7152, 0.0722));
|
|
3921
|
+
vec3 gray = vec3(lum);
|
|
3975
3922
|
|
|
3976
|
-
//
|
|
3977
|
-
|
|
3978
|
-
vec3 newRgb = min(original.rgb + vec3(add), vec3(original.a));
|
|
3923
|
+
// 按 amount 在原色和灰色之间插值
|
|
3924
|
+
vec3 result = mix(original.rgb, gray, uAmount);
|
|
3979
3925
|
|
|
3980
|
-
finalColor = vec4(
|
|
3926
|
+
finalColor = vec4(result, original.a);
|
|
3981
3927
|
}
|
|
3982
3928
|
`
|
|
3983
3929
|
);
|
|
3984
|
-
class
|
|
3985
|
-
_angle;
|
|
3930
|
+
class _c extends G {
|
|
3986
3931
|
constructor(e = {}) {
|
|
3987
|
-
const i = e.
|
|
3988
|
-
vertex:
|
|
3989
|
-
fragment:
|
|
3990
|
-
name: "
|
|
3932
|
+
const i = e.amount ?? 1, n = U.from({
|
|
3933
|
+
vertex: xc,
|
|
3934
|
+
fragment: yc,
|
|
3935
|
+
name: "grayscale-filter"
|
|
3991
3936
|
});
|
|
3992
3937
|
super({
|
|
3993
|
-
glProgram:
|
|
3938
|
+
glProgram: n,
|
|
3994
3939
|
resources: {
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
uWidth: { value: i, type: "f32" },
|
|
3998
|
-
uIntensity: { value: n, type: "f32" },
|
|
3999
|
-
uCosA: { value: Math.cos(r), type: "f32" },
|
|
4000
|
-
uSinA: { value: Math.sin(r), type: "f32" }
|
|
3940
|
+
grayscaleUniforms: new H({
|
|
3941
|
+
uAmount: { value: i, type: "f32" }
|
|
4001
3942
|
})
|
|
4002
3943
|
}
|
|
4003
|
-
})
|
|
3944
|
+
});
|
|
4004
3945
|
}
|
|
4005
3946
|
/* ---------- 便捷存取器 ---------- */
|
|
4006
|
-
get
|
|
4007
|
-
return this.resources.
|
|
4008
|
-
}
|
|
4009
|
-
set phase(e) {
|
|
4010
|
-
this.resources.shimmerUniforms.uniforms.uPhase = e;
|
|
4011
|
-
}
|
|
4012
|
-
get width() {
|
|
4013
|
-
return this.resources.shimmerUniforms.uniforms.uWidth;
|
|
4014
|
-
}
|
|
4015
|
-
set width(e) {
|
|
4016
|
-
this.resources.shimmerUniforms.uniforms.uWidth = e;
|
|
4017
|
-
}
|
|
4018
|
-
get intensity() {
|
|
4019
|
-
return this.resources.shimmerUniforms.uniforms.uIntensity;
|
|
4020
|
-
}
|
|
4021
|
-
set intensity(e) {
|
|
4022
|
-
this.resources.shimmerUniforms.uniforms.uIntensity = e;
|
|
4023
|
-
}
|
|
4024
|
-
get angle() {
|
|
4025
|
-
return this._angle;
|
|
3947
|
+
get amount() {
|
|
3948
|
+
return this.resources.grayscaleUniforms.uniforms.uAmount;
|
|
4026
3949
|
}
|
|
4027
|
-
set
|
|
4028
|
-
this.
|
|
3950
|
+
set amount(e) {
|
|
3951
|
+
this.resources.grayscaleUniforms.uniforms.uAmount = e;
|
|
4029
3952
|
}
|
|
4030
3953
|
}
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
const n = i?.frequency ?? 0.8, r = i?.width ?? 0.35, s = i?.intensity ?? 0.6, o = i?.angle ?? Math.PI / 6;
|
|
3954
|
+
function Lf(t, e) {
|
|
3955
|
+
const i = e?.amount ?? 1;
|
|
4034
3956
|
return {
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
const c = new mc({ width: r, intensity: s, angle: o }), l = a.getGraphics();
|
|
4039
|
-
Rt(a), l.filters = [...l.filters ?? [], c];
|
|
4040
|
-
const h = Math.abs(Math.cos(o)) + Math.abs(Math.sin(o));
|
|
4041
|
-
lt.set(a, { elapsed: 0, filter: c, maxProj: h });
|
|
4042
|
-
},
|
|
4043
|
-
onLeave(a) {
|
|
4044
|
-
const c = lt.get(a);
|
|
4045
|
-
if (c) {
|
|
4046
|
-
const l = a.getGraphics();
|
|
4047
|
-
l.filters = (l.filters ?? []).filter((h) => h !== c.filter), Dt(a), lt.delete(a);
|
|
4048
|
-
}
|
|
3957
|
+
postProcessId: t,
|
|
3958
|
+
createFilter() {
|
|
3959
|
+
return new _c({ amount: i });
|
|
4049
3960
|
},
|
|
4050
|
-
|
|
4051
|
-
const
|
|
4052
|
-
|
|
4053
|
-
l.elapsed += c;
|
|
4054
|
-
const h = l.elapsed * n / 1e3 % 1, u = r * 0.5, f = l.maxProj + r;
|
|
4055
|
-
l.filter.phase = h * f - u;
|
|
3961
|
+
setOptions(n, r) {
|
|
3962
|
+
const s = n;
|
|
3963
|
+
r.amount !== void 0 && (s.amount = r.amount);
|
|
4056
3964
|
}
|
|
4057
3965
|
};
|
|
4058
3966
|
}
|
|
4059
|
-
const
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
class vc extends le {
|
|
4076
|
-
states = /* @__PURE__ */ new Map();
|
|
4077
|
-
/** stateId → 该状态下所有的插件定义 */
|
|
4078
|
-
plugins = /* @__PURE__ */ new Map();
|
|
4079
|
-
/** 添加或批量添加状态 */
|
|
4080
|
-
add(e) {
|
|
4081
|
-
for (const i of Array.isArray(e) ? e : [e]) {
|
|
4082
|
-
const n = this.states.has(i.id);
|
|
4083
|
-
this.states.set(i.id, i), this.emit(n ? "state:updated" : "state:added", i);
|
|
4084
|
-
}
|
|
4085
|
-
return this;
|
|
4086
|
-
}
|
|
4087
|
-
/** 删除状态(同时清除关联的插件) */
|
|
4088
|
-
remove(e) {
|
|
4089
|
-
return this.states.delete(e) ? (this.plugins.delete(e), this.emit("state:removed", { id: e }), !0) : !1;
|
|
4090
|
-
}
|
|
4091
|
-
get(e) {
|
|
4092
|
-
return this.states.get(e);
|
|
4093
|
-
}
|
|
4094
|
-
has(e) {
|
|
4095
|
-
return this.states.has(e);
|
|
4096
|
-
}
|
|
4097
|
-
getAll() {
|
|
4098
|
-
return [...this.states.values()];
|
|
4099
|
-
}
|
|
4100
|
-
clear() {
|
|
4101
|
-
this.states.clear(), this.plugins.clear(), this.emit("states:cleared");
|
|
4102
|
-
}
|
|
4103
|
-
/** 注册状态插件 */
|
|
4104
|
-
registerPlugin(e) {
|
|
4105
|
-
const i = this.plugins.get(e.stateId) ?? [];
|
|
4106
|
-
return i.push(e), this.plugins.set(e.stateId, i), this;
|
|
4107
|
-
}
|
|
4108
|
-
/** 注销指定 stateId + type 的所有插件 */
|
|
4109
|
-
unregisterPlugin(e, i) {
|
|
4110
|
-
const n = this.plugins.get(e);
|
|
4111
|
-
if (n) {
|
|
4112
|
-
const r = n.filter((s) => s.type !== i);
|
|
4113
|
-
r.length ? this.plugins.set(e, r) : this.plugins.delete(e);
|
|
4114
|
-
}
|
|
4115
|
-
return this;
|
|
4116
|
-
}
|
|
4117
|
-
/** 获取匹配 stateId + type 的插件列表 */
|
|
4118
|
-
getPlugins(e, i) {
|
|
4119
|
-
return (this.plugins.get(e) ?? []).filter((n) => n.type === i);
|
|
4120
|
-
}
|
|
4121
|
-
/** 获取状态权重,未定义时为 0 */
|
|
4122
|
-
getWeight(e) {
|
|
4123
|
-
return this.states.get(e)?.weight ?? 0;
|
|
4124
|
-
}
|
|
4125
|
-
/** 按权重升序排列 stateId 列表 */
|
|
4126
|
-
sortByWeight(e) {
|
|
4127
|
-
return [...e].sort((i, n) => this.getWeight(i) - this.getWeight(n));
|
|
4128
|
-
}
|
|
4129
|
-
/** 序列化(仅元数据,插件为运行时代码不参与序列化) */
|
|
4130
|
-
toJSON() {
|
|
4131
|
-
return this.getAll();
|
|
4132
|
-
}
|
|
4133
|
-
/** 反序列化(追加模式) */
|
|
4134
|
-
fromJSON(e) {
|
|
4135
|
-
this.add(e);
|
|
4136
|
-
}
|
|
4137
|
-
toYAML() {
|
|
4138
|
-
return be(this.toJSON());
|
|
4139
|
-
}
|
|
4140
|
-
fromYAML(e) {
|
|
4141
|
-
this.fromJSON(Ce(e));
|
|
4142
|
-
}
|
|
4143
|
-
destroy() {
|
|
4144
|
-
this.clear(), this.removeAllListeners();
|
|
4145
|
-
}
|
|
4146
|
-
}
|
|
4147
|
-
function Ef(t, e) {
|
|
4148
|
-
const i = e?.strength ?? 4, n = e?.quality ?? 4;
|
|
4149
|
-
return {
|
|
4150
|
-
postProcessId: t,
|
|
4151
|
-
createFilter() {
|
|
4152
|
-
return new Jr({ strength: i, quality: n });
|
|
4153
|
-
},
|
|
4154
|
-
setOptions(r, s) {
|
|
4155
|
-
const o = r;
|
|
4156
|
-
s.strength !== void 0 && (o.strength = s.strength), s.quality !== void 0 && (o.quality = s.quality);
|
|
4157
|
-
}
|
|
4158
|
-
};
|
|
4159
|
-
}
|
|
4160
|
-
const xc = (
|
|
4161
|
-
/* glsl */
|
|
4162
|
-
`
|
|
4163
|
-
in vec2 aPosition;
|
|
4164
|
-
out vec2 vTextureCoord;
|
|
4165
|
-
|
|
4166
|
-
uniform vec4 uInputSize;
|
|
4167
|
-
uniform vec4 uOutputFrame;
|
|
4168
|
-
uniform vec4 uOutputTexture;
|
|
4169
|
-
|
|
4170
|
-
vec4 filterVertexPosition(void)
|
|
4171
|
-
{
|
|
4172
|
-
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
|
|
4173
|
-
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
|
|
4174
|
-
position.y = position.y * (2.0 * uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
|
|
4175
|
-
return vec4(position, 0.0, 1.0);
|
|
3967
|
+
const wc = (
|
|
3968
|
+
/* glsl */
|
|
3969
|
+
`
|
|
3970
|
+
in vec2 aPosition;
|
|
3971
|
+
out vec2 vTextureCoord;
|
|
3972
|
+
|
|
3973
|
+
uniform vec4 uInputSize;
|
|
3974
|
+
uniform vec4 uOutputFrame;
|
|
3975
|
+
uniform vec4 uOutputTexture;
|
|
3976
|
+
|
|
3977
|
+
vec4 filterVertexPosition(void)
|
|
3978
|
+
{
|
|
3979
|
+
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
|
|
3980
|
+
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
|
|
3981
|
+
position.y = position.y * (2.0 * uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
|
|
3982
|
+
return vec4(position, 0.0, 1.0);
|
|
4176
3983
|
}
|
|
4177
3984
|
|
|
4178
3985
|
vec2 filterTextureCoord(void)
|
|
@@ -4186,11 +3993,9 @@ void main(void)
|
|
|
4186
3993
|
vTextureCoord = filterTextureCoord();
|
|
4187
3994
|
}
|
|
4188
3995
|
`
|
|
4189
|
-
)
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
/* glsl */
|
|
4193
|
-
`
|
|
3996
|
+
), Sc = (
|
|
3997
|
+
/* glsl */
|
|
3998
|
+
`
|
|
4194
3999
|
precision highp float;
|
|
4195
4000
|
|
|
4196
4001
|
in vec2 vTextureCoord;
|
|
@@ -4198,123 +4003,68 @@ out vec4 finalColor;
|
|
|
4198
4003
|
|
|
4199
4004
|
uniform sampler2D uTexture;
|
|
4200
4005
|
uniform vec4 uInputSize;
|
|
4201
|
-
uniform float
|
|
4202
|
-
uniform float uIntensity;
|
|
4203
|
-
uniform float uRadius;
|
|
4204
|
-
|
|
4205
|
-
const int SAMPLES = ${t};
|
|
4206
|
-
const float FSAMPLES = ${t}.0;
|
|
4006
|
+
uniform float uStrength;
|
|
4207
4007
|
|
|
4208
4008
|
void main(void)
|
|
4209
4009
|
{
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
/* ---- 提取高亮区域并模糊 ---- */
|
|
4213
|
-
vec3 bloom = vec3(0.0);
|
|
4214
|
-
float totalWeight = 0.0;
|
|
4215
|
-
|
|
4216
|
-
for (int i = -SAMPLES; i <= SAMPLES; i++) {
|
|
4217
|
-
for (int j = -SAMPLES; j <= SAMPLES; j++) {
|
|
4218
|
-
vec2 offset = vec2(float(i), float(j)) * uRadius * uInputSize.zw;
|
|
4219
|
-
vec4 samp = texture(uTexture, vTextureCoord + offset);
|
|
4220
|
-
|
|
4221
|
-
// 亮度提取(Luminance)
|
|
4222
|
-
float lum = dot(samp.rgb, vec3(0.2126, 0.7152, 0.0722));
|
|
4223
|
-
float bright = max(0.0, lum - uThreshold);
|
|
4224
|
-
|
|
4225
|
-
// 高斯权重近似
|
|
4226
|
-
float dist = length(vec2(float(i), float(j)));
|
|
4227
|
-
float weight = exp(-dist * dist / (2.0 * FSAMPLES));
|
|
4010
|
+
vec2 step = uInputSize.zw;
|
|
4228
4011
|
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4012
|
+
// 采样 3×3 邻域
|
|
4013
|
+
vec4 center = texture(uTexture, vTextureCoord);
|
|
4014
|
+
vec4 top = texture(uTexture, vTextureCoord + vec2( 0.0, -step.y));
|
|
4015
|
+
vec4 bottom = texture(uTexture, vTextureCoord + vec2( 0.0, step.y));
|
|
4016
|
+
vec4 left = texture(uTexture, vTextureCoord + vec2(-step.x, 0.0));
|
|
4017
|
+
vec4 right = texture(uTexture, vTextureCoord + vec2( step.x, 0.0));
|
|
4233
4018
|
|
|
4234
|
-
|
|
4019
|
+
// 拉普拉斯卷积核: [-1, -1, -1; -1, 8, -1; -1, -1, -1] 的简化版
|
|
4020
|
+
// 仅取上下左右 4 邻域: [0,-1,0; -1,4,-1; 0,-1,0]
|
|
4021
|
+
vec4 edge = center * 4.0 - top - bottom - left - right;
|
|
4235
4022
|
|
|
4236
|
-
|
|
4237
|
-
|
|
4023
|
+
// 按强度叠加锐化
|
|
4024
|
+
vec4 result = center + edge * uStrength;
|
|
4238
4025
|
|
|
4239
|
-
finalColor = vec4(result,
|
|
4026
|
+
finalColor = vec4(clamp(result.rgb, 0.0, 1.0), center.a);
|
|
4240
4027
|
}
|
|
4241
4028
|
`
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
class _c extends G {
|
|
4029
|
+
);
|
|
4030
|
+
class bc extends G {
|
|
4245
4031
|
constructor(e = {}) {
|
|
4246
|
-
const i = e.
|
|
4247
|
-
vertex:
|
|
4248
|
-
fragment:
|
|
4249
|
-
name: "
|
|
4032
|
+
const i = e.strength ?? 0.5, n = U.from({
|
|
4033
|
+
vertex: wc,
|
|
4034
|
+
fragment: Sc,
|
|
4035
|
+
name: "sharpen-filter"
|
|
4250
4036
|
});
|
|
4251
4037
|
super({
|
|
4252
|
-
glProgram:
|
|
4038
|
+
glProgram: n,
|
|
4253
4039
|
resources: {
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
uIntensity: { value: n, type: "f32" },
|
|
4257
|
-
uRadius: { value: r, type: "f32" }
|
|
4040
|
+
sharpenUniforms: new H({
|
|
4041
|
+
uStrength: { value: i, type: "f32" }
|
|
4258
4042
|
})
|
|
4259
4043
|
}
|
|
4260
4044
|
});
|
|
4261
4045
|
}
|
|
4262
4046
|
/* ---------- 便捷存取器 ---------- */
|
|
4263
|
-
get
|
|
4264
|
-
return this.resources.
|
|
4265
|
-
}
|
|
4266
|
-
set threshold(e) {
|
|
4267
|
-
this.resources.bloomUniforms.uniforms.uThreshold = e;
|
|
4268
|
-
}
|
|
4269
|
-
get intensity() {
|
|
4270
|
-
return this.resources.bloomUniforms.uniforms.uIntensity;
|
|
4271
|
-
}
|
|
4272
|
-
set intensity(e) {
|
|
4273
|
-
this.resources.bloomUniforms.uniforms.uIntensity = e;
|
|
4274
|
-
}
|
|
4275
|
-
get radius() {
|
|
4276
|
-
return this.resources.bloomUniforms.uniforms.uRadius;
|
|
4047
|
+
get strength() {
|
|
4048
|
+
return this.resources.sharpenUniforms.uniforms.uStrength;
|
|
4277
4049
|
}
|
|
4278
|
-
set
|
|
4279
|
-
this.resources.
|
|
4050
|
+
set strength(e) {
|
|
4051
|
+
this.resources.sharpenUniforms.uniforms.uStrength = e;
|
|
4280
4052
|
}
|
|
4281
4053
|
}
|
|
4282
|
-
function Lf(t, e) {
|
|
4283
|
-
const i = e?.threshold ?? 0.5, n = e?.intensity ?? 1, r = e?.radius ?? 2, s = e?.samples ?? 3;
|
|
4284
|
-
return {
|
|
4285
|
-
postProcessId: t,
|
|
4286
|
-
createFilter() {
|
|
4287
|
-
return new _c({ threshold: i, intensity: n, radius: r, samples: s });
|
|
4288
|
-
},
|
|
4289
|
-
setOptions(o, a) {
|
|
4290
|
-
const c = o;
|
|
4291
|
-
a.threshold !== void 0 && (c.threshold = a.threshold), a.intensity !== void 0 && (c.intensity = a.intensity), a.radius !== void 0 && (c.radius = a.radius);
|
|
4292
|
-
}
|
|
4293
|
-
};
|
|
4294
|
-
}
|
|
4295
|
-
function Ki(t, e) {
|
|
4296
|
-
const i = e.brightness ?? 1, n = e.contrast ?? 0, r = e.saturate ?? 0, s = e.hue ?? 0;
|
|
4297
|
-
t.reset(), i !== 1 && t.brightness(i, !0), n !== 0 && t.contrast(n, !0), r !== 0 && t.saturate(r, !0), s !== 0 && t.hue(s, !0);
|
|
4298
|
-
}
|
|
4299
4054
|
function kf(t, e) {
|
|
4300
|
-
const i =
|
|
4301
|
-
brightness: e?.brightness ?? 1,
|
|
4302
|
-
contrast: e?.contrast ?? 0,
|
|
4303
|
-
saturate: e?.saturate ?? 0,
|
|
4304
|
-
hue: e?.hue ?? 0
|
|
4305
|
-
};
|
|
4055
|
+
const i = e?.strength ?? 0.5;
|
|
4306
4056
|
return {
|
|
4307
4057
|
postProcessId: t,
|
|
4308
4058
|
createFilter() {
|
|
4309
|
-
|
|
4310
|
-
return Ki(n, i), n;
|
|
4059
|
+
return new bc({ strength: i });
|
|
4311
4060
|
},
|
|
4312
4061
|
setOptions(n, r) {
|
|
4313
|
-
|
|
4062
|
+
const s = n;
|
|
4063
|
+
r.strength !== void 0 && (s.strength = r.strength);
|
|
4314
4064
|
}
|
|
4315
4065
|
};
|
|
4316
4066
|
}
|
|
4317
|
-
const
|
|
4067
|
+
const Cc = (
|
|
4318
4068
|
/* glsl */
|
|
4319
4069
|
`
|
|
4320
4070
|
in vec2 aPosition;
|
|
@@ -4343,7 +4093,7 @@ void main(void)
|
|
|
4343
4093
|
vTextureCoord = filterTextureCoord();
|
|
4344
4094
|
}
|
|
4345
4095
|
`
|
|
4346
|
-
),
|
|
4096
|
+
), Ic = (
|
|
4347
4097
|
/* glsl */
|
|
4348
4098
|
`
|
|
4349
4099
|
precision highp float;
|
|
@@ -4352,736 +4102,928 @@ in vec2 vTextureCoord;
|
|
|
4352
4102
|
out vec4 finalColor;
|
|
4353
4103
|
|
|
4354
4104
|
uniform sampler2D uTexture;
|
|
4355
|
-
uniform
|
|
4356
|
-
uniform vec4 uOutputFrame;
|
|
4357
|
-
uniform float uRadius;
|
|
4358
|
-
uniform float uSoftness;
|
|
4359
|
-
uniform float uIntensity;
|
|
4360
|
-
uniform vec3 uColor;
|
|
4105
|
+
uniform float uAmount;
|
|
4361
4106
|
|
|
4362
4107
|
void main(void)
|
|
4363
4108
|
{
|
|
4364
4109
|
vec4 original = texture(uTexture, vTextureCoord);
|
|
4365
4110
|
|
|
4366
|
-
//
|
|
4367
|
-
|
|
4368
|
-
// 从中心到边缘的距离(归一化回 0~1 空间)
|
|
4369
|
-
vec2 center = (vTextureCoord - texCenter) / (uOutputFrame.zw * uInputSize.zw);
|
|
4370
|
-
float dist = length(center) * 2.0;
|
|
4111
|
+
// 反色
|
|
4112
|
+
vec3 inverted = 1.0 - original.rgb;
|
|
4371
4113
|
|
|
4372
|
-
//
|
|
4373
|
-
|
|
4114
|
+
// 按 amount 在原色和反色之间插值
|
|
4115
|
+
vec3 result = mix(original.rgb, inverted, uAmount);
|
|
4374
4116
|
|
|
4375
|
-
|
|
4376
|
-
finalColor = vec4(mix(original.rgb, uColor, vignetteFactor), original.a);
|
|
4117
|
+
finalColor = vec4(result, original.a);
|
|
4377
4118
|
}
|
|
4378
4119
|
`
|
|
4379
4120
|
);
|
|
4380
|
-
class
|
|
4121
|
+
class Ac extends G {
|
|
4381
4122
|
constructor(e = {}) {
|
|
4382
|
-
const i = e.
|
|
4383
|
-
vertex:
|
|
4384
|
-
fragment:
|
|
4385
|
-
name: "
|
|
4123
|
+
const i = e.amount ?? 1, n = U.from({
|
|
4124
|
+
vertex: Cc,
|
|
4125
|
+
fragment: Ic,
|
|
4126
|
+
name: "invert-filter"
|
|
4386
4127
|
});
|
|
4387
4128
|
super({
|
|
4388
|
-
glProgram:
|
|
4129
|
+
glProgram: n,
|
|
4389
4130
|
resources: {
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
uSoftness: { value: n, type: "f32" },
|
|
4393
|
-
uIntensity: { value: r, type: "f32" },
|
|
4394
|
-
uColor: { value: new Float32Array(s), type: "vec3<f32>" }
|
|
4131
|
+
invertUniforms: new H({
|
|
4132
|
+
uAmount: { value: i, type: "f32" }
|
|
4395
4133
|
})
|
|
4396
4134
|
}
|
|
4397
4135
|
});
|
|
4398
4136
|
}
|
|
4399
4137
|
/* ---------- 便捷存取器 ---------- */
|
|
4400
|
-
get
|
|
4401
|
-
return this.resources.
|
|
4402
|
-
}
|
|
4403
|
-
set radius(e) {
|
|
4404
|
-
this.resources.vignetteUniforms.uniforms.uRadius = e;
|
|
4405
|
-
}
|
|
4406
|
-
get softness() {
|
|
4407
|
-
return this.resources.vignetteUniforms.uniforms.uSoftness;
|
|
4408
|
-
}
|
|
4409
|
-
set softness(e) {
|
|
4410
|
-
this.resources.vignetteUniforms.uniforms.uSoftness = e;
|
|
4411
|
-
}
|
|
4412
|
-
get intensity() {
|
|
4413
|
-
return this.resources.vignetteUniforms.uniforms.uIntensity;
|
|
4414
|
-
}
|
|
4415
|
-
set intensity(e) {
|
|
4416
|
-
this.resources.vignetteUniforms.uniforms.uIntensity = e;
|
|
4417
|
-
}
|
|
4418
|
-
get color() {
|
|
4419
|
-
const e = this.resources.vignetteUniforms.uniforms.uColor;
|
|
4420
|
-
return [e[0], e[1], e[2]];
|
|
4138
|
+
get amount() {
|
|
4139
|
+
return this.resources.invertUniforms.uniforms.uAmount;
|
|
4421
4140
|
}
|
|
4422
|
-
set
|
|
4423
|
-
|
|
4424
|
-
i[0] = e[0], i[1] = e[1], i[2] = e[2];
|
|
4141
|
+
set amount(e) {
|
|
4142
|
+
this.resources.invertUniforms.uniforms.uAmount = e;
|
|
4425
4143
|
}
|
|
4426
4144
|
}
|
|
4427
4145
|
function Ff(t, e) {
|
|
4428
|
-
const i = e?.
|
|
4146
|
+
const i = e?.amount ?? 1;
|
|
4429
4147
|
return {
|
|
4430
4148
|
postProcessId: t,
|
|
4431
4149
|
createFilter() {
|
|
4432
|
-
return new
|
|
4150
|
+
return new Ac({ amount: i });
|
|
4433
4151
|
},
|
|
4434
|
-
setOptions(
|
|
4435
|
-
const
|
|
4436
|
-
|
|
4152
|
+
setOptions(n, r) {
|
|
4153
|
+
const s = n;
|
|
4154
|
+
r.amount !== void 0 && (s.amount = r.amount);
|
|
4437
4155
|
}
|
|
4438
4156
|
};
|
|
4439
4157
|
}
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
|
|
4455
|
-
return vec4(position, 0.0, 1.0);
|
|
4456
|
-
}
|
|
4457
|
-
|
|
4458
|
-
vec2 filterTextureCoord(void)
|
|
4459
|
-
{
|
|
4460
|
-
return aPosition * (uOutputFrame.zw * uInputSize.zw);
|
|
4461
|
-
}
|
|
4462
|
-
|
|
4463
|
-
void main(void)
|
|
4464
|
-
{
|
|
4465
|
-
gl_Position = filterVertexPosition();
|
|
4466
|
-
vTextureCoord = filterTextureCoord();
|
|
4467
|
-
}
|
|
4468
|
-
`
|
|
4469
|
-
), Ic = (
|
|
4470
|
-
/* glsl */
|
|
4471
|
-
`
|
|
4472
|
-
precision highp float;
|
|
4473
|
-
|
|
4474
|
-
in vec2 vTextureCoord;
|
|
4475
|
-
out vec4 finalColor;
|
|
4476
|
-
|
|
4477
|
-
uniform sampler2D uTexture;
|
|
4478
|
-
uniform vec4 uInputSize;
|
|
4479
|
-
uniform float uPixelSize;
|
|
4480
|
-
|
|
4481
|
-
void main(void)
|
|
4482
|
-
{
|
|
4483
|
-
// 将纹理坐标对齐到像素块中心
|
|
4484
|
-
vec2 pixelCoord = vTextureCoord * uInputSize.xy;
|
|
4485
|
-
vec2 snapped = floor(pixelCoord / uPixelSize) * uPixelSize + uPixelSize * 0.5;
|
|
4486
|
-
vec2 uv = snapped * uInputSize.zw;
|
|
4487
|
-
|
|
4488
|
-
finalColor = texture(uTexture, uv);
|
|
4489
|
-
}
|
|
4490
|
-
`
|
|
4491
|
-
);
|
|
4492
|
-
class Ac extends G {
|
|
4493
|
-
constructor(e = {}) {
|
|
4494
|
-
const i = e.pixelSize ?? 8, n = U.from({
|
|
4495
|
-
vertex: Cc,
|
|
4496
|
-
fragment: Ic,
|
|
4497
|
-
name: "pixelate-filter"
|
|
4498
|
-
});
|
|
4499
|
-
super({
|
|
4500
|
-
glProgram: n,
|
|
4501
|
-
resources: {
|
|
4502
|
-
pixelateUniforms: new H({
|
|
4503
|
-
uPixelSize: { value: i, type: "f32" }
|
|
4504
|
-
})
|
|
4505
|
-
}
|
|
4506
|
-
});
|
|
4158
|
+
class Ti extends le {
|
|
4159
|
+
/** 额外 padding:覆盖 BlurFilter spread + 变换舍入误差(与 states/_filter-utils 同理) */
|
|
4160
|
+
static FILTER_AREA_PAD = 80;
|
|
4161
|
+
items = /* @__PURE__ */ new Map();
|
|
4162
|
+
/** postProcessId → 插件定义 */
|
|
4163
|
+
defs = /* @__PURE__ */ new Map();
|
|
4164
|
+
/** postProcessId → 运行时 Filter 实例 */
|
|
4165
|
+
filters = /* @__PURE__ */ new Map();
|
|
4166
|
+
/** 当前绑定的目标容器 */
|
|
4167
|
+
_target = null;
|
|
4168
|
+
/** PixiJS Application 引用,用于获取 screen 尺寸 */
|
|
4169
|
+
_app = null;
|
|
4170
|
+
/** 绑定到目标容器(projectionContainer),启用后滤镜自动挂载 */
|
|
4171
|
+
bind(e, i) {
|
|
4172
|
+
this._target = e, this._app = i, this.rebuildFilters();
|
|
4507
4173
|
}
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4174
|
+
/** 解绑目标容器,清除所有已挂载的滤镜 */
|
|
4175
|
+
unbind() {
|
|
4176
|
+
this._target && (this.clearFilters(), this._target.filterArea = void 0, this._target = null, this._app = null);
|
|
4511
4177
|
}
|
|
4512
|
-
|
|
4513
|
-
|
|
4178
|
+
/** 添加或批量添加后期处理项 */
|
|
4179
|
+
add(e) {
|
|
4180
|
+
for (const i of Array.isArray(e) ? e : [e]) {
|
|
4181
|
+
i.enabled === void 0 && (i.enabled = !0);
|
|
4182
|
+
const n = this.items.has(i.id);
|
|
4183
|
+
this.items.set(i.id, i), this.emit(n ? "postprocess:updated" : "postprocess:added", i);
|
|
4184
|
+
}
|
|
4185
|
+
return this.rebuildFilters(), this;
|
|
4514
4186
|
}
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
|
|
4187
|
+
/** 删除后期处理项(同时清除关联的插件和滤镜) */
|
|
4188
|
+
remove(e) {
|
|
4189
|
+
return this.items.delete(e) ? (this.destroyFilter(e), this.defs.delete(e), this.emit("postprocess:removed", { id: e }), this.rebuildFilters(), !0) : !1;
|
|
4190
|
+
}
|
|
4191
|
+
get(e) {
|
|
4192
|
+
return this.items.get(e);
|
|
4193
|
+
}
|
|
4194
|
+
has(e) {
|
|
4195
|
+
return this.items.has(e);
|
|
4196
|
+
}
|
|
4197
|
+
getAll() {
|
|
4198
|
+
return [...this.items.values()];
|
|
4199
|
+
}
|
|
4200
|
+
clear() {
|
|
4201
|
+
this.clearFilters(), this.items.clear(), this.defs.clear(), this.emit("postprocess:cleared");
|
|
4202
|
+
}
|
|
4203
|
+
/** 启用后期处理效果 */
|
|
4204
|
+
enable(e) {
|
|
4205
|
+
const i = this.items.get(e);
|
|
4206
|
+
return i && !i.enabled && (i.enabled = !0, this.emit("postprocess:enabled", { id: e }), this.rebuildFilters()), this;
|
|
4207
|
+
}
|
|
4208
|
+
/** 禁用后期处理效果 */
|
|
4209
|
+
disable(e) {
|
|
4210
|
+
const i = this.items.get(e);
|
|
4211
|
+
return i && i.enabled !== !1 && (i.enabled = !1, this.emit("postprocess:disabled", { id: e }), this.rebuildFilters()), this;
|
|
4212
|
+
}
|
|
4213
|
+
/** 注册后期处理插件 */
|
|
4214
|
+
register(e) {
|
|
4215
|
+
return this.defs.set(e.postProcessId, e), this.rebuildFilters(), this;
|
|
4216
|
+
}
|
|
4217
|
+
/** 注销后期处理插件 */
|
|
4218
|
+
unregister(e) {
|
|
4219
|
+
return this.destroyFilter(e), this.defs.delete(e), this.rebuildFilters(), this;
|
|
4220
|
+
}
|
|
4221
|
+
/** 获取后期处理权重 */
|
|
4222
|
+
getWeight(e) {
|
|
4223
|
+
return this.items.get(e)?.weight ?? 0;
|
|
4224
|
+
}
|
|
4225
|
+
/** 获取运行时 Filter 实例(供调试用) */
|
|
4226
|
+
getFilter(e) {
|
|
4227
|
+
return this.filters.get(e);
|
|
4228
|
+
}
|
|
4229
|
+
/**
|
|
4230
|
+
* 热更新后期处理参数,直接修改运行时 Filter 的 uniform,无需销毁重建。
|
|
4231
|
+
* 仅当对应 PostProcessDef 实现了 setOptions 时生效。
|
|
4232
|
+
* 不支持热更新的参数(如 bloom 的 samples)需重新调用 register 重建。
|
|
4233
|
+
*/
|
|
4234
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4235
|
+
updateOptions(e, i) {
|
|
4236
|
+
const n = this.filters.get(e), r = this.defs.get(e);
|
|
4237
|
+
return n && r?.setOptions && r.setOptions(n, i), this;
|
|
4238
|
+
}
|
|
4239
|
+
/** 逐帧更新(由 Scene ticker 驱动) */
|
|
4240
|
+
update(e) {
|
|
4241
|
+
this._target && this._app && this._target.filters?.length && (this._target.filterArea = this.computeFilterArea());
|
|
4242
|
+
for (const [i, n] of this.defs) {
|
|
4243
|
+
if (!n.onUpdate) continue;
|
|
4244
|
+
const r = this.items.get(i);
|
|
4245
|
+
if (!r || r.enabled === !1) continue;
|
|
4246
|
+
const s = this.filters.get(i);
|
|
4247
|
+
s && n.onUpdate(s, e);
|
|
4526
4248
|
}
|
|
4527
|
-
}
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4249
|
+
}
|
|
4250
|
+
/** 序列化(仅元数据,插件为运行时代码不参与序列化) */
|
|
4251
|
+
toJSON() {
|
|
4252
|
+
return this.getAll();
|
|
4253
|
+
}
|
|
4254
|
+
/** 反序列化(追加模式) */
|
|
4255
|
+
fromJSON(e) {
|
|
4256
|
+
this.add(e);
|
|
4257
|
+
}
|
|
4258
|
+
toYAML() {
|
|
4259
|
+
return be(this.toJSON());
|
|
4260
|
+
}
|
|
4261
|
+
fromYAML(e) {
|
|
4262
|
+
this.fromJSON(Ce(e));
|
|
4263
|
+
}
|
|
4264
|
+
destroy() {
|
|
4265
|
+
this.clearFilters(), this.items.clear(), this.defs.clear(), this._target = null, this._app = null, this.removeAllListeners();
|
|
4266
|
+
}
|
|
4267
|
+
// ========== 内部方法 ==========
|
|
4268
|
+
/**
|
|
4269
|
+
* 计算 filterArea(projectionContainer 局部坐标空间),参考 states/_filter-utils。
|
|
4270
|
+
*
|
|
4271
|
+
* 将视口四角通过 worldTransform 逆变换到容器局部空间,
|
|
4272
|
+
* 加上 pad 以确保 BlurFilter 等带扩展的滤镜不被裁剪。
|
|
4273
|
+
*
|
|
4274
|
+
* **filterArea 走的是独立且正确的路径:**
|
|
4275
|
+
* ```
|
|
4276
|
+
* filterArea(local)
|
|
4277
|
+
* × container.worldTransform → world
|
|
4278
|
+
* × renderGroup.cacheToLocalTransform → render group local ✓
|
|
4279
|
+
* ```
|
|
4280
|
+
*/
|
|
4281
|
+
computeFilterArea() {
|
|
4282
|
+
const e = this._app.screen, i = this._target.worldTransform.clone().invert(), n = i.apply({ x: e.x, y: e.y }), r = i.apply({ x: e.x + e.width, y: e.y }), s = i.apply({ x: e.x + e.width, y: e.y + e.height }), o = i.apply({ x: e.x, y: e.y + e.height }), a = Ti.FILTER_AREA_PAD, c = Math.min(n.x, r.x, s.x, o.x) - a, l = Math.min(n.y, r.y, s.y, o.y) - a, h = Math.max(n.x, r.x, s.x, o.x) + a, u = Math.max(n.y, r.y, s.y, o.y) + a;
|
|
4283
|
+
return new Lt(c, l, h - c, u - l);
|
|
4284
|
+
}
|
|
4285
|
+
/** 按权重升序排列,返回有效(已注册 + 已启用)的 ID 列表 */
|
|
4286
|
+
getActiveIds() {
|
|
4287
|
+
const e = [];
|
|
4288
|
+
for (const [i, n] of this.items)
|
|
4289
|
+
n.enabled !== !1 && (this.defs.has(i) ? e.push(i) : console.warn(
|
|
4290
|
+
`[PostProcess] "${i}" 后处理插件未注册(register),效果将被跳过。请确保在启用前调用 postprocess.register()。`
|
|
4291
|
+
));
|
|
4292
|
+
return e.sort((i, n) => this.getWeight(i) - this.getWeight(n));
|
|
4293
|
+
}
|
|
4294
|
+
/** 重建 filters 数组并挂载到目标容器 */
|
|
4295
|
+
rebuildFilters() {
|
|
4296
|
+
if (!this._target) return;
|
|
4297
|
+
const e = this.getActiveIds();
|
|
4298
|
+
for (const [n, r] of this.filters)
|
|
4299
|
+
e.includes(n) || this.destroyFilter(n);
|
|
4300
|
+
for (const n of e)
|
|
4301
|
+
if (!this.filters.has(n)) {
|
|
4302
|
+
const r = this.defs.get(n);
|
|
4303
|
+
this.filters.set(n, r.createFilter());
|
|
4304
|
+
}
|
|
4305
|
+
const i = e.map((n) => this.filters.get(n)).filter(Boolean);
|
|
4306
|
+
i.length > 0 ? (this._target.filterArea = this.computeFilterArea(), this._target.filters = i) : (this._target.filterArea = void 0, this._target.filters = null);
|
|
4307
|
+
}
|
|
4308
|
+
/** 销毁单个滤镜实例 */
|
|
4309
|
+
destroyFilter(e) {
|
|
4310
|
+
const i = this.filters.get(e);
|
|
4311
|
+
i && (this.defs.get(e)?.onDestroy?.(i), i.destroy(), this.filters.delete(e));
|
|
4312
|
+
}
|
|
4313
|
+
/** 清除所有运行时滤镜 */
|
|
4314
|
+
clearFilters() {
|
|
4315
|
+
for (const e of [...this.filters.keys()])
|
|
4316
|
+
this.destroyFilter(e);
|
|
4317
|
+
this._target && (this._target.filters = null);
|
|
4318
|
+
}
|
|
4587
4319
|
}
|
|
4588
|
-
|
|
4589
|
-
)
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4320
|
+
function Ze(t) {
|
|
4321
|
+
return `#${t.toString(16).padStart(6, "0")}`;
|
|
4322
|
+
}
|
|
4323
|
+
function Tc(t) {
|
|
4324
|
+
return "convertToBlob" in t && typeof t.convertToBlob == "function" ? t.convertToBlob({ type: "image/png" }) : new Promise((e, i) => {
|
|
4325
|
+
t.toBlob(
|
|
4326
|
+
(n) => n ? e(n) : i(new Error("Failed to create PNG blob")),
|
|
4327
|
+
"image/png"
|
|
4328
|
+
);
|
|
4329
|
+
});
|
|
4330
|
+
}
|
|
4331
|
+
function Oc(t) {
|
|
4332
|
+
return typeof t.toDataURL == "function" ? t.toDataURL("image/png") : "";
|
|
4333
|
+
}
|
|
4334
|
+
function Ct(t) {
|
|
4335
|
+
return t.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
4336
|
+
}
|
|
4337
|
+
function It(t, e) {
|
|
4338
|
+
const i = t instanceof Blob ? URL.createObjectURL(t) : `data:image/svg+xml;charset=utf-8,${encodeURIComponent(t)}`, n = document.createElement("a");
|
|
4339
|
+
n.href = i, n.download = e, document.body.appendChild(n), n.click(), document.body.removeChild(n), t instanceof Blob && URL.revokeObjectURL(i);
|
|
4340
|
+
}
|
|
4341
|
+
async function Pc(t, e) {
|
|
4342
|
+
const { pixelRatio: i = 2 } = e ?? {}, n = t.app, r = n.renderer.resolution, s = n.screen.width, o = n.screen.height;
|
|
4343
|
+
n.renderer.resolution = i, n.renderer.resize(s, o), n.render();
|
|
4344
|
+
const a = Tc(n.canvas);
|
|
4345
|
+
return n.renderer.resolution = r, n.renderer.resize(s, o), n.render(), a;
|
|
4346
|
+
}
|
|
4347
|
+
async function Mc(t, e) {
|
|
4348
|
+
const i = t.app.renderer;
|
|
4349
|
+
try {
|
|
4350
|
+
return await i.extract.base64({ target: e, format: "png" });
|
|
4351
|
+
} catch {
|
|
4352
|
+
try {
|
|
4353
|
+
const n = i.extract.canvas(e);
|
|
4354
|
+
return Oc(n);
|
|
4355
|
+
} catch {
|
|
4356
|
+
return "";
|
|
4357
|
+
}
|
|
4358
|
+
}
|
|
4359
|
+
}
|
|
4360
|
+
async function Ec(t) {
|
|
4361
|
+
const e = /* @__PURE__ */ new Map();
|
|
4362
|
+
for (const i of t.nodes.getAll()) {
|
|
4363
|
+
const n = i.options.icon;
|
|
4364
|
+
if (!e.has(n))
|
|
4365
|
+
try {
|
|
4366
|
+
const r = await t.icons.loadTexture(n), s = await Mc(t, r);
|
|
4367
|
+
e.set(n, s);
|
|
4368
|
+
} catch {
|
|
4369
|
+
e.set(n, "");
|
|
4604
4370
|
}
|
|
4371
|
+
}
|
|
4372
|
+
return e;
|
|
4373
|
+
}
|
|
4374
|
+
async function Lc(t, e) {
|
|
4375
|
+
const { background: i = !0 } = e ?? {}, n = t.projectionContainer, r = n.skew.x, s = n.skew.y, o = n.scale.x, a = n.position.x, c = n.position.y, l = Math.ceil(t.app.screen.width), h = Math.ceil(t.app.screen.height), u = o * Math.cos(s), f = o * Math.sin(s), d = o * Math.sin(r), p = o * Math.cos(r), m = Math.cos(s), v = Math.sin(s), _ = Math.sin(r), x = Math.cos(r), w = m * x - v * _, S = x / w, b = -v / w, E = -_ / w, N = m / w, j = u * p - f * d, ee = [
|
|
4376
|
+
{ x: 0, y: 0 },
|
|
4377
|
+
{ x: l, y: 0 },
|
|
4378
|
+
{ x: 0, y: h },
|
|
4379
|
+
{ x: l, y: h }
|
|
4380
|
+
];
|
|
4381
|
+
let V = 1 / 0, X = 1 / 0, ue = -1 / 0, fe = -1 / 0;
|
|
4382
|
+
for (const { x: I, y: te } of ee) {
|
|
4383
|
+
const pe = I - a, ge = te - c, me = (p * pe - d * ge) / j, ve = (-f * pe + u * ge) / j;
|
|
4384
|
+
V = Math.min(V, me), X = Math.min(X, ve), ue = Math.max(ue, me), fe = Math.max(fe, ve);
|
|
4385
|
+
}
|
|
4386
|
+
const q = g * 2, de = {
|
|
4387
|
+
x: Math.floor((V - q) / g) * g,
|
|
4388
|
+
y: Math.floor((X - q) / g) * g,
|
|
4389
|
+
width: Math.ceil((ue - V + q * 2) / g) * g,
|
|
4390
|
+
height: Math.ceil((fe - X + q * 2) / g) * g
|
|
4391
|
+
}, $ = await Ec(t), O = [];
|
|
4392
|
+
O.push(
|
|
4393
|
+
'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"',
|
|
4394
|
+
` width="${l}" height="${h}" viewBox="0 0 ${l} ${h}">`
|
|
4395
|
+
), O.push(" <defs>");
|
|
4396
|
+
for (const [I, te] of $)
|
|
4397
|
+
te && O.push(
|
|
4398
|
+
` <symbol id="icon-${Ct(I)}" viewBox="0 0 100 100">`,
|
|
4399
|
+
` <image href="${te}" width="100" height="100" />`,
|
|
4400
|
+
" </symbol>"
|
|
4401
|
+
);
|
|
4402
|
+
if (O.push(" </defs>"), i) {
|
|
4403
|
+
const I = t.grid.options, te = Ze(I.bgColor ?? 0);
|
|
4404
|
+
O.push(` <rect width="${l}" height="${h}" fill="${te}" />`);
|
|
4405
|
+
}
|
|
4406
|
+
const Gt = `matrix(${u},${f},${d},${p},${a},${c})`;
|
|
4407
|
+
if (O.push(` <g transform="${Gt}">`), i) {
|
|
4408
|
+
const I = await kc(t, de);
|
|
4409
|
+
I && O.push(I);
|
|
4410
|
+
}
|
|
4411
|
+
for (const I of t.rects.getAll())
|
|
4412
|
+
O.push(Fc(I.options));
|
|
4413
|
+
for (const I of t.lines.getAll())
|
|
4414
|
+
O.push(Rc(I));
|
|
4415
|
+
for (const I of t.nodes.getAll())
|
|
4416
|
+
O.push(Dc(I.options, $, S, b, E, N));
|
|
4417
|
+
for (const I of t.texts.getAll())
|
|
4418
|
+
O.push(zc(I.options, S, b, E, N));
|
|
4419
|
+
return O.push(" </g>"), O.push("</svg>"), O.join(`
|
|
4420
|
+
`);
|
|
4421
|
+
}
|
|
4422
|
+
async function kc(t, e) {
|
|
4423
|
+
const n = t.grid.getGraphics().children[0];
|
|
4424
|
+
if (!n) return "";
|
|
4425
|
+
const r = t.grid.options.tileSize ?? 100, s = n.x, o = n.y, a = n.width, c = n.height, l = n.tilePosition?.x ?? 0, h = n.tilePosition?.y ?? 0;
|
|
4426
|
+
try {
|
|
4427
|
+
n.x = 0, n.y = 0, n.width = e.width, n.height = e.height, n.tilePosition && n.tilePosition.set(
|
|
4428
|
+
-e.x - r / 2,
|
|
4429
|
+
-e.y - r / 2
|
|
4430
|
+
);
|
|
4431
|
+
const u = n.parent;
|
|
4432
|
+
u && u.removeChild(n);
|
|
4433
|
+
const f = await t.app.renderer.extract.base64({
|
|
4434
|
+
target: n,
|
|
4435
|
+
format: "png"
|
|
4605
4436
|
});
|
|
4437
|
+
return u && u.addChild(n), ` <image href="${f}" x="${e.x}" y="${e.y}" width="${e.width}" height="${e.height}" />`;
|
|
4438
|
+
} catch {
|
|
4439
|
+
return "";
|
|
4440
|
+
} finally {
|
|
4441
|
+
n.x = s, n.y = o, n.width = a, n.height = c, n.tilePosition && n.tilePosition.set(l, h);
|
|
4442
|
+
}
|
|
4443
|
+
}
|
|
4444
|
+
function Fc(t) {
|
|
4445
|
+
const e = t.x * g - g / 2, i = t.y * g - g / 2, n = (t.width ?? 1) * g, r = (t.height ?? 1) * g, s = Ze(t.bgColor ?? 3447003), o = t.bgOpacity ?? 0.8, a = Ze(t.borderColor ?? 16777215), c = t.borderWidth ?? 2, l = t.borderOpacity ?? 1, h = t.borderRadius ?? 0, u = h > 0 ? ` rx="${h}" ry="${h}"` : "";
|
|
4446
|
+
return ` <rect x="${e}" y="${i}" width="${n}" height="${r}"${u} fill="${s}" fill-opacity="${o}" stroke="${a}" stroke-width="${c}" stroke-opacity="${l}" />`;
|
|
4447
|
+
}
|
|
4448
|
+
function Rc(t) {
|
|
4449
|
+
const e = t.options, i = Ze(e.color ?? 4473958), n = e.width ?? 6, r = t.getPoints();
|
|
4450
|
+
let s;
|
|
4451
|
+
if (r && r.length >= 2)
|
|
4452
|
+
s = r.map((a) => `${a.x},${a.y}`).join(" ");
|
|
4453
|
+
else {
|
|
4454
|
+
const a = [];
|
|
4455
|
+
for (const c of e.anchor) {
|
|
4456
|
+
const l = t.resolveAnchorPosition(c);
|
|
4457
|
+
l && a.push({ x: l.x * g, y: l.y * g });
|
|
4458
|
+
}
|
|
4459
|
+
if (a.length < 2) return "";
|
|
4460
|
+
s = a.map((c) => `${c.x},${c.y}`).join(" ");
|
|
4461
|
+
}
|
|
4462
|
+
const o = e.mode === "dashed" ? ` stroke-dasharray="${(e.dashPattern ?? [10, 5]).join(",")}"` : "";
|
|
4463
|
+
return ` <polyline points="${s}" fill="none" stroke="${i}" stroke-width="${n}" stroke-linecap="round" stroke-linejoin="round"${o} />`;
|
|
4464
|
+
}
|
|
4465
|
+
function Dc(t, e, i, n, r, s) {
|
|
4466
|
+
const o = t.x * g, a = t.y * g, c = t.scale ?? 1, l = t.isFlat ?? !1, h = l ? 1 : t.scaleY ?? 1, u = t.offsetY ?? 0, f = t.icon;
|
|
4467
|
+
if (!(e.has(f) && e.get(f) !== "")) return "";
|
|
4468
|
+
const p = 100, m = -p / 2 * h + cr / 2 + u, v = [];
|
|
4469
|
+
if (l) {
|
|
4470
|
+
const _ = p * c, x = p * c, w = o - _ / 2, S = a + c * (m - p / 2);
|
|
4471
|
+
v.push(
|
|
4472
|
+
` <use href="#icon-${Ct(f)}" x="${w}" y="${S}" width="${_}" height="${x}" />`
|
|
4473
|
+
);
|
|
4474
|
+
} else {
|
|
4475
|
+
const _ = p * c, x = p * c * h, w = -_ / 2, S = c * h * m - x / 2, b = `matrix(${i},${n},${r},${s},0,0)`;
|
|
4476
|
+
v.push(` <g transform="translate(${o},${a})">`), v.push(` <g transform="${b}">`), v.push(
|
|
4477
|
+
` <use href="#icon-${Ct(f)}" x="${w}" y="${S}" width="${_}" height="${x}" />`
|
|
4478
|
+
), v.push(" </g>"), v.push(" </g>");
|
|
4479
|
+
}
|
|
4480
|
+
return v.join(`
|
|
4481
|
+
`);
|
|
4482
|
+
}
|
|
4483
|
+
function zc(t, e, i, n, r) {
|
|
4484
|
+
const s = t.x * g, o = t.y * g, a = t.fontSize ?? 16, c = Ze(t.color ?? 16777215), l = t.fontWeight ?? "normal", h = t.fontFamily ?? "Arial", u = t.align ?? "center", f = t.position ?? "x", d = u === "left" ? "start" : u === "right" ? "end" : "middle", p = Ct(t.text), m = `text-anchor="${d}" fill="${c}" font-size="${a}" font-weight="${l}" font-family="${h}"`;
|
|
4485
|
+
if (f === "screen") {
|
|
4486
|
+
const v = `matrix(${e},${i},${n},${r},0,0)`;
|
|
4487
|
+
return [
|
|
4488
|
+
` <g transform="translate(${s},${o})">`,
|
|
4489
|
+
` <text transform="${v}" ${m}>${p}</text>`,
|
|
4490
|
+
" </g>"
|
|
4491
|
+
].join(`
|
|
4492
|
+
`);
|
|
4493
|
+
} else return f === "y" ? ` <text x="${s}" y="${o}" transform="rotate(-90,${s},${o})" ${m}>${p}</text>` : ` <text x="${s}" y="${o}" ${m}>${p}</text>`;
|
|
4494
|
+
}
|
|
4495
|
+
class De extends le {
|
|
4496
|
+
/** 默认缩放级别 */
|
|
4497
|
+
static DEFAULT_ZOOM = 0.8;
|
|
4498
|
+
id;
|
|
4499
|
+
app;
|
|
4500
|
+
icons;
|
|
4501
|
+
states;
|
|
4502
|
+
postprocess;
|
|
4503
|
+
projectionContainer;
|
|
4504
|
+
layer;
|
|
4505
|
+
grid;
|
|
4506
|
+
nodes;
|
|
4507
|
+
lines;
|
|
4508
|
+
texts;
|
|
4509
|
+
rects;
|
|
4510
|
+
fences;
|
|
4511
|
+
waves;
|
|
4512
|
+
images;
|
|
4513
|
+
sceneItems = /* @__PURE__ */ new Set();
|
|
4514
|
+
/** 上一帧相机状态,用于 ticker 检测增量变化 */
|
|
4515
|
+
lastCameraState = { x: 0, y: 0, scale: 0 };
|
|
4516
|
+
_isActive = !1;
|
|
4517
|
+
_cameraHandler;
|
|
4518
|
+
constructor(e, i, n, r) {
|
|
4519
|
+
super(), this.id = e, this.app = i, this.icons = n, this.states = r, this.postprocess = new Ti(), this.projectionContainer = new R(), this.layer = new Ja(this.projectionContainer), this.lines = new Ra(this), this.nodes = new Oa(this), this.texts = new Na(this), this.rects = new Ga(this), this.fences = new Ya(this), this.waves = new Wa(this), this.images = new Va(this), this.grid = new Da();
|
|
4520
|
+
const { skewX: s, skewY: o } = lr();
|
|
4521
|
+
this.projectionContainer.sortableChildren = !0, this.projectionContainer.skew.set(s, o), this.projectionContainer.scale.set(De.DEFAULT_ZOOM), this.projectionContainer.position.set(i.screen.width / 2, i.screen.height / 2), this.projectionContainer.addChild(this.grid.getGraphics()), this.grid.getGraphics().zIndex = -1, this.registerItem(this.grid);
|
|
4522
|
+
}
|
|
4523
|
+
// ========== 激活 / 停用 ==========
|
|
4524
|
+
setActive(e) {
|
|
4525
|
+
e !== this._isActive && (this._isActive = e, e ? (this.app.stage.addChild(this.projectionContainer), this.postprocess.bind(this.projectionContainer, this.app), this.app.ticker.add(this.tickerCallback, this), this.notifyCameraChange(!1, !1), this.emit("ready")) : (this.app.ticker.remove(this.tickerCallback, this), this.postprocess.unbind(), this.app.stage.removeChild(this.projectionContainer)));
|
|
4526
|
+
}
|
|
4527
|
+
get isActive() {
|
|
4528
|
+
return this._isActive;
|
|
4529
|
+
}
|
|
4530
|
+
// ========== 序列化 ==========
|
|
4531
|
+
toJSON() {
|
|
4532
|
+
return {
|
|
4533
|
+
nodes: this.nodes.toJSON(),
|
|
4534
|
+
lines: this.lines.toJSON(),
|
|
4535
|
+
texts: this.texts.toJSON(),
|
|
4536
|
+
rects: this.rects.toJSON(),
|
|
4537
|
+
fences: this.fences.toJSON(),
|
|
4538
|
+
waves: this.waves.toJSON(),
|
|
4539
|
+
images: this.images.toJSON(),
|
|
4540
|
+
grid: this.grid.toJSON(),
|
|
4541
|
+
camera: this.getCamera(),
|
|
4542
|
+
layer: this.layer.toJSON(),
|
|
4543
|
+
postprocess: this.postprocess.toJSON()
|
|
4544
|
+
};
|
|
4545
|
+
}
|
|
4546
|
+
fromJSON(e) {
|
|
4547
|
+
this.clear(), e.nodes && this.nodes.fromJSON(e.nodes), e.lines && this.lines.fromJSON(e.lines), e.texts && this.texts.fromJSON(e.texts), e.rects && this.rects.fromJSON(e.rects), e.fences && this.fences.fromJSON(e.fences), e.waves && this.waves.fromJSON(e.waves), e.images && this.images.fromJSON(e.images), e.grid && this.grid.fromJSON(e.grid), e.camera && this.setCamera(e.camera), e.layer?.length && this.layer.fromJSON(e.layer), e.postprocess && this.postprocess.fromJSON(e.postprocess);
|
|
4548
|
+
}
|
|
4549
|
+
/** 序列化为 YAML 字符串 */
|
|
4550
|
+
toYAML() {
|
|
4551
|
+
return be(this.toJSON());
|
|
4552
|
+
}
|
|
4553
|
+
/** 从 YAML 字符串反序列化 */
|
|
4554
|
+
fromYAML(e) {
|
|
4555
|
+
this.fromJSON(Ce(e));
|
|
4556
|
+
}
|
|
4557
|
+
// ========== 导出 ==========
|
|
4558
|
+
/**
|
|
4559
|
+
* 将场景导出为 PNG 图片
|
|
4560
|
+
* @param options 导出选项(padding / pixelRatio)
|
|
4561
|
+
* @returns PNG Blob
|
|
4562
|
+
*/
|
|
4563
|
+
async exportPNG(e) {
|
|
4564
|
+
return Pc(this, e);
|
|
4565
|
+
}
|
|
4566
|
+
/**
|
|
4567
|
+
* 将场景导出为 SVG 字符串
|
|
4568
|
+
* @param options 导出选项(padding / background)
|
|
4569
|
+
* @returns SVG 文档字符串
|
|
4570
|
+
*/
|
|
4571
|
+
async exportSVG(e) {
|
|
4572
|
+
return Lc(this, e);
|
|
4573
|
+
}
|
|
4574
|
+
/**
|
|
4575
|
+
* 导出 PNG 并自动触发浏览器下载
|
|
4576
|
+
* @param filename 文件名,默认为 `{sceneId}.png`
|
|
4577
|
+
* @param options 导出选项
|
|
4578
|
+
*/
|
|
4579
|
+
async downloadPNG(e, i) {
|
|
4580
|
+
const n = await this.exportPNG(i);
|
|
4581
|
+
It(n, e ?? `${this.id}.png`);
|
|
4582
|
+
}
|
|
4583
|
+
/**
|
|
4584
|
+
* 导出 SVG 并自动触发浏览器下载
|
|
4585
|
+
* @param filename 文件名,默认为 `{sceneId}.svg`
|
|
4586
|
+
* @param options 导出选项
|
|
4587
|
+
*/
|
|
4588
|
+
async downloadSVG(e, i) {
|
|
4589
|
+
const n = await this.exportSVG(i);
|
|
4590
|
+
It(n, e ?? `${this.id}.svg`);
|
|
4591
|
+
}
|
|
4592
|
+
// ========== 相机控制 ==========
|
|
4593
|
+
/**
|
|
4594
|
+
* 注册外部相机处理器(通常由 ViewportPlugin 调用)。
|
|
4595
|
+
* 注册后,`setCamera` 将委托给该处理器而非直接更新 projectionContainer,
|
|
4596
|
+
* 从而允许插件实现动画过渡等特性。
|
|
4597
|
+
*
|
|
4598
|
+
* @param handler 处理函数,传 `undefined` 可清除
|
|
4599
|
+
*/
|
|
4600
|
+
setCameraHandler(e) {
|
|
4601
|
+
this._cameraHandler = e;
|
|
4602
|
+
}
|
|
4603
|
+
/**
|
|
4604
|
+
* 获取当前相机状态
|
|
4605
|
+
*/
|
|
4606
|
+
getCamera() {
|
|
4607
|
+
const e = this.projectionContainer;
|
|
4608
|
+
return { zoom: e.scale.x, x: e.position.x, y: e.position.y };
|
|
4609
|
+
}
|
|
4610
|
+
/**
|
|
4611
|
+
* 设置相机状态。
|
|
4612
|
+
* - 如果有外部处理器(ViewportPlugin 等),委托给处理器更新(可带动画过渡)。
|
|
4613
|
+
* - 否则,直接更新 projectionContainer。
|
|
4614
|
+
*
|
|
4615
|
+
* 返回 Promise,在有动画过渡时可 `await` 等待完成。
|
|
4616
|
+
*
|
|
4617
|
+
* @param camera 部分相机参数,未传的字段保留当前值
|
|
4618
|
+
*/
|
|
4619
|
+
setCamera(e) {
|
|
4620
|
+
const i = this.projectionContainer, n = {
|
|
4621
|
+
zoom: e.zoom ?? i.scale.x,
|
|
4622
|
+
x: e.x ?? i.position.x,
|
|
4623
|
+
y: e.y ?? i.position.y
|
|
4624
|
+
};
|
|
4625
|
+
return this._cameraHandler ? Promise.resolve(this._cameraHandler(n)) : (this.applyCamera(n), Promise.resolve());
|
|
4626
|
+
}
|
|
4627
|
+
/**
|
|
4628
|
+
* 直接将相机状态应用到 projectionContainer。
|
|
4629
|
+
* 当没有安装 ViewportPlugin 时由 `setCamera` 内部调用。
|
|
4630
|
+
* 也可被外部直接调用以跳过插件处理。
|
|
4631
|
+
*/
|
|
4632
|
+
applyCamera(e) {
|
|
4633
|
+
const i = this.projectionContainer, n = this.lastCameraState, r = e.x !== n.x || e.y !== n.y, s = e.zoom !== n.scale;
|
|
4634
|
+
i.scale.set(e.zoom), i.position.set(e.x, e.y), this._isActive && (this.lastCameraState = { x: i.x, y: i.y, scale: i.scale.x }, this.notifyCameraChange(r, s));
|
|
4635
|
+
}
|
|
4636
|
+
/**
|
|
4637
|
+
* 获取默认相机状态(居中 + 默认缩放)
|
|
4638
|
+
*/
|
|
4639
|
+
getDefaultCamera() {
|
|
4640
|
+
return {
|
|
4641
|
+
zoom: De.DEFAULT_ZOOM,
|
|
4642
|
+
x: this.app.screen.width / 2,
|
|
4643
|
+
y: this.app.screen.height / 2
|
|
4644
|
+
};
|
|
4645
|
+
}
|
|
4646
|
+
// ========== 常用操作 ==========
|
|
4647
|
+
get stage() {
|
|
4648
|
+
return this.app.stage;
|
|
4649
|
+
}
|
|
4650
|
+
clear() {
|
|
4651
|
+
this.lines.clear(), this.nodes.clear(), this.texts.clear(), this.rects.clear(), this.fences.clear(), this.waves.clear(), this.images.clear(), this.layer.clear(), this.postprocess.clear();
|
|
4652
|
+
}
|
|
4653
|
+
destroy() {
|
|
4654
|
+
this.setActive(!1), this.emit("destroyed"), this.grid?.destroy(), this.lines?.destroy(), this.nodes?.destroy(), this.texts?.destroy(), this.rects?.destroy(), this.fences?.destroy(), this.waves?.destroy(), this.images?.destroy(), this.layer?.destroy(), this.postprocess.destroy(), this.removeAllListeners(), this.sceneItems.clear(), this.app.stage.removeChild(this.projectionContainer), this.projectionContainer.destroy();
|
|
4655
|
+
}
|
|
4656
|
+
// ========== SceneItem 注册和渲染循环 ==========
|
|
4657
|
+
registerItem(e) {
|
|
4658
|
+
this.sceneItems.add(e);
|
|
4659
|
+
}
|
|
4660
|
+
unregisterItem(e) {
|
|
4661
|
+
this.sceneItems.delete(e);
|
|
4662
|
+
}
|
|
4663
|
+
tickerCallback = () => {
|
|
4664
|
+
const e = this.app.ticker.deltaMS;
|
|
4665
|
+
for (const a of this.sceneItems)
|
|
4666
|
+
a.onRender(e), a.tickStates(e);
|
|
4667
|
+
this.postprocess.update(e);
|
|
4668
|
+
const { x: i, y: n } = this.projectionContainer.position, r = this.projectionContainer.scale.x, s = i !== this.lastCameraState.x || n !== this.lastCameraState.y, o = r !== this.lastCameraState.scale;
|
|
4669
|
+
(s || o) && (this.lastCameraState = { x: i, y: n, scale: r }, this.notifyCameraChange(s, o));
|
|
4670
|
+
};
|
|
4671
|
+
/**
|
|
4672
|
+
* 通知所有 SceneItem 相机已变化,并向外发射相机事件。
|
|
4673
|
+
*
|
|
4674
|
+
* @param positionChanged 位置(x/y)是否改变;传 `false` 时不发射 `camera:move` 事件
|
|
4675
|
+
* @param zoomChanged 缩放是否改变;传 `false` 时不发射 `camera:zoom` 事件
|
|
4676
|
+
*
|
|
4677
|
+
* 两者均为 `false` 时仅通知 SceneItem(用于场景初始化),不发射任何相机事件。
|
|
4678
|
+
*/
|
|
4679
|
+
notifyCameraChange(e = !0, i = !0) {
|
|
4680
|
+
const n = this.getViewRect(), r = this.projectionContainer.scale.x;
|
|
4681
|
+
for (const o of this.sceneItems) o.onCameraChange(n, r);
|
|
4682
|
+
if (!e && !i) return;
|
|
4683
|
+
const s = {
|
|
4684
|
+
...this.getCamera(),
|
|
4685
|
+
positionChanged: e,
|
|
4686
|
+
zoomChanged: i
|
|
4687
|
+
};
|
|
4688
|
+
this.emit("camera:change", s), e && this.emit("camera:move", s), i && this.emit("camera:zoom", s);
|
|
4689
|
+
}
|
|
4690
|
+
getViewRect() {
|
|
4691
|
+
const { width: e, height: i } = this.app.screen, n = this.projectionContainer, r = n.skew.x, s = n.skew.y, o = n.scale.x, a = n.scale.y, c = Math.cos(s) * o, l = Math.sin(s) * o, h = Math.sin(r) * a, u = Math.cos(r) * a, f = n.x, d = n.y, p = c * u - l * h, m = u / p, v = -l / p, _ = -h / p, x = c / p, w = (ue, fe) => {
|
|
4692
|
+
const q = ue - f, de = fe - d;
|
|
4693
|
+
return { x: m * q + _ * de, y: v * q + x * de };
|
|
4694
|
+
}, S = w(0, 0), b = w(e, 0), E = w(0, i), N = w(e, i), j = Math.min(S.x, b.x, E.x, N.x), ee = Math.min(S.y, b.y, E.y, N.y), V = Math.max(S.x, b.x, E.x, N.x), X = Math.max(S.y, b.y, E.y, N.y);
|
|
4695
|
+
return { x: j, y: ee, width: V - j, height: X - ee };
|
|
4696
|
+
}
|
|
4697
|
+
/**
|
|
4698
|
+
* 计算场景中所有内容的包围盒(projectionContainer 本地坐标系)
|
|
4699
|
+
* @returns 包围盒,如果场景为空则返回 null
|
|
4700
|
+
*/
|
|
4701
|
+
getContentBounds() {
|
|
4702
|
+
let i = 1 / 0, n = 1 / 0, r = -1 / 0, s = -1 / 0, o = !1;
|
|
4703
|
+
const a = (c, l) => {
|
|
4704
|
+
o = !0, c < i && (i = c), l < n && (n = l), c > r && (r = c), l > s && (s = l);
|
|
4705
|
+
};
|
|
4706
|
+
for (const c of this.nodes.getAll())
|
|
4707
|
+
a(c.options.x * 100, c.options.y * 100);
|
|
4708
|
+
for (const c of this.rects.getAll()) {
|
|
4709
|
+
const l = c.options.x * 100, h = c.options.y * 100, u = (c.options.width ?? 1) * 100, f = (c.options.height ?? 1) * 100;
|
|
4710
|
+
a(l, h), a(l + u, h + f);
|
|
4711
|
+
}
|
|
4712
|
+
for (const c of this.texts.getAll())
|
|
4713
|
+
a(c.options.x * 100, c.options.y * 100);
|
|
4714
|
+
for (const c of this.lines.getAll())
|
|
4715
|
+
for (const l of c.options.anchor) {
|
|
4716
|
+
const h = c.resolveAnchorPosition(l);
|
|
4717
|
+
h && a(h.x * 100, h.y * 100);
|
|
4718
|
+
}
|
|
4719
|
+
for (const c of this.fences.getAll()) {
|
|
4720
|
+
const l = c.options.x * 100, h = c.options.y * 100, u = c.options.direction ?? "+x", f = (c.options.length ?? 4) * 100;
|
|
4721
|
+
switch (a(l, h), u) {
|
|
4722
|
+
case "x":
|
|
4723
|
+
case "+x":
|
|
4724
|
+
a(l + f, h);
|
|
4725
|
+
break;
|
|
4726
|
+
case "-x":
|
|
4727
|
+
a(l - f, h);
|
|
4728
|
+
break;
|
|
4729
|
+
case "y":
|
|
4730
|
+
case "+y":
|
|
4731
|
+
a(l, h + f);
|
|
4732
|
+
break;
|
|
4733
|
+
case "-y":
|
|
4734
|
+
a(l, h - f);
|
|
4735
|
+
break;
|
|
4736
|
+
}
|
|
4737
|
+
}
|
|
4738
|
+
for (const c of this.waves.getAll()) {
|
|
4739
|
+
const l = (c.options.width ?? 4) * 100, h = (c.options.height ?? 4) * 100;
|
|
4740
|
+
a(c.options.x * 100 - l / 2, c.options.y * 100 - h / 2), a(c.options.x * 100 + l / 2, c.options.y * 100 + h / 2);
|
|
4741
|
+
}
|
|
4742
|
+
for (const c of this.images.getAll())
|
|
4743
|
+
a(c.options.x * 100, c.options.y * 100);
|
|
4744
|
+
return o ? { x: i, y: n, width: r - i, height: s - n } : null;
|
|
4745
|
+
}
|
|
4746
|
+
}
|
|
4747
|
+
class Oe {
|
|
4748
|
+
topology;
|
|
4749
|
+
sceneCleanups = /* @__PURE__ */ new Map();
|
|
4750
|
+
_onSceneAdded;
|
|
4751
|
+
_onSceneRemoved;
|
|
4752
|
+
_onSceneSwitched;
|
|
4753
|
+
_onItemPointerDown;
|
|
4754
|
+
_onItemPointerUp;
|
|
4755
|
+
_onItemPointerOver;
|
|
4756
|
+
_onItemPointerOut;
|
|
4757
|
+
install(e) {
|
|
4758
|
+
this.topology = e;
|
|
4759
|
+
for (const i of e.getSceneIds()) {
|
|
4760
|
+
const n = e.getScene(i);
|
|
4761
|
+
n && this.invokeHookScene(n);
|
|
4762
|
+
}
|
|
4763
|
+
this._onSceneAdded = (i) => this.invokeHookScene(i), this._onSceneRemoved = ({ id: i }) => {
|
|
4764
|
+
this.unhookScene(i), this.onSceneRemoved(i);
|
|
4765
|
+
}, this._onSceneSwitched = (i) => this.onSceneSwitched(i), this._onItemPointerDown = (i) => this.onItemPointerDown(i), this._onItemPointerUp = (i) => this.onItemPointerUp(i), this._onItemPointerOver = (i) => this.onItemPointerOver(i), this._onItemPointerOut = (i) => this.onItemPointerOut(i), e.on("scene:added", this._onSceneAdded), e.on("scene:removed", this._onSceneRemoved), e.on("scene:switched", this._onSceneSwitched), e.on("item:pointerdown", this._onItemPointerDown), e.on("item:pointerup", this._onItemPointerUp), e.on("item:pointerover", this._onItemPointerOver), e.on("item:pointerout", this._onItemPointerOut);
|
|
4606
4766
|
}
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4767
|
+
uninstall(e) {
|
|
4768
|
+
for (const [i] of this.sceneCleanups) this.unhookScene(i);
|
|
4769
|
+
this._onSceneAdded && e.off("scene:added", this._onSceneAdded), this._onSceneRemoved && e.off("scene:removed", this._onSceneRemoved), this._onSceneSwitched && e.off("scene:switched", this._onSceneSwitched), this._onItemPointerDown && e.off("item:pointerdown", this._onItemPointerDown), this._onItemPointerUp && e.off("item:pointerup", this._onItemPointerUp), this._onItemPointerOver && e.off("item:pointerover", this._onItemPointerOver), this._onItemPointerOut && e.off("item:pointerout", this._onItemPointerOut), this._onSceneAdded = void 0, this._onSceneRemoved = void 0, this._onSceneSwitched = void 0, this._onItemPointerDown = void 0, this._onItemPointerUp = void 0, this._onItemPointerOver = void 0, this._onItemPointerOut = void 0, this.topology = void 0;
|
|
4610
4770
|
}
|
|
4611
|
-
|
|
4612
|
-
this.
|
|
4771
|
+
unhookScene(e) {
|
|
4772
|
+
const i = this.sceneCleanups.get(e);
|
|
4773
|
+
i && (i(), this.sceneCleanups.delete(e));
|
|
4613
4774
|
}
|
|
4614
|
-
|
|
4615
|
-
|
|
4775
|
+
invokeHookScene(e) {
|
|
4776
|
+
const i = this.hookScene(e);
|
|
4777
|
+
i && this.sceneCleanups.set(e.id, i);
|
|
4616
4778
|
}
|
|
4617
|
-
|
|
4618
|
-
this.resources.noiseUniforms.uniforms.uSeed = e;
|
|
4779
|
+
onItemPointerDown(e) {
|
|
4619
4780
|
}
|
|
4620
|
-
|
|
4621
|
-
function Df(t, e) {
|
|
4622
|
-
const i = e?.intensity ?? 0.15;
|
|
4623
|
-
let n = e?.animated ?? !0;
|
|
4624
|
-
return {
|
|
4625
|
-
postProcessId: t,
|
|
4626
|
-
createFilter() {
|
|
4627
|
-
return new Pc({ intensity: i });
|
|
4628
|
-
},
|
|
4629
|
-
onUpdate(r, s) {
|
|
4630
|
-
n && (r.seed = Math.random());
|
|
4631
|
-
},
|
|
4632
|
-
setOptions(r, s) {
|
|
4633
|
-
const o = r;
|
|
4634
|
-
s.intensity !== void 0 && (o.intensity = s.intensity), s.animated !== void 0 && (n = s.animated);
|
|
4635
|
-
}
|
|
4636
|
-
};
|
|
4637
|
-
}
|
|
4638
|
-
const Mc = (
|
|
4639
|
-
/* glsl */
|
|
4640
|
-
`
|
|
4641
|
-
in vec2 aPosition;
|
|
4642
|
-
out vec2 vTextureCoord;
|
|
4643
|
-
|
|
4644
|
-
uniform vec4 uInputSize;
|
|
4645
|
-
uniform vec4 uOutputFrame;
|
|
4646
|
-
uniform vec4 uOutputTexture;
|
|
4647
|
-
|
|
4648
|
-
vec4 filterVertexPosition(void)
|
|
4649
|
-
{
|
|
4650
|
-
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
|
|
4651
|
-
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
|
|
4652
|
-
position.y = position.y * (2.0 * uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
|
|
4653
|
-
return vec4(position, 0.0, 1.0);
|
|
4654
|
-
}
|
|
4655
|
-
|
|
4656
|
-
vec2 filterTextureCoord(void)
|
|
4657
|
-
{
|
|
4658
|
-
return aPosition * (uOutputFrame.zw * uInputSize.zw);
|
|
4659
|
-
}
|
|
4660
|
-
|
|
4661
|
-
void main(void)
|
|
4662
|
-
{
|
|
4663
|
-
gl_Position = filterVertexPosition();
|
|
4664
|
-
vTextureCoord = filterTextureCoord();
|
|
4665
|
-
}
|
|
4666
|
-
`
|
|
4667
|
-
), Ec = (
|
|
4668
|
-
/* glsl */
|
|
4669
|
-
`
|
|
4670
|
-
precision highp float;
|
|
4671
|
-
|
|
4672
|
-
in vec2 vTextureCoord;
|
|
4673
|
-
out vec4 finalColor;
|
|
4674
|
-
|
|
4675
|
-
uniform sampler2D uTexture;
|
|
4676
|
-
uniform vec4 uInputSize;
|
|
4677
|
-
uniform vec4 uOutputFrame;
|
|
4678
|
-
uniform float uOffset;
|
|
4679
|
-
uniform vec2 uDirection;
|
|
4680
|
-
|
|
4681
|
-
void main(void)
|
|
4682
|
-
{
|
|
4683
|
-
// 将归一化 0.5 中心映射到实际纹理坐标空间
|
|
4684
|
-
vec2 texCenter = vec2(0.5) * (uOutputFrame.zw * uInputSize.zw);
|
|
4685
|
-
// 从中心到当前像素的方向
|
|
4686
|
-
vec2 center = vTextureCoord - texCenter;
|
|
4687
|
-
vec2 dir = normalize(center) * uOffset * 0.01;
|
|
4688
|
-
|
|
4689
|
-
// 沿径向偏移采样 RGB 三通道
|
|
4690
|
-
float r = texture(uTexture, vTextureCoord + dir).r;
|
|
4691
|
-
float g = texture(uTexture, vTextureCoord).g;
|
|
4692
|
-
float b = texture(uTexture, vTextureCoord - dir).b;
|
|
4693
|
-
float a = texture(uTexture, vTextureCoord).a;
|
|
4694
|
-
|
|
4695
|
-
finalColor = vec4(r, g, b, a);
|
|
4696
|
-
}
|
|
4697
|
-
`
|
|
4698
|
-
);
|
|
4699
|
-
class Lc extends G {
|
|
4700
|
-
constructor(e = {}) {
|
|
4701
|
-
const i = e.offset ?? 3, n = U.from({
|
|
4702
|
-
vertex: Mc,
|
|
4703
|
-
fragment: Ec,
|
|
4704
|
-
name: "chromatic-aberration-filter"
|
|
4705
|
-
});
|
|
4706
|
-
super({
|
|
4707
|
-
glProgram: n,
|
|
4708
|
-
resources: {
|
|
4709
|
-
chromaticUniforms: new H({
|
|
4710
|
-
uOffset: { value: i, type: "f32" },
|
|
4711
|
-
uDirection: { value: new Float32Array([1, 1]), type: "vec2<f32>" }
|
|
4712
|
-
})
|
|
4713
|
-
}
|
|
4714
|
-
});
|
|
4781
|
+
onItemPointerUp(e) {
|
|
4715
4782
|
}
|
|
4716
|
-
|
|
4717
|
-
get offset() {
|
|
4718
|
-
return this.resources.chromaticUniforms.uniforms.uOffset;
|
|
4783
|
+
onItemPointerOver(e) {
|
|
4719
4784
|
}
|
|
4720
|
-
|
|
4721
|
-
|
|
4785
|
+
onItemPointerOut(e) {
|
|
4786
|
+
}
|
|
4787
|
+
onSceneSwitched(e) {
|
|
4788
|
+
}
|
|
4789
|
+
onSceneRemoved(e) {
|
|
4722
4790
|
}
|
|
4723
4791
|
}
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
|
|
4727
|
-
postProcessId: t,
|
|
4728
|
-
createFilter() {
|
|
4729
|
-
return new Lc({ offset: i });
|
|
4730
|
-
},
|
|
4731
|
-
setOptions(n, r) {
|
|
4732
|
-
const s = n;
|
|
4733
|
-
r.offset !== void 0 && (s.offset = r.offset);
|
|
4734
|
-
}
|
|
4735
|
-
};
|
|
4736
|
-
}
|
|
4737
|
-
const kc = (
|
|
4738
|
-
/* glsl */
|
|
4739
|
-
`
|
|
4740
|
-
in vec2 aPosition;
|
|
4741
|
-
out vec2 vTextureCoord;
|
|
4742
|
-
|
|
4743
|
-
uniform vec4 uInputSize;
|
|
4744
|
-
uniform vec4 uOutputFrame;
|
|
4745
|
-
uniform vec4 uOutputTexture;
|
|
4746
|
-
|
|
4747
|
-
vec4 filterVertexPosition(void)
|
|
4748
|
-
{
|
|
4749
|
-
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
|
|
4750
|
-
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
|
|
4751
|
-
position.y = position.y * (2.0 * uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
|
|
4752
|
-
return vec4(position, 0.0, 1.0);
|
|
4753
|
-
}
|
|
4754
|
-
|
|
4755
|
-
vec2 filterTextureCoord(void)
|
|
4756
|
-
{
|
|
4757
|
-
return aPosition * (uOutputFrame.zw * uInputSize.zw);
|
|
4758
|
-
}
|
|
4759
|
-
|
|
4760
|
-
void main(void)
|
|
4761
|
-
{
|
|
4762
|
-
gl_Position = filterVertexPosition();
|
|
4763
|
-
vTextureCoord = filterTextureCoord();
|
|
4764
|
-
}
|
|
4765
|
-
`
|
|
4766
|
-
), Fc = (
|
|
4767
|
-
/* glsl */
|
|
4768
|
-
`
|
|
4769
|
-
precision highp float;
|
|
4770
|
-
|
|
4771
|
-
in vec2 vTextureCoord;
|
|
4772
|
-
out vec4 finalColor;
|
|
4773
|
-
|
|
4774
|
-
uniform sampler2D uTexture;
|
|
4775
|
-
uniform vec4 uInputSize;
|
|
4776
|
-
uniform float uLineWidth;
|
|
4777
|
-
uniform float uIntensity;
|
|
4778
|
-
uniform float uOffset;
|
|
4779
|
-
|
|
4780
|
-
void main(void)
|
|
4781
|
-
{
|
|
4782
|
-
vec4 original = texture(uTexture, vTextureCoord);
|
|
4783
|
-
|
|
4784
|
-
// 按像素行计算扫描线
|
|
4785
|
-
float y = vTextureCoord.y * uInputSize.y + uOffset;
|
|
4786
|
-
float scanline = step(0.5, fract(y / uLineWidth));
|
|
4787
|
-
|
|
4788
|
-
// 暗行降低亮度
|
|
4789
|
-
float factor = 1.0 - scanline * uIntensity;
|
|
4790
|
-
|
|
4791
|
-
finalColor = vec4(original.rgb * factor, original.a);
|
|
4792
|
-
}
|
|
4793
|
-
`
|
|
4794
|
-
);
|
|
4795
|
-
class Rc extends G {
|
|
4796
|
-
constructor(e = {}) {
|
|
4797
|
-
const i = e.lineWidth ?? 2, n = e.intensity ?? 0.3, r = e.offset ?? 0, s = U.from({
|
|
4798
|
-
vertex: kc,
|
|
4799
|
-
fragment: Fc,
|
|
4800
|
-
name: "scanlines-filter"
|
|
4801
|
-
});
|
|
4802
|
-
super({
|
|
4803
|
-
glProgram: s,
|
|
4804
|
-
resources: {
|
|
4805
|
-
scanlinesUniforms: new H({
|
|
4806
|
-
uLineWidth: { value: i, type: "f32" },
|
|
4807
|
-
uIntensity: { value: n, type: "f32" },
|
|
4808
|
-
uOffset: { value: r, type: "f32" }
|
|
4809
|
-
})
|
|
4810
|
-
}
|
|
4811
|
-
});
|
|
4792
|
+
class Oi extends Oe {
|
|
4793
|
+
activeScene;
|
|
4794
|
+
hookScene(e) {
|
|
4812
4795
|
}
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
return this.resources.scanlinesUniforms.uniforms.uLineWidth;
|
|
4796
|
+
install(e) {
|
|
4797
|
+
super.install(e), e.activeScene && this.bindActive(e.activeScene);
|
|
4816
4798
|
}
|
|
4817
|
-
|
|
4818
|
-
this.
|
|
4799
|
+
onSceneSwitched({ to: e }) {
|
|
4800
|
+
this.unbindActive(), this.bindActive(e);
|
|
4819
4801
|
}
|
|
4820
|
-
|
|
4821
|
-
|
|
4802
|
+
onSceneRemoved(e) {
|
|
4803
|
+
this.activeScene?.id === e && (this.onUnbindActiveScene(), this.activeScene = void 0);
|
|
4822
4804
|
}
|
|
4823
|
-
|
|
4824
|
-
this.
|
|
4805
|
+
bindActive(e) {
|
|
4806
|
+
this.activeScene = e, this.onBindActiveScene(e);
|
|
4825
4807
|
}
|
|
4826
|
-
|
|
4827
|
-
|
|
4808
|
+
unbindActive() {
|
|
4809
|
+
this.activeScene && (this.onUnbindActiveScene(), this.activeScene = void 0);
|
|
4810
|
+
}
|
|
4811
|
+
uninstall(e) {
|
|
4812
|
+
this.unbindActive(), super.uninstall(e);
|
|
4813
|
+
}
|
|
4814
|
+
}
|
|
4815
|
+
class Nc extends Oi {
|
|
4816
|
+
name = "hit-test";
|
|
4817
|
+
_enabled = !0;
|
|
4818
|
+
_hoveredItemId = null;
|
|
4819
|
+
_hoveredItemType = null;
|
|
4820
|
+
get enabled() {
|
|
4821
|
+
return this._enabled;
|
|
4822
|
+
}
|
|
4823
|
+
set enabled(e) {
|
|
4824
|
+
this._enabled = e;
|
|
4825
|
+
}
|
|
4826
|
+
_handlers;
|
|
4827
|
+
onBindActiveScene(e) {
|
|
4828
|
+
const i = this.topology, n = i.app.stage, r = (c) => {
|
|
4829
|
+
let l = c.target;
|
|
4830
|
+
for (; l && l !== n; ) {
|
|
4831
|
+
const h = Ta(l);
|
|
4832
|
+
if (h) {
|
|
4833
|
+
const { itemType: u, itemId: f } = h;
|
|
4834
|
+
return { itemType: u, itemId: f };
|
|
4835
|
+
}
|
|
4836
|
+
l = l.parent;
|
|
4837
|
+
}
|
|
4838
|
+
return { itemType: null, itemId: null };
|
|
4839
|
+
}, s = (c) => {
|
|
4840
|
+
if (!this._enabled) return;
|
|
4841
|
+
const { itemType: l, itemId: h } = r(c);
|
|
4842
|
+
i.emit("item:pointerdown", { itemType: l, itemId: h, sceneId: e.id, event: c });
|
|
4843
|
+
}, o = (c) => {
|
|
4844
|
+
if (!this._enabled) return;
|
|
4845
|
+
const { itemType: l, itemId: h } = r(c);
|
|
4846
|
+
i.emit("item:pointerup", { itemType: l, itemId: h, sceneId: e.id, event: c });
|
|
4847
|
+
}, a = (c) => {
|
|
4848
|
+
if (!this._enabled) return;
|
|
4849
|
+
const { itemType: l, itemId: h } = r(c);
|
|
4850
|
+
(this._hoveredItemId !== h || this._hoveredItemType !== l) && (this._hoveredItemId !== null && this._hoveredItemType !== null && i.emit("item:pointerout", {
|
|
4851
|
+
itemType: this._hoveredItemType,
|
|
4852
|
+
itemId: this._hoveredItemId,
|
|
4853
|
+
sceneId: e.id,
|
|
4854
|
+
event: c
|
|
4855
|
+
}), h !== null && l !== null && i.emit("item:pointerover", { itemType: l, itemId: h, sceneId: e.id, event: c }), this._hoveredItemId = h, this._hoveredItemType = l);
|
|
4856
|
+
};
|
|
4857
|
+
n.on("pointerdown", s), n.on("pointerup", o), n.on("pointermove", a), this._handlers = { onPointerDown: s, onPointerUp: o, onPointerMove: a };
|
|
4828
4858
|
}
|
|
4829
|
-
|
|
4830
|
-
this.
|
|
4859
|
+
onUnbindActiveScene() {
|
|
4860
|
+
if (!this._handlers) return;
|
|
4861
|
+
const e = this.topology?.app.stage;
|
|
4862
|
+
e && (e.off("pointerdown", this._handlers.onPointerDown), e.off("pointerup", this._handlers.onPointerUp), e.off("pointermove", this._handlers.onPointerMove)), this._handlers = void 0, this._hoveredItemId = null, this._hoveredItemType = null;
|
|
4831
4863
|
}
|
|
4832
4864
|
}
|
|
4833
|
-
|
|
4834
|
-
|
|
4835
|
-
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
r && (o += s * c, a.offset = o);
|
|
4843
|
-
},
|
|
4844
|
-
setOptions(a, c) {
|
|
4845
|
-
const l = a;
|
|
4846
|
-
c.lineWidth !== void 0 && (l.lineWidth = c.lineWidth), c.intensity !== void 0 && (l.intensity = c.intensity), c.animated !== void 0 && (r = c.animated), c.speed !== void 0 && (s = c.speed);
|
|
4847
|
-
}
|
|
4848
|
-
};
|
|
4849
|
-
}
|
|
4850
|
-
const Dc = (
|
|
4851
|
-
/* glsl */
|
|
4852
|
-
`
|
|
4853
|
-
in vec2 aPosition;
|
|
4854
|
-
out vec2 vTextureCoord;
|
|
4855
|
-
|
|
4856
|
-
uniform vec4 uInputSize;
|
|
4857
|
-
uniform vec4 uOutputFrame;
|
|
4858
|
-
uniform vec4 uOutputTexture;
|
|
4859
|
-
|
|
4860
|
-
vec4 filterVertexPosition(void)
|
|
4861
|
-
{
|
|
4862
|
-
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
|
|
4863
|
-
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
|
|
4864
|
-
position.y = position.y * (2.0 * uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
|
|
4865
|
-
return vec4(position, 0.0, 1.0);
|
|
4866
|
-
}
|
|
4867
|
-
|
|
4868
|
-
vec2 filterTextureCoord(void)
|
|
4869
|
-
{
|
|
4870
|
-
return aPosition * (uOutputFrame.zw * uInputSize.zw);
|
|
4871
|
-
}
|
|
4872
|
-
|
|
4873
|
-
void main(void)
|
|
4874
|
-
{
|
|
4875
|
-
gl_Position = filterVertexPosition();
|
|
4876
|
-
vTextureCoord = filterTextureCoord();
|
|
4877
|
-
}
|
|
4878
|
-
`
|
|
4879
|
-
), zc = (
|
|
4880
|
-
/* glsl */
|
|
4881
|
-
`
|
|
4882
|
-
precision highp float;
|
|
4883
|
-
|
|
4884
|
-
in vec2 vTextureCoord;
|
|
4885
|
-
out vec4 finalColor;
|
|
4886
|
-
|
|
4887
|
-
uniform sampler2D uTexture;
|
|
4888
|
-
uniform vec4 uInputSize;
|
|
4889
|
-
uniform vec4 uOutputFrame;
|
|
4890
|
-
uniform vec2 uCenter;
|
|
4891
|
-
uniform float uIntensity;
|
|
4892
|
-
uniform float uDecay;
|
|
4893
|
-
uniform float uDensity;
|
|
4894
|
-
uniform float uWeight;
|
|
4895
|
-
|
|
4896
|
-
const int NUM_SAMPLES = 30;
|
|
4897
|
-
|
|
4898
|
-
void main(void)
|
|
4899
|
-
{
|
|
4900
|
-
vec2 texCoord = vTextureCoord;
|
|
4901
|
-
// 将归一化 0~1 的光源中心映射到实际纹理坐标空间
|
|
4902
|
-
vec2 center = uCenter * (uOutputFrame.zw * uInputSize.zw);
|
|
4903
|
-
vec2 deltaTexCoord = (texCoord - center) * (1.0 / float(NUM_SAMPLES)) * uDensity;
|
|
4904
|
-
|
|
4905
|
-
vec4 color = texture(uTexture, texCoord);
|
|
4906
|
-
float illuminationDecay = 1.0;
|
|
4907
|
-
|
|
4908
|
-
for (int i = 0; i < NUM_SAMPLES; i++) {
|
|
4909
|
-
texCoord -= deltaTexCoord;
|
|
4910
|
-
vec4 samp = texture(uTexture, texCoord);
|
|
4911
|
-
samp *= illuminationDecay * uWeight;
|
|
4912
|
-
color += samp;
|
|
4913
|
-
illuminationDecay *= uDecay;
|
|
4865
|
+
class $c extends le {
|
|
4866
|
+
icons = /* @__PURE__ */ new Map();
|
|
4867
|
+
textureCache = /* @__PURE__ */ new Map();
|
|
4868
|
+
loading = /* @__PURE__ */ new Map();
|
|
4869
|
+
/** 添加或批量添加图标 */
|
|
4870
|
+
add(e) {
|
|
4871
|
+
for (const i of Array.isArray(e) ? e : [e]) {
|
|
4872
|
+
const { id: n } = i, r = this.icons.has(n);
|
|
4873
|
+
this.icons.set(n, i), r ? (this.textureCache.delete(n), this.loading.delete(n), this.emit("icon:updated", i)) : this.emit("icon:added", i);
|
|
4914
4874
|
}
|
|
4915
|
-
|
|
4916
|
-
vec4 original = texture(uTexture, vTextureCoord);
|
|
4917
|
-
finalColor = mix(original, color * uIntensity / float(NUM_SAMPLES), uIntensity);
|
|
4918
|
-
}
|
|
4919
|
-
`
|
|
4920
|
-
);
|
|
4921
|
-
class Nc extends G {
|
|
4922
|
-
constructor(e = {}) {
|
|
4923
|
-
const i = e.centerX ?? 0.5, n = e.centerY ?? 0.5, r = e.intensity ?? 0.3, s = e.decay ?? 0.96, o = e.density ?? 1, a = e.weight ?? 0.5, c = U.from({
|
|
4924
|
-
vertex: Dc,
|
|
4925
|
-
fragment: zc,
|
|
4926
|
-
name: "god-rays-filter"
|
|
4927
|
-
});
|
|
4928
|
-
super({
|
|
4929
|
-
glProgram: c,
|
|
4930
|
-
resources: {
|
|
4931
|
-
godRaysUniforms: new H({
|
|
4932
|
-
uCenter: { value: new Float32Array([i, n]), type: "vec2<f32>" },
|
|
4933
|
-
uIntensity: { value: r, type: "f32" },
|
|
4934
|
-
uDecay: { value: s, type: "f32" },
|
|
4935
|
-
uDensity: { value: o, type: "f32" },
|
|
4936
|
-
uWeight: { value: a, type: "f32" }
|
|
4937
|
-
})
|
|
4938
|
-
}
|
|
4939
|
-
});
|
|
4875
|
+
return this;
|
|
4940
4876
|
}
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
return this.
|
|
4877
|
+
/** 删除图标(按 id) */
|
|
4878
|
+
remove(e) {
|
|
4879
|
+
return this.icons.delete(e) ? (this.textureCache.delete(e), this.loading.delete(e), this.emit("icon:removed", { id: e }), !0) : !1;
|
|
4944
4880
|
}
|
|
4945
|
-
|
|
4946
|
-
|
|
4881
|
+
/** 获取图标 URL(按 id) */
|
|
4882
|
+
getUrl(e) {
|
|
4883
|
+
return this.icons.get(e)?.url;
|
|
4947
4884
|
}
|
|
4948
|
-
|
|
4949
|
-
|
|
4885
|
+
/** 获取图标完整信息(按 id) */
|
|
4886
|
+
get(e) {
|
|
4887
|
+
return this.icons.get(e);
|
|
4950
4888
|
}
|
|
4951
|
-
|
|
4952
|
-
|
|
4889
|
+
/** 是否已注册(按 id) */
|
|
4890
|
+
has(e) {
|
|
4891
|
+
return this.icons.has(e);
|
|
4953
4892
|
}
|
|
4954
|
-
|
|
4955
|
-
|
|
4893
|
+
/** 获取所有图标 */
|
|
4894
|
+
getAll() {
|
|
4895
|
+
return [...this.icons.values()];
|
|
4956
4896
|
}
|
|
4957
|
-
|
|
4958
|
-
|
|
4897
|
+
/**
|
|
4898
|
+
* 加载图标纹理,自动缓存。
|
|
4899
|
+
* 参数为图标 id;若 id 未注册则当作 URL 直接加载。
|
|
4900
|
+
*/
|
|
4901
|
+
async loadTexture(e) {
|
|
4902
|
+
const i = this.textureCache.get(e);
|
|
4903
|
+
if (i) return i;
|
|
4904
|
+
const n = this.loading.get(e);
|
|
4905
|
+
if (n) return n;
|
|
4906
|
+
const r = this.icons.get(e)?.url ?? e, s = gi.load(r).then((o) => (this.textureCache.set(e, o), this.loading.delete(e), o));
|
|
4907
|
+
return this.loading.set(e, s), s;
|
|
4959
4908
|
}
|
|
4960
|
-
|
|
4961
|
-
|
|
4909
|
+
/** 清空所有图标和缓存 */
|
|
4910
|
+
clear() {
|
|
4911
|
+
this.icons.clear(), this.textureCache.clear(), this.loading.clear(), this.emit("icons:cleared");
|
|
4962
4912
|
}
|
|
4963
|
-
|
|
4964
|
-
|
|
4913
|
+
/** 序列化 */
|
|
4914
|
+
toJSON() {
|
|
4915
|
+
return this.getAll();
|
|
4965
4916
|
}
|
|
4966
|
-
|
|
4967
|
-
|
|
4917
|
+
/** 反序列化(追加模式) */
|
|
4918
|
+
fromJSON(e) {
|
|
4919
|
+
this.add(e);
|
|
4968
4920
|
}
|
|
4969
|
-
|
|
4970
|
-
|
|
4921
|
+
/** 序列化为 YAML 字符串 */
|
|
4922
|
+
toYAML() {
|
|
4923
|
+
return be(this.toJSON());
|
|
4971
4924
|
}
|
|
4972
|
-
|
|
4973
|
-
|
|
4925
|
+
/** 从 YAML 字符串反序列化(追加模式) */
|
|
4926
|
+
fromYAML(e) {
|
|
4927
|
+
this.fromJSON(Ce(e));
|
|
4974
4928
|
}
|
|
4975
|
-
|
|
4976
|
-
this.
|
|
4929
|
+
destroy() {
|
|
4930
|
+
this.clear(), this.removeAllListeners();
|
|
4977
4931
|
}
|
|
4978
4932
|
}
|
|
4979
|
-
|
|
4980
|
-
|
|
4933
|
+
const Wt = /* @__PURE__ */ new WeakMap();
|
|
4934
|
+
function Rf(t, e, i) {
|
|
4935
|
+
const n = i?.frequency ?? 2, r = i?.minAlpha ?? 0.2, s = i?.maxAlpha ?? 1;
|
|
4981
4936
|
return {
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4937
|
+
stateId: t,
|
|
4938
|
+
type: e,
|
|
4939
|
+
onEnter(o) {
|
|
4940
|
+
Wt.set(o, { elapsed: 0 });
|
|
4985
4941
|
},
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4942
|
+
onLeave(o) {
|
|
4943
|
+
Wt.delete(o), o.getGraphics().alpha = 1;
|
|
4944
|
+
},
|
|
4945
|
+
onUpdate(o, a) {
|
|
4946
|
+
const c = Wt.get(o);
|
|
4947
|
+
if (!c) return;
|
|
4948
|
+
c.elapsed += a;
|
|
4949
|
+
const l = (Math.sin(c.elapsed * n * Math.PI * 2 / 1e3) + 1) / 2;
|
|
4950
|
+
o.getGraphics().alpha = r + l * (s - r);
|
|
4989
4951
|
}
|
|
4990
4952
|
};
|
|
4991
4953
|
}
|
|
4992
|
-
const
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
5004
|
-
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
4954
|
+
const ot = /* @__PURE__ */ new WeakMap();
|
|
4955
|
+
function Df(t, e, i) {
|
|
4956
|
+
const n = i?.frequency ?? 2, r = i?.height ?? 12;
|
|
4957
|
+
return {
|
|
4958
|
+
stateId: t,
|
|
4959
|
+
type: e,
|
|
4960
|
+
onEnter(s) {
|
|
4961
|
+
const o = s.getGraphics();
|
|
4962
|
+
ot.set(s, { elapsed: 0, origY: o.position.y, origX: o.position.x });
|
|
4963
|
+
},
|
|
4964
|
+
onLeave(s) {
|
|
4965
|
+
const o = ot.get(s);
|
|
4966
|
+
o && (s.getGraphics().position.y = o.origY, s.getGraphics().position.x = o.origX, ot.delete(s));
|
|
4967
|
+
},
|
|
4968
|
+
onUpdate(s, o) {
|
|
4969
|
+
const a = ot.get(s);
|
|
4970
|
+
if (!a) return;
|
|
4971
|
+
a.elapsed += o;
|
|
4972
|
+
const c = Math.abs(Math.sin(a.elapsed * n * Math.PI / 1e3));
|
|
4973
|
+
s.getGraphics().position.y = a.origY - r * c, s.getGraphics().position.x = a.origX - r * c;
|
|
4974
|
+
}
|
|
4975
|
+
};
|
|
5013
4976
|
}
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
4977
|
+
const Ve = /* @__PURE__ */ new WeakMap();
|
|
4978
|
+
function Rt(t) {
|
|
4979
|
+
const e = t.getGraphics(), i = (Ve.get(e) ?? 0) + 1;
|
|
4980
|
+
if (Ve.set(e, i), i > 1) return;
|
|
4981
|
+
const n = e.getLocalBounds(), r = 100, s = 80, o = Math.min(n.x, -r) - s, a = Math.min(n.y, -r) - s, c = Math.max(n.x + n.width, r) + s, l = Math.max(n.y + n.height, r) + s;
|
|
4982
|
+
e.filterArea = new Lt(o, a, c - o, l - a);
|
|
5019
4983
|
}
|
|
5020
|
-
|
|
5021
|
-
),
|
|
5022
|
-
|
|
5023
|
-
`
|
|
5024
|
-
precision highp float;
|
|
5025
|
-
|
|
5026
|
-
in vec2 vTextureCoord;
|
|
5027
|
-
out vec4 finalColor;
|
|
5028
|
-
|
|
5029
|
-
uniform sampler2D uTexture;
|
|
5030
|
-
uniform float uAmount;
|
|
5031
|
-
|
|
5032
|
-
void main(void)
|
|
5033
|
-
{
|
|
5034
|
-
vec4 original = texture(uTexture, vTextureCoord);
|
|
5035
|
-
|
|
5036
|
-
// Rec.709 亮度系数
|
|
5037
|
-
float lum = dot(original.rgb, vec3(0.2126, 0.7152, 0.0722));
|
|
5038
|
-
vec3 gray = vec3(lum);
|
|
5039
|
-
|
|
5040
|
-
// 按 amount 在原色和灰色之间插值
|
|
5041
|
-
vec3 result = mix(original.rgb, gray, uAmount);
|
|
5042
|
-
|
|
5043
|
-
finalColor = vec4(result, original.a);
|
|
4984
|
+
function Dt(t) {
|
|
4985
|
+
const e = t.getGraphics(), i = (Ve.get(e) ?? 1) - 1;
|
|
4986
|
+
i <= 0 ? (Ve.delete(e), e.filterArea = void 0) : Ve.set(e, i);
|
|
5044
4987
|
}
|
|
5045
|
-
|
|
5046
|
-
)
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
4988
|
+
const jt = /* @__PURE__ */ new WeakMap();
|
|
4989
|
+
function zf(t, e, i) {
|
|
4990
|
+
const n = i?.brightness ?? 1.5;
|
|
4991
|
+
return {
|
|
4992
|
+
stateId: t,
|
|
4993
|
+
type: e,
|
|
4994
|
+
onEnter(r) {
|
|
4995
|
+
const s = r.getGraphics(), o = new mi();
|
|
4996
|
+
o.brightness(n, !1), jt.set(r, o), Rt(r), s.filters = [...s.filters ?? [], o];
|
|
4997
|
+
},
|
|
4998
|
+
onLeave(r) {
|
|
4999
|
+
const s = jt.get(r);
|
|
5000
|
+
if (s) {
|
|
5001
|
+
const o = r.getGraphics();
|
|
5002
|
+
o.filters = (o.filters ?? []).filter((a) => a !== s), Dt(r), jt.delete(r);
|
|
5060
5003
|
}
|
|
5061
|
-
}
|
|
5062
|
-
}
|
|
5063
|
-
/* ---------- 便捷存取器 ---------- */
|
|
5064
|
-
get amount() {
|
|
5065
|
-
return this.resources.grayscaleUniforms.uniforms.uAmount;
|
|
5066
|
-
}
|
|
5067
|
-
set amount(e) {
|
|
5068
|
-
this.resources.grayscaleUniforms.uniforms.uAmount = e;
|
|
5069
|
-
}
|
|
5004
|
+
}
|
|
5005
|
+
};
|
|
5070
5006
|
}
|
|
5071
|
-
|
|
5072
|
-
|
|
5007
|
+
const Vt = /* @__PURE__ */ new WeakMap();
|
|
5008
|
+
function Nf(t, e, i) {
|
|
5009
|
+
const n = Math.max(0, Math.min(1, i?.brightness ?? 0.5));
|
|
5073
5010
|
return {
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5011
|
+
stateId: t,
|
|
5012
|
+
type: e,
|
|
5013
|
+
onEnter(r) {
|
|
5014
|
+
const s = r.getGraphics(), o = new mi();
|
|
5015
|
+
o.brightness(n, !1), Vt.set(r, o), Rt(r), s.filters = [...s.filters ?? [], o];
|
|
5077
5016
|
},
|
|
5078
|
-
|
|
5079
|
-
const s =
|
|
5080
|
-
|
|
5017
|
+
onLeave(r) {
|
|
5018
|
+
const s = Vt.get(r);
|
|
5019
|
+
if (s) {
|
|
5020
|
+
const o = r.getGraphics();
|
|
5021
|
+
o.filters = (o.filters ?? []).filter((a) => a !== s), Dt(r), Vt.delete(r);
|
|
5022
|
+
}
|
|
5081
5023
|
}
|
|
5082
5024
|
};
|
|
5083
5025
|
}
|
|
5084
|
-
const
|
|
5026
|
+
const Gc = (
|
|
5085
5027
|
/* glsl */
|
|
5086
5028
|
`
|
|
5087
5029
|
in vec2 aPosition;
|
|
@@ -5110,9 +5052,12 @@ void main(void)
|
|
|
5110
5052
|
vTextureCoord = filterTextureCoord();
|
|
5111
5053
|
}
|
|
5112
5054
|
`
|
|
5113
|
-
)
|
|
5114
|
-
|
|
5115
|
-
|
|
5055
|
+
);
|
|
5056
|
+
function Uc(t) {
|
|
5057
|
+
const e = Math.max(8, Math.round(t * 3)), i = Math.max(2, Math.round(t)), n = e * i;
|
|
5058
|
+
return (
|
|
5059
|
+
/* glsl */
|
|
5060
|
+
`
|
|
5116
5061
|
precision highp float;
|
|
5117
5062
|
|
|
5118
5063
|
in vec2 vTextureCoord;
|
|
@@ -5120,68 +5065,150 @@ out vec4 finalColor;
|
|
|
5120
5065
|
|
|
5121
5066
|
uniform sampler2D uTexture;
|
|
5122
5067
|
uniform vec4 uInputSize;
|
|
5123
|
-
uniform float
|
|
5068
|
+
uniform float uDistance;
|
|
5069
|
+
uniform float uOuterStrength;
|
|
5070
|
+
uniform vec3 uColor;
|
|
5071
|
+
|
|
5072
|
+
const int ANGLE_STEPS = ${e};
|
|
5073
|
+
const int DIST_STEPS = ${i};
|
|
5074
|
+
const float TOTAL = ${n}.0;
|
|
5075
|
+
const float PI2 = 6.28318530718;
|
|
5124
5076
|
|
|
5125
5077
|
void main(void)
|
|
5126
5078
|
{
|
|
5127
|
-
|
|
5079
|
+
vec4 original = texture(uTexture, vTextureCoord);
|
|
5128
5080
|
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
vec4 top = texture(uTexture, vTextureCoord + vec2( 0.0, -step.y));
|
|
5132
|
-
vec4 bottom = texture(uTexture, vTextureCoord + vec2( 0.0, step.y));
|
|
5133
|
-
vec4 left = texture(uTexture, vTextureCoord + vec2(-step.x, 0.0));
|
|
5134
|
-
vec4 right = texture(uTexture, vTextureCoord + vec2( step.x, 0.0));
|
|
5081
|
+
/* ---- 环形采样:累计周围像素的 alpha ---- */
|
|
5082
|
+
float totalAlpha = 0.0;
|
|
5135
5083
|
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5084
|
+
for (int i = 0; i < ANGLE_STEPS; i++) {
|
|
5085
|
+
float angle = float(i) * PI2 / float(ANGLE_STEPS);
|
|
5086
|
+
vec2 dir = vec2(cos(angle), sin(angle));
|
|
5139
5087
|
|
|
5140
|
-
|
|
5141
|
-
|
|
5088
|
+
for (int j = 1; j <= DIST_STEPS; j++) {
|
|
5089
|
+
float pct = float(j) / float(DIST_STEPS);
|
|
5090
|
+
vec2 offset = dir * pct * uDistance * uInputSize.zw;
|
|
5091
|
+
totalAlpha += texture(uTexture, vTextureCoord + offset).a;
|
|
5092
|
+
}
|
|
5093
|
+
}
|
|
5142
5094
|
|
|
5143
|
-
|
|
5095
|
+
totalAlpha /= TOTAL;
|
|
5096
|
+
|
|
5097
|
+
/* ---- 外发光:仅在原始像素透明处显示 ---- */
|
|
5098
|
+
float glowAlpha = clamp(totalAlpha * uOuterStrength * (1.0 - original.a), 0.0, 1.0);
|
|
5099
|
+
|
|
5100
|
+
/* ---- premultiplied-alpha 合成:original 在上,glow 在下 ---- */
|
|
5101
|
+
vec4 glow = vec4(uColor * glowAlpha, glowAlpha);
|
|
5102
|
+
finalColor = original + glow * (1.0 - original.a);
|
|
5144
5103
|
}
|
|
5145
5104
|
`
|
|
5146
|
-
);
|
|
5147
|
-
|
|
5105
|
+
);
|
|
5106
|
+
}
|
|
5107
|
+
class Hc extends G {
|
|
5148
5108
|
constructor(e = {}) {
|
|
5149
|
-
const i = e.
|
|
5150
|
-
vertex:
|
|
5151
|
-
fragment:
|
|
5152
|
-
name: "
|
|
5109
|
+
const i = e.quality ?? 4, n = e.distance ?? 10, r = e.color ?? [1, 1, 0], s = e.outerStrength ?? 4, o = U.from({
|
|
5110
|
+
vertex: Gc,
|
|
5111
|
+
fragment: Uc(i),
|
|
5112
|
+
name: "glow-filter"
|
|
5153
5113
|
});
|
|
5154
5114
|
super({
|
|
5155
|
-
glProgram:
|
|
5115
|
+
glProgram: o,
|
|
5156
5116
|
resources: {
|
|
5157
|
-
|
|
5158
|
-
|
|
5117
|
+
glowUniforms: new H({
|
|
5118
|
+
uDistance: { value: n, type: "f32" },
|
|
5119
|
+
uOuterStrength: { value: s, type: "f32" },
|
|
5120
|
+
uColor: {
|
|
5121
|
+
value: new Float32Array(r),
|
|
5122
|
+
type: "vec3<f32>"
|
|
5123
|
+
}
|
|
5159
5124
|
})
|
|
5160
|
-
}
|
|
5125
|
+
},
|
|
5126
|
+
padding: n + 5
|
|
5161
5127
|
});
|
|
5162
5128
|
}
|
|
5163
5129
|
/* ---------- 便捷存取器 ---------- */
|
|
5164
|
-
get
|
|
5165
|
-
return this.resources.
|
|
5130
|
+
get distance() {
|
|
5131
|
+
return this.resources.glowUniforms.uniforms.uDistance;
|
|
5166
5132
|
}
|
|
5167
|
-
set
|
|
5168
|
-
this.resources.
|
|
5133
|
+
set distance(e) {
|
|
5134
|
+
this.resources.glowUniforms.uniforms.uDistance = e, this.padding = e + 5;
|
|
5135
|
+
}
|
|
5136
|
+
get outerStrength() {
|
|
5137
|
+
return this.resources.glowUniforms.uniforms.uOuterStrength;
|
|
5138
|
+
}
|
|
5139
|
+
set outerStrength(e) {
|
|
5140
|
+
this.resources.glowUniforms.uniforms.uOuterStrength = e;
|
|
5141
|
+
}
|
|
5142
|
+
get color() {
|
|
5143
|
+
return this.resources.glowUniforms.uniforms.uColor;
|
|
5144
|
+
}
|
|
5145
|
+
set color(e) {
|
|
5146
|
+
const i = this.resources.glowUniforms.uniforms.uColor;
|
|
5147
|
+
i[0] = e[0], i[1] = e[1], i[2] = e[2];
|
|
5169
5148
|
}
|
|
5170
5149
|
}
|
|
5171
|
-
|
|
5172
|
-
|
|
5150
|
+
const at = /* @__PURE__ */ new WeakMap();
|
|
5151
|
+
function Yc(t) {
|
|
5152
|
+
return [
|
|
5153
|
+
(t >> 16 & 255) / 255,
|
|
5154
|
+
(t >> 8 & 255) / 255,
|
|
5155
|
+
(t & 255) / 255
|
|
5156
|
+
];
|
|
5157
|
+
}
|
|
5158
|
+
function $f(t, e, i) {
|
|
5159
|
+
const n = i?.color ?? 16776960, r = i?.distance ?? 10, [s, o] = i?.strength ?? [2, 6], a = i?.frequency ?? 1.5, c = i?.quality ?? 4, l = Yc(n);
|
|
5173
5160
|
return {
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5161
|
+
stateId: t,
|
|
5162
|
+
type: e,
|
|
5163
|
+
onEnter(h) {
|
|
5164
|
+
const u = h.getGraphics(), f = new Hc({
|
|
5165
|
+
color: l,
|
|
5166
|
+
distance: r,
|
|
5167
|
+
outerStrength: s,
|
|
5168
|
+
quality: c
|
|
5169
|
+
});
|
|
5170
|
+
at.set(h, { elapsed: 0, filter: f }), Rt(h), u.filters = [...u.filters ?? [], f];
|
|
5177
5171
|
},
|
|
5178
|
-
|
|
5179
|
-
const
|
|
5180
|
-
|
|
5172
|
+
onLeave(h) {
|
|
5173
|
+
const u = at.get(h);
|
|
5174
|
+
if (u) {
|
|
5175
|
+
const f = h.getGraphics();
|
|
5176
|
+
f.filters = (f.filters ?? []).filter((d) => d !== u.filter), Dt(h), at.delete(h);
|
|
5177
|
+
}
|
|
5178
|
+
},
|
|
5179
|
+
onUpdate(h, u) {
|
|
5180
|
+
const f = at.get(h);
|
|
5181
|
+
if (!f) return;
|
|
5182
|
+
f.elapsed += u;
|
|
5183
|
+
const d = (Math.sin(f.elapsed * a * Math.PI * 2 / 1e3) + 1) / 2;
|
|
5184
|
+
f.filter.outerStrength = s + d * (o - s);
|
|
5185
|
+
}
|
|
5186
|
+
};
|
|
5187
|
+
}
|
|
5188
|
+
const ct = /* @__PURE__ */ new WeakMap();
|
|
5189
|
+
function Gf(t, e, i) {
|
|
5190
|
+
const n = i?.frequency ?? 1.2, r = i?.minScale ?? 0.92, s = i?.maxScale ?? 1.08;
|
|
5191
|
+
return {
|
|
5192
|
+
stateId: t,
|
|
5193
|
+
type: e,
|
|
5194
|
+
onEnter(o) {
|
|
5195
|
+
const a = o.getGraphics();
|
|
5196
|
+
ct.set(o, { elapsed: 0, origScaleX: a.scale.x, origScaleY: a.scale.y });
|
|
5197
|
+
},
|
|
5198
|
+
onLeave(o) {
|
|
5199
|
+
const a = ct.get(o);
|
|
5200
|
+
a && (o.getGraphics().scale.set(a.origScaleX, a.origScaleY), ct.delete(o));
|
|
5201
|
+
},
|
|
5202
|
+
onUpdate(o, a) {
|
|
5203
|
+
const c = ct.get(o);
|
|
5204
|
+
if (!c) return;
|
|
5205
|
+
c.elapsed += a;
|
|
5206
|
+
const l = c.elapsed * n / 1e3 % 1, h = Math.pow(Math.abs(Math.sin(l * Math.PI)), 0.6), u = r + h * (s - r);
|
|
5207
|
+
o.getGraphics().scale.set(c.origScaleX * u, c.origScaleY * u);
|
|
5181
5208
|
}
|
|
5182
5209
|
};
|
|
5183
5210
|
}
|
|
5184
|
-
const
|
|
5211
|
+
const Bc = (
|
|
5185
5212
|
/* glsl */
|
|
5186
5213
|
`
|
|
5187
5214
|
in vec2 aPosition;
|
|
@@ -5210,7 +5237,7 @@ void main(void)
|
|
|
5210
5237
|
vTextureCoord = filterTextureCoord();
|
|
5211
5238
|
}
|
|
5212
5239
|
`
|
|
5213
|
-
),
|
|
5240
|
+
), Wc = (
|
|
5214
5241
|
/* glsl */
|
|
5215
5242
|
`
|
|
5216
5243
|
precision highp float;
|
|
@@ -5219,150 +5246,176 @@ in vec2 vTextureCoord;
|
|
|
5219
5246
|
out vec4 finalColor;
|
|
5220
5247
|
|
|
5221
5248
|
uniform sampler2D uTexture;
|
|
5222
|
-
uniform float
|
|
5249
|
+
uniform float uPhase; // 光带中心位置(投影轴坐标)
|
|
5250
|
+
uniform float uWidth; // 光带宽度(投影轴空间)
|
|
5251
|
+
uniform float uIntensity; // 白光峰值强度 0-1
|
|
5252
|
+
uniform float uCosA; // cos(angle)
|
|
5253
|
+
uniform float uSinA; // sin(angle)
|
|
5223
5254
|
|
|
5224
5255
|
void main(void)
|
|
5225
5256
|
{
|
|
5226
5257
|
vec4 original = texture(uTexture, vTextureCoord);
|
|
5227
5258
|
|
|
5228
|
-
//
|
|
5229
|
-
|
|
5259
|
+
// 将纹理坐标投影到扫光方向上
|
|
5260
|
+
float pos = vTextureCoord.x * uCosA + vTextureCoord.y * uSinA;
|
|
5230
5261
|
|
|
5231
|
-
//
|
|
5232
|
-
|
|
5262
|
+
// 计算到光带中心的距离,smooth 衰减
|
|
5263
|
+
float dist = abs(pos - uPhase);
|
|
5264
|
+
float halfW = uWidth * 0.5;
|
|
5265
|
+
float t = 1.0 - smoothstep(0.0, halfW, dist);
|
|
5233
5266
|
|
|
5234
|
-
|
|
5267
|
+
// 仅在不透明区域叠加白光(premultiplied-alpha)
|
|
5268
|
+
float add = t * uIntensity * original.a;
|
|
5269
|
+
vec3 newRgb = min(original.rgb + vec3(add), vec3(original.a));
|
|
5270
|
+
|
|
5271
|
+
finalColor = vec4(newRgb, original.a);
|
|
5235
5272
|
}
|
|
5236
5273
|
`
|
|
5237
5274
|
);
|
|
5238
|
-
class
|
|
5275
|
+
class jc extends G {
|
|
5276
|
+
_angle;
|
|
5239
5277
|
constructor(e = {}) {
|
|
5240
|
-
const i = e.
|
|
5241
|
-
vertex:
|
|
5242
|
-
fragment:
|
|
5243
|
-
name: "
|
|
5278
|
+
const i = e.width ?? 0.35, n = e.intensity ?? 0.6, r = e.angle ?? Math.PI / 6, s = U.from({
|
|
5279
|
+
vertex: Bc,
|
|
5280
|
+
fragment: Wc,
|
|
5281
|
+
name: "shimmer-filter"
|
|
5244
5282
|
});
|
|
5245
5283
|
super({
|
|
5246
|
-
glProgram:
|
|
5284
|
+
glProgram: s,
|
|
5247
5285
|
resources: {
|
|
5248
|
-
|
|
5249
|
-
|
|
5286
|
+
shimmerUniforms: new H({
|
|
5287
|
+
uPhase: { value: 0, type: "f32" },
|
|
5288
|
+
uWidth: { value: i, type: "f32" },
|
|
5289
|
+
uIntensity: { value: n, type: "f32" },
|
|
5290
|
+
uCosA: { value: Math.cos(r), type: "f32" },
|
|
5291
|
+
uSinA: { value: Math.sin(r), type: "f32" }
|
|
5250
5292
|
})
|
|
5251
5293
|
}
|
|
5252
|
-
});
|
|
5294
|
+
}), this._angle = r;
|
|
5253
5295
|
}
|
|
5254
5296
|
/* ---------- 便捷存取器 ---------- */
|
|
5255
|
-
get
|
|
5256
|
-
return this.resources.
|
|
5297
|
+
get phase() {
|
|
5298
|
+
return this.resources.shimmerUniforms.uniforms.uPhase;
|
|
5257
5299
|
}
|
|
5258
|
-
set
|
|
5259
|
-
this.resources.
|
|
5300
|
+
set phase(e) {
|
|
5301
|
+
this.resources.shimmerUniforms.uniforms.uPhase = e;
|
|
5302
|
+
}
|
|
5303
|
+
get width() {
|
|
5304
|
+
return this.resources.shimmerUniforms.uniforms.uWidth;
|
|
5305
|
+
}
|
|
5306
|
+
set width(e) {
|
|
5307
|
+
this.resources.shimmerUniforms.uniforms.uWidth = e;
|
|
5308
|
+
}
|
|
5309
|
+
get intensity() {
|
|
5310
|
+
return this.resources.shimmerUniforms.uniforms.uIntensity;
|
|
5311
|
+
}
|
|
5312
|
+
set intensity(e) {
|
|
5313
|
+
this.resources.shimmerUniforms.uniforms.uIntensity = e;
|
|
5314
|
+
}
|
|
5315
|
+
get angle() {
|
|
5316
|
+
return this._angle;
|
|
5317
|
+
}
|
|
5318
|
+
set angle(e) {
|
|
5319
|
+
this._angle = e, this.resources.shimmerUniforms.uniforms.uCosA = Math.cos(e), this.resources.shimmerUniforms.uniforms.uSinA = Math.sin(e);
|
|
5260
5320
|
}
|
|
5261
5321
|
}
|
|
5262
|
-
|
|
5263
|
-
|
|
5322
|
+
const lt = /* @__PURE__ */ new WeakMap();
|
|
5323
|
+
function Uf(t, e, i) {
|
|
5324
|
+
const n = i?.frequency ?? 0.8, r = i?.width ?? 0.35, s = i?.intensity ?? 0.6, o = i?.angle ?? Math.PI / 6;
|
|
5264
5325
|
return {
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5326
|
+
stateId: t,
|
|
5327
|
+
type: e,
|
|
5328
|
+
onEnter(a) {
|
|
5329
|
+
const c = new jc({ width: r, intensity: s, angle: o }), l = a.getGraphics();
|
|
5330
|
+
Rt(a), l.filters = [...l.filters ?? [], c];
|
|
5331
|
+
const h = Math.abs(Math.cos(o)) + Math.abs(Math.sin(o));
|
|
5332
|
+
lt.set(a, { elapsed: 0, filter: c, maxProj: h });
|
|
5268
5333
|
},
|
|
5269
|
-
|
|
5270
|
-
const
|
|
5271
|
-
|
|
5334
|
+
onLeave(a) {
|
|
5335
|
+
const c = lt.get(a);
|
|
5336
|
+
if (c) {
|
|
5337
|
+
const l = a.getGraphics();
|
|
5338
|
+
l.filters = (l.filters ?? []).filter((h) => h !== c.filter), Dt(a), lt.delete(a);
|
|
5339
|
+
}
|
|
5340
|
+
},
|
|
5341
|
+
onUpdate(a, c) {
|
|
5342
|
+
const l = lt.get(a);
|
|
5343
|
+
if (!l) return;
|
|
5344
|
+
l.elapsed += c;
|
|
5345
|
+
const h = l.elapsed * n / 1e3 % 1, u = r * 0.5, f = l.maxProj + r;
|
|
5346
|
+
l.filter.phase = h * f - u;
|
|
5272
5347
|
}
|
|
5273
5348
|
};
|
|
5274
5349
|
}
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
/**
|
|
5350
|
+
const Xt = /* @__PURE__ */ new WeakMap();
|
|
5351
|
+
function Hf(t, e, i) {
|
|
5352
|
+
const n = i?.color ?? 16711680;
|
|
5353
|
+
return {
|
|
5354
|
+
stateId: t,
|
|
5355
|
+
type: e,
|
|
5356
|
+
onEnter(r) {
|
|
5357
|
+
const s = r.getGraphics();
|
|
5358
|
+
Xt.set(r, s.tint), s.tint = n;
|
|
5359
|
+
},
|
|
5360
|
+
onLeave(r) {
|
|
5361
|
+
const s = Xt.get(r);
|
|
5362
|
+
s !== void 0 && (r.getGraphics().tint = s, Xt.delete(r));
|
|
5363
|
+
}
|
|
5364
|
+
};
|
|
5365
|
+
}
|
|
5366
|
+
class Vc extends le {
|
|
5367
|
+
states = /* @__PURE__ */ new Map();
|
|
5368
|
+
/** stateId → 该状态下所有的插件定义 */
|
|
5369
|
+
plugins = /* @__PURE__ */ new Map();
|
|
5370
|
+
/** 添加或批量添加状态 */
|
|
5296
5371
|
add(e) {
|
|
5297
5372
|
for (const i of Array.isArray(e) ? e : [e]) {
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
this.items.set(i.id, i), this.emit(n ? "postprocess:updated" : "postprocess:added", i);
|
|
5373
|
+
const n = this.states.has(i.id);
|
|
5374
|
+
this.states.set(i.id, i), this.emit(n ? "state:updated" : "state:added", i);
|
|
5301
5375
|
}
|
|
5302
|
-
return this
|
|
5376
|
+
return this;
|
|
5303
5377
|
}
|
|
5304
|
-
/**
|
|
5378
|
+
/** 删除状态(同时清除关联的插件) */
|
|
5305
5379
|
remove(e) {
|
|
5306
|
-
return this.
|
|
5380
|
+
return this.states.delete(e) ? (this.plugins.delete(e), this.emit("state:removed", { id: e }), !0) : !1;
|
|
5307
5381
|
}
|
|
5308
5382
|
get(e) {
|
|
5309
|
-
return this.
|
|
5383
|
+
return this.states.get(e);
|
|
5310
5384
|
}
|
|
5311
5385
|
has(e) {
|
|
5312
|
-
return this.
|
|
5386
|
+
return this.states.has(e);
|
|
5313
5387
|
}
|
|
5314
5388
|
getAll() {
|
|
5315
|
-
return [...this.
|
|
5389
|
+
return [...this.states.values()];
|
|
5316
5390
|
}
|
|
5317
5391
|
clear() {
|
|
5318
|
-
this.
|
|
5319
|
-
}
|
|
5320
|
-
/** 启用后期处理效果 */
|
|
5321
|
-
enable(e) {
|
|
5322
|
-
const i = this.items.get(e);
|
|
5323
|
-
return i && !i.enabled && (i.enabled = !0, this.emit("postprocess:enabled", { id: e }), this.rebuildFilters()), this;
|
|
5392
|
+
this.states.clear(), this.plugins.clear(), this.emit("states:cleared");
|
|
5324
5393
|
}
|
|
5325
|
-
/**
|
|
5326
|
-
|
|
5327
|
-
const i = this.
|
|
5328
|
-
return i
|
|
5394
|
+
/** 注册状态插件 */
|
|
5395
|
+
registerPlugin(e) {
|
|
5396
|
+
const i = this.plugins.get(e.stateId) ?? [];
|
|
5397
|
+
return i.push(e), this.plugins.set(e.stateId, i), this;
|
|
5329
5398
|
}
|
|
5330
|
-
/**
|
|
5331
|
-
|
|
5332
|
-
|
|
5399
|
+
/** 注销指定 stateId + type 的所有插件 */
|
|
5400
|
+
unregisterPlugin(e, i) {
|
|
5401
|
+
const n = this.plugins.get(e);
|
|
5402
|
+
if (n) {
|
|
5403
|
+
const r = n.filter((s) => s.type !== i);
|
|
5404
|
+
r.length ? this.plugins.set(e, r) : this.plugins.delete(e);
|
|
5405
|
+
}
|
|
5406
|
+
return this;
|
|
5333
5407
|
}
|
|
5334
|
-
/**
|
|
5335
|
-
|
|
5336
|
-
return this.
|
|
5408
|
+
/** 获取匹配 stateId + type 的插件列表 */
|
|
5409
|
+
getPlugins(e, i) {
|
|
5410
|
+
return (this.plugins.get(e) ?? []).filter((n) => n.type === i);
|
|
5337
5411
|
}
|
|
5338
|
-
/**
|
|
5412
|
+
/** 获取状态权重,未定义时为 0 */
|
|
5339
5413
|
getWeight(e) {
|
|
5340
|
-
return this.
|
|
5341
|
-
}
|
|
5342
|
-
/** 获取运行时 Filter 实例(供调试用) */
|
|
5343
|
-
getFilter(e) {
|
|
5344
|
-
return this.filters.get(e);
|
|
5345
|
-
}
|
|
5346
|
-
/**
|
|
5347
|
-
* 热更新后期处理参数,直接修改运行时 Filter 的 uniform,无需销毁重建。
|
|
5348
|
-
* 仅当对应 PostProcessDef 实现了 setOptions 时生效。
|
|
5349
|
-
* 不支持热更新的参数(如 bloom 的 samples)需重新调用 register 重建。
|
|
5350
|
-
*/
|
|
5351
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5352
|
-
updateOptions(e, i) {
|
|
5353
|
-
const n = this.filters.get(e), r = this.defs.get(e);
|
|
5354
|
-
return n && r?.setOptions && r.setOptions(n, i), this;
|
|
5414
|
+
return this.states.get(e)?.weight ?? 0;
|
|
5355
5415
|
}
|
|
5356
|
-
/**
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
for (const [i, n] of this.defs) {
|
|
5360
|
-
if (!n.onUpdate) continue;
|
|
5361
|
-
const r = this.items.get(i);
|
|
5362
|
-
if (!r || r.enabled === !1) continue;
|
|
5363
|
-
const s = this.filters.get(i);
|
|
5364
|
-
s && n.onUpdate(s, e);
|
|
5365
|
-
}
|
|
5416
|
+
/** 按权重升序排列 stateId 列表 */
|
|
5417
|
+
sortByWeight(e) {
|
|
5418
|
+
return [...e].sort((i, n) => this.getWeight(i) - this.getWeight(n));
|
|
5366
5419
|
}
|
|
5367
5420
|
/** 序列化(仅元数据,插件为运行时代码不参与序列化) */
|
|
5368
5421
|
toJSON() {
|
|
@@ -5379,64 +5432,13 @@ class Oi extends le {
|
|
|
5379
5432
|
this.fromJSON(Ce(e));
|
|
5380
5433
|
}
|
|
5381
5434
|
destroy() {
|
|
5382
|
-
this.
|
|
5383
|
-
}
|
|
5384
|
-
// ========== 内部方法 ==========
|
|
5385
|
-
/**
|
|
5386
|
-
* 计算 filterArea(projectionContainer 局部坐标空间),参考 states/_filter-utils。
|
|
5387
|
-
*
|
|
5388
|
-
* 将视口四角通过 worldTransform 逆变换到容器局部空间,
|
|
5389
|
-
* 加上 pad 以确保 BlurFilter 等带扩展的滤镜不被裁剪。
|
|
5390
|
-
*
|
|
5391
|
-
* **filterArea 走的是独立且正确的路径:**
|
|
5392
|
-
* ```
|
|
5393
|
-
* filterArea(local)
|
|
5394
|
-
* × container.worldTransform → world
|
|
5395
|
-
* × renderGroup.cacheToLocalTransform → render group local ✓
|
|
5396
|
-
* ```
|
|
5397
|
-
*/
|
|
5398
|
-
computeFilterArea() {
|
|
5399
|
-
const e = this._app.screen, i = this._target.worldTransform.clone().invert(), n = i.apply({ x: e.x, y: e.y }), r = i.apply({ x: e.x + e.width, y: e.y }), s = i.apply({ x: e.x + e.width, y: e.y + e.height }), o = i.apply({ x: e.x, y: e.y + e.height }), a = Oi.FILTER_AREA_PAD, c = Math.min(n.x, r.x, s.x, o.x) - a, l = Math.min(n.y, r.y, s.y, o.y) - a, h = Math.max(n.x, r.x, s.x, o.x) + a, u = Math.max(n.y, r.y, s.y, o.y) + a;
|
|
5400
|
-
return new Lt(c, l, h - c, u - l);
|
|
5401
|
-
}
|
|
5402
|
-
/** 按权重升序排列,返回有效(已注册 + 已启用)的 ID 列表 */
|
|
5403
|
-
getActiveIds() {
|
|
5404
|
-
const e = [];
|
|
5405
|
-
for (const [i, n] of this.items)
|
|
5406
|
-
n.enabled !== !1 && this.defs.has(i) && e.push(i);
|
|
5407
|
-
return e.sort((i, n) => this.getWeight(i) - this.getWeight(n));
|
|
5408
|
-
}
|
|
5409
|
-
/** 重建 filters 数组并挂载到目标容器 */
|
|
5410
|
-
rebuildFilters() {
|
|
5411
|
-
if (!this._target) return;
|
|
5412
|
-
const e = this.getActiveIds();
|
|
5413
|
-
for (const [n, r] of this.filters)
|
|
5414
|
-
e.includes(n) || this.destroyFilter(n);
|
|
5415
|
-
for (const n of e)
|
|
5416
|
-
if (!this.filters.has(n)) {
|
|
5417
|
-
const r = this.defs.get(n);
|
|
5418
|
-
this.filters.set(n, r.createFilter());
|
|
5419
|
-
}
|
|
5420
|
-
const i = e.map((n) => this.filters.get(n)).filter(Boolean);
|
|
5421
|
-
i.length > 0 ? (this._target.filterArea = this.computeFilterArea(), this._target.filters = i) : (this._target.filterArea = void 0, this._target.filters = null);
|
|
5422
|
-
}
|
|
5423
|
-
/** 销毁单个滤镜实例 */
|
|
5424
|
-
destroyFilter(e) {
|
|
5425
|
-
const i = this.filters.get(e);
|
|
5426
|
-
i && (this.defs.get(e)?.onDestroy?.(i), i.destroy(), this.filters.delete(e));
|
|
5427
|
-
}
|
|
5428
|
-
/** 清除所有运行时滤镜 */
|
|
5429
|
-
clearFilters() {
|
|
5430
|
-
for (const e of [...this.filters.keys()])
|
|
5431
|
-
this.destroyFilter(e);
|
|
5432
|
-
this._target && (this._target.filters = null);
|
|
5435
|
+
this.clear(), this.removeAllListeners();
|
|
5433
5436
|
}
|
|
5434
5437
|
}
|
|
5435
5438
|
class _r extends le {
|
|
5436
5439
|
_app;
|
|
5437
|
-
icons = new
|
|
5438
|
-
states = new
|
|
5439
|
-
postprocess = new Oi();
|
|
5440
|
+
icons = new $c();
|
|
5441
|
+
states = new Vc();
|
|
5440
5442
|
scenes = /* @__PURE__ */ new Map();
|
|
5441
5443
|
_activeSceneId = null;
|
|
5442
5444
|
_isReady = !1;
|
|
@@ -5469,7 +5471,7 @@ class _r extends le {
|
|
|
5469
5471
|
width: n ?? i.clientWidth,
|
|
5470
5472
|
height: r ?? i.clientHeight,
|
|
5471
5473
|
antialias: !0
|
|
5472
|
-
}), i.appendChild(this._app.canvas), this._app.stage.eventMode = "static", this._app.stage.hitArea = this._app.screen, this._isReady = !0, this.use(new
|
|
5474
|
+
}), i.appendChild(this._app.canvas), this._app.stage.eventMode = "static", this._app.stage.hitArea = this._app.screen, this._isReady = !0, this.use(new Nc()), this.emit("ready");
|
|
5473
5475
|
}
|
|
5474
5476
|
/** 静态工厂方法,创建并初始化 Topology 实例 */
|
|
5475
5477
|
static async create(e) {
|
|
@@ -5484,7 +5486,7 @@ class _r extends le {
|
|
|
5484
5486
|
/** 添加场景,首个场景自动激活 */
|
|
5485
5487
|
addScene(e, i) {
|
|
5486
5488
|
if (this.ensureReady(), this.scenes.has(e)) throw new Error(`Scene "${e}" already exists`);
|
|
5487
|
-
const n = new De(e, this.app, this.icons, this.states
|
|
5489
|
+
const n = new De(e, this.app, this.icons, this.states);
|
|
5488
5490
|
return this.scenes.set(e, n), i && n.fromJSON(i), !this._isBatchLoading && this.scenes.size === 1 ? this.switchScene(e) : n.setActive(!1), this.emit("scene:added", n), n;
|
|
5489
5491
|
}
|
|
5490
5492
|
removeScene(e) {
|
|
@@ -5560,13 +5562,12 @@ class _r extends le {
|
|
|
5560
5562
|
scenes: e,
|
|
5561
5563
|
icons: this.icons.toJSON(),
|
|
5562
5564
|
states: this.states.toJSON(),
|
|
5563
|
-
postprocess: this.postprocess.toJSON(),
|
|
5564
5565
|
_activeSceneId: this._activeSceneId ?? void 0
|
|
5565
5566
|
};
|
|
5566
5567
|
}
|
|
5567
5568
|
fromJSON(e) {
|
|
5568
5569
|
for (const n of [...this.scenes.keys()]) this.removeScene(n);
|
|
5569
|
-
e.icons && this.icons.fromJSON(e.icons), e.states && this.states.fromJSON(e.states),
|
|
5570
|
+
e.icons && this.icons.fromJSON(e.icons), e.states && this.states.fromJSON(e.states), this._isBatchLoading = !0;
|
|
5570
5571
|
for (const [n, r] of Object.entries(e.scenes))
|
|
5571
5572
|
this.addScene(n, r);
|
|
5572
5573
|
this._isBatchLoading = !1;
|
|
@@ -5665,7 +5666,7 @@ class _r extends le {
|
|
|
5665
5666
|
e.uninstall(this);
|
|
5666
5667
|
this.plugins.clear();
|
|
5667
5668
|
for (const e of [...this.scenes.keys()]) this.removeScene(e);
|
|
5668
|
-
this.icons.clear(), this.states.clear(),
|
|
5669
|
+
this.icons.clear(), this.states.clear(), ka(), this.emit("destroyed"), this.removeAllListeners(), this.app?.destroy(!0), this._isReady = !1;
|
|
5669
5670
|
}
|
|
5670
5671
|
}
|
|
5671
5672
|
class Pe extends Oe {
|
|
@@ -7450,7 +7451,7 @@ function ff(t) {
|
|
|
7450
7451
|
}
|
|
7451
7452
|
nt.prototype.interrupt = Gh;
|
|
7452
7453
|
nt.prototype.transition = ff;
|
|
7453
|
-
class Yf extends
|
|
7454
|
+
class Yf extends Oi {
|
|
7454
7455
|
name = "viewport";
|
|
7455
7456
|
minScale;
|
|
7456
7457
|
maxScale;
|
|
@@ -8408,7 +8409,7 @@ class od extends Pe {
|
|
|
8408
8409
|
return e.id;
|
|
8409
8410
|
}
|
|
8410
8411
|
}
|
|
8411
|
-
class Me extends
|
|
8412
|
+
class Me extends Oi {
|
|
8412
8413
|
_isActive = !1;
|
|
8413
8414
|
_opts;
|
|
8414
8415
|
_prevDragEnabled = null;
|
|
@@ -8905,7 +8906,7 @@ class dd extends Me {
|
|
|
8905
8906
|
}
|
|
8906
8907
|
export {
|
|
8907
8908
|
Re as AZIMUTH,
|
|
8908
|
-
|
|
8909
|
+
Oi as ActiveScenePlugin,
|
|
8909
8910
|
Ii as BILLBOARD_SCALE_X,
|
|
8910
8911
|
D as BILLBOARD_SCALE_Y,
|
|
8911
8912
|
bi as BILLBOARD_SKEW_X,
|
|
@@ -8918,10 +8919,10 @@ export {
|
|
|
8918
8919
|
Kf as FenceEndpointPlugin,
|
|
8919
8920
|
sd as FenceRuntimePlugin,
|
|
8920
8921
|
Xa as GroupElement,
|
|
8921
|
-
|
|
8922
|
+
Nc as HitTestPlugin,
|
|
8922
8923
|
ur as ISOMETRIC_SKEW_X,
|
|
8923
8924
|
fr as ISOMETRIC_SKEW_Y,
|
|
8924
|
-
|
|
8925
|
+
$c as IconManager,
|
|
8925
8926
|
dd as ImageCreatorPlugin,
|
|
8926
8927
|
qf as ImageEditorPlugin,
|
|
8927
8928
|
rd as ImageRuntimePlugin,
|
|
@@ -8933,7 +8934,7 @@ export {
|
|
|
8933
8934
|
hd as NodeCreatorPlugin,
|
|
8934
8935
|
Bf as NodeEditorPlugin,
|
|
8935
8936
|
ed as NodeRuntimePlugin,
|
|
8936
|
-
|
|
8937
|
+
Ti as PostProcessManager,
|
|
8937
8938
|
cd as RectCreatorPlugin,
|
|
8938
8939
|
Vf as RectDragPlugin,
|
|
8939
8940
|
Xf as RectResizePlugin,
|
|
@@ -8943,7 +8944,7 @@ export {
|
|
|
8943
8944
|
Oe as SceneAwarePlugin,
|
|
8944
8945
|
Ue as SelectableEditorPlugin,
|
|
8945
8946
|
qc as SelectionHighlight,
|
|
8946
|
-
|
|
8947
|
+
Vc as StateManager,
|
|
8947
8948
|
xf as TILE_HDIAGONAL,
|
|
8948
8949
|
vf as TILE_HEIGHT,
|
|
8949
8950
|
g as TILE_SIZE,
|
|
@@ -8961,26 +8962,26 @@ export {
|
|
|
8961
8962
|
md as ZoomTransform,
|
|
8962
8963
|
lr as calculateIsometricSkew,
|
|
8963
8964
|
yf as calculateIsometricTileDiagonals,
|
|
8964
|
-
|
|
8965
|
-
|
|
8966
|
-
|
|
8967
|
-
|
|
8968
|
-
|
|
8969
|
-
|
|
8970
|
-
|
|
8971
|
-
|
|
8972
|
-
|
|
8973
|
-
|
|
8974
|
-
|
|
8975
|
-
|
|
8976
|
-
|
|
8977
|
-
|
|
8978
|
-
|
|
8979
|
-
|
|
8980
|
-
|
|
8981
|
-
|
|
8982
|
-
|
|
8983
|
-
|
|
8965
|
+
Rf as createBlinkStatePlugin,
|
|
8966
|
+
Cf as createBloomPostProcess,
|
|
8967
|
+
bf as createBlurPostProcess,
|
|
8968
|
+
Df as createBounceStatePlugin,
|
|
8969
|
+
zf as createBrightenStatePlugin,
|
|
8970
|
+
Pf as createChromaticAberrationPostProcess,
|
|
8971
|
+
If as createColorAdjustPostProcess,
|
|
8972
|
+
Nf as createDarkenStatePlugin,
|
|
8973
|
+
$f as createGlowStatePlugin,
|
|
8974
|
+
Ef as createGodRaysPostProcess,
|
|
8975
|
+
Lf as createGrayscalePostProcess,
|
|
8976
|
+
Gf as createHeartbeatStatePlugin,
|
|
8977
|
+
Ff as createInvertPostProcess,
|
|
8978
|
+
Of as createNoisePostProcess,
|
|
8979
|
+
Tf as createPixelatePostProcess,
|
|
8980
|
+
Mf as createScanlinesPostProcess,
|
|
8981
|
+
kf as createSharpenPostProcess,
|
|
8982
|
+
Uf as createShimmerStatePlugin,
|
|
8983
|
+
Hf as createTintStatePlugin,
|
|
8984
|
+
Af as createVignettePostProcess,
|
|
8984
8985
|
_r as default,
|
|
8985
8986
|
It as downloadFile,
|
|
8986
8987
|
ba as findPath,
|