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,243 @@
//! Mesh batch renderer for arbitrary 2D geometry.
//! 用于任意 2D 几何体的网格批处理渲染器。
//!
//! Unlike SpriteBatch which only supports quads, MeshBatch can render
//! arbitrary triangulated meshes (ellipses, polygons, rounded rectangles, etc.).
//!
//! 与仅支持四边形的 SpriteBatch 不同MeshBatch 可以渲染
//! 任意三角化的网格(椭圆、多边形、圆角矩形等)。
use es_engine_shared::{
traits::backend::{GraphicsBackend, BufferUsage},
types::{
handle::{BufferHandle, VertexArrayHandle},
vertex::{VertexLayout, VertexAttribute, VertexAttributeType},
},
};
/// Floats per mesh vertex: position(2) + texCoord(2) + color(4) = 8
/// 每个网格顶点的浮点数:位置(2) + 纹理坐标(2) + 颜色(4) = 8
const FLOATS_PER_VERTEX: usize = 8;
/// Mesh batch for rendering arbitrary 2D geometry.
/// 用于渲染任意 2D 几何体的网格批处理。
pub struct MeshBatch {
vbo: BufferHandle,
ibo: BufferHandle,
vao: VertexArrayHandle,
max_vertices: usize,
max_indices: usize,
vertex_data: Vec<f32>,
index_data: Vec<u16>,
vertex_count: usize,
index_count: usize,
}
impl MeshBatch {
/// Create a new mesh batch.
/// 创建新的网格批处理。
///
/// # Arguments | 参数
/// * `backend` - Graphics backend
/// * `max_vertices` - Maximum number of vertices
/// * `max_indices` - Maximum number of indices
pub fn new(
backend: &mut impl GraphicsBackend,
max_vertices: usize,
max_indices: usize,
) -> Result<Self, String> {
let vertex_buffer_size = max_vertices * FLOATS_PER_VERTEX * 4;
let vbo = backend.create_vertex_buffer(
&vec![0u8; vertex_buffer_size],
BufferUsage::Dynamic,
).map_err(|e| format!("Mesh VBO: {:?}", e))?;
let ibo = backend.create_index_buffer(
bytemuck::cast_slice(&vec![0u16; max_indices]),
BufferUsage::Dynamic,
).map_err(|e| format!("Mesh IBO: {:?}", e))?;
// Mesh vertex layout:
// a_position: vec2 (location 0)
// a_texCoord: vec2 (location 1)
// a_color: vec4 (location 2)
let layout = VertexLayout {
attributes: vec![
VertexAttribute {
name: "a_position".into(),
attr_type: VertexAttributeType::Float2,
offset: 0,
normalized: false,
},
VertexAttribute {
name: "a_texcoord".into(),
attr_type: VertexAttributeType::Float2,
offset: 8,
normalized: false,
},
VertexAttribute {
name: "a_color".into(),
attr_type: VertexAttributeType::Float4,
offset: 16,
normalized: false,
},
],
stride: FLOATS_PER_VERTEX * 4,
};
let vao = backend.create_vertex_array(vbo, Some(ibo), &layout)
.map_err(|e| format!("Mesh VAO: {:?}", e))?;
Ok(Self {
vbo,
ibo,
vao,
max_vertices,
max_indices,
vertex_data: Vec::with_capacity(max_vertices * FLOATS_PER_VERTEX),
index_data: Vec::with_capacity(max_indices),
vertex_count: 0,
index_count: 0,
})
}
/// Clear the batch.
/// 清除批处理。
pub fn clear(&mut self) {
self.vertex_data.clear();
self.index_data.clear();
self.vertex_count = 0;
self.index_count = 0;
}
/// Add a mesh to the batch.
/// 将网格添加到批处理。
///
/// # Arguments | 参数
/// * `positions` - Float array [x, y, ...] for each vertex
/// * `uvs` - Float array [u, v, ...] for each vertex
/// * `colors` - Packed RGBA colors (one per vertex)
/// * `indices` - Triangle indices
/// * `offset_x` - X offset to apply to all positions
/// * `offset_y` - Y offset to apply to all positions
pub fn add_mesh(
&mut self,
positions: &[f32],
uvs: &[f32],
colors: &[u32],
indices: &[u16],
offset_x: f32,
offset_y: f32,
) -> Result<(), String> {
let vertex_count = positions.len() / 2;
if self.vertex_count + vertex_count > self.max_vertices {
return Err(format!(
"Mesh batch vertex overflow: {} + {} > {}",
self.vertex_count, vertex_count, self.max_vertices
));
}
if self.index_count + indices.len() > self.max_indices {
return Err(format!(
"Mesh batch index overflow: {} + {} > {}",
self.index_count, indices.len(), self.max_indices
));
}
// Validate input sizes
if uvs.len() != positions.len() {
return Err(format!(
"UV size mismatch: {} vs {}",
uvs.len(), positions.len()
));
}
if colors.len() != vertex_count {
return Err(format!(
"Color count mismatch: {} vs {}",
colors.len(), vertex_count
));
}
// Build vertex data
let base_index = self.vertex_count as u16;
for v in 0..vertex_count {
let pos_idx = v * 2;
// Position with offset (2 floats)
self.vertex_data.push(positions[pos_idx] + offset_x);
self.vertex_data.push(positions[pos_idx + 1] + offset_y);
// TexCoord (2 floats)
self.vertex_data.push(uvs[pos_idx]);
self.vertex_data.push(uvs[pos_idx + 1]);
// Color (4 floats from packed RGBA)
let color = colors[v];
let r = ((color >> 24) & 0xFF) as f32 / 255.0;
let g = ((color >> 16) & 0xFF) as f32 / 255.0;
let b = ((color >> 8) & 0xFF) as f32 / 255.0;
let a = (color & 0xFF) as f32 / 255.0;
self.vertex_data.push(r);
self.vertex_data.push(g);
self.vertex_data.push(b);
self.vertex_data.push(a);
}
// Add indices with base offset
for &idx in indices {
self.index_data.push(base_index + idx);
}
self.vertex_count += vertex_count;
self.index_count += indices.len();
Ok(())
}
/// Get the vertex count.
/// 获取顶点数量。
#[inline]
pub fn vertex_count(&self) -> usize {
self.vertex_count
}
/// Get the index count.
/// 获取索引数量。
#[inline]
pub fn index_count(&self) -> usize {
self.index_count
}
/// Get the VAO handle.
/// 获取 VAO 句柄。
#[inline]
pub fn vao(&self) -> VertexArrayHandle {
self.vao
}
/// Flush and render the batch.
/// 刷新并渲染批处理。
pub fn flush(&self, backend: &mut impl GraphicsBackend) {
if self.vertex_data.is_empty() || self.index_data.is_empty() {
return;
}
// Upload vertex data
backend.update_buffer(self.vbo, 0, bytemuck::cast_slice(&self.vertex_data)).ok();
// Upload index data
backend.update_buffer(self.ibo, 0, bytemuck::cast_slice(&self.index_data)).ok();
// Draw indexed
backend.draw_indexed(self.vao, self.index_count as u32, 0).ok();
}
/// Destroy the batch resources.
/// 销毁批处理资源。
pub fn destroy(self, backend: &mut impl GraphicsBackend) {
backend.destroy_vertex_array(self.vao);
backend.destroy_buffer(self.vbo);
backend.destroy_buffer(self.ibo);
}
}