@eva/plugin-renderer 2.0.2 → 2.1.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -26,6 +26,10 @@ function __decorate(decorators, target, key, desc) {
26
26
  return c > 3 && r && Object.defineProperty(target, key, r), r;
27
27
  }
28
28
 
29
+ function __metadata(metadataKey, metadataValue) {
30
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
31
+ }
32
+
29
33
  function __awaiter(thisArg, _arguments, P, generator) {
30
34
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
31
35
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -137,6 +141,22 @@ class RendererManager {
137
141
  }
138
142
  var RendererManager$1 = RendererManager;
139
143
 
144
+ const toRenderBounds = (bounds, coordinateSpace, source) => {
145
+ const x = Number.isFinite(bounds.x) ? bounds.x : 0;
146
+ const y = Number.isFinite(bounds.y) ? bounds.y : 0;
147
+ const width = Number.isFinite(bounds.width) ? bounds.width : 0;
148
+ const height = Number.isFinite(bounds.height) ? bounds.height : 0;
149
+ return {
150
+ x,
151
+ y,
152
+ width,
153
+ height,
154
+ right: x + width,
155
+ bottom: y + height,
156
+ coordinateSpace,
157
+ source,
158
+ };
159
+ };
140
160
  class ContainerManager {
141
161
  constructor() {
142
162
  this.containerMap = {};
@@ -148,6 +168,64 @@ class ContainerManager {
148
168
  getContainer(name) {
149
169
  return this.containerMap[name];
150
170
  }
171
+ /**
172
+ * Return actual rendered bounds for a GameObject.
173
+ *
174
+ * The primary path uses PixiJS Container#getBounds(), so renderers such as
175
+ * Text/Img/Graphics/Sprite/Spine report the real display size after loading
176
+ * and style application. If the display object is not ready yet, callers can
177
+ * fall back to Transform.size in the same Eva design/canvas coordinate space.
178
+ */
179
+ getBounds(gameObject, options = {}) {
180
+ if (!gameObject || gameObject.destroyed)
181
+ return null;
182
+ const coordinateSpace = options.coordinateSpace || 'world';
183
+ const fallbackToTransform = options.fallbackToTransform !== false;
184
+ const container = this.getContainer(gameObject.id);
185
+ if (container === null || container === void 0 ? void 0 : container.getBounds) {
186
+ try {
187
+ const bounds = container.getBounds();
188
+ if (bounds && Number.isFinite(bounds.width) && Number.isFinite(bounds.height) && (bounds.width !== 0 || bounds.height !== 0)) {
189
+ return toRenderBounds(bounds, coordinateSpace, 'pixi');
190
+ }
191
+ }
192
+ catch (error) {
193
+ // Pixi can throw while async resources are still being attached; fallback below keeps editor tools stable.
194
+ }
195
+ }
196
+ if (!fallbackToTransform)
197
+ return null;
198
+ return this.getTransformBounds(gameObject, coordinateSpace);
199
+ }
200
+ getTransformBounds(gameObject, coordinateSpace) {
201
+ var _a, _b, _c, _d, _e, _f;
202
+ const transform = gameObject.transform;
203
+ const container = this.getContainer(gameObject.id);
204
+ let x = (_a = container === null || container === void 0 ? void 0 : container.worldTransform) === null || _a === void 0 ? void 0 : _a.tx;
205
+ let y = (_b = container === null || container === void 0 ? void 0 : container.worldTransform) === null || _b === void 0 ? void 0 : _b.ty;
206
+ if (!Number.isFinite(x) || !Number.isFinite(y)) {
207
+ const position = this.resolveFallbackWorldPosition(transform);
208
+ x = position.x;
209
+ y = position.y;
210
+ }
211
+ const scaleX = Number.isFinite((_c = transform.scale) === null || _c === void 0 ? void 0 : _c.x) ? transform.scale.x : 1;
212
+ const scaleY = Number.isFinite((_d = transform.scale) === null || _d === void 0 ? void 0 : _d.y) ? transform.scale.y : 1;
213
+ const width = Math.abs((((_e = transform.size) === null || _e === void 0 ? void 0 : _e.width) || 0) * scaleX);
214
+ const height = Math.abs((((_f = transform.size) === null || _f === void 0 ? void 0 : _f.height) || 0) * scaleY);
215
+ return toRenderBounds({ x, y, width, height }, coordinateSpace, 'transform');
216
+ }
217
+ resolveFallbackWorldPosition(transform) {
218
+ var _a, _b, _c, _d;
219
+ if (!transform)
220
+ return { x: 0, y: 0 };
221
+ const parent = transform.parent;
222
+ const parentPosition = parent ? this.resolveFallbackWorldPosition(parent) : { x: 0, y: 0 };
223
+ const parentSize = (parent === null || parent === void 0 ? void 0 : parent.size) || { width: 0, height: 0 };
224
+ return {
225
+ x: parentPosition.x + (((_a = transform.position) === null || _a === void 0 ? void 0 : _a.x) || 0) + parentSize.width * (((_b = transform.anchor) === null || _b === void 0 ? void 0 : _b.x) || 0),
226
+ y: parentPosition.y + (((_c = transform.position) === null || _c === void 0 ? void 0 : _c.y) || 0) + parentSize.height * (((_d = transform.anchor) === null || _d === void 0 ? void 0 : _d.y) || 0),
227
+ };
228
+ }
151
229
  removeContainer(name) {
152
230
  const container = this.containerMap[name];
153
231
  if (container) {
@@ -267,7 +345,8 @@ let Transform = class Transform extends EventEmitter {
267
345
  Transform = __decorate([
268
346
  decorators.componentObserver({
269
347
  Transform: ['_parent'],
270
- })
348
+ }),
349
+ __metadata("design:paramtypes", [Object])
271
350
  ], Transform);
272
351
  var Transform$1 = Transform;
273
352
 
@@ -285,26 +364,42 @@ const enableScroll = renderer => {
285
364
  renderer.events.autoPreventDefault = false;
286
365
  renderer.canvas.style.touchAction = 'auto';
287
366
  };
367
+ function isRendererGameLike(value) {
368
+ if (!value || typeof value !== 'object')
369
+ return false;
370
+ const candidate = value;
371
+ return Boolean(candidate.scene || candidate.gameObjects || typeof candidate.on === 'function');
372
+ }
288
373
  let Renderer$1 = class Renderer extends System {
289
374
  constructor() {
290
375
  super(...arguments);
291
376
  this.multiApps = [];
377
+ this.destroyed = false;
292
378
  }
293
- init(params) {
379
+ init(params = {}) {
380
+ var _a, _b, _c, _d, _e, _f, _g, _h;
294
381
  return __awaiter(this, void 0, void 0, function* () {
295
- this.params = params;
296
- this.application = yield this.createApplication(params);
382
+ this.destroyed = false;
383
+ const gameLike = !this.game && isRendererGameLike(params) ? params : undefined;
384
+ if (gameLike) {
385
+ this.game = gameLike;
386
+ }
387
+ const rendererParams = gameLike ? this.__systemDefaultParams || {} : params;
388
+ this.params = rendererParams;
389
+ this.application = yield this.createApplication(rendererParams);
297
390
  this.containerManager = new ContainerManager();
298
391
  this.rendererManager = new RendererManager$1({
299
392
  game: this.game,
300
393
  rendererSystem: this,
301
394
  });
302
- this.game.canvas = this.application.canvas;
395
+ if (this.game) {
396
+ this.game.canvas = this.application.canvas;
397
+ }
303
398
  this.transform = new Transform$1({
304
399
  system: this,
305
400
  containerManager: this.containerManager,
306
401
  });
307
- this.game.on('sceneChanged', ({ scene, mode, params }) => __awaiter(this, void 0, void 0, function* () {
402
+ (_b = (_a = this.game) === null || _a === void 0 ? void 0 : _a.on) === null || _b === void 0 ? void 0 : _b.call(_a, 'sceneChanged', ({ scene, mode, params }) => __awaiter(this, void 0, void 0, function* () {
308
403
  let application;
309
404
  switch (mode) {
310
405
  case LOAD_SCENE_MODE.SINGLE:
@@ -321,13 +416,13 @@ let Renderer$1 = class Renderer extends System {
321
416
  application,
322
417
  });
323
418
  }));
324
- this.game.on('pauseScene', ({ scene }) => {
419
+ (_d = (_c = this.game) === null || _c === void 0 ? void 0 : _c.on) === null || _d === void 0 ? void 0 : _d.call(_c, 'pauseScene', ({ scene }) => {
325
420
  this.onPauseScene(scene);
326
421
  });
327
- this.game.on('startScene', ({ scene }) => {
422
+ (_f = (_e = this.game) === null || _e === void 0 ? void 0 : _e.on) === null || _f === void 0 ? void 0 : _f.call(_e, 'startScene', ({ scene }) => {
328
423
  this.onStartScene(scene);
329
424
  });
330
- this.game.on('sceneDestroyed', ({ scene }) => __awaiter(this, void 0, void 0, function* () {
425
+ (_h = (_g = this.game) === null || _g === void 0 ? void 0 : _g.on) === null || _h === void 0 ? void 0 : _h.call(_g, 'sceneDestroyed', ({ scene }) => __awaiter(this, void 0, void 0, function* () {
331
426
  const index = this.multiApps.findIndex(app => app.canvas === scene.canvas);
332
427
  if (index > -1) {
333
428
  const app = this.multiApps.splice(index, 1)[0];
@@ -372,6 +467,8 @@ let Renderer$1 = class Renderer extends System {
372
467
  });
373
468
  }
374
469
  update() {
470
+ if (this.destroyed || !this.game || !this.containerManager || !this.rendererManager)
471
+ return;
375
472
  const changes = this.componentObserver.clear();
376
473
  for (const changed of changes) {
377
474
  this.transform.componentChanged(changed);
@@ -385,15 +482,23 @@ let Renderer$1 = class Renderer extends System {
385
482
  }
386
483
  }
387
484
  lateUpdate(e) {
485
+ if (this.destroyed || !this.transform || !this.application)
486
+ return;
388
487
  this.transform.update();
389
488
  this.application.ticker.update(e.time);
390
489
  }
391
490
  onDestroy() {
392
- this.application.destroy();
491
+ var _a, _b, _c, _d, _e, _f, _g;
492
+ if (this.destroyed)
493
+ return;
494
+ this.destroyed = true;
495
+ (_c = (_b = (_a = this.application) === null || _a === void 0 ? void 0 : _a.ticker) === null || _b === void 0 ? void 0 : _b.stop) === null || _c === void 0 ? void 0 : _c.call(_b);
496
+ (_d = this.application) === null || _d === void 0 ? void 0 : _d.destroy(false, { children: true, context: true });
393
497
  for (const app of this.multiApps) {
394
- app && app.destroy();
498
+ (_f = (_e = app === null || app === void 0 ? void 0 : app.ticker) === null || _e === void 0 ? void 0 : _e.stop) === null || _f === void 0 ? void 0 : _f.call(_e);
499
+ app && app.destroy(false, { children: true, context: true });
395
500
  }
396
- this.transform.destroy();
501
+ (_g = this.transform) === null || _g === void 0 ? void 0 : _g.destroy();
397
502
  this.transform = null;
398
503
  this.params = null;
399
504
  this.rendererManager = null;
@@ -402,11 +507,102 @@ let Renderer$1 = class Renderer extends System {
402
507
  this.game = null;
403
508
  this.multiApps = null;
404
509
  }
405
- resize(width, height) {
510
+ resize(width, height, resolution) {
406
511
  this.params.width = width;
407
512
  this.params.height = height;
513
+ if (resolution != null) {
514
+ this.params.resolution = this.clampResolution(resolution);
515
+ }
408
516
  // @ts-ignore
409
- this.application.renderer.resize(width, height);
517
+ this.application.renderer.resize(width, height, this.params.resolution);
518
+ if (resolution != null) {
519
+ this.syncDisplayObjectResolution(this.params.resolution);
520
+ }
521
+ }
522
+ /**
523
+ * 更新 Pixi renderer backing-store resolution,不改变 Eva 设计坐标系。
524
+ *
525
+ * 预览画布可用该入口在 zoom/devicePixelRatio 变化时提高清晰度;
526
+ * getBounds/Transform/worldTransform 仍返回设计逻辑坐标,不乘 resolution。
527
+ */
528
+ resizeRenderer(options) {
529
+ var _a, _b, _c, _d, _e, _f;
530
+ const width = (_b = (_a = options.width) !== null && _a !== void 0 ? _a : this.params.width) !== null && _b !== void 0 ? _b : this.application.renderer.width;
531
+ const height = (_d = (_c = options.height) !== null && _c !== void 0 ? _c : this.params.height) !== null && _d !== void 0 ? _d : this.application.renderer.height;
532
+ const resolution = options.resolution == null
533
+ ? (_f = (_e = this.params.resolution) !== null && _e !== void 0 ? _e : this.application.renderer.resolution) !== null && _f !== void 0 ? _f : 1
534
+ : this.clampResolution(options.resolution, options.maxResolution);
535
+ this.params.width = width;
536
+ this.params.height = height;
537
+ this.params.resolution = resolution;
538
+ // @ts-ignore Pixi v8 accepts resolution as the third resize argument.
539
+ this.application.renderer.resize(width, height, resolution);
540
+ const displayResolutionSyncCount = this.syncDisplayObjectResolution(resolution);
541
+ return { width, height, resolution, displayResolutionSyncCount };
542
+ }
543
+ setResolution(resolution, options = {}) {
544
+ return this.resizeRenderer(Object.assign(Object.assign({}, options), { resolution }));
545
+ }
546
+ clampResolution(resolution, maxResolution = 3) {
547
+ const normalized = Number.isFinite(resolution) && resolution > 0 ? resolution : 1;
548
+ return Math.min(normalized, maxResolution);
549
+ }
550
+ /**
551
+ * Keep renderer-owned display objects that expose a resolution property in
552
+ * sync with the backing-store resolution. This is intentionally display-tree
553
+ * based rather than component-type based, so Text/HTMLText and future Pixi
554
+ * objects with resolution support all follow the same renderer contract.
555
+ */
556
+ syncDisplayObjectResolution(resolution) {
557
+ var _a;
558
+ const roots = ((_a = this.containerManager) === null || _a === void 0 ? void 0 : _a.containerMap) ? Object.values(this.containerManager.containerMap) : [];
559
+ const visited = typeof WeakSet !== 'undefined' ? new WeakSet() : undefined;
560
+ let syncedCount = 0;
561
+ const visit = (displayObject) => {
562
+ if (!displayObject || typeof displayObject !== 'object')
563
+ return;
564
+ if (visited === null || visited === void 0 ? void 0 : visited.has(displayObject))
565
+ return;
566
+ visited === null || visited === void 0 ? void 0 : visited.add(displayObject);
567
+ if ('resolution' in displayObject) {
568
+ const currentResolution = displayObject.resolution;
569
+ if ((typeof currentResolution === 'number' || currentResolution === null) &&
570
+ Math.abs((currentResolution !== null && currentResolution !== void 0 ? currentResolution : 1) - resolution) > 0.001) {
571
+ try {
572
+ displayObject.resolution = resolution;
573
+ if (typeof displayObject.resolution === 'number' &&
574
+ Math.abs(displayObject.resolution - resolution) <= 0.001) {
575
+ syncedCount += 1;
576
+ }
577
+ }
578
+ catch (_) {
579
+ // Some Pixi objects expose a readonly or unsupported resolution setter.
580
+ }
581
+ }
582
+ }
583
+ if (Array.isArray(displayObject.children)) {
584
+ for (const child of displayObject.children) {
585
+ visit(child);
586
+ }
587
+ }
588
+ };
589
+ for (const root of roots) {
590
+ visit(root);
591
+ }
592
+ return syncedCount;
593
+ }
594
+ /**
595
+ * 获取 GameObject 的真实渲染 bounds。
596
+ *
597
+ * 默认返回 PixiJS display object 的 world bounds。Eva 的 Pixi world 坐标
598
+ * 与 canvas/design 逻辑坐标一致;如果画布被 CSS 缩放,调用方再按
599
+ * canvas.getBoundingClientRect() / renderer width 做屏幕坐标换算。
600
+ *
601
+ * 当渲染对象尚未挂载或资源未加载完成时,会回退到 Transform.size。
602
+ */
603
+ getBounds(gameObject, options) {
604
+ var _a;
605
+ return ((_a = this.containerManager) === null || _a === void 0 ? void 0 : _a.getBounds(gameObject, options)) || null;
410
606
  }
411
607
  getApplicationByScene(scene) {
412
608
  const index = this.multiApps.findIndex(app => app.canvas === scene.canvas);
@@ -430,11 +626,11 @@ let Renderer$1 = class Renderer extends System {
430
626
  app.start();
431
627
  }
432
628
  }
433
- resizeByScene(scene, width, height) {
629
+ resizeByScene(scene, width, height, resolution) {
434
630
  const app = this.getApplicationByScene(scene);
435
631
  if (app) {
436
632
  // @ts-ignore
437
- app.renderer.resize(width, height);
633
+ app.renderer.resize(width, height, resolution);
438
634
  }
439
635
  }
440
636
  };
@@ -527,7 +723,7 @@ class Renderer extends System {
527
723
  * 每帧调用
528
724
  *
529
725
  * called by every loop
530
- * @param _gameObject gameObject
726
+ * @param _gameObject - gameObject
531
727
  */
532
728
  rendererUpdate(_gameObject) { }
533
729
  // @ts-ignore
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eva/plugin-renderer",
3
- "version": "2.0.2",
3
+ "version": "2.1.0-beta.1",
4
4
  "description": "@eva/plugin-renderer",
5
5
  "main": "index.js",
6
6
  "module": "dist/plugin-renderer.esm.js",
@@ -18,8 +18,8 @@
18
18
  "license": "MIT",
19
19
  "homepage": "https://eva.js.org",
20
20
  "dependencies": {
21
- "@eva/eva.js": "2.0.2",
22
- "@eva/renderer-adapter": "2.0.2",
21
+ "@eva/eva.js": "2.1.0-beta.1",
22
+ "@eva/renderer-adapter": "2.1.0-beta.1",
23
23
  "eventemitter3": "^5.0.4",
24
24
  "lodash-es": "^4.17.21",
25
25
  "pixi.js": "^8.17.0"