Feature/render pipeline (#232)
* refactor(engine): 重构2D渲染管线坐标系统 * feat(engine): 完善2D渲染管线和编辑器视口功能 * feat(editor): 实现Viewport变换工具系统 * feat(editor): 优化Inspector渲染性能并修复Gizmo变换工具显示 * feat(editor): 实现Run on Device移动预览功能 * feat(editor): 添加组件属性控制和依赖关系系统 * feat(editor): 实现动画预览功能和优化SpriteAnimator编辑器 * feat(editor): 修复SpriteAnimator动画预览功能并迁移CI到pnpm * feat(editor): 修复SpriteAnimator动画预览并迁移到pnpm * feat(editor): 修复SpriteAnimator动画预览并迁移到pnpm * feat(editor): 修复SpriteAnimator动画预览并迁移到pnpm * feat(editor): 修复SpriteAnimator动画预览并迁移到pnpm * feat(ci): 迁移项目到pnpm并修复CI构建问题 * chore: 迁移CI工作流到pnpm并添加WASM构建支持 * chore: 迁移CI工作流到pnpm并添加WASM构建支持 * chore: 迁移CI工作流到pnpm并添加WASM构建支持 * chore: 迁移CI工作流到pnpm并添加WASM构建支持 * chore: 迁移CI工作流到pnpm并添加WASM构建支持 * chore: 迁移CI工作流到pnpm并添加WASM构建支持 * chore: 移除 network 相关包 * chore: 移除 network 相关包
This commit is contained in:
@@ -6,7 +6,7 @@ use wasm_bindgen::prelude::*;
|
||||
use super::context::WebGLContext;
|
||||
use super::error::Result;
|
||||
use crate::input::InputManager;
|
||||
use crate::renderer::Renderer2D;
|
||||
use crate::renderer::{Renderer2D, GridRenderer, GizmoRenderer, TransformMode, ViewportManager};
|
||||
use crate::resource::TextureManager;
|
||||
|
||||
/// Engine configuration options.
|
||||
@@ -45,6 +45,14 @@ pub struct Engine {
|
||||
/// 2D渲染器。
|
||||
renderer: Renderer2D,
|
||||
|
||||
/// Grid renderer for editor.
|
||||
/// 编辑器网格渲染器。
|
||||
grid_renderer: GridRenderer,
|
||||
|
||||
/// Gizmo renderer for editor overlays.
|
||||
/// 编辑器叠加层Gizmo渲染器。
|
||||
gizmo_renderer: GizmoRenderer,
|
||||
|
||||
/// Texture manager.
|
||||
/// 纹理管理器。
|
||||
texture_manager: TextureManager,
|
||||
@@ -57,6 +65,18 @@ pub struct Engine {
|
||||
/// 引擎配置。
|
||||
#[allow(dead_code)]
|
||||
config: EngineConfig,
|
||||
|
||||
/// Whether to show grid.
|
||||
/// 是否显示网格。
|
||||
show_grid: bool,
|
||||
|
||||
/// Viewport manager for multi-viewport rendering.
|
||||
/// 多视口渲染的视口管理器。
|
||||
viewport_manager: ViewportManager,
|
||||
|
||||
/// Whether to show gizmos.
|
||||
/// 是否显示辅助工具。
|
||||
show_gizmos: bool,
|
||||
}
|
||||
|
||||
impl Engine {
|
||||
@@ -78,6 +98,8 @@ impl Engine {
|
||||
|
||||
// Create subsystems | 创建子系统
|
||||
let renderer = Renderer2D::new(context.gl(), config.max_sprites)?;
|
||||
let grid_renderer = GridRenderer::new(context.gl())?;
|
||||
let gizmo_renderer = GizmoRenderer::new(context.gl())?;
|
||||
let texture_manager = TextureManager::new(context.gl().clone());
|
||||
let input_manager = InputManager::new();
|
||||
|
||||
@@ -86,9 +108,14 @@ impl Engine {
|
||||
Ok(Self {
|
||||
context,
|
||||
renderer,
|
||||
grid_renderer,
|
||||
gizmo_renderer,
|
||||
texture_manager,
|
||||
input_manager,
|
||||
config,
|
||||
show_grid: true,
|
||||
viewport_manager: ViewportManager::new(),
|
||||
show_gizmos: true,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -109,6 +136,8 @@ impl Engine {
|
||||
context.enable_blend();
|
||||
|
||||
let renderer = Renderer2D::new(context.gl(), config.max_sprites)?;
|
||||
let grid_renderer = GridRenderer::new(context.gl())?;
|
||||
let gizmo_renderer = GizmoRenderer::new(context.gl())?;
|
||||
let texture_manager = TextureManager::new(context.gl().clone());
|
||||
let input_manager = InputManager::new();
|
||||
|
||||
@@ -117,9 +146,14 @@ impl Engine {
|
||||
Ok(Self {
|
||||
context,
|
||||
renderer,
|
||||
grid_renderer,
|
||||
gizmo_renderer,
|
||||
texture_manager,
|
||||
input_manager,
|
||||
config,
|
||||
show_grid: true,
|
||||
viewport_manager: ViewportManager::new(),
|
||||
show_gizmos: true,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -152,6 +186,14 @@ impl Engine {
|
||||
uvs: &[f32],
|
||||
colors: &[u32],
|
||||
) -> Result<()> {
|
||||
// Debug: log once
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
static LOGGED: AtomicBool = AtomicBool::new(false);
|
||||
if !LOGGED.swap(true, Ordering::Relaxed) {
|
||||
let sprite_count = texture_ids.len();
|
||||
log::info!("Engine submit_sprite_batch: {} sprites, texture_ids: {:?}", sprite_count, texture_ids);
|
||||
}
|
||||
|
||||
self.renderer.submit_batch(
|
||||
transforms,
|
||||
texture_ids,
|
||||
@@ -164,7 +206,56 @@ impl Engine {
|
||||
/// Render the current frame.
|
||||
/// 渲染当前帧。
|
||||
pub fn render(&mut self) -> Result<()> {
|
||||
self.renderer.render(self.context.gl())
|
||||
// Clear background with clear color
|
||||
let [r, g, b, a] = self.renderer.get_clear_color();
|
||||
self.context.clear(r, g, b, a);
|
||||
|
||||
// Render grid first (background)
|
||||
if self.show_grid {
|
||||
self.grid_renderer.render(self.context.gl(), self.renderer.camera());
|
||||
self.grid_renderer.render_axes(self.context.gl(), self.renderer.camera());
|
||||
}
|
||||
|
||||
// Render sprites
|
||||
self.renderer.render(self.context.gl(), &self.texture_manager)?;
|
||||
|
||||
// Render gizmos on top
|
||||
self.gizmo_renderer.render(self.context.gl(), self.renderer.camera());
|
||||
self.gizmo_renderer.clear();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Add a rectangle gizmo.
|
||||
/// 添加矩形Gizmo。
|
||||
pub fn add_gizmo_rect(
|
||||
&mut self,
|
||||
x: f32,
|
||||
y: f32,
|
||||
width: f32,
|
||||
height: f32,
|
||||
rotation: f32,
|
||||
origin_x: f32,
|
||||
origin_y: f32,
|
||||
r: f32,
|
||||
g: f32,
|
||||
b: f32,
|
||||
a: f32,
|
||||
show_handles: bool,
|
||||
) {
|
||||
self.gizmo_renderer.add_rect(x, y, width, height, rotation, origin_x, origin_y, r, g, b, a, show_handles);
|
||||
}
|
||||
|
||||
/// Set transform tool mode.
|
||||
/// 设置变换工具模式。
|
||||
pub fn set_transform_mode(&mut self, mode: u8) {
|
||||
let transform_mode = match mode {
|
||||
1 => TransformMode::Move,
|
||||
2 => TransformMode::Rotate,
|
||||
3 => TransformMode::Scale,
|
||||
_ => TransformMode::Select,
|
||||
};
|
||||
self.gizmo_renderer.set_transform_mode(transform_mode);
|
||||
}
|
||||
|
||||
/// Load a texture from URL.
|
||||
@@ -173,6 +264,24 @@ impl Engine {
|
||||
self.texture_manager.load_texture(id, url)
|
||||
}
|
||||
|
||||
/// Load texture by path, returning texture ID.
|
||||
/// 按路径加载纹理,返回纹理ID。
|
||||
pub fn load_texture_by_path(&mut self, path: &str) -> Result<u32> {
|
||||
self.texture_manager.load_texture_by_path(path)
|
||||
}
|
||||
|
||||
/// Get texture ID by path.
|
||||
/// 按路径获取纹理ID。
|
||||
pub fn get_texture_id_by_path(&self, path: &str) -> Option<u32> {
|
||||
self.texture_manager.get_texture_id_by_path(path)
|
||||
}
|
||||
|
||||
/// Get or load texture by path.
|
||||
/// 按路径获取或加载纹理。
|
||||
pub fn get_or_load_by_path(&mut self, path: &str) -> Result<u32> {
|
||||
self.texture_manager.get_or_load_by_path(path)
|
||||
}
|
||||
|
||||
/// Check if a key is currently pressed.
|
||||
/// 检查某个键是否当前被按下。
|
||||
pub fn is_key_down(&self, key_code: &str) -> bool {
|
||||
@@ -184,4 +293,169 @@ impl Engine {
|
||||
pub fn update_input(&mut self) {
|
||||
self.input_manager.update();
|
||||
}
|
||||
|
||||
/// Resize viewport.
|
||||
/// 调整视口大小。
|
||||
pub fn resize(&mut self, width: f32, height: f32) {
|
||||
self.context.resize(width as u32, height as u32);
|
||||
self.renderer.resize(width, height);
|
||||
}
|
||||
|
||||
/// Set camera position, zoom, and rotation.
|
||||
/// 设置相机位置、缩放和旋转。
|
||||
///
|
||||
/// # Arguments | 参数
|
||||
/// * `x` - Camera X position | 相机X位置
|
||||
/// * `y` - Camera Y position | 相机Y位置
|
||||
/// * `zoom` - Zoom level | 缩放级别
|
||||
/// * `rotation` - Rotation in radians | 旋转角度(弧度)
|
||||
pub fn set_camera(&mut self, x: f32, y: f32, zoom: f32, rotation: f32) {
|
||||
let camera = self.renderer.camera_mut();
|
||||
camera.position.x = x;
|
||||
camera.position.y = y;
|
||||
camera.set_zoom(zoom);
|
||||
camera.rotation = rotation;
|
||||
}
|
||||
|
||||
/// Get camera position.
|
||||
/// 获取相机位置。
|
||||
pub fn get_camera(&self) -> (f32, f32, f32, f32) {
|
||||
let camera = self.renderer.camera();
|
||||
(camera.position.x, camera.position.y, camera.zoom, camera.rotation)
|
||||
}
|
||||
|
||||
/// Set grid visibility.
|
||||
/// 设置网格可见性。
|
||||
pub fn set_show_grid(&mut self, show: bool) {
|
||||
self.show_grid = show;
|
||||
}
|
||||
|
||||
/// Set gizmo visibility.
|
||||
/// 设置辅助工具可见性。
|
||||
pub fn set_show_gizmos(&mut self, show: bool) {
|
||||
self.show_gizmos = show;
|
||||
}
|
||||
|
||||
/// Get gizmo visibility.
|
||||
/// 获取辅助工具可见性。
|
||||
pub fn show_gizmos(&self) -> bool {
|
||||
self.show_gizmos
|
||||
}
|
||||
|
||||
/// Set clear color for the active viewport.
|
||||
/// 设置活动视口的清除颜色。
|
||||
pub fn set_clear_color(&mut self, r: f32, g: f32, b: f32, a: f32) {
|
||||
if let Some(target) = self.viewport_manager.active_mut() {
|
||||
target.set_clear_color(r, g, b, a);
|
||||
} else {
|
||||
// Fallback to primary renderer
|
||||
self.renderer.set_clear_color(r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
// ===== Multi-viewport API =====
|
||||
// ===== 多视口 API =====
|
||||
|
||||
/// Register a new viewport.
|
||||
/// 注册新视口。
|
||||
pub fn register_viewport(&mut self, id: &str, canvas_id: &str) -> Result<()> {
|
||||
self.viewport_manager.register(id, canvas_id)
|
||||
}
|
||||
|
||||
/// Unregister a viewport.
|
||||
/// 注销视口。
|
||||
pub fn unregister_viewport(&mut self, id: &str) {
|
||||
self.viewport_manager.unregister(id);
|
||||
}
|
||||
|
||||
/// Set the active viewport.
|
||||
/// 设置活动视口。
|
||||
pub fn set_active_viewport(&mut self, id: &str) -> bool {
|
||||
self.viewport_manager.set_active(id)
|
||||
}
|
||||
|
||||
/// Get active viewport ID.
|
||||
/// 获取活动视口ID。
|
||||
pub fn active_viewport_id(&self) -> Option<&str> {
|
||||
self.viewport_manager.active().map(|v| v.id.as_str())
|
||||
}
|
||||
|
||||
/// Set camera for a specific viewport.
|
||||
/// 为特定视口设置相机。
|
||||
pub fn set_viewport_camera(&mut self, viewport_id: &str, x: f32, y: f32, zoom: f32, rotation: f32) {
|
||||
if let Some(viewport) = self.viewport_manager.get_mut(viewport_id) {
|
||||
viewport.set_camera(x, y, zoom, rotation);
|
||||
}
|
||||
}
|
||||
|
||||
/// Get camera for a specific viewport.
|
||||
/// 获取特定视口的相机。
|
||||
pub fn get_viewport_camera(&self, viewport_id: &str) -> Option<(f32, f32, f32, f32)> {
|
||||
self.viewport_manager.get(viewport_id).map(|v| v.get_camera())
|
||||
}
|
||||
|
||||
/// Set viewport configuration.
|
||||
/// 设置视口配置。
|
||||
pub fn set_viewport_config(&mut self, viewport_id: &str, show_grid: bool, show_gizmos: bool) {
|
||||
if let Some(viewport) = self.viewport_manager.get_mut(viewport_id) {
|
||||
viewport.config.show_grid = show_grid;
|
||||
viewport.config.show_gizmos = show_gizmos;
|
||||
}
|
||||
}
|
||||
|
||||
/// Resize a specific viewport.
|
||||
/// 调整特定视口大小。
|
||||
pub fn resize_viewport(&mut self, viewport_id: &str, width: u32, height: u32) {
|
||||
if let Some(viewport) = self.viewport_manager.get_mut(viewport_id) {
|
||||
viewport.resize(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
/// Render to a specific viewport.
|
||||
/// 渲染到特定视口。
|
||||
pub fn render_to_viewport(&mut self, viewport_id: &str) -> Result<()> {
|
||||
let viewport = match self.viewport_manager.get(viewport_id) {
|
||||
Some(v) => v,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
// Get viewport settings
|
||||
let show_grid = viewport.config.show_grid;
|
||||
let show_gizmos = viewport.config.show_gizmos;
|
||||
let camera = viewport.camera.clone();
|
||||
|
||||
// Bind viewport and clear
|
||||
viewport.bind();
|
||||
viewport.clear();
|
||||
|
||||
// Update renderer camera to match viewport camera
|
||||
let renderer_camera = self.renderer.camera_mut();
|
||||
renderer_camera.position = camera.position;
|
||||
renderer_camera.set_zoom(camera.zoom);
|
||||
renderer_camera.rotation = camera.rotation;
|
||||
renderer_camera.set_viewport(camera.viewport_width(), camera.viewport_height());
|
||||
|
||||
// Render grid if enabled
|
||||
if show_grid {
|
||||
self.grid_renderer.render(viewport.gl(), &camera);
|
||||
self.grid_renderer.render_axes(viewport.gl(), &camera);
|
||||
}
|
||||
|
||||
// Render sprites
|
||||
self.renderer.render(viewport.gl(), &self.texture_manager)?;
|
||||
|
||||
// Render gizmos if enabled
|
||||
if show_gizmos {
|
||||
self.gizmo_renderer.render(viewport.gl(), &camera);
|
||||
}
|
||||
self.gizmo_renderer.clear();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get all registered viewport IDs.
|
||||
/// 获取所有已注册的视口ID。
|
||||
pub fn viewport_ids(&self) -> Vec<String> {
|
||||
self.viewport_manager.viewport_ids().into_iter().cloned().collect()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user