Feature/runtime cdn and plugin loader (#240)
* feat(ui): 完善 UI 布局系统和编辑器可视化工具 * refactor: 移除 ModuleRegistry,统一使用 PluginManager 插件系统 * fix: 修复 CodeQL 警告并提升测试覆盖率 * refactor: 分离运行时入口点,解决 runtime bundle 包含 React 的问题 * fix(ci): 添加 editor-core 和 editor-runtime 到 CI 依赖构建步骤 * docs: 完善 ServiceContainer 文档,新增 Symbol.for 模式和 @InjectProperty 说明 * fix(ci): 修复 type-check 失败问题 * fix(ci): 修复类型检查失败问题 * fix(ci): 修复类型检查失败问题 * fix(ci): behavior-tree 构建添加 @tauri-apps 外部依赖 * fix(ci): behavior-tree 添加 @tauri-apps/plugin-fs 类型依赖 * fix(ci): platform-web 添加缺失的 behavior-tree 依赖 * fix(lint): 移除正则表达式中不必要的转义字符
This commit is contained in:
193
packages/ui/src/systems/render/UIRectRenderSystem.ts
Normal file
193
packages/ui/src/systems/render/UIRectRenderSystem.ts
Normal file
@@ -0,0 +1,193 @@
|
||||
/**
|
||||
* UI Rect Render System
|
||||
* UI 矩形渲染系统
|
||||
*
|
||||
* Renders basic UIRenderComponent entities (those without specialized widget components)
|
||||
* by submitting render primitives to the shared UIRenderCollector.
|
||||
* 通过向共享的 UIRenderCollector 提交渲染原语来渲染基础 UIRenderComponent 实体
|
||||
* (没有专门 widget 组件的实体)。
|
||||
*/
|
||||
|
||||
import { EntitySystem, Matcher, Entity, ECSSystem } from '@esengine/ecs-framework';
|
||||
import { UITransformComponent } from '../../components/UITransformComponent';
|
||||
import { UIRenderComponent } from '../../components/UIRenderComponent';
|
||||
import { UIButtonComponent } from '../../components/widgets/UIButtonComponent';
|
||||
import { UIProgressBarComponent } from '../../components/widgets/UIProgressBarComponent';
|
||||
import { UISliderComponent } from '../../components/widgets/UISliderComponent';
|
||||
import { UIScrollViewComponent } from '../../components/widgets/UIScrollViewComponent';
|
||||
import { getUIRenderCollector } from './UIRenderCollector';
|
||||
|
||||
/**
|
||||
* UI Rect Render System
|
||||
* UI 矩形渲染系统
|
||||
*
|
||||
* Handles rendering of basic UI elements with UIRenderComponent that don't have
|
||||
* specialized widget components (like buttons, progress bars, etc.).
|
||||
*
|
||||
* This is the "catch-all" renderer for simple rectangles, images, and panels.
|
||||
*
|
||||
* 处理具有 UIRenderComponent 但没有专门 widget 组件(如按钮、进度条等)的基础 UI 元素的渲染。
|
||||
* 这是简单矩形、图像和面板的"兜底"渲染器。
|
||||
*/
|
||||
@ECSSystem('UIRectRender', { updateOrder: 100 })
|
||||
export class UIRectRenderSystem extends EntitySystem {
|
||||
constructor() {
|
||||
super(Matcher.empty().all(UITransformComponent, UIRenderComponent));
|
||||
}
|
||||
|
||||
protected process(entities: readonly Entity[]): void {
|
||||
const collector = getUIRenderCollector();
|
||||
|
||||
for (const entity of entities) {
|
||||
// Skip if entity has specialized widget components
|
||||
// (they have their own render systems)
|
||||
// 如果实体有专门的 widget 组件,跳过(它们有自己的渲染系统)
|
||||
if (entity.hasComponent(UIButtonComponent) ||
|
||||
entity.hasComponent(UIProgressBarComponent) ||
|
||||
entity.hasComponent(UISliderComponent) ||
|
||||
entity.hasComponent(UIScrollViewComponent)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const transform = entity.getComponent(UITransformComponent)!;
|
||||
const render = entity.getComponent(UIRenderComponent)!;
|
||||
|
||||
if (!transform.visible) continue;
|
||||
|
||||
const x = transform.worldX ?? transform.x;
|
||||
const y = transform.worldY ?? transform.y;
|
||||
const width = (transform.computedWidth ?? transform.width) * transform.scaleX;
|
||||
const height = (transform.computedHeight ?? transform.height) * transform.scaleY;
|
||||
const alpha = transform.worldAlpha ?? transform.alpha;
|
||||
const baseOrder = 100 + transform.zIndex;
|
||||
|
||||
// Use top-left position with origin at (0, 0)
|
||||
// Like Sprite: x,y is anchor position, origin determines where anchor is on the rect
|
||||
// For UI: x,y is top-left corner, so origin should be (0, 0)
|
||||
// 使用左上角位置,原点在 (0, 0)
|
||||
// 类似 Sprite:x,y 是锚点位置,origin 决定锚点在矩形上的位置
|
||||
// 对于 UI:x,y 是左上角,所以 origin 应该是 (0, 0)
|
||||
|
||||
// Render shadow if enabled
|
||||
// 如果启用,渲染阴影
|
||||
if (render.shadowEnabled && render.shadowAlpha > 0) {
|
||||
collector.addRect(
|
||||
x + render.shadowOffsetX - render.shadowBlur,
|
||||
y + render.shadowOffsetY - render.shadowBlur,
|
||||
width + render.shadowBlur * 2,
|
||||
height + render.shadowBlur * 2,
|
||||
render.shadowColor,
|
||||
render.shadowAlpha * alpha,
|
||||
baseOrder - 0.1,
|
||||
{
|
||||
rotation: transform.rotation,
|
||||
pivotX: 0,
|
||||
pivotY: 0
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Render texture if present
|
||||
// 如果有纹理,渲染纹理
|
||||
if (render.texture) {
|
||||
const texturePath = typeof render.texture === 'string' ? render.texture : undefined;
|
||||
const textureId = typeof render.texture === 'number' ? render.texture : undefined;
|
||||
|
||||
collector.addRect(
|
||||
x, y,
|
||||
width, height,
|
||||
render.textureTint,
|
||||
alpha,
|
||||
baseOrder,
|
||||
{
|
||||
rotation: transform.rotation,
|
||||
pivotX: 0,
|
||||
pivotY: 0,
|
||||
textureId,
|
||||
texturePath,
|
||||
uv: render.textureUV
|
||||
? [render.textureUV.u0, render.textureUV.v0, render.textureUV.u1, render.textureUV.v1]
|
||||
: undefined
|
||||
}
|
||||
);
|
||||
}
|
||||
// Render background color if fill is enabled
|
||||
// 如果启用填充,渲染背景颜色
|
||||
else if (render.fillBackground && render.backgroundAlpha > 0) {
|
||||
collector.addRect(
|
||||
x, y,
|
||||
width, height,
|
||||
render.backgroundColor,
|
||||
render.backgroundAlpha * alpha,
|
||||
baseOrder,
|
||||
{
|
||||
rotation: transform.rotation,
|
||||
pivotX: 0,
|
||||
pivotY: 0
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Render border if present
|
||||
// 如果有边框,渲染边框
|
||||
if (render.borderWidth > 0 && render.borderAlpha > 0) {
|
||||
this.renderBorder(
|
||||
collector,
|
||||
x, y, width, height,
|
||||
render.borderWidth,
|
||||
render.borderColor,
|
||||
render.borderAlpha * alpha,
|
||||
baseOrder + 0.1,
|
||||
transform.rotation
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render border using top-left coordinates
|
||||
* 使用左上角坐标渲染边框
|
||||
*/
|
||||
private renderBorder(
|
||||
collector: ReturnType<typeof getUIRenderCollector>,
|
||||
x: number, y: number,
|
||||
width: number, height: number,
|
||||
borderWidth: number,
|
||||
borderColor: number,
|
||||
alpha: number,
|
||||
sortOrder: number,
|
||||
rotation: number
|
||||
): void {
|
||||
// Top border (from top-left corner)
|
||||
collector.addRect(
|
||||
x, y,
|
||||
width, borderWidth,
|
||||
borderColor, alpha, sortOrder,
|
||||
{ rotation, pivotX: 0, pivotY: 0 }
|
||||
);
|
||||
|
||||
// Bottom border
|
||||
collector.addRect(
|
||||
x, y + height - borderWidth,
|
||||
width, borderWidth,
|
||||
borderColor, alpha, sortOrder,
|
||||
{ rotation, pivotX: 0, pivotY: 0 }
|
||||
);
|
||||
|
||||
// Left border (excluding corners)
|
||||
collector.addRect(
|
||||
x, y + borderWidth,
|
||||
borderWidth, height - borderWidth * 2,
|
||||
borderColor, alpha, sortOrder,
|
||||
{ rotation, pivotX: 0, pivotY: 0 }
|
||||
);
|
||||
|
||||
// Right border (excluding corners)
|
||||
collector.addRect(
|
||||
x + width - borderWidth, y + borderWidth,
|
||||
borderWidth, height - borderWidth * 2,
|
||||
borderColor, alpha, sortOrder,
|
||||
{ rotation, pivotX: 0, pivotY: 0 }
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user