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.js
CHANGED
|
@@ -403,7 +403,7 @@ getEmitter_fn = function() {
|
|
|
403
403
|
};
|
|
404
404
|
|
|
405
405
|
// src/core/graphics.ts
|
|
406
|
-
var _nameMap, _classlist, _Graphics_instances, removeFromNameMap_fn, updateMat2d_fn, updateWorldMatrix_fn, updateEZ_fn;
|
|
406
|
+
var _nameMap, _classlist, _Graphics_instances, removeFromNameMap_fn, inheritState_fn, updateMat2d_fn, updateWorldMatrix_fn, updateEZ_fn;
|
|
407
407
|
var Graphics = class extends EventTarget {
|
|
408
408
|
constructor() {
|
|
409
409
|
super(...arguments);
|
|
@@ -519,6 +519,7 @@ var Graphics = class extends EventTarget {
|
|
|
519
519
|
this.children.push(child);
|
|
520
520
|
if (__privateGet(this, _nameMap).has(child.name)) throw new Error(`The name "${child.name}" is already used.`);
|
|
521
521
|
if (child.name) __privateGet(this, _nameMap).set(child.name, child);
|
|
522
|
+
__privateMethod(this, _Graphics_instances, inheritState_fn).call(this, child);
|
|
522
523
|
this.setDirty(true);
|
|
523
524
|
return this;
|
|
524
525
|
}
|
|
@@ -527,6 +528,7 @@ var Graphics = class extends EventTarget {
|
|
|
527
528
|
child.parent = this;
|
|
528
529
|
this.children.unshift(child);
|
|
529
530
|
__privateMethod(this, _Graphics_instances, removeFromNameMap_fn).call(this, child);
|
|
531
|
+
__privateMethod(this, _Graphics_instances, inheritState_fn).call(this, child);
|
|
530
532
|
this.setDirty(true);
|
|
531
533
|
return this;
|
|
532
534
|
}
|
|
@@ -769,6 +771,22 @@ _Graphics_instances = new WeakSet();
|
|
|
769
771
|
removeFromNameMap_fn = function(g) {
|
|
770
772
|
if (__privateGet(this, _nameMap).has(g.name)) __privateGet(this, _nameMap).delete(g.name);
|
|
771
773
|
};
|
|
774
|
+
/**
|
|
775
|
+
* 将父节点的可继承状态(visible / display / pointerEvents)传播给新增子节点。
|
|
776
|
+
* 模拟 DOM 中 CSS 继承属性的行为:
|
|
777
|
+
* - 父级 pointer-events: none → 子级默认继承 none,除非子级显式覆盖
|
|
778
|
+
* - 父级 visibility: hidden → 同上
|
|
779
|
+
* - 父级 display: none → 整棵子树不渲染
|
|
780
|
+
*
|
|
781
|
+
* 使用 bySelf=false 调用,尊重子节点的 autoX 标记:
|
|
782
|
+
* - autoX=true(默认)→ 接受父级值
|
|
783
|
+
* - autoX=false(子节点显式设置过)→ 保持自身值不变
|
|
784
|
+
*/
|
|
785
|
+
inheritState_fn = function(child) {
|
|
786
|
+
if (!this.visible) child.setVisible(false, false);
|
|
787
|
+
if (!this.display) child.setDisplay(false, false);
|
|
788
|
+
if (!this.pointerEvents) child.setPointerEvents(false, false);
|
|
789
|
+
};
|
|
772
790
|
updateMat2d_fn = function() {
|
|
773
791
|
if (!this.needUpdate) return;
|
|
774
792
|
mat2d.identity(this.matrix);
|
|
@@ -1178,7 +1196,7 @@ var Group = class extends Graphics {
|
|
|
1178
1196
|
|
|
1179
1197
|
// src/scene/node.ts
|
|
1180
1198
|
import { mat2d as mat2d3, vec2 as vec23 } from "gl-matrix";
|
|
1181
|
-
import { BoundingBox as
|
|
1199
|
+
import { BoundingBox as BoundingBox16 } from "rendx-bounding";
|
|
1182
1200
|
|
|
1183
1201
|
// src/shapes/symbol.ts
|
|
1184
1202
|
import { BoundingBox as BoundingBox2 } from "rendx-bounding";
|
|
@@ -1575,6 +1593,8 @@ var ArcShape = class extends Shape {
|
|
|
1575
1593
|
};
|
|
1576
1594
|
|
|
1577
1595
|
// src/shapes/path.ts
|
|
1596
|
+
import { BoundingBox as BoundingBox9 } from "rendx-bounding";
|
|
1597
|
+
import { pathBBox } from "rendx-path";
|
|
1578
1598
|
var PathShape = class extends Shape {
|
|
1579
1599
|
constructor() {
|
|
1580
1600
|
super(...arguments);
|
|
@@ -1583,11 +1603,19 @@ var PathShape = class extends Shape {
|
|
|
1583
1603
|
from(d) {
|
|
1584
1604
|
this.d = d;
|
|
1585
1605
|
this.p = null;
|
|
1606
|
+
if (this.autoNeedUpdate) this.needUpdate = true;
|
|
1607
|
+
}
|
|
1608
|
+
box() {
|
|
1609
|
+
const result = pathBBox(this.d);
|
|
1610
|
+
if (result) {
|
|
1611
|
+
this.boundingBox = BoundingBox9.fromPoints(result[0], result[1], result[2], result[3]);
|
|
1612
|
+
}
|
|
1613
|
+
return this.boundingBox;
|
|
1586
1614
|
}
|
|
1587
1615
|
};
|
|
1588
1616
|
|
|
1589
1617
|
// src/shapes/text.ts
|
|
1590
|
-
import { BoundingBox as
|
|
1618
|
+
import { BoundingBox as BoundingBox10 } from "rendx-bounding";
|
|
1591
1619
|
var _attrs;
|
|
1592
1620
|
var _TextShape = class _TextShape extends Shape {
|
|
1593
1621
|
constructor() {
|
|
@@ -1620,7 +1648,7 @@ var _TextShape = class _TextShape extends Shape {
|
|
|
1620
1648
|
if (measureFn && this.text) {
|
|
1621
1649
|
const bb = measureFn(this.text, __privateGet(this, _attrs));
|
|
1622
1650
|
if (bb) {
|
|
1623
|
-
this.boundingBox =
|
|
1651
|
+
this.boundingBox = BoundingBox10.fromRect(this.x, this.y - bb.height, bb.width, bb.height);
|
|
1624
1652
|
return this.boundingBox;
|
|
1625
1653
|
}
|
|
1626
1654
|
}
|
|
@@ -1651,7 +1679,7 @@ _TextShape.defaultMeasure = null;
|
|
|
1651
1679
|
var TextShape = _TextShape;
|
|
1652
1680
|
|
|
1653
1681
|
// src/shapes/line.ts
|
|
1654
|
-
import { BoundingBox as
|
|
1682
|
+
import { BoundingBox as BoundingBox11 } from "rendx-bounding";
|
|
1655
1683
|
var LineShape = class extends Shape {
|
|
1656
1684
|
constructor() {
|
|
1657
1685
|
super(...arguments);
|
|
@@ -1683,13 +1711,13 @@ var LineShape = class extends Shape {
|
|
|
1683
1711
|
}
|
|
1684
1712
|
box() {
|
|
1685
1713
|
const { x1, y1, x2, y2 } = this;
|
|
1686
|
-
this.boundingBox =
|
|
1714
|
+
this.boundingBox = BoundingBox11.fromPoints(x1, y1, x2, y2);
|
|
1687
1715
|
return this.boundingBox;
|
|
1688
1716
|
}
|
|
1689
1717
|
};
|
|
1690
1718
|
|
|
1691
1719
|
// src/shapes/rect.ts
|
|
1692
|
-
import { BoundingBox as
|
|
1720
|
+
import { BoundingBox as BoundingBox12 } from "rendx-bounding";
|
|
1693
1721
|
var RectShape = class extends Shape {
|
|
1694
1722
|
constructor() {
|
|
1695
1723
|
super(...arguments);
|
|
@@ -1719,13 +1747,13 @@ var RectShape = class extends Shape {
|
|
|
1719
1747
|
}
|
|
1720
1748
|
box() {
|
|
1721
1749
|
const { x, y, width, height } = this;
|
|
1722
|
-
this.boundingBox =
|
|
1750
|
+
this.boundingBox = BoundingBox12.fromRect(x, y, width, height);
|
|
1723
1751
|
return this.boundingBox;
|
|
1724
1752
|
}
|
|
1725
1753
|
};
|
|
1726
1754
|
|
|
1727
1755
|
// src/shapes/circle.ts
|
|
1728
|
-
import { BoundingBox as
|
|
1756
|
+
import { BoundingBox as BoundingBox13 } from "rendx-bounding";
|
|
1729
1757
|
var CircleShape = class extends Shape {
|
|
1730
1758
|
constructor() {
|
|
1731
1759
|
super(...arguments);
|
|
@@ -1752,13 +1780,13 @@ var CircleShape = class extends Shape {
|
|
|
1752
1780
|
}
|
|
1753
1781
|
box() {
|
|
1754
1782
|
const { cx, cy, r } = this;
|
|
1755
|
-
this.boundingBox =
|
|
1783
|
+
this.boundingBox = BoundingBox13.fromPoints(cx - r, cy - r, cx + r, cy + r);
|
|
1756
1784
|
return this.boundingBox;
|
|
1757
1785
|
}
|
|
1758
1786
|
};
|
|
1759
1787
|
|
|
1760
1788
|
// src/shapes/image.ts
|
|
1761
|
-
import { BoundingBox as
|
|
1789
|
+
import { BoundingBox as BoundingBox14 } from "rendx-bounding";
|
|
1762
1790
|
var ImageShape = class extends Shape {
|
|
1763
1791
|
constructor() {
|
|
1764
1792
|
super(...arguments);
|
|
@@ -1802,13 +1830,13 @@ var ImageShape = class extends Shape {
|
|
|
1802
1830
|
}
|
|
1803
1831
|
box() {
|
|
1804
1832
|
const { x, y, width, height } = this;
|
|
1805
|
-
this.boundingBox =
|
|
1833
|
+
this.boundingBox = BoundingBox14.fromRect(x, y, width, height);
|
|
1806
1834
|
return this.boundingBox;
|
|
1807
1835
|
}
|
|
1808
1836
|
};
|
|
1809
1837
|
|
|
1810
1838
|
// src/shapes/rect-buffer.ts
|
|
1811
|
-
import { BoundingBox as
|
|
1839
|
+
import { BoundingBox as BoundingBox15 } from "rendx-bounding";
|
|
1812
1840
|
import { createShape as createShape7 } from "rendx-shape";
|
|
1813
1841
|
import { Path as Path9 } from "rendx-path";
|
|
1814
1842
|
var RectBufferShape = class extends Shape {
|
|
@@ -1874,7 +1902,7 @@ var RectBufferShape = class extends Shape {
|
|
|
1874
1902
|
x1 = Math.max(x1, x + width);
|
|
1875
1903
|
y1 = Math.max(y1, y + height);
|
|
1876
1904
|
}
|
|
1877
|
-
this.boundingBox =
|
|
1905
|
+
this.boundingBox = BoundingBox15.fromPoints(x0, y0, x1, y1);
|
|
1878
1906
|
return this.boundingBox;
|
|
1879
1907
|
}
|
|
1880
1908
|
};
|
|
@@ -1977,7 +2005,7 @@ var _Node = class _Node extends Graphics {
|
|
|
1977
2005
|
if (wx > maxX) maxX = wx;
|
|
1978
2006
|
if (wy < minY) minY = wy;
|
|
1979
2007
|
if (wy > maxY) maxY = wy;
|
|
1980
|
-
return
|
|
2008
|
+
return BoundingBox16.fromPoints(minX, minY, maxX, maxY);
|
|
1981
2009
|
}
|
|
1982
2010
|
/**
|
|
1983
2011
|
* 命中检测:将屏幕坐标通过逆世界矩阵变换为本地坐标,然后检测是否命中
|
|
@@ -2487,6 +2515,48 @@ createListener_fn = function(type) {
|
|
|
2487
2515
|
};
|
|
2488
2516
|
};
|
|
2489
2517
|
|
|
2518
|
+
// src/app.ts
|
|
2519
|
+
import EventEmitter2 from "eventemitter3";
|
|
2520
|
+
|
|
2521
|
+
// src/scheduler.ts
|
|
2522
|
+
var _pendingState, _microTaskQueued, _onFlush;
|
|
2523
|
+
var Scheduler = class {
|
|
2524
|
+
constructor(onFlush) {
|
|
2525
|
+
__privateAdd(this, _pendingState, /* @__PURE__ */ new Set());
|
|
2526
|
+
__privateAdd(this, _microTaskQueued, false);
|
|
2527
|
+
__privateAdd(this, _onFlush);
|
|
2528
|
+
__privateSet(this, _onFlush, onFlush);
|
|
2529
|
+
}
|
|
2530
|
+
/**
|
|
2531
|
+
* 标记 state key 变更,批量到微任务统一通知。
|
|
2532
|
+
* 同一轮微任务内多次调用同一 key 只通知一次。
|
|
2533
|
+
*/
|
|
2534
|
+
markState(key) {
|
|
2535
|
+
__privateGet(this, _pendingState).add(key);
|
|
2536
|
+
if (!__privateGet(this, _microTaskQueued)) {
|
|
2537
|
+
__privateSet(this, _microTaskQueued, true);
|
|
2538
|
+
queueMicrotask(() => {
|
|
2539
|
+
__privateSet(this, _microTaskQueued, false);
|
|
2540
|
+
const keys = new Set(__privateGet(this, _pendingState));
|
|
2541
|
+
__privateGet(this, _pendingState).clear();
|
|
2542
|
+
__privateGet(this, _onFlush).call(this, keys);
|
|
2543
|
+
});
|
|
2544
|
+
}
|
|
2545
|
+
}
|
|
2546
|
+
/** 是否有待通知的 state 变更 */
|
|
2547
|
+
get hasPending() {
|
|
2548
|
+
return __privateGet(this, _pendingState).size > 0;
|
|
2549
|
+
}
|
|
2550
|
+
/** 清空待通知队列(用于 dispose) */
|
|
2551
|
+
clear() {
|
|
2552
|
+
__privateGet(this, _pendingState).clear();
|
|
2553
|
+
__privateSet(this, _microTaskQueued, false);
|
|
2554
|
+
}
|
|
2555
|
+
};
|
|
2556
|
+
_pendingState = new WeakMap();
|
|
2557
|
+
_microTaskQueued = new WeakMap();
|
|
2558
|
+
_onFlush = new WeakMap();
|
|
2559
|
+
|
|
2490
2560
|
// src/serialization.ts
|
|
2491
2561
|
var SHAPE_FROM_KEYS = {
|
|
2492
2562
|
text: ["text", "x", "y"],
|
|
@@ -2648,21 +2718,39 @@ function deserialize(json, cfg) {
|
|
|
2648
2718
|
}
|
|
2649
2719
|
|
|
2650
2720
|
// src/app.ts
|
|
2651
|
-
var _rafId, _mounted, _container, _eventLayer, _resizeObserver, _plugins, _App_instances,
|
|
2721
|
+
var _rafId, _renderDirty, _mounted, _container, _eventLayer, _resizeObserver, _plugins, _state, _stateMeta, _scheduler, _App_instances, resolveIndex_fn, nextAvailableIndex_fn, frame_fn;
|
|
2652
2722
|
var _App = class _App {
|
|
2653
2723
|
/**
|
|
2654
2724
|
* @param cfg - 引擎配置(width/height/layers/autoResize 等)
|
|
2655
2725
|
*/
|
|
2656
2726
|
constructor(cfg = {}) {
|
|
2657
2727
|
__privateAdd(this, _App_instances);
|
|
2728
|
+
/**
|
|
2729
|
+
* 中心化事件总线 — 纯信号(不传数据)。
|
|
2730
|
+
* 插件通过 `app.bus.emit('eventName')` 发布信号,
|
|
2731
|
+
* 消费方通过 `app.bus.on('eventName', handler)` 订阅。
|
|
2732
|
+
*/
|
|
2733
|
+
this.bus = new EventEmitter2();
|
|
2658
2734
|
__privateAdd(this, _rafId, null);
|
|
2735
|
+
__privateAdd(this, _renderDirty, false);
|
|
2659
2736
|
__privateAdd(this, _mounted, false);
|
|
2660
2737
|
__privateAdd(this, _container, null);
|
|
2661
2738
|
__privateAdd(this, _eventLayer);
|
|
2662
2739
|
__privateAdd(this, _resizeObserver, null);
|
|
2663
2740
|
__privateAdd(this, _plugins, []);
|
|
2741
|
+
// ========================
|
|
2742
|
+
// State Management
|
|
2743
|
+
// ========================
|
|
2744
|
+
__privateAdd(this, _state, /* @__PURE__ */ new Map());
|
|
2745
|
+
__privateAdd(this, _stateMeta, /* @__PURE__ */ new Map());
|
|
2746
|
+
__privateAdd(this, _scheduler);
|
|
2664
2747
|
this.cfg = cfg;
|
|
2665
2748
|
this.scene = new Scene();
|
|
2749
|
+
__privateSet(this, _scheduler, new Scheduler((keys) => {
|
|
2750
|
+
for (const key of keys) {
|
|
2751
|
+
this.bus.emit(`state:${key}`);
|
|
2752
|
+
}
|
|
2753
|
+
}));
|
|
2666
2754
|
__privateSet(this, _eventLayer, new Layer("__event__", 99999, this.cfg, true));
|
|
2667
2755
|
this.scene.registerLayer(__privateGet(this, _eventLayer));
|
|
2668
2756
|
this.scene.registerLayer(new Layer("default", 0, this.cfg));
|
|
@@ -2735,7 +2823,30 @@ var _App = class _App {
|
|
|
2735
2823
|
return this.scene.getLayer(name);
|
|
2736
2824
|
}
|
|
2737
2825
|
/**
|
|
2738
|
-
*
|
|
2826
|
+
* 获取或创建图层(get-or-create 语义)。
|
|
2827
|
+
* 多个插件声明同名图层时,只会创建一次。
|
|
2828
|
+
*
|
|
2829
|
+
* zIndex 语义:
|
|
2830
|
+
* - 传入时代表全局层级意图(负数 = default 之下,正数 = default 之上)
|
|
2831
|
+
* - 若与已有层冲突,自动向上偏移到最近可用值
|
|
2832
|
+
* - 省略时自动分配(当前最高非事件层 + 1)
|
|
2833
|
+
*
|
|
2834
|
+
* @param name - 层名称
|
|
2835
|
+
* @param zIndex - 全局层级意图(可选)
|
|
2836
|
+
*/
|
|
2837
|
+
acquireLayer(name, zIndex) {
|
|
2838
|
+
const existing = this.scene.getLayer(name);
|
|
2839
|
+
if (existing) return existing;
|
|
2840
|
+
const index = zIndex !== void 0 ? __privateMethod(this, _App_instances, resolveIndex_fn).call(this, zIndex) : __privateMethod(this, _App_instances, nextAvailableIndex_fn).call(this);
|
|
2841
|
+
return this.addLayer(name, index);
|
|
2842
|
+
}
|
|
2843
|
+
/**
|
|
2844
|
+
* 注册插件。流程:
|
|
2845
|
+
* 1. 去重检查(同名跳过)
|
|
2846
|
+
* 2. 注册 state 声明(key 冲突则抛错)
|
|
2847
|
+
* 3. 自动 acquireLayer(声明的图层)
|
|
2848
|
+
* 4. 调用 plugin.install(app)
|
|
2849
|
+
*
|
|
2739
2850
|
* @param plugin - 实现 Plugin 接口的插件实例
|
|
2740
2851
|
*/
|
|
2741
2852
|
use(plugin) {
|
|
@@ -2743,6 +2854,22 @@ var _App = class _App {
|
|
|
2743
2854
|
console.warn(`Plugin "${plugin.name}" is already registered.`);
|
|
2744
2855
|
return this;
|
|
2745
2856
|
}
|
|
2857
|
+
if (plugin.state) {
|
|
2858
|
+
for (const decl of plugin.state) {
|
|
2859
|
+
if (__privateGet(this, _stateMeta).has(decl.key)) {
|
|
2860
|
+
const owner = __privateGet(this, _stateMeta).get(decl.key).owner;
|
|
2861
|
+
throw new Error(`State key "${decl.key}" already declared by plugin "${owner}". Plugin "${plugin.name}" cannot redeclare it.`);
|
|
2862
|
+
}
|
|
2863
|
+
__privateGet(this, _stateMeta).set(decl.key, { owner: plugin.name, description: decl.description });
|
|
2864
|
+
__privateGet(this, _state).set(decl.key, decl.initial);
|
|
2865
|
+
}
|
|
2866
|
+
}
|
|
2867
|
+
if (plugin.layers) {
|
|
2868
|
+
const sorted = [...plugin.layers].sort((a, b) => (a.zIndex ?? 0) - (b.zIndex ?? 0));
|
|
2869
|
+
for (const decl of sorted) {
|
|
2870
|
+
this.acquireLayer(decl.name, decl.zIndex);
|
|
2871
|
+
}
|
|
2872
|
+
}
|
|
2746
2873
|
__privateGet(this, _plugins).push(plugin);
|
|
2747
2874
|
plugin.install(this);
|
|
2748
2875
|
return this;
|
|
@@ -2751,6 +2878,40 @@ var _App = class _App {
|
|
|
2751
2878
|
getPlugin(name) {
|
|
2752
2879
|
return __privateGet(this, _plugins).find((p) => p.name === name);
|
|
2753
2880
|
}
|
|
2881
|
+
// ========================
|
|
2882
|
+
// Centralized State
|
|
2883
|
+
// ========================
|
|
2884
|
+
/**
|
|
2885
|
+
* 写入 state(同步写入 + 异步批量通知)。
|
|
2886
|
+
* key 必须先由某个插件在 `state[]` 中声明,否则抛错。
|
|
2887
|
+
* 写入后立即可通过 `getState()` 读到最新值,通知在微任务中批量发出。
|
|
2888
|
+
*/
|
|
2889
|
+
setState(key, value) {
|
|
2890
|
+
if (!__privateGet(this, _stateMeta).has(key)) {
|
|
2891
|
+
throw new Error(`State key "${key}" is not declared by any plugin. Plugins must declare state keys in their "state" array.`);
|
|
2892
|
+
}
|
|
2893
|
+
__privateGet(this, _state).set(key, value);
|
|
2894
|
+
__privateGet(this, _scheduler).markState(key);
|
|
2895
|
+
}
|
|
2896
|
+
/**
|
|
2897
|
+
* 读取 state(同步读取,始终返回最新值)。
|
|
2898
|
+
* @returns 对应 key 的当前值,不存在则返回 undefined
|
|
2899
|
+
*/
|
|
2900
|
+
getState(key) {
|
|
2901
|
+
return __privateGet(this, _state).get(key);
|
|
2902
|
+
}
|
|
2903
|
+
/**
|
|
2904
|
+
* 导出完整 state 快照(调试/devtools 用)。
|
|
2905
|
+
* 返回每个 key 的当前值、所属插件和描述信息。
|
|
2906
|
+
*/
|
|
2907
|
+
dumpState() {
|
|
2908
|
+
const result = {};
|
|
2909
|
+
for (const [key, value] of __privateGet(this, _state)) {
|
|
2910
|
+
const meta = __privateGet(this, _stateMeta).get(key);
|
|
2911
|
+
result[key] = { value, owner: meta.owner, description: meta.description };
|
|
2912
|
+
}
|
|
2913
|
+
return result;
|
|
2914
|
+
}
|
|
2754
2915
|
/** 同步渲染一帧。适用于静态内容,仅重绘脏层 */
|
|
2755
2916
|
render() {
|
|
2756
2917
|
for (const layer of this.scene.layers) {
|
|
@@ -2759,10 +2920,12 @@ var _App = class _App {
|
|
|
2759
2920
|
}
|
|
2760
2921
|
}
|
|
2761
2922
|
}
|
|
2762
|
-
/**
|
|
2923
|
+
/** 请求异步渲染帧(幂等,一帧只执行一次)。无变化时自动停止 rAF 链 */
|
|
2763
2924
|
requestRender() {
|
|
2764
|
-
|
|
2765
|
-
|
|
2925
|
+
__privateSet(this, _renderDirty, true);
|
|
2926
|
+
if (__privateGet(this, _rafId) === null) {
|
|
2927
|
+
__privateSet(this, _rafId, requestAnimationFrame((t) => __privateMethod(this, _App_instances, frame_fn).call(this, t)));
|
|
2928
|
+
}
|
|
2766
2929
|
}
|
|
2767
2930
|
/**
|
|
2768
2931
|
* 调整画布尺寸,同步更新所有层、容器和视口矩阵
|
|
@@ -2788,6 +2951,26 @@ var _App = class _App {
|
|
|
2788
2951
|
plugin.resize?.(width, height);
|
|
2789
2952
|
}
|
|
2790
2953
|
}
|
|
2954
|
+
// ========================
|
|
2955
|
+
// Cursor
|
|
2956
|
+
// ========================
|
|
2957
|
+
/**
|
|
2958
|
+
* 设置容器的鼠标光标样式。
|
|
2959
|
+
* @param cursor - CSS cursor 值(如 'pointer'、'crosshair'、'grab')
|
|
2960
|
+
*/
|
|
2961
|
+
setCursor(cursor) {
|
|
2962
|
+
if (__privateGet(this, _container)) {
|
|
2963
|
+
__privateGet(this, _container).style.cursor = cursor;
|
|
2964
|
+
}
|
|
2965
|
+
}
|
|
2966
|
+
/**
|
|
2967
|
+
* 重置鼠标光标为默认值。
|
|
2968
|
+
*/
|
|
2969
|
+
resetCursor() {
|
|
2970
|
+
if (__privateGet(this, _container)) {
|
|
2971
|
+
__privateGet(this, _container).style.cursor = "";
|
|
2972
|
+
}
|
|
2973
|
+
}
|
|
2791
2974
|
clear() {
|
|
2792
2975
|
if (__privateGet(this, _rafId) !== null) {
|
|
2793
2976
|
cancelAnimationFrame(__privateGet(this, _rafId));
|
|
@@ -2803,6 +2986,10 @@ var _App = class _App {
|
|
|
2803
2986
|
plugin.dispose?.();
|
|
2804
2987
|
}
|
|
2805
2988
|
__privateSet(this, _plugins, []);
|
|
2989
|
+
this.bus.removeAllListeners();
|
|
2990
|
+
__privateGet(this, _state).clear();
|
|
2991
|
+
__privateGet(this, _stateMeta).clear();
|
|
2992
|
+
__privateGet(this, _scheduler).clear();
|
|
2806
2993
|
if (__privateGet(this, _resizeObserver)) {
|
|
2807
2994
|
__privateGet(this, _resizeObserver).disconnect();
|
|
2808
2995
|
__privateSet(this, _resizeObserver, null);
|
|
@@ -2837,7 +3024,17 @@ var _App = class _App {
|
|
|
2837
3024
|
}
|
|
2838
3025
|
/** 序列化所有渲染层的场景图为 JSON,可用于保存/回放 */
|
|
2839
3026
|
toJSON() {
|
|
2840
|
-
|
|
3027
|
+
const json = serialize(this.scene.layers, this.cfg.width ?? 800, this.cfg.height ?? 600);
|
|
3028
|
+
const pluginsData = {};
|
|
3029
|
+
for (const plugin of __privateGet(this, _plugins)) {
|
|
3030
|
+
if (plugin.serialize) {
|
|
3031
|
+
pluginsData[plugin.name] = plugin.serialize();
|
|
3032
|
+
}
|
|
3033
|
+
}
|
|
3034
|
+
if (Object.keys(pluginsData).length > 0) {
|
|
3035
|
+
json.plugins = pluginsData;
|
|
3036
|
+
}
|
|
3037
|
+
return json;
|
|
2841
3038
|
}
|
|
2842
3039
|
/**
|
|
2843
3040
|
* 从 JSON 快照创建新的 App 实例(静态工厂方法)
|
|
@@ -2876,17 +3073,49 @@ var _App = class _App {
|
|
|
2876
3073
|
__privateGet(this, _container).insertBefore(layer.renderer.el, __privateGet(this, _eventLayer).renderer.el);
|
|
2877
3074
|
}
|
|
2878
3075
|
}
|
|
3076
|
+
if (json.plugins) {
|
|
3077
|
+
for (const plugin of __privateGet(this, _plugins)) {
|
|
3078
|
+
const data = json.plugins[plugin.name];
|
|
3079
|
+
if (data && plugin.deserialize) {
|
|
3080
|
+
plugin.deserialize(data);
|
|
3081
|
+
}
|
|
3082
|
+
}
|
|
3083
|
+
}
|
|
2879
3084
|
}
|
|
2880
3085
|
};
|
|
2881
3086
|
_rafId = new WeakMap();
|
|
3087
|
+
_renderDirty = new WeakMap();
|
|
2882
3088
|
_mounted = new WeakMap();
|
|
2883
3089
|
_container = new WeakMap();
|
|
2884
3090
|
_eventLayer = new WeakMap();
|
|
2885
3091
|
_resizeObserver = new WeakMap();
|
|
2886
3092
|
_plugins = new WeakMap();
|
|
3093
|
+
_state = new WeakMap();
|
|
3094
|
+
_stateMeta = new WeakMap();
|
|
3095
|
+
_scheduler = new WeakMap();
|
|
2887
3096
|
_App_instances = new WeakSet();
|
|
2888
|
-
|
|
2889
|
-
|
|
3097
|
+
/**
|
|
3098
|
+
* 解析 zIndex:若已被占用则向上偏移到最近可用值。
|
|
3099
|
+
* 保证返回值不会与任何已有层的 layerIndex 冲突。
|
|
3100
|
+
*/
|
|
3101
|
+
resolveIndex_fn = function(desired) {
|
|
3102
|
+
const used = new Set(this.scene.layers.map((l) => l.layerIndex));
|
|
3103
|
+
while (used.has(desired)) desired++;
|
|
3104
|
+
return desired;
|
|
3105
|
+
};
|
|
3106
|
+
/**
|
|
3107
|
+
* 自动分配:当前最高非事件层 index + 1。
|
|
3108
|
+
* 保证返回值始终 >= 1(default 层固定为 0)。
|
|
3109
|
+
*/
|
|
3110
|
+
nextAvailableIndex_fn = function() {
|
|
3111
|
+
let max = 0;
|
|
3112
|
+
for (const l of this.scene.layers) {
|
|
3113
|
+
if (!l.isEventLayer && l.layerIndex > max) max = l.layerIndex;
|
|
3114
|
+
}
|
|
3115
|
+
return max + 1;
|
|
3116
|
+
};
|
|
3117
|
+
frame_fn = function(time) {
|
|
3118
|
+
__privateSet(this, _renderDirty, false);
|
|
2890
3119
|
this.scene.tick(time);
|
|
2891
3120
|
let anyDirty = false;
|
|
2892
3121
|
for (const layer of this.scene.layers) {
|
|
@@ -2895,8 +3124,10 @@ tick_fn = function(time) {
|
|
|
2895
3124
|
anyDirty = true;
|
|
2896
3125
|
}
|
|
2897
3126
|
}
|
|
2898
|
-
if (anyDirty) {
|
|
2899
|
-
this.
|
|
3127
|
+
if (anyDirty || __privateGet(this, _renderDirty)) {
|
|
3128
|
+
__privateSet(this, _rafId, requestAnimationFrame((t) => __privateMethod(this, _App_instances, frame_fn).call(this, t)));
|
|
3129
|
+
} else {
|
|
3130
|
+
__privateSet(this, _rafId, null);
|
|
2900
3131
|
}
|
|
2901
3132
|
};
|
|
2902
3133
|
var App = _App;
|
|
@@ -2927,6 +3158,7 @@ export {
|
|
|
2927
3158
|
Renderer,
|
|
2928
3159
|
RoundShape,
|
|
2929
3160
|
Scene,
|
|
3161
|
+
Scheduler,
|
|
2930
3162
|
SectorShape,
|
|
2931
3163
|
SectorTransform,
|
|
2932
3164
|
Shape,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rendx-engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "2D scene graph engine with animation, events, and plugin system",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "wei.liang (https://github.com/weiliang0121)",
|
|
@@ -32,14 +32,14 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"eventemitter3": "^5.0.4",
|
|
34
34
|
"gl-matrix": "^3.4.4",
|
|
35
|
-
"rendx-bounding": "^0.1.
|
|
36
|
-
"rendx-canvas": "^0.1.
|
|
37
|
-
"rendx-ease": "^0.1.
|
|
38
|
-
"rendx-interpolate": "^0.1.
|
|
39
|
-
"rendx-path": "^0.
|
|
40
|
-
"rendx-shape": "^0.1.
|
|
41
|
-
"rendx-svg": "^0.1.
|
|
42
|
-
"rendx-core": "^0.1.
|
|
35
|
+
"rendx-bounding": "^0.1.1",
|
|
36
|
+
"rendx-canvas": "^0.1.1",
|
|
37
|
+
"rendx-ease": "^0.1.1",
|
|
38
|
+
"rendx-interpolate": "^0.1.1",
|
|
39
|
+
"rendx-path": "^0.2.0",
|
|
40
|
+
"rendx-shape": "^0.1.2",
|
|
41
|
+
"rendx-svg": "^0.1.1",
|
|
42
|
+
"rendx-core": "^0.1.1"
|
|
43
43
|
},
|
|
44
44
|
"sideEffects": false,
|
|
45
45
|
"files": [
|