@eva/plugin-renderer-filter 2.1.0-beta.2 → 2.1.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,296 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var eva_js = require('@eva/eva.js');
6
+ var pluginRenderer = require('@eva/plugin-renderer');
7
+ var pixi_js = require('pixi.js');
8
+
9
+ /**
10
+ * Filter 组件
11
+ *
12
+ * 给挂载它的 GameObject 应用一组 PixiJS 内置 2D 滤镜:Blur / ColorMatrix / Displacement / Noise / Alpha。
13
+ * 实现层是 PixiJS DisplayObject.filters 数组,FilterSystem 把 spec 实例化为 PixiJS Filter 实例并绑到容器上。
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * sprite.addComponent(new Filter({
18
+ * filters: [
19
+ * { type: "blur", strength: 8 },
20
+ * { type: "colorMatrix", preset: "sepia" },
21
+ * ],
22
+ * }));
23
+ * ```
24
+ */
25
+ class Filter extends eva_js.Component {
26
+ constructor() {
27
+ super(...arguments);
28
+ this.filters = [];
29
+ this.filterArea = null;
30
+ }
31
+ init(params) {
32
+ var _a, _b;
33
+ if (params) {
34
+ this.filters = (_a = params.filters) !== null && _a !== void 0 ? _a : [];
35
+ this.filterArea = (_b = params.filterArea) !== null && _b !== void 0 ? _b : null;
36
+ }
37
+ }
38
+ }
39
+ Filter.componentName = "Filter";
40
+
41
+ /******************************************************************************
42
+ Copyright (c) Microsoft Corporation.
43
+
44
+ Permission to use, copy, modify, and/or distribute this software for any
45
+ purpose with or without fee is hereby granted.
46
+
47
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
48
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
49
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
50
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
51
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
52
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
53
+ PERFORMANCE OF THIS SOFTWARE.
54
+ ***************************************************************************** */
55
+
56
+ function __decorate(decorators, target, key, desc) {
57
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
58
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
59
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
60
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
61
+ }
62
+
63
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
64
+ var e = new Error(message);
65
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
66
+ };
67
+
68
+ function createBlurFilter(spec) {
69
+ var _a, _b;
70
+ const strength = (_a = spec.strength) !== null && _a !== void 0 ? _a : 8;
71
+ const opts = {
72
+ strength,
73
+ quality: (_b = spec.quality) !== null && _b !== void 0 ? _b : 4,
74
+ };
75
+ if (spec.blurX != null)
76
+ opts.strengthX = spec.blurX;
77
+ if (spec.blurY != null)
78
+ opts.strengthY = spec.blurY;
79
+ return new pixi_js.BlurFilter(opts);
80
+ }
81
+
82
+ function createColorMatrixFilter(spec) {
83
+ var _a;
84
+ const cm = new pixi_js.ColorMatrixFilter();
85
+ if (spec.matrix && spec.matrix.length === 20) {
86
+ cm.matrix = spec.matrix;
87
+ return cm;
88
+ }
89
+ const arg = (_a = spec.presetArg) !== null && _a !== void 0 ? _a : 1;
90
+ switch (spec.preset) {
91
+ case "sepia":
92
+ cm.sepia(true);
93
+ break;
94
+ case "grayscale":
95
+ cm.greyscale(arg, true);
96
+ break;
97
+ case "negative":
98
+ cm.negative(true);
99
+ break;
100
+ case "polaroid":
101
+ cm.polaroid(true);
102
+ break;
103
+ case "vintage":
104
+ cm.vintage(true);
105
+ break;
106
+ case "lsd":
107
+ cm.lsd(true);
108
+ break;
109
+ case "predator":
110
+ cm.predator(arg, true);
111
+ break;
112
+ case "kodachrome":
113
+ cm.kodachrome(true);
114
+ break;
115
+ case "browni":
116
+ cm.browni(true);
117
+ break;
118
+ case "technicolor":
119
+ cm.technicolor(true);
120
+ break;
121
+ case "blackAndWhite":
122
+ cm.blackAndWhite(true);
123
+ break;
124
+ case "tint":
125
+ cm.tint(arg, true);
126
+ break;
127
+ case "saturate":
128
+ cm.saturate(arg, true);
129
+ break;
130
+ case "brightness":
131
+ cm.brightness(arg, true);
132
+ break;
133
+ case "contrast":
134
+ cm.contrast(arg, true);
135
+ break;
136
+ case "hue":
137
+ cm.hue(arg * 360, true);
138
+ break;
139
+ case "night":
140
+ cm.night(arg, true);
141
+ break;
142
+ }
143
+ return cm;
144
+ }
145
+
146
+ /**
147
+ * Build a DisplacementFilter from FilterSpec.
148
+ * Pulls the displacement texture from the Eva.js resource registry.
149
+ * If the resource isn't ready yet, returns a no-op filter (caller can later swap).
150
+ */
151
+ function createDisplacementFilter(spec) {
152
+ var _a, _b, _c, _d, _e, _f;
153
+ const scale = { x: (_a = spec.scaleX) !== null && _a !== void 0 ? _a : 20, y: (_b = spec.scaleY) !== null && _b !== void 0 ? _b : 20 };
154
+ let sprite;
155
+ if (spec.resource) {
156
+ const res = (_d = (_c = eva_js.resource).getResource) === null || _d === void 0 ? void 0 : _d.call(_c, spec.resource);
157
+ const data = (_f = (_e = res === null || res === void 0 ? void 0 : res.data) !== null && _e !== void 0 ? _e : res === null || res === void 0 ? void 0 : res.instance) !== null && _f !== void 0 ? _f : null;
158
+ const tex = (data === null || data === void 0 ? void 0 : data.texture) instanceof pixi_js.Texture
159
+ ? data.texture
160
+ : (data === null || data === void 0 ? void 0 : data.image)
161
+ ? pixi_js.Texture.from(data.image)
162
+ : null;
163
+ sprite = new pixi_js.Sprite(tex !== null && tex !== void 0 ? tex : pixi_js.Texture.EMPTY);
164
+ }
165
+ else {
166
+ sprite = new pixi_js.Sprite(pixi_js.Texture.EMPTY);
167
+ }
168
+ return new pixi_js.DisplacementFilter({ sprite, scale });
169
+ }
170
+
171
+ function createNoiseFilter(spec) {
172
+ var _a, _b;
173
+ return new pixi_js.NoiseFilter({
174
+ noise: (_a = spec.noise) !== null && _a !== void 0 ? _a : 0.5,
175
+ seed: (_b = spec.seed) !== null && _b !== void 0 ? _b : Math.random(),
176
+ });
177
+ }
178
+
179
+ function createAlphaFilter(spec) {
180
+ var _a;
181
+ return new pixi_js.AlphaFilter({ alpha: (_a = spec.alpha) !== null && _a !== void 0 ? _a : 1 });
182
+ }
183
+
184
+ let FilterSystem = class FilterSystem extends pluginRenderer.Renderer {
185
+ constructor() {
186
+ super(...arguments);
187
+ this.name = "FilterSystem";
188
+ this.bound = new Map();
189
+ this.elapsed = 0;
190
+ }
191
+ init() {
192
+ this.renderSystem = this.game.getSystem(pluginRenderer.RendererSystem);
193
+ this.renderSystem.rendererManager.register(this);
194
+ }
195
+ rendererUpdate(_gameObject) {
196
+ // no-op (filters are static; filterArea applied on change only)
197
+ }
198
+ componentChanged(changed) {
199
+ if (changed.componentName !== "Filter")
200
+ return;
201
+ const id = changed.gameObject.id;
202
+ if (changed.type === eva_js.OBSERVER_TYPE.REMOVE) {
203
+ this.removeFilters(id);
204
+ return;
205
+ }
206
+ // ADD or CHANGE
207
+ this.applyFilters(changed.gameObject, changed.component);
208
+ }
209
+ applyFilters(go, component) {
210
+ const container = this.containerManager.getContainer(go.id);
211
+ if (!container)
212
+ return;
213
+ // Dispose existing
214
+ this.disposeBound(go.id);
215
+ const specs = (component.filters || []).filter((s) => s.enabled !== false);
216
+ const pixiFilters = specs.map((s) => this.createOne(s)).filter(Boolean);
217
+ container.filters = pixiFilters;
218
+ if (component.filterArea) {
219
+ const fa = component.filterArea;
220
+ container.filterArea = { x: fa.x, y: fa.y, width: fa.width, height: fa.height };
221
+ }
222
+ else {
223
+ container.filterArea = null;
224
+ }
225
+ this.bound.set(go.id, { pixiFilters, specs });
226
+ }
227
+ removeFilters(id) {
228
+ const container = this.containerManager.getContainer(id);
229
+ if (container) {
230
+ container.filters = null;
231
+ container.filterArea = null;
232
+ }
233
+ this.disposeBound(id);
234
+ }
235
+ disposeBound(id) {
236
+ var _a, _b;
237
+ const b = this.bound.get(id);
238
+ if (!b)
239
+ return;
240
+ for (const f of b.pixiFilters) {
241
+ try {
242
+ (_b = (_a = f).destroy) === null || _b === void 0 ? void 0 : _b.call(_a);
243
+ }
244
+ catch (_c) {
245
+ /* ignore */
246
+ }
247
+ }
248
+ this.bound.delete(id);
249
+ }
250
+ createOne(spec) {
251
+ switch (spec.type) {
252
+ case "blur":
253
+ return createBlurFilter(spec);
254
+ case "colorMatrix":
255
+ return createColorMatrixFilter(spec);
256
+ case "displacement":
257
+ return createDisplacementFilter(spec);
258
+ case "noise":
259
+ return createNoiseFilter(spec);
260
+ case "alpha":
261
+ return createAlphaFilter(spec);
262
+ default:
263
+ return null;
264
+ }
265
+ }
266
+ update(time) {
267
+ var _a;
268
+ // Drain componentObserver so componentChanged fires for ADD/CHANGE/REMOVE.
269
+ super.update(time);
270
+ // Animate noise seed for filters with noiseAnimSpeed
271
+ const dt = ((_a = time === null || time === void 0 ? void 0 : time.deltaTime) !== null && _a !== void 0 ? _a : 16) / 1000;
272
+ this.elapsed += dt;
273
+ for (const { pixiFilters, specs } of this.bound.values()) {
274
+ for (let i = 0; i < specs.length; i++) {
275
+ const s = specs[i];
276
+ if (s.type === "noise" && s.noiseAnimSpeed) {
277
+ const f = pixiFilters[i];
278
+ if (f)
279
+ f.seed = (this.elapsed * s.noiseAnimSpeed) % 1;
280
+ }
281
+ }
282
+ }
283
+ }
284
+ };
285
+ FilterSystem = __decorate([
286
+ eva_js.decorators.componentObserver({
287
+ Filter: [
288
+ { prop: ["filters"], deep: true },
289
+ { prop: ["filterArea"], deep: true },
290
+ ],
291
+ })
292
+ ], FilterSystem);
293
+ var FilterSystem$1 = FilterSystem;
294
+
295
+ exports.Filter = Filter;
296
+ exports.FilterSystem = FilterSystem$1;
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@eva/eva.js"),t=require("@eva/plugin-renderer"),r=require("pixi.js");class i extends e.Component{constructor(){super(...arguments),this.filters=[],this.filterArea=null}init(e){var t,r;e&&(this.filters=null!==(t=e.filters)&&void 0!==t?t:[],this.filterArea=null!==(r=e.filterArea)&&void 0!==r?r:null)}}i.componentName="Filter","function"==typeof SuppressedError&&SuppressedError;let n=class extends t.Renderer{constructor(){super(...arguments),this.name="FilterSystem",this.bound=new Map,this.elapsed=0}init(){this.renderSystem=this.game.getSystem(t.RendererSystem),this.renderSystem.rendererManager.register(this)}rendererUpdate(e){}componentChanged(t){if("Filter"!==t.componentName)return;const r=t.gameObject.id;t.type!==e.OBSERVER_TYPE.REMOVE?this.applyFilters(t.gameObject,t.component):this.removeFilters(r)}applyFilters(e,t){const r=this.containerManager.getContainer(e.id);if(!r)return;this.disposeBound(e.id);const i=(t.filters||[]).filter(e=>!1!==e.enabled),n=i.map(e=>this.createOne(e)).filter(Boolean);if(r.filters=n,t.filterArea){const e=t.filterArea;r.filterArea={x:e.x,y:e.y,width:e.width,height:e.height}}else r.filterArea=null;this.bound.set(e.id,{pixiFilters:n,specs:i})}removeFilters(e){const t=this.containerManager.getContainer(e);t&&(t.filters=null,t.filterArea=null),this.disposeBound(e)}disposeBound(e){var t,r;const i=this.bound.get(e);if(i){for(const e of i.pixiFilters)try{null===(r=(t=e).destroy)||void 0===r||r.call(t)}catch(e){}this.bound.delete(e)}}createOne(t){switch(t.type){case"blur":return function(e){var t,i;const n={strength:null!==(t=e.strength)&&void 0!==t?t:8,quality:null!==(i=e.quality)&&void 0!==i?i:4};return null!=e.blurX&&(n.strengthX=e.blurX),null!=e.blurY&&(n.strengthY=e.blurY),new r.BlurFilter(n)}(t);case"colorMatrix":return function(e){var t;const i=new r.ColorMatrixFilter;if(e.matrix&&20===e.matrix.length)return i.matrix=e.matrix,i;const n=null!==(t=e.presetArg)&&void 0!==t?t:1;switch(e.preset){case"sepia":i.sepia(!0);break;case"grayscale":i.greyscale(n,!0);break;case"negative":i.negative(!0);break;case"polaroid":i.polaroid(!0);break;case"vintage":i.vintage(!0);break;case"lsd":i.lsd(!0);break;case"predator":i.predator(n,!0);break;case"kodachrome":i.kodachrome(!0);break;case"browni":i.browni(!0);break;case"technicolor":i.technicolor(!0);break;case"blackAndWhite":i.blackAndWhite(!0);break;case"tint":i.tint(n,!0);break;case"saturate":i.saturate(n,!0);break;case"brightness":i.brightness(n,!0);break;case"contrast":i.contrast(n,!0);break;case"hue":i.hue(360*n,!0);break;case"night":i.night(n,!0)}return i}(t);case"displacement":return function(t){var i,n,s,l,a,o;const c={x:null!==(i=t.scaleX)&&void 0!==i?i:20,y:null!==(n=t.scaleY)&&void 0!==n?n:20};let u;if(t.resource){const i=null===(l=(s=e.resource).getResource)||void 0===l?void 0:l.call(s,t.resource),n=null!==(o=null!==(a=null==i?void 0:i.data)&&void 0!==a?a:null==i?void 0:i.instance)&&void 0!==o?o:null,c=(null==n?void 0:n.texture)instanceof r.Texture?n.texture:(null==n?void 0:n.image)?r.Texture.from(n.image):null;u=new r.Sprite(null!=c?c:r.Texture.EMPTY)}else u=new r.Sprite(r.Texture.EMPTY);return new r.DisplacementFilter({sprite:u,scale:c})}(t);case"noise":return function(e){var t,i;return new r.NoiseFilter({noise:null!==(t=e.noise)&&void 0!==t?t:.5,seed:null!==(i=e.seed)&&void 0!==i?i:Math.random()})}(t);case"alpha":return function(e){var t;return new r.AlphaFilter({alpha:null!==(t=e.alpha)&&void 0!==t?t:1})}(t);default:return null}}update(e){var t;super.update(e);const r=(null!==(t=null==e?void 0:e.deltaTime)&&void 0!==t?t:16)/1e3;this.elapsed+=r;for(const{pixiFilters:e,specs:t}of this.bound.values())for(let r=0;r<t.length;r++){const i=t[r];if("noise"===i.type&&i.noiseAnimSpeed){const t=e[r];t&&(t.seed=this.elapsed*i.noiseAnimSpeed%1)}}}};n=function(e,t,r,i){var n,s=arguments.length,l=s<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)l=Reflect.decorate(e,t,r,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(l=(s<3?n(l):s>3?n(t,r,l):n(t,r))||l);return s>3&&l&&Object.defineProperty(t,r,l),l}([e.decorators.componentObserver({Filter:[{prop:["filters"],deep:!0},{prop:["filterArea"],deep:!0}]})],n);var s=n;exports.Filter=i,exports.FilterSystem=s;
@@ -0,0 +1,85 @@
1
+ import { Component } from '@eva/eva.js';
2
+ import { ComponentChanged } from '@eva/eva.js';
3
+ import { ContainerManager } from '@eva/plugin-renderer';
4
+ import { GameObject } from '@eva/eva.js';
5
+ import { Renderer } from '@eva/plugin-renderer';
6
+ import { RendererSystem } from '@eva/plugin-renderer';
7
+
8
+ export declare type ColorMatrixPreset = "sepia" | "grayscale" | "negative" | "polaroid" | "vintage" | "lsd" | "predator" | "kodachrome" | "browni" | "technicolor" | "blackAndWhite" | "tint" | "saturate" | "brightness" | "contrast" | "hue" | "night";
9
+
10
+ /**
11
+ * Filter 组件
12
+ *
13
+ * 给挂载它的 GameObject 应用一组 PixiJS 内置 2D 滤镜:Blur / ColorMatrix / Displacement / Noise / Alpha。
14
+ * 实现层是 PixiJS DisplayObject.filters 数组,FilterSystem 把 spec 实例化为 PixiJS Filter 实例并绑到容器上。
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * sprite.addComponent(new Filter({
19
+ * filters: [
20
+ * { type: "blur", strength: 8 },
21
+ * { type: "colorMatrix", preset: "sepia" },
22
+ * ],
23
+ * }));
24
+ * ```
25
+ */
26
+ export declare class Filter extends Component<FilterParams> {
27
+ static componentName: string;
28
+ filters: FilterSpec[];
29
+ filterArea: FilterParams["filterArea"] | null;
30
+ init(params?: FilterParams): void;
31
+ }
32
+
33
+ export declare interface FilterParams {
34
+ filters?: FilterSpec[];
35
+ filterArea?: {
36
+ x: number;
37
+ y: number;
38
+ width: number;
39
+ height: number;
40
+ };
41
+ }
42
+
43
+ /**
44
+ * 单条 filter spec — 各类型共用的字段池,只读自己关心的字段。
45
+ */
46
+ export declare interface FilterSpec {
47
+ type: FilterType;
48
+ enabled?: boolean;
49
+ strength?: number;
50
+ quality?: number;
51
+ blurX?: number;
52
+ blurY?: number;
53
+ preset?: ColorMatrixPreset;
54
+ presetArg?: number;
55
+ matrix?: number[];
56
+ resource?: string;
57
+ scaleX?: number;
58
+ scaleY?: number;
59
+ noise?: number;
60
+ seed?: number;
61
+ noiseAnimSpeed?: number;
62
+ alpha?: number;
63
+ }
64
+
65
+ export declare class FilterSystem extends Renderer {
66
+ name: string;
67
+ containerManager: ContainerManager;
68
+ renderSystem: RendererSystem;
69
+ private bound;
70
+ private elapsed;
71
+ init(): void;
72
+ rendererUpdate(_gameObject: GameObject): void;
73
+ componentChanged(changed: ComponentChanged): void;
74
+ private applyFilters;
75
+ private removeFilters;
76
+ private disposeBound;
77
+ private createOne;
78
+ update(time?: {
79
+ deltaTime: number;
80
+ }): void;
81
+ }
82
+
83
+ export declare type FilterType = "blur" | "colorMatrix" | "displacement" | "noise" | "alpha";
84
+
85
+ export { }
@@ -0,0 +1,291 @@
1
+ import { Component, resource, OBSERVER_TYPE, decorators } from '@eva/eva.js';
2
+ import { Renderer, RendererSystem } from '@eva/plugin-renderer';
3
+ import { BlurFilter, ColorMatrixFilter, Texture, Sprite, DisplacementFilter, NoiseFilter, AlphaFilter } from 'pixi.js';
4
+
5
+ /**
6
+ * Filter 组件
7
+ *
8
+ * 给挂载它的 GameObject 应用一组 PixiJS 内置 2D 滤镜:Blur / ColorMatrix / Displacement / Noise / Alpha。
9
+ * 实现层是 PixiJS DisplayObject.filters 数组,FilterSystem 把 spec 实例化为 PixiJS Filter 实例并绑到容器上。
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * sprite.addComponent(new Filter({
14
+ * filters: [
15
+ * { type: "blur", strength: 8 },
16
+ * { type: "colorMatrix", preset: "sepia" },
17
+ * ],
18
+ * }));
19
+ * ```
20
+ */
21
+ class Filter extends Component {
22
+ constructor() {
23
+ super(...arguments);
24
+ this.filters = [];
25
+ this.filterArea = null;
26
+ }
27
+ init(params) {
28
+ var _a, _b;
29
+ if (params) {
30
+ this.filters = (_a = params.filters) !== null && _a !== void 0 ? _a : [];
31
+ this.filterArea = (_b = params.filterArea) !== null && _b !== void 0 ? _b : null;
32
+ }
33
+ }
34
+ }
35
+ Filter.componentName = "Filter";
36
+
37
+ /******************************************************************************
38
+ Copyright (c) Microsoft Corporation.
39
+
40
+ Permission to use, copy, modify, and/or distribute this software for any
41
+ purpose with or without fee is hereby granted.
42
+
43
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
44
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
45
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
46
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
47
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
48
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
49
+ PERFORMANCE OF THIS SOFTWARE.
50
+ ***************************************************************************** */
51
+
52
+ function __decorate(decorators, target, key, desc) {
53
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
54
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
55
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
56
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
57
+ }
58
+
59
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
60
+ var e = new Error(message);
61
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
62
+ };
63
+
64
+ function createBlurFilter(spec) {
65
+ var _a, _b;
66
+ const strength = (_a = spec.strength) !== null && _a !== void 0 ? _a : 8;
67
+ const opts = {
68
+ strength,
69
+ quality: (_b = spec.quality) !== null && _b !== void 0 ? _b : 4,
70
+ };
71
+ if (spec.blurX != null)
72
+ opts.strengthX = spec.blurX;
73
+ if (spec.blurY != null)
74
+ opts.strengthY = spec.blurY;
75
+ return new BlurFilter(opts);
76
+ }
77
+
78
+ function createColorMatrixFilter(spec) {
79
+ var _a;
80
+ const cm = new ColorMatrixFilter();
81
+ if (spec.matrix && spec.matrix.length === 20) {
82
+ cm.matrix = spec.matrix;
83
+ return cm;
84
+ }
85
+ const arg = (_a = spec.presetArg) !== null && _a !== void 0 ? _a : 1;
86
+ switch (spec.preset) {
87
+ case "sepia":
88
+ cm.sepia(true);
89
+ break;
90
+ case "grayscale":
91
+ cm.greyscale(arg, true);
92
+ break;
93
+ case "negative":
94
+ cm.negative(true);
95
+ break;
96
+ case "polaroid":
97
+ cm.polaroid(true);
98
+ break;
99
+ case "vintage":
100
+ cm.vintage(true);
101
+ break;
102
+ case "lsd":
103
+ cm.lsd(true);
104
+ break;
105
+ case "predator":
106
+ cm.predator(arg, true);
107
+ break;
108
+ case "kodachrome":
109
+ cm.kodachrome(true);
110
+ break;
111
+ case "browni":
112
+ cm.browni(true);
113
+ break;
114
+ case "technicolor":
115
+ cm.technicolor(true);
116
+ break;
117
+ case "blackAndWhite":
118
+ cm.blackAndWhite(true);
119
+ break;
120
+ case "tint":
121
+ cm.tint(arg, true);
122
+ break;
123
+ case "saturate":
124
+ cm.saturate(arg, true);
125
+ break;
126
+ case "brightness":
127
+ cm.brightness(arg, true);
128
+ break;
129
+ case "contrast":
130
+ cm.contrast(arg, true);
131
+ break;
132
+ case "hue":
133
+ cm.hue(arg * 360, true);
134
+ break;
135
+ case "night":
136
+ cm.night(arg, true);
137
+ break;
138
+ }
139
+ return cm;
140
+ }
141
+
142
+ /**
143
+ * Build a DisplacementFilter from FilterSpec.
144
+ * Pulls the displacement texture from the Eva.js resource registry.
145
+ * If the resource isn't ready yet, returns a no-op filter (caller can later swap).
146
+ */
147
+ function createDisplacementFilter(spec) {
148
+ var _a, _b, _c, _d, _e, _f;
149
+ const scale = { x: (_a = spec.scaleX) !== null && _a !== void 0 ? _a : 20, y: (_b = spec.scaleY) !== null && _b !== void 0 ? _b : 20 };
150
+ let sprite;
151
+ if (spec.resource) {
152
+ const res = (_d = (_c = resource).getResource) === null || _d === void 0 ? void 0 : _d.call(_c, spec.resource);
153
+ const data = (_f = (_e = res === null || res === void 0 ? void 0 : res.data) !== null && _e !== void 0 ? _e : res === null || res === void 0 ? void 0 : res.instance) !== null && _f !== void 0 ? _f : null;
154
+ const tex = (data === null || data === void 0 ? void 0 : data.texture) instanceof Texture
155
+ ? data.texture
156
+ : (data === null || data === void 0 ? void 0 : data.image)
157
+ ? Texture.from(data.image)
158
+ : null;
159
+ sprite = new Sprite(tex !== null && tex !== void 0 ? tex : Texture.EMPTY);
160
+ }
161
+ else {
162
+ sprite = new Sprite(Texture.EMPTY);
163
+ }
164
+ return new DisplacementFilter({ sprite, scale });
165
+ }
166
+
167
+ function createNoiseFilter(spec) {
168
+ var _a, _b;
169
+ return new NoiseFilter({
170
+ noise: (_a = spec.noise) !== null && _a !== void 0 ? _a : 0.5,
171
+ seed: (_b = spec.seed) !== null && _b !== void 0 ? _b : Math.random(),
172
+ });
173
+ }
174
+
175
+ function createAlphaFilter(spec) {
176
+ var _a;
177
+ return new AlphaFilter({ alpha: (_a = spec.alpha) !== null && _a !== void 0 ? _a : 1 });
178
+ }
179
+
180
+ let FilterSystem = class FilterSystem extends Renderer {
181
+ constructor() {
182
+ super(...arguments);
183
+ this.name = "FilterSystem";
184
+ this.bound = new Map();
185
+ this.elapsed = 0;
186
+ }
187
+ init() {
188
+ this.renderSystem = this.game.getSystem(RendererSystem);
189
+ this.renderSystem.rendererManager.register(this);
190
+ }
191
+ rendererUpdate(_gameObject) {
192
+ // no-op (filters are static; filterArea applied on change only)
193
+ }
194
+ componentChanged(changed) {
195
+ if (changed.componentName !== "Filter")
196
+ return;
197
+ const id = changed.gameObject.id;
198
+ if (changed.type === OBSERVER_TYPE.REMOVE) {
199
+ this.removeFilters(id);
200
+ return;
201
+ }
202
+ // ADD or CHANGE
203
+ this.applyFilters(changed.gameObject, changed.component);
204
+ }
205
+ applyFilters(go, component) {
206
+ const container = this.containerManager.getContainer(go.id);
207
+ if (!container)
208
+ return;
209
+ // Dispose existing
210
+ this.disposeBound(go.id);
211
+ const specs = (component.filters || []).filter((s) => s.enabled !== false);
212
+ const pixiFilters = specs.map((s) => this.createOne(s)).filter(Boolean);
213
+ container.filters = pixiFilters;
214
+ if (component.filterArea) {
215
+ const fa = component.filterArea;
216
+ container.filterArea = { x: fa.x, y: fa.y, width: fa.width, height: fa.height };
217
+ }
218
+ else {
219
+ container.filterArea = null;
220
+ }
221
+ this.bound.set(go.id, { pixiFilters, specs });
222
+ }
223
+ removeFilters(id) {
224
+ const container = this.containerManager.getContainer(id);
225
+ if (container) {
226
+ container.filters = null;
227
+ container.filterArea = null;
228
+ }
229
+ this.disposeBound(id);
230
+ }
231
+ disposeBound(id) {
232
+ var _a, _b;
233
+ const b = this.bound.get(id);
234
+ if (!b)
235
+ return;
236
+ for (const f of b.pixiFilters) {
237
+ try {
238
+ (_b = (_a = f).destroy) === null || _b === void 0 ? void 0 : _b.call(_a);
239
+ }
240
+ catch (_c) {
241
+ /* ignore */
242
+ }
243
+ }
244
+ this.bound.delete(id);
245
+ }
246
+ createOne(spec) {
247
+ switch (spec.type) {
248
+ case "blur":
249
+ return createBlurFilter(spec);
250
+ case "colorMatrix":
251
+ return createColorMatrixFilter(spec);
252
+ case "displacement":
253
+ return createDisplacementFilter(spec);
254
+ case "noise":
255
+ return createNoiseFilter(spec);
256
+ case "alpha":
257
+ return createAlphaFilter(spec);
258
+ default:
259
+ return null;
260
+ }
261
+ }
262
+ update(time) {
263
+ var _a;
264
+ // Drain componentObserver so componentChanged fires for ADD/CHANGE/REMOVE.
265
+ super.update(time);
266
+ // Animate noise seed for filters with noiseAnimSpeed
267
+ const dt = ((_a = time === null || time === void 0 ? void 0 : time.deltaTime) !== null && _a !== void 0 ? _a : 16) / 1000;
268
+ this.elapsed += dt;
269
+ for (const { pixiFilters, specs } of this.bound.values()) {
270
+ for (let i = 0; i < specs.length; i++) {
271
+ const s = specs[i];
272
+ if (s.type === "noise" && s.noiseAnimSpeed) {
273
+ const f = pixiFilters[i];
274
+ if (f)
275
+ f.seed = (this.elapsed * s.noiseAnimSpeed) % 1;
276
+ }
277
+ }
278
+ }
279
+ }
280
+ };
281
+ FilterSystem = __decorate([
282
+ decorators.componentObserver({
283
+ Filter: [
284
+ { prop: ["filters"], deep: true },
285
+ { prop: ["filterArea"], deep: true },
286
+ ],
287
+ })
288
+ ], FilterSystem);
289
+ var FilterSystem$1 = FilterSystem;
290
+
291
+ export { Filter, FilterSystem$1 as FilterSystem };
package/index.js ADDED
@@ -0,0 +1,7 @@
1
+ 'use strict';
2
+
3
+ if (process.env.NODE_ENV === 'production') {
4
+ module.exports = require('./dist/plugin-renderer-filter.cjs.prod.js');
5
+ } else {
6
+ module.exports = require('./dist/plugin-renderer-filter.cjs.js');
7
+ }
package/package.json CHANGED
@@ -1,21 +1,22 @@
1
1
  {
2
2
  "name": "@eva/plugin-renderer-filter",
3
- "version": "2.1.0-beta.2",
3
+ "version": "2.1.0-beta.4",
4
4
  "description": "@eva/plugin-renderer-filter — wraps PixiJS built-in 2D filters (Blur/ColorMatrix/Displacement/Noise/Alpha) as Eva.js components.",
5
- "main": "lib/index.ts",
6
- "module": "lib/index.ts",
7
- "types": "lib/index.ts",
5
+ "main": "index.js",
6
+ "module": "dist/plugin-renderer-filter.esm.js",
7
+ "types": "dist/plugin-renderer-filter.d.ts",
8
8
  "files": [
9
- "lib"
9
+ "index.js",
10
+ "dist"
10
11
  ],
11
12
  "keywords": [
12
13
  "eva.js"
13
14
  ],
14
15
  "license": "MIT",
15
16
  "dependencies": {
16
- "@eva/eva.js": "2.1.0-beta.2",
17
+ "@eva/eva.js": "2.1.0-beta.4",
17
18
  "@eva/inspector-decorator": "^2.0.0-beta.0",
18
- "@eva/plugin-renderer": "2.1.0-beta.2",
19
+ "@eva/plugin-renderer": "2.1.0-beta.4",
19
20
  "pixi.js": "^8.17.0"
20
21
  }
21
22
  }
