Files
esengine/packages/fairygui/src/text/BitmapFont.ts

270 lines
6.7 KiB
TypeScript
Raw Normal View History

feat(fairygui): FairyGUI 完整集成 (#314) * 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 引用
2025-12-22 10:52:54 +08:00
/**
* 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
};
}