rendx-engine 0.2.0 → 0.4.0
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/main.cjs +260 -27
- package/dist/main.d.cts +122 -4
- package/dist/main.d.ts +122 -4
- package/dist/main.js +257 -25
- package/package.json +9 -9
package/dist/main.cjs
CHANGED
|
@@ -64,6 +64,7 @@ __export(main_exports, {
|
|
|
64
64
|
Renderer: () => Renderer,
|
|
65
65
|
RoundShape: () => RoundShape,
|
|
66
66
|
Scene: () => Scene,
|
|
67
|
+
Scheduler: () => Scheduler,
|
|
67
68
|
SectorShape: () => SectorShape,
|
|
68
69
|
SectorTransform: () => SectorTransform,
|
|
69
70
|
Shape: () => Shape,
|
|
@@ -476,7 +477,7 @@ getEmitter_fn = function() {
|
|
|
476
477
|
};
|
|
477
478
|
|
|
478
479
|
// src/core/graphics.ts
|
|
479
|
-
var _nameMap, _classlist, _Graphics_instances, removeFromNameMap_fn, updateMat2d_fn, updateWorldMatrix_fn, updateEZ_fn;
|
|
480
|
+
var _nameMap, _classlist, _Graphics_instances, removeFromNameMap_fn, inheritState_fn, updateMat2d_fn, updateWorldMatrix_fn, updateEZ_fn;
|
|
480
481
|
var Graphics = class extends EventTarget {
|
|
481
482
|
constructor() {
|
|
482
483
|
super(...arguments);
|
|
@@ -592,6 +593,7 @@ var Graphics = class extends EventTarget {
|
|
|
592
593
|
this.children.push(child);
|
|
593
594
|
if (__privateGet(this, _nameMap).has(child.name)) throw new Error(`The name "${child.name}" is already used.`);
|
|
594
595
|
if (child.name) __privateGet(this, _nameMap).set(child.name, child);
|
|
596
|
+
__privateMethod(this, _Graphics_instances, inheritState_fn).call(this, child);
|
|
595
597
|
this.setDirty(true);
|
|
596
598
|
return this;
|
|
597
599
|
}
|
|
@@ -600,6 +602,7 @@ var Graphics = class extends EventTarget {
|
|
|
600
602
|
child.parent = this;
|
|
601
603
|
this.children.unshift(child);
|
|
602
604
|
__privateMethod(this, _Graphics_instances, removeFromNameMap_fn).call(this, child);
|
|
605
|
+
__privateMethod(this, _Graphics_instances, inheritState_fn).call(this, child);
|
|
603
606
|
this.setDirty(true);
|
|
604
607
|
return this;
|
|
605
608
|
}
|
|
@@ -842,6 +845,22 @@ _Graphics_instances = new WeakSet();
|
|
|
842
845
|
removeFromNameMap_fn = function(g) {
|
|
843
846
|
if (__privateGet(this, _nameMap).has(g.name)) __privateGet(this, _nameMap).delete(g.name);
|
|
844
847
|
};
|
|
848
|
+
/**
|
|
849
|
+
* 将父节点的可继承状态(visible / display / pointerEvents)传播给新增子节点。
|
|
850
|
+
* 模拟 DOM 中 CSS 继承属性的行为:
|
|
851
|
+
* - 父级 pointer-events: none → 子级默认继承 none,除非子级显式覆盖
|
|
852
|
+
* - 父级 visibility: hidden → 同上
|
|
853
|
+
* - 父级 display: none → 整棵子树不渲染
|
|
854
|
+
*
|
|
855
|
+
* 使用 bySelf=false 调用,尊重子节点的 autoX 标记:
|
|
856
|
+
* - autoX=true(默认)→ 接受父级值
|
|
857
|
+
* - autoX=false(子节点显式设置过)→ 保持自身值不变
|
|
858
|
+
*/
|
|
859
|
+
inheritState_fn = function(child) {
|
|
860
|
+
if (!this.visible) child.setVisible(false, false);
|
|
861
|
+
if (!this.display) child.setDisplay(false, false);
|
|
862
|
+
if (!this.pointerEvents) child.setPointerEvents(false, false);
|
|
863
|
+
};
|
|
845
864
|
updateMat2d_fn = function() {
|
|
846
865
|
if (!this.needUpdate) return;
|
|
847
866
|
import_gl_matrix.mat2d.identity(this.matrix);
|
|
@@ -1251,7 +1270,7 @@ var Group = class extends Graphics {
|
|
|
1251
1270
|
|
|
1252
1271
|
// src/scene/node.ts
|
|
1253
1272
|
var import_gl_matrix3 = require("gl-matrix");
|
|
1254
|
-
var
|
|
1273
|
+
var import_rendx_bounding16 = require("rendx-bounding");
|
|
1255
1274
|
|
|
1256
1275
|
// src/shapes/symbol.ts
|
|
1257
1276
|
var import_rendx_bounding2 = require("rendx-bounding");
|
|
@@ -1648,6 +1667,8 @@ var ArcShape = class extends Shape {
|
|
|
1648
1667
|
};
|
|
1649
1668
|
|
|
1650
1669
|
// src/shapes/path.ts
|
|
1670
|
+
var import_rendx_bounding9 = require("rendx-bounding");
|
|
1671
|
+
var import_rendx_path9 = require("rendx-path");
|
|
1651
1672
|
var PathShape = class extends Shape {
|
|
1652
1673
|
constructor() {
|
|
1653
1674
|
super(...arguments);
|
|
@@ -1656,11 +1677,19 @@ var PathShape = class extends Shape {
|
|
|
1656
1677
|
from(d) {
|
|
1657
1678
|
this.d = d;
|
|
1658
1679
|
this.p = null;
|
|
1680
|
+
if (this.autoNeedUpdate) this.needUpdate = true;
|
|
1681
|
+
}
|
|
1682
|
+
box() {
|
|
1683
|
+
const result = (0, import_rendx_path9.pathBBox)(this.d);
|
|
1684
|
+
if (result) {
|
|
1685
|
+
this.boundingBox = import_rendx_bounding9.BoundingBox.fromPoints(result[0], result[1], result[2], result[3]);
|
|
1686
|
+
}
|
|
1687
|
+
return this.boundingBox;
|
|
1659
1688
|
}
|
|
1660
1689
|
};
|
|
1661
1690
|
|
|
1662
1691
|
// src/shapes/text.ts
|
|
1663
|
-
var
|
|
1692
|
+
var import_rendx_bounding10 = require("rendx-bounding");
|
|
1664
1693
|
var _attrs;
|
|
1665
1694
|
var _TextShape = class _TextShape extends Shape {
|
|
1666
1695
|
constructor() {
|
|
@@ -1693,7 +1722,7 @@ var _TextShape = class _TextShape extends Shape {
|
|
|
1693
1722
|
if (measureFn && this.text) {
|
|
1694
1723
|
const bb = measureFn(this.text, __privateGet(this, _attrs));
|
|
1695
1724
|
if (bb) {
|
|
1696
|
-
this.boundingBox =
|
|
1725
|
+
this.boundingBox = import_rendx_bounding10.BoundingBox.fromRect(this.x, this.y - bb.height, bb.width, bb.height);
|
|
1697
1726
|
return this.boundingBox;
|
|
1698
1727
|
}
|
|
1699
1728
|
}
|
|
@@ -1724,7 +1753,7 @@ _TextShape.defaultMeasure = null;
|
|
|
1724
1753
|
var TextShape = _TextShape;
|
|
1725
1754
|
|
|
1726
1755
|
// src/shapes/line.ts
|
|
1727
|
-
var
|
|
1756
|
+
var import_rendx_bounding11 = require("rendx-bounding");
|
|
1728
1757
|
var LineShape = class extends Shape {
|
|
1729
1758
|
constructor() {
|
|
1730
1759
|
super(...arguments);
|
|
@@ -1756,13 +1785,13 @@ var LineShape = class extends Shape {
|
|
|
1756
1785
|
}
|
|
1757
1786
|
box() {
|
|
1758
1787
|
const { x1, y1, x2, y2 } = this;
|
|
1759
|
-
this.boundingBox =
|
|
1788
|
+
this.boundingBox = import_rendx_bounding11.BoundingBox.fromPoints(x1, y1, x2, y2);
|
|
1760
1789
|
return this.boundingBox;
|
|
1761
1790
|
}
|
|
1762
1791
|
};
|
|
1763
1792
|
|
|
1764
1793
|
// src/shapes/rect.ts
|
|
1765
|
-
var
|
|
1794
|
+
var import_rendx_bounding12 = require("rendx-bounding");
|
|
1766
1795
|
var RectShape = class extends Shape {
|
|
1767
1796
|
constructor() {
|
|
1768
1797
|
super(...arguments);
|
|
@@ -1792,13 +1821,13 @@ var RectShape = class extends Shape {
|
|
|
1792
1821
|
}
|
|
1793
1822
|
box() {
|
|
1794
1823
|
const { x, y, width, height } = this;
|
|
1795
|
-
this.boundingBox =
|
|
1824
|
+
this.boundingBox = import_rendx_bounding12.BoundingBox.fromRect(x, y, width, height);
|
|
1796
1825
|
return this.boundingBox;
|
|
1797
1826
|
}
|
|
1798
1827
|
};
|
|
1799
1828
|
|
|
1800
1829
|
// src/shapes/circle.ts
|
|
1801
|
-
var
|
|
1830
|
+
var import_rendx_bounding13 = require("rendx-bounding");
|
|
1802
1831
|
var CircleShape = class extends Shape {
|
|
1803
1832
|
constructor() {
|
|
1804
1833
|
super(...arguments);
|
|
@@ -1825,13 +1854,13 @@ var CircleShape = class extends Shape {
|
|
|
1825
1854
|
}
|
|
1826
1855
|
box() {
|
|
1827
1856
|
const { cx, cy, r } = this;
|
|
1828
|
-
this.boundingBox =
|
|
1857
|
+
this.boundingBox = import_rendx_bounding13.BoundingBox.fromPoints(cx - r, cy - r, cx + r, cy + r);
|
|
1829
1858
|
return this.boundingBox;
|
|
1830
1859
|
}
|
|
1831
1860
|
};
|
|
1832
1861
|
|
|
1833
1862
|
// src/shapes/image.ts
|
|
1834
|
-
var
|
|
1863
|
+
var import_rendx_bounding14 = require("rendx-bounding");
|
|
1835
1864
|
var ImageShape = class extends Shape {
|
|
1836
1865
|
constructor() {
|
|
1837
1866
|
super(...arguments);
|
|
@@ -1875,15 +1904,15 @@ var ImageShape = class extends Shape {
|
|
|
1875
1904
|
}
|
|
1876
1905
|
box() {
|
|
1877
1906
|
const { x, y, width, height } = this;
|
|
1878
|
-
this.boundingBox =
|
|
1907
|
+
this.boundingBox = import_rendx_bounding14.BoundingBox.fromRect(x, y, width, height);
|
|
1879
1908
|
return this.boundingBox;
|
|
1880
1909
|
}
|
|
1881
1910
|
};
|
|
1882
1911
|
|
|
1883
1912
|
// src/shapes/rect-buffer.ts
|
|
1884
|
-
var
|
|
1913
|
+
var import_rendx_bounding15 = require("rendx-bounding");
|
|
1885
1914
|
var import_rendx_shape8 = require("rendx-shape");
|
|
1886
|
-
var
|
|
1915
|
+
var import_rendx_path10 = require("rendx-path");
|
|
1887
1916
|
var RectBufferShape = class extends Shape {
|
|
1888
1917
|
constructor() {
|
|
1889
1918
|
super(...arguments);
|
|
@@ -1900,7 +1929,7 @@ var RectBufferShape = class extends Shape {
|
|
|
1900
1929
|
build() {
|
|
1901
1930
|
if (!this.needUpdate) return;
|
|
1902
1931
|
if (this.mode === "render") {
|
|
1903
|
-
if (!this.creator) this.creator = new
|
|
1932
|
+
if (!this.creator) this.creator = new import_rendx_path10.Path();
|
|
1904
1933
|
else this.creator.clear();
|
|
1905
1934
|
const { buffer } = this;
|
|
1906
1935
|
for (let i = 0; i < buffer.length; i += 4) {
|
|
@@ -1947,7 +1976,7 @@ var RectBufferShape = class extends Shape {
|
|
|
1947
1976
|
x1 = Math.max(x1, x + width);
|
|
1948
1977
|
y1 = Math.max(y1, y + height);
|
|
1949
1978
|
}
|
|
1950
|
-
this.boundingBox =
|
|
1979
|
+
this.boundingBox = import_rendx_bounding15.BoundingBox.fromPoints(x0, y0, x1, y1);
|
|
1951
1980
|
return this.boundingBox;
|
|
1952
1981
|
}
|
|
1953
1982
|
};
|
|
@@ -2050,7 +2079,7 @@ var _Node = class _Node extends Graphics {
|
|
|
2050
2079
|
if (wx > maxX) maxX = wx;
|
|
2051
2080
|
if (wy < minY) minY = wy;
|
|
2052
2081
|
if (wy > maxY) maxY = wy;
|
|
2053
|
-
return
|
|
2082
|
+
return import_rendx_bounding16.BoundingBox.fromPoints(minX, minY, maxX, maxY);
|
|
2054
2083
|
}
|
|
2055
2084
|
/**
|
|
2056
2085
|
* 命中检测:将屏幕坐标通过逆世界矩阵变换为本地坐标,然后检测是否命中
|
|
@@ -2560,6 +2589,48 @@ createListener_fn = function(type) {
|
|
|
2560
2589
|
};
|
|
2561
2590
|
};
|
|
2562
2591
|
|
|
2592
|
+
// src/app.ts
|
|
2593
|
+
var import_eventemitter32 = __toESM(require("eventemitter3"), 1);
|
|
2594
|
+
|
|
2595
|
+
// src/scheduler.ts
|
|
2596
|
+
var _pendingState, _microTaskQueued, _onFlush;
|
|
2597
|
+
var Scheduler = class {
|
|
2598
|
+
constructor(onFlush) {
|
|
2599
|
+
__privateAdd(this, _pendingState, /* @__PURE__ */ new Set());
|
|
2600
|
+
__privateAdd(this, _microTaskQueued, false);
|
|
2601
|
+
__privateAdd(this, _onFlush);
|
|
2602
|
+
__privateSet(this, _onFlush, onFlush);
|
|
2603
|
+
}
|
|
2604
|
+
/**
|
|
2605
|
+
* 标记 state key 变更,批量到微任务统一通知。
|
|
2606
|
+
* 同一轮微任务内多次调用同一 key 只通知一次。
|
|
2607
|
+
*/
|
|
2608
|
+
markState(key) {
|
|
2609
|
+
__privateGet(this, _pendingState).add(key);
|
|
2610
|
+
if (!__privateGet(this, _microTaskQueued)) {
|
|
2611
|
+
__privateSet(this, _microTaskQueued, true);
|
|
2612
|
+
queueMicrotask(() => {
|
|
2613
|
+
__privateSet(this, _microTaskQueued, false);
|
|
2614
|
+
const keys = new Set(__privateGet(this, _pendingState));
|
|
2615
|
+
__privateGet(this, _pendingState).clear();
|
|
2616
|
+
__privateGet(this, _onFlush).call(this, keys);
|
|
2617
|
+
});
|
|
2618
|
+
}
|
|
2619
|
+
}
|
|
2620
|
+
/** 是否有待通知的 state 变更 */
|
|
2621
|
+
get hasPending() {
|
|
2622
|
+
return __privateGet(this, _pendingState).size > 0;
|
|
2623
|
+
}
|
|
2624
|
+
/** 清空待通知队列(用于 dispose) */
|
|
2625
|
+
clear() {
|
|
2626
|
+
__privateGet(this, _pendingState).clear();
|
|
2627
|
+
__privateSet(this, _microTaskQueued, false);
|
|
2628
|
+
}
|
|
2629
|
+
};
|
|
2630
|
+
_pendingState = new WeakMap();
|
|
2631
|
+
_microTaskQueued = new WeakMap();
|
|
2632
|
+
_onFlush = new WeakMap();
|
|
2633
|
+
|
|
2563
2634
|
// src/serialization.ts
|
|
2564
2635
|
var SHAPE_FROM_KEYS = {
|
|
2565
2636
|
text: ["text", "x", "y"],
|
|
@@ -2721,21 +2792,39 @@ function deserialize(json, cfg) {
|
|
|
2721
2792
|
}
|
|
2722
2793
|
|
|
2723
2794
|
// src/app.ts
|
|
2724
|
-
var _rafId, _mounted, _container, _eventLayer, _resizeObserver, _plugins, _App_instances,
|
|
2795
|
+
var _rafId, _renderDirty, _mounted, _container, _eventLayer, _resizeObserver, _plugins, _state, _stateMeta, _scheduler, _App_instances, resolveIndex_fn, nextAvailableIndex_fn, frame_fn;
|
|
2725
2796
|
var _App = class _App {
|
|
2726
2797
|
/**
|
|
2727
2798
|
* @param cfg - 引擎配置(width/height/layers/autoResize 等)
|
|
2728
2799
|
*/
|
|
2729
2800
|
constructor(cfg = {}) {
|
|
2730
2801
|
__privateAdd(this, _App_instances);
|
|
2802
|
+
/**
|
|
2803
|
+
* 中心化事件总线 — 纯信号(不传数据)。
|
|
2804
|
+
* 插件通过 `app.bus.emit('eventName')` 发布信号,
|
|
2805
|
+
* 消费方通过 `app.bus.on('eventName', handler)` 订阅。
|
|
2806
|
+
*/
|
|
2807
|
+
this.bus = new import_eventemitter32.default();
|
|
2731
2808
|
__privateAdd(this, _rafId, null);
|
|
2809
|
+
__privateAdd(this, _renderDirty, false);
|
|
2732
2810
|
__privateAdd(this, _mounted, false);
|
|
2733
2811
|
__privateAdd(this, _container, null);
|
|
2734
2812
|
__privateAdd(this, _eventLayer);
|
|
2735
2813
|
__privateAdd(this, _resizeObserver, null);
|
|
2736
2814
|
__privateAdd(this, _plugins, []);
|
|
2815
|
+
// ========================
|
|
2816
|
+
// State Management
|
|
2817
|
+
// ========================
|
|
2818
|
+
__privateAdd(this, _state, /* @__PURE__ */ new Map());
|
|
2819
|
+
__privateAdd(this, _stateMeta, /* @__PURE__ */ new Map());
|
|
2820
|
+
__privateAdd(this, _scheduler);
|
|
2737
2821
|
this.cfg = cfg;
|
|
2738
2822
|
this.scene = new Scene();
|
|
2823
|
+
__privateSet(this, _scheduler, new Scheduler((keys) => {
|
|
2824
|
+
for (const key of keys) {
|
|
2825
|
+
this.bus.emit(`state:${key}`);
|
|
2826
|
+
}
|
|
2827
|
+
}));
|
|
2739
2828
|
__privateSet(this, _eventLayer, new Layer("__event__", 99999, this.cfg, true));
|
|
2740
2829
|
this.scene.registerLayer(__privateGet(this, _eventLayer));
|
|
2741
2830
|
this.scene.registerLayer(new Layer("default", 0, this.cfg));
|
|
@@ -2808,7 +2897,30 @@ var _App = class _App {
|
|
|
2808
2897
|
return this.scene.getLayer(name);
|
|
2809
2898
|
}
|
|
2810
2899
|
/**
|
|
2811
|
-
*
|
|
2900
|
+
* 获取或创建图层(get-or-create 语义)。
|
|
2901
|
+
* 多个插件声明同名图层时,只会创建一次。
|
|
2902
|
+
*
|
|
2903
|
+
* zIndex 语义:
|
|
2904
|
+
* - 传入时代表全局层级意图(负数 = default 之下,正数 = default 之上)
|
|
2905
|
+
* - 若与已有层冲突,自动向上偏移到最近可用值
|
|
2906
|
+
* - 省略时自动分配(当前最高非事件层 + 1)
|
|
2907
|
+
*
|
|
2908
|
+
* @param name - 层名称
|
|
2909
|
+
* @param zIndex - 全局层级意图(可选)
|
|
2910
|
+
*/
|
|
2911
|
+
acquireLayer(name, zIndex) {
|
|
2912
|
+
const existing = this.scene.getLayer(name);
|
|
2913
|
+
if (existing) return existing;
|
|
2914
|
+
const index = zIndex !== void 0 ? __privateMethod(this, _App_instances, resolveIndex_fn).call(this, zIndex) : __privateMethod(this, _App_instances, nextAvailableIndex_fn).call(this);
|
|
2915
|
+
return this.addLayer(name, index);
|
|
2916
|
+
}
|
|
2917
|
+
/**
|
|
2918
|
+
* 注册插件。流程:
|
|
2919
|
+
* 1. 去重检查(同名跳过)
|
|
2920
|
+
* 2. 注册 state 声明(key 冲突则抛错)
|
|
2921
|
+
* 3. 自动 acquireLayer(声明的图层)
|
|
2922
|
+
* 4. 调用 plugin.install(app)
|
|
2923
|
+
*
|
|
2812
2924
|
* @param plugin - 实现 Plugin 接口的插件实例
|
|
2813
2925
|
*/
|
|
2814
2926
|
use(plugin) {
|
|
@@ -2816,6 +2928,22 @@ var _App = class _App {
|
|
|
2816
2928
|
console.warn(`Plugin "${plugin.name}" is already registered.`);
|
|
2817
2929
|
return this;
|
|
2818
2930
|
}
|
|
2931
|
+
if (plugin.state) {
|
|
2932
|
+
for (const decl of plugin.state) {
|
|
2933
|
+
if (__privateGet(this, _stateMeta).has(decl.key)) {
|
|
2934
|
+
const owner = __privateGet(this, _stateMeta).get(decl.key).owner;
|
|
2935
|
+
throw new Error(`State key "${decl.key}" already declared by plugin "${owner}". Plugin "${plugin.name}" cannot redeclare it.`);
|
|
2936
|
+
}
|
|
2937
|
+
__privateGet(this, _stateMeta).set(decl.key, { owner: plugin.name, description: decl.description });
|
|
2938
|
+
__privateGet(this, _state).set(decl.key, decl.initial);
|
|
2939
|
+
}
|
|
2940
|
+
}
|
|
2941
|
+
if (plugin.layers) {
|
|
2942
|
+
const sorted = [...plugin.layers].sort((a, b) => (a.zIndex ?? 0) - (b.zIndex ?? 0));
|
|
2943
|
+
for (const decl of sorted) {
|
|
2944
|
+
this.acquireLayer(decl.name, decl.zIndex);
|
|
2945
|
+
}
|
|
2946
|
+
}
|
|
2819
2947
|
__privateGet(this, _plugins).push(plugin);
|
|
2820
2948
|
plugin.install(this);
|
|
2821
2949
|
return this;
|
|
@@ -2824,6 +2952,40 @@ var _App = class _App {
|
|
|
2824
2952
|
getPlugin(name) {
|
|
2825
2953
|
return __privateGet(this, _plugins).find((p) => p.name === name);
|
|
2826
2954
|
}
|
|
2955
|
+
// ========================
|
|
2956
|
+
// Centralized State
|
|
2957
|
+
// ========================
|
|
2958
|
+
/**
|
|
2959
|
+
* 写入 state(同步写入 + 异步批量通知)。
|
|
2960
|
+
* key 必须先由某个插件在 `state[]` 中声明,否则抛错。
|
|
2961
|
+
* 写入后立即可通过 `getState()` 读到最新值,通知在微任务中批量发出。
|
|
2962
|
+
*/
|
|
2963
|
+
setState(key, value) {
|
|
2964
|
+
if (!__privateGet(this, _stateMeta).has(key)) {
|
|
2965
|
+
throw new Error(`State key "${key}" is not declared by any plugin. Plugins must declare state keys in their "state" array.`);
|
|
2966
|
+
}
|
|
2967
|
+
__privateGet(this, _state).set(key, value);
|
|
2968
|
+
__privateGet(this, _scheduler).markState(key);
|
|
2969
|
+
}
|
|
2970
|
+
/**
|
|
2971
|
+
* 读取 state(同步读取,始终返回最新值)。
|
|
2972
|
+
* @returns 对应 key 的当前值,不存在则返回 undefined
|
|
2973
|
+
*/
|
|
2974
|
+
getState(key) {
|
|
2975
|
+
return __privateGet(this, _state).get(key);
|
|
2976
|
+
}
|
|
2977
|
+
/**
|
|
2978
|
+
* 导出完整 state 快照(调试/devtools 用)。
|
|
2979
|
+
* 返回每个 key 的当前值、所属插件和描述信息。
|
|
2980
|
+
*/
|
|
2981
|
+
dumpState() {
|
|
2982
|
+
const result = {};
|
|
2983
|
+
for (const [key, value] of __privateGet(this, _state)) {
|
|
2984
|
+
const meta = __privateGet(this, _stateMeta).get(key);
|
|
2985
|
+
result[key] = { value, owner: meta.owner, description: meta.description };
|
|
2986
|
+
}
|
|
2987
|
+
return result;
|
|
2988
|
+
}
|
|
2827
2989
|
/** 同步渲染一帧。适用于静态内容,仅重绘脏层 */
|
|
2828
2990
|
render() {
|
|
2829
2991
|
for (const layer of this.scene.layers) {
|
|
@@ -2832,10 +2994,12 @@ var _App = class _App {
|
|
|
2832
2994
|
}
|
|
2833
2995
|
}
|
|
2834
2996
|
}
|
|
2835
|
-
/**
|
|
2997
|
+
/** 请求异步渲染帧(幂等,一帧只执行一次)。无变化时自动停止 rAF 链 */
|
|
2836
2998
|
requestRender() {
|
|
2837
|
-
|
|
2838
|
-
|
|
2999
|
+
__privateSet(this, _renderDirty, true);
|
|
3000
|
+
if (__privateGet(this, _rafId) === null) {
|
|
3001
|
+
__privateSet(this, _rafId, requestAnimationFrame((t) => __privateMethod(this, _App_instances, frame_fn).call(this, t)));
|
|
3002
|
+
}
|
|
2839
3003
|
}
|
|
2840
3004
|
/**
|
|
2841
3005
|
* 调整画布尺寸,同步更新所有层、容器和视口矩阵
|
|
@@ -2861,6 +3025,26 @@ var _App = class _App {
|
|
|
2861
3025
|
plugin.resize?.(width, height);
|
|
2862
3026
|
}
|
|
2863
3027
|
}
|
|
3028
|
+
// ========================
|
|
3029
|
+
// Cursor
|
|
3030
|
+
// ========================
|
|
3031
|
+
/**
|
|
3032
|
+
* 设置容器的鼠标光标样式。
|
|
3033
|
+
* @param cursor - CSS cursor 值(如 'pointer'、'crosshair'、'grab')
|
|
3034
|
+
*/
|
|
3035
|
+
setCursor(cursor) {
|
|
3036
|
+
if (__privateGet(this, _container)) {
|
|
3037
|
+
__privateGet(this, _container).style.cursor = cursor;
|
|
3038
|
+
}
|
|
3039
|
+
}
|
|
3040
|
+
/**
|
|
3041
|
+
* 重置鼠标光标为默认值。
|
|
3042
|
+
*/
|
|
3043
|
+
resetCursor() {
|
|
3044
|
+
if (__privateGet(this, _container)) {
|
|
3045
|
+
__privateGet(this, _container).style.cursor = "";
|
|
3046
|
+
}
|
|
3047
|
+
}
|
|
2864
3048
|
clear() {
|
|
2865
3049
|
if (__privateGet(this, _rafId) !== null) {
|
|
2866
3050
|
cancelAnimationFrame(__privateGet(this, _rafId));
|
|
@@ -2876,6 +3060,10 @@ var _App = class _App {
|
|
|
2876
3060
|
plugin.dispose?.();
|
|
2877
3061
|
}
|
|
2878
3062
|
__privateSet(this, _plugins, []);
|
|
3063
|
+
this.bus.removeAllListeners();
|
|
3064
|
+
__privateGet(this, _state).clear();
|
|
3065
|
+
__privateGet(this, _stateMeta).clear();
|
|
3066
|
+
__privateGet(this, _scheduler).clear();
|
|
2879
3067
|
if (__privateGet(this, _resizeObserver)) {
|
|
2880
3068
|
__privateGet(this, _resizeObserver).disconnect();
|
|
2881
3069
|
__privateSet(this, _resizeObserver, null);
|
|
@@ -2910,7 +3098,17 @@ var _App = class _App {
|
|
|
2910
3098
|
}
|
|
2911
3099
|
/** 序列化所有渲染层的场景图为 JSON,可用于保存/回放 */
|
|
2912
3100
|
toJSON() {
|
|
2913
|
-
|
|
3101
|
+
const json = serialize(this.scene.layers, this.cfg.width ?? 800, this.cfg.height ?? 600);
|
|
3102
|
+
const pluginsData = {};
|
|
3103
|
+
for (const plugin of __privateGet(this, _plugins)) {
|
|
3104
|
+
if (plugin.serialize) {
|
|
3105
|
+
pluginsData[plugin.name] = plugin.serialize();
|
|
3106
|
+
}
|
|
3107
|
+
}
|
|
3108
|
+
if (Object.keys(pluginsData).length > 0) {
|
|
3109
|
+
json.plugins = pluginsData;
|
|
3110
|
+
}
|
|
3111
|
+
return json;
|
|
2914
3112
|
}
|
|
2915
3113
|
/**
|
|
2916
3114
|
* 从 JSON 快照创建新的 App 实例(静态工厂方法)
|
|
@@ -2949,17 +3147,49 @@ var _App = class _App {
|
|
|
2949
3147
|
__privateGet(this, _container).insertBefore(layer.renderer.el, __privateGet(this, _eventLayer).renderer.el);
|
|
2950
3148
|
}
|
|
2951
3149
|
}
|
|
3150
|
+
if (json.plugins) {
|
|
3151
|
+
for (const plugin of __privateGet(this, _plugins)) {
|
|
3152
|
+
const data = json.plugins[plugin.name];
|
|
3153
|
+
if (data && plugin.deserialize) {
|
|
3154
|
+
plugin.deserialize(data);
|
|
3155
|
+
}
|
|
3156
|
+
}
|
|
3157
|
+
}
|
|
2952
3158
|
}
|
|
2953
3159
|
};
|
|
2954
3160
|
_rafId = new WeakMap();
|
|
3161
|
+
_renderDirty = new WeakMap();
|
|
2955
3162
|
_mounted = new WeakMap();
|
|
2956
3163
|
_container = new WeakMap();
|
|
2957
3164
|
_eventLayer = new WeakMap();
|
|
2958
3165
|
_resizeObserver = new WeakMap();
|
|
2959
3166
|
_plugins = new WeakMap();
|
|
3167
|
+
_state = new WeakMap();
|
|
3168
|
+
_stateMeta = new WeakMap();
|
|
3169
|
+
_scheduler = new WeakMap();
|
|
2960
3170
|
_App_instances = new WeakSet();
|
|
2961
|
-
|
|
2962
|
-
|
|
3171
|
+
/**
|
|
3172
|
+
* 解析 zIndex:若已被占用则向上偏移到最近可用值。
|
|
3173
|
+
* 保证返回值不会与任何已有层的 layerIndex 冲突。
|
|
3174
|
+
*/
|
|
3175
|
+
resolveIndex_fn = function(desired) {
|
|
3176
|
+
const used = new Set(this.scene.layers.map((l) => l.layerIndex));
|
|
3177
|
+
while (used.has(desired)) desired++;
|
|
3178
|
+
return desired;
|
|
3179
|
+
};
|
|
3180
|
+
/**
|
|
3181
|
+
* 自动分配:当前最高非事件层 index + 1。
|
|
3182
|
+
* 保证返回值始终 >= 1(default 层固定为 0)。
|
|
3183
|
+
*/
|
|
3184
|
+
nextAvailableIndex_fn = function() {
|
|
3185
|
+
let max = 0;
|
|
3186
|
+
for (const l of this.scene.layers) {
|
|
3187
|
+
if (!l.isEventLayer && l.layerIndex > max) max = l.layerIndex;
|
|
3188
|
+
}
|
|
3189
|
+
return max + 1;
|
|
3190
|
+
};
|
|
3191
|
+
frame_fn = function(time) {
|
|
3192
|
+
__privateSet(this, _renderDirty, false);
|
|
2963
3193
|
this.scene.tick(time);
|
|
2964
3194
|
let anyDirty = false;
|
|
2965
3195
|
for (const layer of this.scene.layers) {
|
|
@@ -2968,8 +3198,10 @@ tick_fn = function(time) {
|
|
|
2968
3198
|
anyDirty = true;
|
|
2969
3199
|
}
|
|
2970
3200
|
}
|
|
2971
|
-
if (anyDirty) {
|
|
2972
|
-
this.
|
|
3201
|
+
if (anyDirty || __privateGet(this, _renderDirty)) {
|
|
3202
|
+
__privateSet(this, _rafId, requestAnimationFrame((t) => __privateMethod(this, _App_instances, frame_fn).call(this, t)));
|
|
3203
|
+
} else {
|
|
3204
|
+
__privateSet(this, _rafId, null);
|
|
2973
3205
|
}
|
|
2974
3206
|
};
|
|
2975
3207
|
var App = _App;
|
|
@@ -3001,6 +3233,7 @@ var App = _App;
|
|
|
3001
3233
|
Renderer,
|
|
3002
3234
|
RoundShape,
|
|
3003
3235
|
Scene,
|
|
3236
|
+
Scheduler,
|
|
3004
3237
|
SectorShape,
|
|
3005
3238
|
SectorTransform,
|
|
3006
3239
|
Shape,
|