package/lib/component.ts DELETED
@@ -1,89 +0,0 @@
1
- import { Component } from "@eva/eva.js";
2
-
3
- export type FilterType = "blur" | "colorMatrix" | "displacement" | "noise" | "alpha";
4
-
5
- export type ColorMatrixPreset =
6
- | "sepia"
7
- | "grayscale"
8
- | "negative"
9
- | "polaroid"
10
- | "vintage"
11
- | "lsd"
12
- | "predator"
13
- | "kodachrome"
14
- | "browni"
15
- | "technicolor"
16
- | "blackAndWhite"
17
- | "tint"
18
- | "saturate"
19
- | "brightness"
20
- | "contrast"
21
- | "hue"
22
- | "night";
23
-
24
- /**
25
- * 单条 filter spec — 各类型共用的字段池,只读自己关心的字段。
26
- */
27
- export interface FilterSpec {
28
- type: FilterType;
29
- enabled?: boolean;
30
-
31
- // BlurFilter
32
- strength?: number;
33
- quality?: number;
34
- blurX?: number;
35
- blurY?: number;
36
-
37
- // ColorMatrixFilter
38
- preset?: ColorMatrixPreset;
39
- presetArg?: number;
40
- matrix?: number[];
41
-
42
- // DisplacementFilter
43
- resource?: string;
44
- scaleX?: number;
45
- scaleY?: number;
46
-
47
- // NoiseFilter
48
- noise?: number;
49
- seed?: number;
50
- noiseAnimSpeed?: number;
51
-
52
- // AlphaFilter
53
- alpha?: number;
54
- }
55
-
56
- export interface FilterParams {
57
- filters?: FilterSpec[];
58
- filterArea?: { x: number; y: number; width: number; height: number };
59
- }
60
-
61
- /**
62
- * Filter 组件
63
- *
64
- * 给挂载它的 GameObject 应用一组 PixiJS 内置 2D 滤镜:Blur / ColorMatrix / Displacement / Noise / Alpha。
65
- * 实现层是 PixiJS DisplayObject.filters 数组,FilterSystem 把 spec 实例化为 PixiJS Filter 实例并绑到容器上。
66
- *
67
- * @example
68
- * ```typescript
69
- * sprite.addComponent(new Filter({
70
- * filters: [
71
- * { type: "blur", strength: 8 },
72
- * { type: "colorMatrix", preset: "sepia" },
73
- * ],
74
- * }));
75
- * ```
76
- */
77
- export default class Filter extends Component<FilterParams> {
78
- static componentName: string = "Filter";
79
-
80
- filters: FilterSpec[] = [];
81
- filterArea: FilterParams["filterArea"] | null = null;
82
-
83
- init(params?: FilterParams) {
84
- if (params) {
85
- this.filters = params.filters ?? [];
86
- this.filterArea = params.filterArea ?? null;
87
- }
88
- }
89
- }
@@ -1,6 +0,0 @@
1
- import { AlphaFilter } from "pixi.js";
2
- import type { FilterSpec } from "../component";
3
-
4
- export function createAlphaFilter(spec: FilterSpec): AlphaFilter {
5
- return new AlphaFilter({ alpha: spec.alpha ?? 1 } as any);
6
- }
@@ -1,13 +0,0 @@
1
- import { BlurFilter } from "pixi.js";
2
- import type { FilterSpec } from "../component";
3
-
4
- export function createBlurFilter(spec: FilterSpec): BlurFilter {
5
- const strength = spec.strength ?? 8;
6
- const opts: any = {
7
- strength,
8
- quality: spec.quality ?? 4,
9
- };
10
- if (spec.blurX != null) opts.strengthX = spec.blurX;
11
- if (spec.blurY != null) opts.strengthY = spec.blurY;
12
- return new BlurFilter(opts);
13
- }
@@ -1,31 +0,0 @@
1
- import { ColorMatrixFilter } from "pixi.js";
2
- import type { FilterSpec } from "../component";
3
-
4
- export function createColorMatrixFilter(spec: FilterSpec): ColorMatrixFilter {
5
- const cm = new ColorMatrixFilter();
6
- if (spec.matrix && spec.matrix.length === 20) {
7
- (cm as any).matrix = spec.matrix as any;
8
- return cm;
9
- }
10
- const arg = spec.presetArg ?? 1;
11
- switch (spec.preset) {
12
- case "sepia": (cm as any).sepia(true); break;
13
- case "grayscale": (cm as any).greyscale(arg, true); break;
14
- case "negative": (cm as any).negative(true); break;
15
- case "polaroid": (cm as any).polaroid(true); break;
16
- case "vintage": (cm as any).vintage(true); break;
17
- case "lsd": (cm as any).lsd(true); break;
18
- case "predator": (cm as any).predator(arg, true); break;
19
- case "kodachrome": (cm as any).kodachrome(true); break;
20
- case "browni": (cm as any).browni(true); break;
21
- case "technicolor": (cm as any).technicolor(true); break;
22
- case "blackAndWhite": (cm as any).blackAndWhite(true); break;
23
- case "tint": (cm as any).tint(arg, true); break;
24
- case "saturate": (cm as any).saturate(arg, true); break;
25
- case "brightness": (cm as any).brightness(arg, true); break;
26
- case "contrast": (cm as any).contrast(arg, true); break;
27
- case "hue": (cm as any).hue(arg * 360, true); break;
28
- case "night": (cm as any).night(arg, true); break;
29
- }
30
- return cm;
31
- }
@@ -1,27 +0,0 @@
1
- import { DisplacementFilter, Sprite, Texture } from "pixi.js";
2
- import { resource } from "@eva/eva.js";
3
- import type { FilterSpec } from "../component";
4
-
5
- /**
6
- * Build a DisplacementFilter from FilterSpec.
7
- * Pulls the displacement texture from the Eva.js resource registry.
8
- * If the resource isn't ready yet, returns a no-op filter (caller can later swap).
9
- */
10
- export function createDisplacementFilter(spec: FilterSpec): DisplacementFilter {
11
- const scale = { x: spec.scaleX ?? 20, y: spec.scaleY ?? 20 };
12
- let sprite: Sprite;
13
- if (spec.resource) {
14
- const res = (resource as any).getResource?.(spec.resource);
15
- const data = res?.data ?? res?.instance ?? null;
16
- const tex: Texture | null =
17
- data?.texture instanceof Texture
18
- ? data.texture
19
- : data?.image
20
- ? Texture.from(data.image)
21
- : null;
22
- sprite = new Sprite(tex ?? Texture.EMPTY);
23
- } else {
24
- sprite = new Sprite(Texture.EMPTY);
25
- }
26
- return new DisplacementFilter({ sprite, scale });
27
- }
@@ -1,9 +0,0 @@
1
- import { NoiseFilter } from "pixi.js";
2
- import type { FilterSpec } from "../component";
3
-
4
- export function createNoiseFilter(spec: FilterSpec): NoiseFilter {
5
- return new NoiseFilter({
6
- noise: spec.noise ?? 0.5,
7
- seed: spec.seed ?? Math.random(),
8
- } as any);
9
- }
package/lib/index.ts DELETED
@@ -1,3 +0,0 @@
1
- export { default as Filter } from "./component";
2
- export { default as FilterSystem } from "./system";
3
- export type { FilterParams, FilterSpec, FilterType, ColorMatrixPreset } from "./component";
package/lib/system.ts DELETED
@@ -1,137 +0,0 @@
1
- import {
2
- GameObject,
3
- decorators,
4
- ComponentChanged,
5
- OBSERVER_TYPE,
6
- } from "@eva/eva.js";
7
- import { ContainerManager, RendererSystem, Renderer } from "@eva/plugin-renderer";
8
- import type { Filter as PIXIFilter, Rectangle } from "pixi.js";
9
- import FilterComponent, { FilterSpec } from "./component";
10
- import { createBlurFilter } from "./filters/blur";
11
- import { createColorMatrixFilter } from "./filters/colorMatrix";
12
- import { createDisplacementFilter } from "./filters/displacement";
13
- import { createNoiseFilter } from "./filters/noise";
14
- import { createAlphaFilter } from "./filters/alpha";
15
-
16
- interface BoundFilter {
17
- pixiFilters: PIXIFilter[];
18
- specs: FilterSpec[];
19
- }
20
-
21
- @decorators.componentObserver({
22
- Filter: [
23
- { prop: ["filters"], deep: true },
24
- { prop: ["filterArea"], deep: true },
25
- ],
26
- })
27
- export default class FilterSystem extends Renderer {
28
- name: string = "FilterSystem";
29
- containerManager: ContainerManager;
30
- renderSystem: RendererSystem;
31
-
32
- private bound: Map<number, BoundFilter> = new Map();
33
- private elapsed = 0;
34
-
35
- init() {
36
- this.renderSystem = this.game.getSystem(RendererSystem) as RendererSystem;
37
- this.renderSystem.rendererManager.register(this);
38
- }
39
-
40
- rendererUpdate(_gameObject: GameObject) {
41
- // no-op (filters are static; filterArea applied on change only)
42
- }
43
-
44
- componentChanged(changed: ComponentChanged) {
45
- if (changed.componentName !== "Filter") return;
46
- const id = changed.gameObject.id;
47
-
48
- if (changed.type === OBSERVER_TYPE.REMOVE) {
49
- this.removeFilters(id);
50
- return;
51
- }
52
-
53
- // ADD or CHANGE
54
- this.applyFilters(changed.gameObject, changed.component as FilterComponent);
55
- }
56
-
57
- private applyFilters(go: GameObject, component: FilterComponent) {
58
- const container = this.containerManager.getContainer(go.id);
59
- if (!container) return;
60
-
61
- // Dispose existing
62
- this.disposeBound(go.id);
63
-
64
- const specs: FilterSpec[] = (component.filters || []).filter(
65
- (s) => s.enabled !== false,
66
- );
67
- const pixiFilters = specs.map((s) => this.createOne(s)).filter(Boolean) as PIXIFilter[];
68
-
69
- (container as any).filters = pixiFilters;
70
-
71
- if (component.filterArea) {
72
- const fa = component.filterArea;
73
- (container as any).filterArea = { x: fa.x, y: fa.y, width: fa.width, height: fa.height } as Rectangle;
74
- } else {
75
- (container as any).filterArea = null;
76
- }
77
-
78
- this.bound.set(go.id, { pixiFilters, specs });
79
- }
80
-
81
- private removeFilters(id: number) {
82
- const container = this.containerManager.getContainer(id);
83
- if (container) {
84
- (container as any).filters = null;
85
- (container as any).filterArea = null;
86
- }
87
- this.disposeBound(id);
88
- }
89
-
90
- private disposeBound(id: number) {
91
- const b = this.bound.get(id);
92
- if (!b) return;
93
- for (const f of b.pixiFilters) {
94
- try {
95
- (f as any).destroy?.();
96
- } catch {
97
- /* ignore */
98
- }
99
- }
100
- this.bound.delete(id);
101
- }
102
-
103
- private createOne(spec: FilterSpec): PIXIFilter | null {
104
- switch (spec.type) {
105
- case "blur":
106
- return createBlurFilter(spec) as unknown as PIXIFilter;
107
- case "colorMatrix":
108
- return createColorMatrixFilter(spec) as unknown as PIXIFilter;
109
- case "displacement":
110
- return createDisplacementFilter(spec) as unknown as PIXIFilter;
111
- case "noise":
112
- return createNoiseFilter(spec) as unknown as PIXIFilter;
113
- case "alpha":
114
- return createAlphaFilter(spec) as unknown as PIXIFilter;
115
- default:
116
- return null;
117
- }
118
- }
119
-
120
- update(time?: { deltaTime: number }) {
121
- // Drain componentObserver so componentChanged fires for ADD/CHANGE/REMOVE.
122
- super.update(time as any);
123
-
124
- // Animate noise seed for filters with noiseAnimSpeed
125
- const dt = (time?.deltaTime ?? 16) / 1000;
126
- this.elapsed += dt;
127
- for (const { pixiFilters, specs } of this.bound.values()) {
128
- for (let i = 0; i < specs.length; i++) {
129
- const s = specs[i];
130
- if (s.type === "noise" && s.noiseAnimSpeed) {
131
- const f = pixiFilters[i] as any;
132
- if (f) f.seed = (this.elapsed * s.noiseAnimSpeed) % 1;
133
- }
134
- }
135
- }
136
- }
137
- }