refactor: reorganize package structure and decouple framework packages (#338)

* refactor: reorganize package structure and decouple framework packages

## Package Structure Reorganization
- Reorganized 55 packages into categorized subdirectories:
  - packages/framework/ - Generic framework (Laya/Cocos compatible)
  - packages/engine/ - ESEngine core modules
  - packages/rendering/ - Rendering modules (WASM dependent)
  - packages/physics/ - Physics modules
  - packages/streaming/ - World streaming
  - packages/network-ext/ - Network extensions
  - packages/editor/ - Editor framework and plugins
  - packages/rust/ - Rust WASM engine
  - packages/tools/ - Build tools and SDK

## Framework Package Decoupling
- Decoupled behavior-tree and blueprint packages from ESEngine dependencies
- Created abstracted interfaces (IBTAssetManager, IBehaviorTreeAssetContent)
- ESEngine-specific code moved to esengine/ subpath exports
- Framework packages now usable with Cocos/Laya without ESEngine

## CI Configuration
- Updated CI to only type-check and lint framework packages
- Added type-check:framework and lint:framework scripts

## Breaking Changes
- Package import paths changed due to directory reorganization
- ESEngine integrations now use subpath imports (e.g., '@esengine/behavior-tree/esengine')

* fix: update es-engine file path after directory reorganization

* docs: update README to focus on framework over engine

* ci: only build framework packages, remove Rust/WASM dependencies

* fix: remove esengine subpath from behavior-tree and blueprint builds

ESEngine integration code will only be available in full engine builds.
Framework packages are now purely engine-agnostic.

* fix: move network-protocols to framework, build both in CI

* fix: update workflow paths from packages/core to packages/framework/core

* fix: exclude esengine folder from type-check in behavior-tree and blueprint

* fix: update network tsconfig references to new paths

* fix: add test:ci:framework to only test framework packages in CI

* fix: only build core and math npm packages in CI

* fix: exclude test files from CodeQL and fix string escaping security issue
This commit is contained in:
YHH
2025-12-26 14:50:35 +08:00
committed by GitHub
parent a84ff902e4
commit 155411e743
1936 changed files with 4147 additions and 11578 deletions

View File

@@ -0,0 +1,70 @@
import { GearBase } from './GearBase';
import { EObjectPropID } from '../core/FieldTypes';
import type { GObject } from '../core/GObject';
/**
* Animation value for GearAnimation
* GearAnimation 的动画值
*/
interface IAnimationValue {
playing: boolean;
frame: number;
}
/**
* GearAnimation
*
* Controls object animation state based on controller state.
* 根据控制器状态控制对象动画状态
*/
export class GearAnimation extends GearBase {
private _storage: Map<string, IAnimationValue> = new Map();
private _default: IAnimationValue = { playing: true, frame: 0 };
constructor(owner: GObject) {
super(owner);
}
protected init(): void {
this._default = {
playing: (this.owner.getProp(EObjectPropID.Playing) as boolean) ?? true,
frame: (this.owner.getProp(EObjectPropID.Frame) as number) ?? 0
};
this._storage.clear();
}
public apply(): void {
if (!this._controller) return;
const gv = this._storage.get(this._controller.selectedPageId) ?? this._default;
this.owner._gearLocked = true;
this.owner.setProp(EObjectPropID.Playing, gv.playing);
this.owner.setProp(EObjectPropID.Frame, gv.frame);
this.owner._gearLocked = false;
}
public updateState(): void {
if (!this._controller) return;
const gv: IAnimationValue = {
playing: (this.owner.getProp(EObjectPropID.Playing) as boolean) ?? true,
frame: (this.owner.getProp(EObjectPropID.Frame) as number) ?? 0
};
this._storage.set(this._controller.selectedPageId, gv);
}
/**
* Add status
* 添加状态
*/
public addStatus(pageId: string | null, playing: boolean, frame: number): void {
if (pageId === null) {
this._default.playing = playing;
this._default.frame = frame;
} else {
this._storage.set(pageId, { playing, frame });
}
}
}

View File

@@ -0,0 +1,152 @@
import type { GObject } from '../core/GObject';
import type { Controller } from '../core/Controller';
import type { ByteBuffer } from '../utils/ByteBuffer';
import { EEaseType } from '../core/FieldTypes';
/**
* GearBase
*
* Base class for all gear types.
* Gears connect object properties to controller states.
*
* 所有齿轮类型的基类,齿轮将对象属性连接到控制器状态
*/
export abstract class GearBase {
/** Owner object | 所有者对象 */
public readonly owner: GObject;
/** Controller | 控制器 */
protected _controller: Controller | null = null;
/** Tween config | 缓动配置 */
public tweenConfig: GearTweenConfig | null = null;
constructor(owner: GObject) {
this.owner = owner;
}
/**
* Get controller
* 获取控制器
*/
public get controller(): Controller | null {
return this._controller;
}
/**
* Set controller
* 设置控制器
*/
public set controller(value: Controller | null) {
if (this._controller !== value) {
this._controller = value;
if (this._controller) {
this.init();
}
}
}
/**
* Check if connected to a controller
* 检查是否连接到控制器
*/
public get connected(): boolean {
return this._controller !== null;
}
/**
* Initialize gear
* 初始化齿轮
*/
protected abstract init(): void;
/**
* Apply gear values
* 应用齿轮值
*/
public abstract apply(): void;
/**
* Update current state
* 更新当前状态
*/
public abstract updateState(): void;
/**
* Setup gear from buffer
* 从缓冲区设置齿轮
*/
public setup(buffer: ByteBuffer): void {
const parent = this.owner.parent;
if (!parent) return;
this._controller = parent.getControllerAt(buffer.getInt16());
this.init();
const cnt = buffer.getInt16();
// Read pages - subclasses should override to parse their specific data
this.readStatusFromBuffer(buffer, cnt);
// Read default status
if (buffer.readBool()) {
this.readDefaultStatusFromBuffer(buffer);
}
// Read tween config
if (buffer.readBool()) {
this.tweenConfig = new GearTweenConfig();
this.tweenConfig.easeType = buffer.readByte() as EEaseType;
this.tweenConfig.duration = buffer.getFloat32();
this.tweenConfig.delay = buffer.getFloat32();
}
}
/**
* Read status data from buffer
* 从缓冲区读取状态数据
*/
protected readStatusFromBuffer(_buffer: ByteBuffer, _cnt: number): void {
// Override in subclasses to parse specific gear data
// Default: skip the data (each page has a string ID)
for (let i = 0; i < _cnt; i++) {
_buffer.readS(); // page id
// Subclass should read its specific data here
}
}
/**
* Read default status from buffer
* 从缓冲区读取默认状态
*/
protected readDefaultStatusFromBuffer(_buffer: ByteBuffer): void {
// Override in subclasses
}
/**
* Dispose
* 销毁
*/
public dispose(): void {
this._controller = null;
this.tweenConfig = null;
}
}
/**
* Gear tween configuration
* 齿轮缓动配置
*/
export class GearTweenConfig {
/** Tween enabled | 是否启用缓动 */
public tween: boolean = true;
/** Ease type | 缓动类型 */
public easeType: EEaseType = EEaseType.QuadOut;
/** Duration in seconds | 持续时间(秒) */
public duration: number = 0.3;
/** Delay in seconds | 延迟时间(秒) */
public delay: number = 0;
}

View File

@@ -0,0 +1,74 @@
import { GearBase } from './GearBase';
import { EObjectPropID } from '../core/FieldTypes';
import type { GObject } from '../core/GObject';
/**
* Color value for GearColor
* GearColor 的颜色值
*/
interface IColorValue {
color: number | null;
strokeColor: number | null;
}
/**
* GearColor
*
* Controls object color and stroke color based on controller state.
* 根据控制器状态控制对象颜色和描边颜色
*/
export class GearColor extends GearBase {
private _storage: Map<string, IColorValue> = new Map();
private _default: IColorValue = { color: null, strokeColor: null };
constructor(owner: GObject) {
super(owner);
}
protected init(): void {
this._default = {
color: this.owner.getProp(EObjectPropID.Color) as number | null,
strokeColor: this.owner.getProp(EObjectPropID.OutlineColor) as number | null
};
this._storage.clear();
}
public apply(): void {
if (!this._controller) return;
const gv = this._storage.get(this._controller.selectedPageId) ?? this._default;
this.owner._gearLocked = true;
if (gv.color !== null) {
this.owner.setProp(EObjectPropID.Color, gv.color);
}
if (gv.strokeColor !== null) {
this.owner.setProp(EObjectPropID.OutlineColor, gv.strokeColor);
}
this.owner._gearLocked = false;
}
public updateState(): void {
if (!this._controller) return;
const gv: IColorValue = {
color: this.owner.getProp(EObjectPropID.Color) as number | null,
strokeColor: this.owner.getProp(EObjectPropID.OutlineColor) as number | null
};
this._storage.set(this._controller.selectedPageId, gv);
}
/**
* Add status from buffer
* 从缓冲区添加状态
*/
public addStatus(pageId: string | null, color: number | null, strokeColor: number | null): void {
if (pageId === null) {
this._default.color = color;
this._default.strokeColor = strokeColor;
} else {
this._storage.set(pageId, { color, strokeColor });
}
}
}

View File

@@ -0,0 +1,71 @@
import { GearBase } from './GearBase';
import type { GObject } from '../core/GObject';
/**
* GearDisplay
*
* Controls object visibility based on controller state.
* 根据控制器状态控制对象可见性
*/
export class GearDisplay extends GearBase {
/** Pages where object is visible | 对象可见的页面列表 */
public pages: string[] = [];
private _visible: number = 0;
private _displayLockToken: number = 1;
constructor(owner: GObject) {
super(owner);
}
protected init(): void {
this.pages = [];
}
public apply(): void {
this._displayLockToken++;
if (this._displayLockToken === 0) {
this._displayLockToken = 1;
}
if (
this.pages.length === 0 ||
(this._controller && this.pages.indexOf(this._controller.selectedPageId) !== -1)
) {
this._visible = 1;
} else {
this._visible = 0;
}
}
public updateState(): void {
// GearDisplay doesn't need to save state
}
/**
* Add display lock
* 添加显示锁
*/
public addLock(): number {
this._visible++;
return this._displayLockToken;
}
/**
* Release display lock
* 释放显示锁
*/
public releaseLock(token: number): void {
if (token === this._displayLockToken) {
this._visible--;
}
}
/**
* Check if object should be visible
* 检查对象是否应该可见
*/
public override get connected(): boolean {
return this._controller === null || this._visible > 0;
}
}

View File

@@ -0,0 +1,67 @@
import { GearBase } from './GearBase';
import type { GObject } from '../core/GObject';
/**
* GearDisplay2
*
* Advanced display control that combines multiple controllers.
* 高级显示控制,组合多个控制器
*/
export class GearDisplay2 extends GearBase {
/** Pages where object is visible | 对象可见的页面列表 */
public pages: string[] = [];
/** Condition: 0=AND, 1=OR | 条件0=与1=或 */
public condition: number = 0;
private _visible: number = 0;
constructor(owner: GObject) {
super(owner);
}
protected init(): void {
this.pages = [];
}
public apply(): void {
if (
this.pages.length === 0 ||
(this._controller && this.pages.indexOf(this._controller.selectedPageId) !== -1)
) {
this._visible = 1;
} else {
this._visible = 0;
}
}
public updateState(): void {
// GearDisplay2 doesn't need to save state
}
/**
* Evaluate visibility with condition
* 根据条件评估可见性
*/
public evaluate(bConnected: boolean): boolean {
if (this._controller === null) {
return true;
}
if (this.condition === 0) {
// AND condition
return bConnected && this._visible > 0;
} else {
// OR condition
return bConnected || this._visible > 0;
}
}
/**
* Check if object should be visible
* 检查对象是否应该可见
*/
public override get connected(): boolean {
return this._controller === null || this._visible > 0;
}
}

View File

@@ -0,0 +1,53 @@
import { GearBase } from './GearBase';
import { EObjectPropID } from '../core/FieldTypes';
import type { GObject } from '../core/GObject';
/**
* GearFontSize
*
* Controls object font size based on controller state.
* 根据控制器状态控制对象字体大小
*/
export class GearFontSize extends GearBase {
private _storage: Map<string, number> = new Map();
private _default: number = 12;
constructor(owner: GObject) {
super(owner);
}
protected init(): void {
this._default = (this.owner.getProp(EObjectPropID.FontSize) as number) ?? 12;
this._storage.clear();
}
public apply(): void {
if (!this._controller) return;
const fontSize = this._storage.get(this._controller.selectedPageId) ?? this._default;
this.owner._gearLocked = true;
this.owner.setProp(EObjectPropID.FontSize, fontSize);
this.owner._gearLocked = false;
}
public updateState(): void {
if (!this._controller) return;
this._storage.set(
this._controller.selectedPageId,
(this.owner.getProp(EObjectPropID.FontSize) as number) ?? 12
);
}
/**
* Add status
* 添加状态
*/
public addStatus(pageId: string | null, fontSize: number): void {
if (pageId === null) {
this._default = fontSize;
} else {
this._storage.set(pageId, fontSize);
}
}
}

View File

@@ -0,0 +1,49 @@
import { GearBase } from './GearBase';
import type { GObject } from '../core/GObject';
/**
* GearIcon
*
* Controls object icon based on controller state.
* 根据控制器状态控制对象图标
*/
export class GearIcon extends GearBase {
private _storage: Map<string, string> = new Map();
private _default: string = '';
constructor(owner: GObject) {
super(owner);
}
protected init(): void {
this._default = this.owner.icon ?? '';
this._storage.clear();
}
public apply(): void {
if (!this._controller) return;
const icon = this._storage.get(this._controller.selectedPageId) ?? this._default;
this.owner._gearLocked = true;
this.owner.icon = icon;
this.owner._gearLocked = false;
}
public updateState(): void {
if (!this._controller) return;
this._storage.set(this._controller.selectedPageId, this.owner.icon ?? '');
}
/**
* Add status
* 添加状态
*/
public addStatus(pageId: string | null, icon: string): void {
if (pageId === null) {
this._default = icon;
} else {
this._storage.set(pageId, icon);
}
}
}

View File

@@ -0,0 +1,122 @@
import { GearBase } from './GearBase';
import { GTween } from '../tween/GTween';
import type { GTweener } from '../tween/GTweener';
import type { GObject } from '../core/GObject';
/**
* Look value for GearLook
* GearLook 的外观值
*/
interface ILookValue {
alpha: number;
rotation: number;
grayed: boolean;
touchable: boolean;
}
/**
* GearLook
*
* Controls object appearance (alpha, rotation, grayed, touchable) based on controller state.
* 根据控制器状态控制对象外观(透明度、旋转、灰度、可触摸)
*/
export class GearLook extends GearBase {
private _storage: Map<string, ILookValue> = new Map();
private _default: ILookValue = { alpha: 1, rotation: 0, grayed: false, touchable: true };
private _tweener: GTweener | null = null;
constructor(owner: GObject) {
super(owner);
}
protected init(): void {
this._default = {
alpha: this.owner.alpha,
rotation: this.owner.rotation,
grayed: this.owner.grayed,
touchable: this.owner.touchable
};
this._storage.clear();
}
public apply(): void {
if (!this._controller) return;
const gv = this._storage.get(this._controller.selectedPageId) ?? this._default;
// grayed and touchable cannot be tweened, apply immediately
this.owner._gearLocked = true;
this.owner.grayed = gv.grayed;
this.owner.touchable = gv.touchable;
this.owner._gearLocked = false;
if (this.tweenConfig?.tween && this.owner.onStage) {
if (this._tweener) {
if (this._tweener.endValue.x !== gv.alpha || this._tweener.endValue.y !== gv.rotation) {
this._tweener.kill();
this._tweener = null;
} else {
return;
}
}
const oa = this.owner.alpha;
const or = this.owner.rotation;
if (oa !== gv.alpha || or !== gv.rotation) {
this._tweener = GTween.to2(oa, or, gv.alpha, gv.rotation, this.tweenConfig.duration)
.setDelay(this.tweenConfig.delay)
.setEase(this.tweenConfig.easeType)
.setTarget(this, 'look')
.onUpdate((tweener) => {
this.owner._gearLocked = true;
this.owner.alpha = tweener.value.x;
this.owner.rotation = tweener.value.y;
this.owner._gearLocked = false;
})
.onComplete(() => {
this._tweener = null;
});
}
} else {
this.owner._gearLocked = true;
this.owner.alpha = gv.alpha;
this.owner.rotation = gv.rotation;
this.owner._gearLocked = false;
}
}
public updateState(): void {
if (!this._controller) return;
const gv: ILookValue = {
alpha: this.owner.alpha,
rotation: this.owner.rotation,
grayed: this.owner.grayed,
touchable: this.owner.touchable
};
this._storage.set(this._controller.selectedPageId, gv);
}
/**
* Add status from buffer
* 从缓冲区添加状态
*/
public addStatus(
pageId: string | null,
alpha: number,
rotation: number,
grayed: boolean,
touchable: boolean
): void {
if (pageId === null) {
this._default.alpha = alpha;
this._default.rotation = rotation;
this._default.grayed = grayed;
this._default.touchable = touchable;
} else {
this._storage.set(pageId, { alpha, rotation, grayed, touchable });
}
}
}

View File

@@ -0,0 +1,150 @@
import { GearBase } from './GearBase';
import { GTween } from '../tween/GTween';
import type { GTweener } from '../tween/GTweener';
import type { GObject } from '../core/GObject';
/**
* Size value for GearSize
* GearSize 的尺寸值
*/
interface ISizeValue {
width: number;
height: number;
scaleX: number;
scaleY: number;
}
/**
* GearSize
*
* Controls object size and scale based on controller state.
* 根据控制器状态控制对象尺寸和缩放
*/
export class GearSize extends GearBase {
private _storage: Map<string, ISizeValue> = new Map();
private _default: ISizeValue = { width: 0, height: 0, scaleX: 1, scaleY: 1 };
private _tweener: GTweener | null = null;
constructor(owner: GObject) {
super(owner);
}
protected init(): void {
this._default = {
width: this.owner.width,
height: this.owner.height,
scaleX: this.owner.scaleX,
scaleY: this.owner.scaleY
};
this._storage.clear();
}
public apply(): void {
if (!this._controller) return;
const gv = this._storage.get(this._controller.selectedPageId) ?? this._default;
if (this.tweenConfig?.tween && this.owner.onStage) {
if (this._tweener) {
if (
this._tweener.endValue.x !== gv.width ||
this._tweener.endValue.y !== gv.height ||
this._tweener.endValue.z !== gv.scaleX ||
this._tweener.endValue.w !== gv.scaleY
) {
this._tweener.kill();
this._tweener = null;
} else {
return;
}
}
const ow = this.owner.width;
const oh = this.owner.height;
const osx = this.owner.scaleX;
const osy = this.owner.scaleY;
if (ow !== gv.width || oh !== gv.height || osx !== gv.scaleX || osy !== gv.scaleY) {
this._tweener = GTween.to4(
ow,
oh,
osx,
osy,
gv.width,
gv.height,
gv.scaleX,
gv.scaleY,
this.tweenConfig.duration
)
.setDelay(this.tweenConfig.delay)
.setEase(this.tweenConfig.easeType)
.setTarget(this, 'size')
.onUpdate((tweener) => {
this.owner._gearLocked = true;
this.owner.setSize(tweener.value.x, tweener.value.y);
this.owner.setScale(tweener.value.z, tweener.value.w);
this.owner._gearLocked = false;
})
.onComplete(() => {
this._tweener = null;
});
}
} else {
this.owner._gearLocked = true;
this.owner.setSize(gv.width, gv.height);
this.owner.setScale(gv.scaleX, gv.scaleY);
this.owner._gearLocked = false;
}
}
public updateState(): void {
if (!this._controller) return;
const gv: ISizeValue = {
width: this.owner.width,
height: this.owner.height,
scaleX: this.owner.scaleX,
scaleY: this.owner.scaleY
};
this._storage.set(this._controller.selectedPageId, gv);
}
/**
* Update size from relation changes
* 从关联变更中更新尺寸
*/
public updateFromRelations(dWidth: number, dHeight: number): void {
if (!this._controller) return;
for (const gv of this._storage.values()) {
gv.width += dWidth;
gv.height += dHeight;
}
this._default.width += dWidth;
this._default.height += dHeight;
this.updateState();
}
/**
* Add status from buffer
* 从缓冲区添加状态
*/
public addStatus(
pageId: string | null,
width: number,
height: number,
scaleX: number,
scaleY: number
): void {
if (pageId === null) {
this._default.width = width;
this._default.height = height;
this._default.scaleX = scaleX;
this._default.scaleY = scaleY;
} else {
this._storage.set(pageId, { width, height, scaleX, scaleY });
}
}
}

View File

@@ -0,0 +1,50 @@
import { GearBase } from './GearBase';
import { EObjectPropID } from '../core/FieldTypes';
import type { GObject } from '../core/GObject';
/**
* GearText
*
* Controls object text content based on controller state.
* 根据控制器状态控制对象文本内容
*/
export class GearText extends GearBase {
private _storage: Map<string, string> = new Map();
private _default: string = '';
constructor(owner: GObject) {
super(owner);
}
protected init(): void {
this._default = this.owner.text ?? '';
this._storage.clear();
}
public apply(): void {
if (!this._controller) return;
const text = this._storage.get(this._controller.selectedPageId) ?? this._default;
this.owner._gearLocked = true;
this.owner.text = text;
this.owner._gearLocked = false;
}
public updateState(): void {
if (!this._controller) return;
this._storage.set(this._controller.selectedPageId, this.owner.text ?? '');
}
/**
* Add status
* 添加状态
*/
public addStatus(pageId: string | null, text: string): void {
if (pageId === null) {
this._default = text;
} else {
this._storage.set(pageId, text);
}
}
}

View File

@@ -0,0 +1,159 @@
import { GearBase } from './GearBase';
import { GTween } from '../tween/GTween';
import type { GTweener } from '../tween/GTweener';
import type { GObject } from '../core/GObject';
/**
* Position value for GearXY
* GearXY 的位置值
*/
interface IPositionValue {
x: number;
y: number;
px: number;
py: number;
}
/**
* GearXY
*
* Controls object position based on controller state.
* 根据控制器状态控制对象位置
*/
export class GearXY extends GearBase {
/** Use percent positions | 使用百分比位置 */
public positionsInPercent: boolean = false;
private _storage: Map<string, IPositionValue> = new Map();
private _default: IPositionValue = { x: 0, y: 0, px: 0, py: 0 };
private _tweener: GTweener | null = null;
constructor(owner: GObject) {
super(owner);
}
protected init(): void {
const parent = this.owner.parent;
this._default = {
x: this.owner.x,
y: this.owner.y,
px: parent ? this.owner.x / parent.width : 0,
py: parent ? this.owner.y / parent.height : 0
};
this._storage.clear();
}
public apply(): void {
if (!this._controller) return;
const gv = this._storage.get(this._controller.selectedPageId) ?? this._default;
const parent = this.owner.parent;
let ex: number;
let ey: number;
if (this.positionsInPercent && parent) {
ex = gv.px * parent.width;
ey = gv.py * parent.height;
} else {
ex = gv.x;
ey = gv.y;
}
if (this.tweenConfig?.tween && this.owner.onStage) {
if (this._tweener) {
if (this._tweener.endValue.x !== ex || this._tweener.endValue.y !== ey) {
this._tweener.kill();
this._tweener = null;
} else {
return;
}
}
const ox = this.owner.x;
const oy = this.owner.y;
if (ox !== ex || oy !== ey) {
this._tweener = GTween.to2(ox, oy, ex, ey, this.tweenConfig.duration)
.setDelay(this.tweenConfig.delay)
.setEase(this.tweenConfig.easeType)
.setTarget(this, 'xy')
.onUpdate((tweener) => {
this.owner._gearLocked = true;
this.owner.setXY(tweener.value.x, tweener.value.y);
this.owner._gearLocked = false;
})
.onComplete(() => {
this._tweener = null;
});
}
} else {
this.owner._gearLocked = true;
this.owner.setXY(ex, ey);
this.owner._gearLocked = false;
}
}
public updateState(): void {
if (!this._controller) return;
const parent = this.owner.parent;
const gv: IPositionValue = {
x: this.owner.x,
y: this.owner.y,
px: parent ? this.owner.x / parent.width : 0,
py: parent ? this.owner.y / parent.height : 0
};
this._storage.set(this._controller.selectedPageId, gv);
}
/**
* Update positions from relation changes
* 从关联变更中更新位置
*/
public updateFromRelations(dx: number, dy: number): void {
if (!this._controller || this.positionsInPercent) return;
for (const gv of this._storage.values()) {
gv.x += dx;
gv.y += dy;
}
this._default.x += dx;
this._default.y += dy;
this.updateState();
}
/**
* Add status from buffer
* 从缓冲区添加状态
*/
public addStatus(pageId: string | null, x: number, y: number): void {
if (pageId === null) {
this._default.x = x;
this._default.y = y;
} else {
const gv = this._storage.get(pageId) ?? { x: 0, y: 0, px: 0, py: 0 };
gv.x = x;
gv.y = y;
this._storage.set(pageId, gv);
}
}
/**
* Add extended status (percent values)
* 添加扩展状态(百分比值)
*/
public addExtStatus(pageId: string | null, px: number, py: number): void {
if (pageId === null) {
this._default.px = px;
this._default.py = py;
} else {
const gv = this._storage.get(pageId);
if (gv) {
gv.px = px;
gv.py = py;
}
}
}
}

View File

@@ -0,0 +1,11 @@
export { GearBase, GearTweenConfig } from './GearBase';
export { GearDisplay } from './GearDisplay';
export { GearDisplay2 } from './GearDisplay2';
export { GearXY } from './GearXY';
export { GearSize } from './GearSize';
export { GearLook } from './GearLook';
export { GearColor } from './GearColor';
export { GearText } from './GearText';
export { GearIcon } from './GearIcon';
export { GearFontSize } from './GearFontSize';
export { GearAnimation } from './GearAnimation';