* feat(fairygui): FairyGUI ECS 集成核心架构 实现 FairyGUI 的 ECS 原生集成,完全替代旧 UI 系统: 核心类: - GObject: UI 对象基类,支持变换、可见性、关联、齿轮 - GComponent: 容器组件,管理子对象和控制器 - GRoot: 根容器,管理焦点、弹窗、输入分发 - GGroup: 组容器,支持水平/垂直布局 抽象层: - DisplayObject: 显示对象基类 - EventDispatcher: 事件分发 - Timer: 计时器 - Stage: 舞台,管理输入和缩放 布局系统: - Relations: 约束关联管理 - RelationItem: 24 种关联类型 基础设施: - Controller: 状态控制器 - Transition: 过渡动画 - ScrollPane: 滚动面板 - UIPackage: 包管理 - ByteBuffer: 二进制解析 * refactor(ui): 删除旧 UI 系统,使用 FairyGUI 替代 * feat(fairygui): 实现 UI 控件 - 添加显示类:Image、TextField、Graph - 添加基础控件:GImage、GTextField、GGraph - 添加交互控件:GButton、GProgressBar、GSlider - 更新 IRenderCollector 支持 Graph 渲染 - 扩展 Controller 添加 selectedPageId - 添加 STATE_CHANGED 事件类型 * feat(fairygui): 现代化架构重构 - 增强 EventDispatcher 支持类型安全、优先级和传播控制 - 添加 PropertyBinding 响应式属性绑定系统 - 添加 ServiceContainer 依赖注入容器 - 添加 UIConfig 全局配置系统 - 添加 UIObjectFactory 对象工厂 - 实现 RenderBridge 渲染桥接层 - 实现 Canvas2DBackend 作为默认渲染后端 - 扩展 IRenderCollector 支持更多图元类型 * feat(fairygui): 九宫格渲染和资源加载修复 - 修复 FGUIUpdateSystem 支持路径和 GUID 两种加载方式 - 修复 GTextInput 同时设置 _displayObject 和 _textField - 实现九宫格渲染展开为 9 个子图元 - 添加 sourceWidth/sourceHeight 用于九宫格计算 - 添加 DOMTextRenderer 文本渲染层(临时方案) * fix(fairygui): 修复 GGraph 颜色读取 * feat(fairygui): 虚拟节点 Inspector 和文本渲染支持 * fix(fairygui): 编辑器状态刷新和遗留引用修复 - 修复切换 FGUI 包后组件列表未刷新问题 - 修复切换组件后 viewport 未清理旧内容问题 - 修复虚拟节点在包加载后未刷新问题 - 重构为事件驱动架构,移除轮询机制 - 修复 @esengine/ui 遗留引用,统一使用 @esengine/fairygui * fix: 移除 tsconfig 中的 @esengine/ui 引用
270 lines
6.7 KiB
TypeScript
270 lines
6.7 KiB
TypeScript
/**
|
||
* BitmapFont
|
||
*
|
||
* Bitmap font support for FairyGUI.
|
||
* Handles BMFont format from FairyGUI Editor exports.
|
||
*
|
||
* 位图字体支持
|
||
* 处理 FairyGUI 编辑器导出的 BMFont 格式
|
||
*/
|
||
|
||
import type { MSDFFont, IMSDFFontData, IMSDFGlyph } from './MSDFFont';
|
||
|
||
/**
|
||
* FairyGUI bitmap font glyph
|
||
* FairyGUI 位图字体字形
|
||
*/
|
||
export interface IBitmapGlyph {
|
||
/** X offset in the glyph | 字形内 X 偏移 */
|
||
x: number;
|
||
/** Y offset in the glyph | 字形内 Y 偏移 */
|
||
y: number;
|
||
/** Glyph width | 字形宽度 */
|
||
width: number;
|
||
/** Glyph height | 字形高度 */
|
||
height: number;
|
||
/** Horizontal advance | 水平前进量 */
|
||
advance: number;
|
||
/** Source texture region (if from atlas) | 源纹理区域 */
|
||
textureRegion?: {
|
||
x: number;
|
||
y: number;
|
||
width: number;
|
||
height: number;
|
||
};
|
||
/** Texture ID for this glyph | 此字形的纹理 ID */
|
||
textureId?: number;
|
||
}
|
||
|
||
/**
|
||
* FairyGUI bitmap font data (from UIPackage)
|
||
* FairyGUI 位图字体数据(来自 UIPackage)
|
||
*/
|
||
export interface IBitmapFontData {
|
||
/** Is TTF (dynamic font) | 是否是 TTF(动态字体) */
|
||
ttf: boolean;
|
||
/** Can be tinted | 可以着色 */
|
||
tint: boolean;
|
||
/** Font size | 字体大小 */
|
||
fontSize: number;
|
||
/** Line height | 行高 */
|
||
lineHeight: number;
|
||
/** Glyphs map (charCode -> glyph) | 字形映射 */
|
||
glyphs: Map<number, IBitmapGlyph>;
|
||
/** Texture ID for the font atlas | 字体图集纹理 ID */
|
||
textureId?: number;
|
||
}
|
||
|
||
/**
|
||
* BitmapFont
|
||
*
|
||
* Adapter for FairyGUI bitmap fonts.
|
||
* Can be used for rendering when MSDF fonts are not available.
|
||
*
|
||
* FairyGUI 位图字体适配器
|
||
* 当 MSDF 字体不可用时可用于渲染
|
||
*/
|
||
export class BitmapFont {
|
||
/** Font name | 字体名称 */
|
||
public readonly name: string;
|
||
|
||
/** Texture ID | 纹理 ID */
|
||
public textureId: number = 0;
|
||
|
||
/** Font data | 字体数据 */
|
||
private _data: IBitmapFontData;
|
||
|
||
constructor(name: string, data: IBitmapFontData) {
|
||
this.name = name;
|
||
this._data = data;
|
||
if (data.textureId !== undefined) {
|
||
this.textureId = data.textureId;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Is this a TTF (dynamic) font
|
||
* 是否是 TTF(动态)字体
|
||
*/
|
||
public get isTTF(): boolean {
|
||
return this._data.ttf;
|
||
}
|
||
|
||
/**
|
||
* Can the font be tinted
|
||
* 字体是否可以着色
|
||
*/
|
||
public get canTint(): boolean {
|
||
return this._data.tint;
|
||
}
|
||
|
||
/**
|
||
* Font size | 字体大小
|
||
*/
|
||
public get fontSize(): number {
|
||
return this._data.fontSize;
|
||
}
|
||
|
||
/**
|
||
* Line height | 行高
|
||
*/
|
||
public get lineHeight(): number {
|
||
return this._data.lineHeight;
|
||
}
|
||
|
||
/**
|
||
* Get glyph for a character
|
||
* 获取字符的字形
|
||
*/
|
||
public getGlyph(charCode: number): IBitmapGlyph | undefined {
|
||
return this._data.glyphs.get(charCode);
|
||
}
|
||
|
||
/**
|
||
* Check if font has a glyph
|
||
* 检查字体是否有字形
|
||
*/
|
||
public hasGlyph(charCode: number): boolean {
|
||
return this._data.glyphs.has(charCode);
|
||
}
|
||
|
||
/**
|
||
* Get all glyphs
|
||
* 获取所有字形
|
||
*/
|
||
public get glyphs(): Map<number, IBitmapGlyph> {
|
||
return this._data.glyphs;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Bitmap Font Manager
|
||
* 位图字体管理器
|
||
*/
|
||
export class BitmapFontManager {
|
||
/** Loaded fonts | 已加载的字体 */
|
||
private _fonts: Map<string, BitmapFont> = new Map();
|
||
|
||
/**
|
||
* Register a bitmap font
|
||
* 注册位图字体
|
||
*/
|
||
public registerFont(font: BitmapFont): void {
|
||
this._fonts.set(font.name, font);
|
||
}
|
||
|
||
/**
|
||
* Get a font by name
|
||
* 按名称获取字体
|
||
*/
|
||
public getFont(name: string): BitmapFont | undefined {
|
||
return this._fonts.get(name);
|
||
}
|
||
|
||
/**
|
||
* Check if a font is registered
|
||
* 检查字体是否已注册
|
||
*/
|
||
public hasFont(name: string): boolean {
|
||
return this._fonts.has(name);
|
||
}
|
||
|
||
/**
|
||
* Unload a font
|
||
* 卸载字体
|
||
*/
|
||
public unloadFont(name: string): void {
|
||
this._fonts.delete(name);
|
||
}
|
||
|
||
/**
|
||
* Clear all fonts
|
||
* 清除所有字体
|
||
*/
|
||
public clear(): void {
|
||
this._fonts.clear();
|
||
}
|
||
|
||
/**
|
||
* Create from FairyGUI package font data
|
||
* 从 FairyGUI 包字体数据创建
|
||
*/
|
||
public createFromPackageData(name: string, data: IBitmapFontData): BitmapFont {
|
||
const font = new BitmapFont(name, data);
|
||
this.registerFont(font);
|
||
return font;
|
||
}
|
||
}
|
||
|
||
/** Global bitmap font manager | 全局位图字体管理器 */
|
||
let _bitmapFontManager: BitmapFontManager | null = null;
|
||
|
||
/**
|
||
* Get global bitmap font manager
|
||
* 获取全局位图字体管理器
|
||
*/
|
||
export function getBitmapFontManager(): BitmapFontManager {
|
||
if (!_bitmapFontManager) {
|
||
_bitmapFontManager = new BitmapFontManager();
|
||
}
|
||
return _bitmapFontManager;
|
||
}
|
||
|
||
/**
|
||
* Convert bitmap font to MSDF-compatible format
|
||
* 将位图字体转换为 MSDF 兼容格式
|
||
*
|
||
* Note: This creates a "fake" MSDF font that uses bitmap rendering.
|
||
* The pxRange is set to 0 to disable MSDF processing in the shader.
|
||
*
|
||
* 注意:这会创建一个使用位图渲染的"伪" MSDF 字体。
|
||
* pxRange 设置为 0 以在着色器中禁用 MSDF 处理。
|
||
*/
|
||
export function convertBitmapToMSDFFormat(
|
||
bitmapFont: BitmapFont,
|
||
atlasWidth: number,
|
||
atlasHeight: number
|
||
): IMSDFFontData {
|
||
const glyphs: IMSDFGlyph[] = [];
|
||
|
||
for (const [charCode, glyph] of bitmapFont.glyphs) {
|
||
const region = glyph.textureRegion;
|
||
if (!region) continue;
|
||
|
||
glyphs.push({
|
||
unicode: charCode,
|
||
advance: glyph.advance / bitmapFont.fontSize,
|
||
planeBounds: {
|
||
left: glyph.x / bitmapFont.fontSize,
|
||
bottom: -(glyph.y + glyph.height) / bitmapFont.fontSize,
|
||
right: (glyph.x + glyph.width) / bitmapFont.fontSize,
|
||
top: -glyph.y / bitmapFont.fontSize
|
||
},
|
||
atlasBounds: {
|
||
left: region.x,
|
||
bottom: region.y,
|
||
right: region.x + region.width,
|
||
top: region.y + region.height
|
||
}
|
||
});
|
||
}
|
||
|
||
return {
|
||
atlas: {
|
||
type: 'sdf', // Use simple SDF mode for bitmap
|
||
distanceRange: 0, // 0 = disable MSDF processing, use as regular texture
|
||
size: bitmapFont.fontSize,
|
||
width: atlasWidth,
|
||
height: atlasHeight,
|
||
yOrigin: 'top'
|
||
},
|
||
metrics: {
|
||
emSize: bitmapFont.fontSize,
|
||
lineHeight: bitmapFont.lineHeight / bitmapFont.fontSize,
|
||
ascender: 1,
|
||
descender: 0
|
||
},
|
||
glyphs
|
||
};
|
||
}
|