* feat(engine): 添加编辑器模式标志控制编辑器UI显示 - 在 Rust 引擎中添加 isEditor 标志,控制网格、gizmos、坐标轴指示器的显示 - 运行时模式下自动隐藏所有编辑器专用 UI - 编辑器预览和浏览器运行时通过 setEditorMode(false) 禁用编辑器 UI - 添加 Scene.isEditorMode 延迟组件生命周期回调,直到 begin() 调用 - 修复用户组件注册到 Core ComponentRegistry 以支持序列化 - 修复 Run in Browser 时用户组件加载问题 * fix: 复制引擎模块的类型定义文件到 dist/engine * fix: 修复用户项目 tsconfig paths 类型定义路径 - 从 module.json 读取实际包名而不是使用目录名 - 修复 .d.ts 文件复制逻辑,支持 .mjs 扩展名
742 lines
23 KiB
Rust
742 lines
23 KiB
Rust
//! Main engine implementation.
|
||
//! 主引擎实现。
|
||
|
||
use wasm_bindgen::prelude::*;
|
||
|
||
use super::context::WebGLContext;
|
||
use super::error::Result;
|
||
use crate::input::InputManager;
|
||
use crate::renderer::{Renderer2D, GridRenderer, GizmoRenderer, TransformMode, ViewportManager};
|
||
use crate::resource::TextureManager;
|
||
|
||
/// Engine configuration options.
|
||
/// 引擎配置选项。
|
||
#[derive(Debug, Clone)]
|
||
pub struct EngineConfig {
|
||
/// Maximum sprites per batch.
|
||
/// 每批次最大精灵数。
|
||
pub max_sprites: usize,
|
||
|
||
/// Enable debug mode.
|
||
/// 启用调试模式。
|
||
pub debug: bool,
|
||
}
|
||
|
||
impl Default for EngineConfig {
|
||
fn default() -> Self {
|
||
Self {
|
||
max_sprites: 10000,
|
||
debug: false,
|
||
}
|
||
}
|
||
}
|
||
|
||
/// Main game engine.
|
||
/// 主游戏引擎。
|
||
///
|
||
/// Coordinates all engine subsystems including rendering, input, and resources.
|
||
/// 协调所有引擎子系统,包括渲染、输入和资源。
|
||
pub struct Engine {
|
||
/// WebGL context.
|
||
/// WebGL上下文。
|
||
context: WebGLContext,
|
||
|
||
/// 2D renderer.
|
||
/// 2D渲染器。
|
||
renderer: Renderer2D,
|
||
|
||
/// Grid renderer for editor.
|
||
/// 编辑器网格渲染器。
|
||
grid_renderer: GridRenderer,
|
||
|
||
/// Gizmo renderer for editor overlays.
|
||
/// 编辑器叠加层Gizmo渲染器。
|
||
gizmo_renderer: GizmoRenderer,
|
||
|
||
/// Texture manager.
|
||
/// 纹理管理器。
|
||
texture_manager: TextureManager,
|
||
|
||
/// Input manager.
|
||
/// 输入管理器。
|
||
input_manager: InputManager,
|
||
|
||
/// Engine configuration.
|
||
/// 引擎配置。
|
||
#[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,
|
||
|
||
/// Whether the engine is running in editor mode.
|
||
/// 引擎是否在编辑器模式下运行。
|
||
///
|
||
/// When false (runtime mode), editor-only UI like grid, gizmos,
|
||
/// and axis indicator are automatically hidden.
|
||
/// 当为 false(运行时模式)时,编辑器专用 UI(如网格、gizmos、坐标轴指示器)会自动隐藏。
|
||
is_editor: bool,
|
||
}
|
||
|
||
impl Engine {
|
||
/// Create a new engine instance.
|
||
/// 创建新的引擎实例。
|
||
///
|
||
/// # Arguments | 参数
|
||
/// * `canvas_id` - The HTML canvas element ID | HTML canvas元素ID
|
||
/// * `config` - Engine configuration | 引擎配置
|
||
///
|
||
/// # Returns | 返回
|
||
/// A new Engine instance or an error | 新的Engine实例或错误
|
||
pub fn new(canvas_id: &str, config: EngineConfig) -> Result<Self> {
|
||
let context = WebGLContext::new(canvas_id)?;
|
||
|
||
// Initialize WebGL state | 初始化WebGL状态
|
||
context.set_viewport();
|
||
context.enable_blend();
|
||
|
||
// 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();
|
||
|
||
log::info!("Engine created successfully | 引擎创建成功");
|
||
|
||
Ok(Self {
|
||
context,
|
||
renderer,
|
||
grid_renderer,
|
||
gizmo_renderer,
|
||
texture_manager,
|
||
input_manager,
|
||
config,
|
||
show_grid: true,
|
||
viewport_manager: ViewportManager::new(),
|
||
show_gizmos: true,
|
||
is_editor: true, // 默认为编辑器模式 | Default to editor mode
|
||
})
|
||
}
|
||
|
||
/// Create a new engine instance from external WebGL context.
|
||
/// 从外部 WebGL 上下文创建引擎实例。
|
||
///
|
||
/// This is designed for environments like WeChat MiniGame.
|
||
/// 适用于微信小游戏等环境。
|
||
pub fn from_external(
|
||
gl_context: JsValue,
|
||
width: u32,
|
||
height: u32,
|
||
config: EngineConfig,
|
||
) -> Result<Self> {
|
||
let context = WebGLContext::from_external(gl_context, width, height)?;
|
||
|
||
context.set_viewport();
|
||
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();
|
||
|
||
log::info!("Engine created from external context | 从外部上下文创建引擎");
|
||
|
||
Ok(Self {
|
||
context,
|
||
renderer,
|
||
grid_renderer,
|
||
gizmo_renderer,
|
||
texture_manager,
|
||
input_manager,
|
||
config,
|
||
show_grid: true,
|
||
viewport_manager: ViewportManager::new(),
|
||
show_gizmos: true,
|
||
is_editor: true, // 默认为编辑器模式 | Default to editor mode
|
||
})
|
||
}
|
||
|
||
/// Clear the screen with specified color.
|
||
/// 使用指定颜色清除屏幕。
|
||
pub fn clear(&self, r: f32, g: f32, b: f32, a: f32) {
|
||
self.context.clear(r, g, b, a);
|
||
}
|
||
|
||
/// Get canvas width.
|
||
/// 获取画布宽度。
|
||
#[inline]
|
||
pub fn width(&self) -> u32 {
|
||
self.context.width()
|
||
}
|
||
|
||
/// Get canvas height.
|
||
/// 获取画布高度。
|
||
#[inline]
|
||
pub fn height(&self) -> u32 {
|
||
self.context.height()
|
||
}
|
||
|
||
/// Submit sprite batch data for rendering.
|
||
/// 提交精灵批次数据进行渲染。
|
||
pub fn submit_sprite_batch(
|
||
&mut self,
|
||
transforms: &[f32],
|
||
texture_ids: &[u32],
|
||
uvs: &[f32],
|
||
colors: &[u32],
|
||
material_ids: &[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,
|
||
uvs,
|
||
colors,
|
||
material_ids,
|
||
&self.texture_manager,
|
||
)
|
||
}
|
||
|
||
/// Render the current frame.
|
||
/// 渲染当前帧。
|
||
pub fn render(&mut self) -> Result<()> {
|
||
// 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) - only in editor mode
|
||
// 首先渲染网格(背景)- 仅在编辑器模式下
|
||
if self.is_editor && 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 - only in editor mode
|
||
// 在顶部渲染 gizmos - 仅在编辑器模式下
|
||
if self.is_editor && self.show_gizmos {
|
||
self.gizmo_renderer.render(self.context.gl(), self.renderer.camera());
|
||
// Render axis indicator in corner
|
||
// 在角落渲染坐标轴指示器
|
||
self.gizmo_renderer.render_axis_indicator(
|
||
self.context.gl(),
|
||
self.context.width() as f32,
|
||
self.context.height() as f32,
|
||
);
|
||
}
|
||
self.gizmo_renderer.clear();
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Render sprites only without clearing the screen.
|
||
/// 仅渲染精灵,不清除屏幕。
|
||
///
|
||
/// This is used for overlay rendering (e.g., UI layer on top of world).
|
||
/// 用于叠加渲染(例如,UI 层叠加在世界上)。
|
||
pub fn render_overlay(&mut self) -> Result<()> {
|
||
// Render sprites without clearing
|
||
// 渲染精灵但不清屏
|
||
self.renderer.render(self.context.gl(), &self.texture_manager)?;
|
||
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);
|
||
}
|
||
|
||
/// Add a circle gizmo.
|
||
/// 添加圆形Gizmo。
|
||
pub fn add_gizmo_circle(
|
||
&mut self,
|
||
x: f32,
|
||
y: f32,
|
||
radius: f32,
|
||
r: f32,
|
||
g: f32,
|
||
b: f32,
|
||
a: f32,
|
||
) {
|
||
self.gizmo_renderer.add_circle(x, y, radius, r, g, b, a);
|
||
}
|
||
|
||
/// Add a line gizmo.
|
||
/// 添加线条Gizmo。
|
||
pub fn add_gizmo_line(
|
||
&mut self,
|
||
points: Vec<f32>,
|
||
r: f32,
|
||
g: f32,
|
||
b: f32,
|
||
a: f32,
|
||
closed: bool,
|
||
) {
|
||
self.gizmo_renderer.add_line(points, r, g, b, a, closed);
|
||
}
|
||
|
||
/// Add a capsule gizmo.
|
||
/// 添加胶囊Gizmo。
|
||
pub fn add_gizmo_capsule(
|
||
&mut self,
|
||
x: f32,
|
||
y: f32,
|
||
radius: f32,
|
||
half_height: f32,
|
||
rotation: f32,
|
||
r: f32,
|
||
g: f32,
|
||
b: f32,
|
||
a: f32,
|
||
) {
|
||
self.gizmo_renderer.add_capsule(x, y, radius, half_height, rotation, r, g, b, a);
|
||
}
|
||
|
||
/// 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.
|
||
/// 从URL加载纹理。
|
||
pub fn load_texture(&mut self, id: u32, url: &str) -> Result<()> {
|
||
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 {
|
||
self.input_manager.is_key_down(key_code)
|
||
}
|
||
|
||
/// Update input state.
|
||
/// 更新输入状态。
|
||
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 editor mode.
|
||
/// 设置编辑器模式。
|
||
///
|
||
/// When false (runtime mode), editor-only UI like grid, gizmos,
|
||
/// and axis indicator are automatically hidden regardless of their individual settings.
|
||
/// 当为 false(运行时模式)时,编辑器专用 UI(如网格、gizmos、坐标轴指示器)
|
||
/// 会自动隐藏,无论它们的单独设置如何。
|
||
pub fn set_editor_mode(&mut self, is_editor: bool) {
|
||
self.is_editor = is_editor;
|
||
}
|
||
|
||
/// Get editor mode.
|
||
/// 获取编辑器模式。
|
||
pub fn is_editor(&self) -> bool {
|
||
self.is_editor
|
||
}
|
||
|
||
/// 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 - only in editor mode
|
||
// 渲染网格(如果启用)- 仅在编辑器模式下
|
||
if self.is_editor && 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 - only in editor mode
|
||
// 渲染 gizmos(如果启用)- 仅在编辑器模式下
|
||
if self.is_editor && show_gizmos {
|
||
self.gizmo_renderer.render(viewport.gl(), &camera);
|
||
// Render axis indicator in corner
|
||
// 在角落渲染坐标轴指示器
|
||
let (vp_width, vp_height) = viewport.dimensions();
|
||
self.gizmo_renderer.render_axis_indicator(
|
||
viewport.gl(),
|
||
vp_width as f32,
|
||
vp_height as f32,
|
||
);
|
||
}
|
||
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()
|
||
}
|
||
|
||
// ===== Shader Management =====
|
||
// ===== 着色器管理 =====
|
||
|
||
/// Compile and register a custom shader.
|
||
/// 编译并注册自定义着色器。
|
||
pub fn compile_shader(
|
||
&mut self,
|
||
vertex_source: &str,
|
||
fragment_source: &str,
|
||
) -> Result<u32> {
|
||
self.renderer.compile_shader(self.context.gl(), vertex_source, fragment_source)
|
||
}
|
||
|
||
/// Compile a shader with a specific ID.
|
||
/// 使用特定ID编译着色器。
|
||
pub fn compile_shader_with_id(
|
||
&mut self,
|
||
shader_id: u32,
|
||
vertex_source: &str,
|
||
fragment_source: &str,
|
||
) -> Result<()> {
|
||
self.renderer.compile_shader_with_id(self.context.gl(), shader_id, vertex_source, fragment_source)
|
||
}
|
||
|
||
/// Check if a shader exists.
|
||
/// 检查着色器是否存在。
|
||
pub fn has_shader(&self, shader_id: u32) -> bool {
|
||
self.renderer.has_shader(shader_id)
|
||
}
|
||
|
||
/// Remove a shader.
|
||
/// 移除着色器。
|
||
pub fn remove_shader(&mut self, shader_id: u32) -> bool {
|
||
self.renderer.remove_shader(shader_id)
|
||
}
|
||
|
||
// ===== Material Management =====
|
||
// ===== 材质管理 =====
|
||
|
||
/// Create and register a new material.
|
||
/// 创建并注册新材质。
|
||
pub fn create_material(
|
||
&mut self,
|
||
name: &str,
|
||
shader_id: u32,
|
||
blend_mode: u8,
|
||
) -> u32 {
|
||
use crate::renderer::material::{Material, BlendMode};
|
||
|
||
let blend = match blend_mode {
|
||
0 => BlendMode::None,
|
||
1 => BlendMode::Alpha,
|
||
2 => BlendMode::Additive,
|
||
3 => BlendMode::Multiply,
|
||
4 => BlendMode::Screen,
|
||
5 => BlendMode::PremultipliedAlpha,
|
||
_ => BlendMode::Alpha,
|
||
};
|
||
|
||
let mut material = Material::with_shader(name, shader_id);
|
||
material.blend_mode = blend;
|
||
|
||
self.renderer.register_material(material)
|
||
}
|
||
|
||
/// Create a material with a specific ID.
|
||
/// 使用特定ID创建材质。
|
||
pub fn create_material_with_id(
|
||
&mut self,
|
||
material_id: u32,
|
||
name: &str,
|
||
shader_id: u32,
|
||
blend_mode: u8,
|
||
) {
|
||
use crate::renderer::material::{Material, BlendMode};
|
||
|
||
let blend = match blend_mode {
|
||
0 => BlendMode::None,
|
||
1 => BlendMode::Alpha,
|
||
2 => BlendMode::Additive,
|
||
3 => BlendMode::Multiply,
|
||
4 => BlendMode::Screen,
|
||
5 => BlendMode::PremultipliedAlpha,
|
||
_ => BlendMode::Alpha,
|
||
};
|
||
|
||
let mut material = Material::with_shader(name, shader_id);
|
||
material.blend_mode = blend;
|
||
|
||
self.renderer.register_material_with_id(material_id, material);
|
||
}
|
||
|
||
/// Check if a material exists.
|
||
/// 检查材质是否存在。
|
||
pub fn has_material(&self, material_id: u32) -> bool {
|
||
self.renderer.has_material(material_id)
|
||
}
|
||
|
||
/// Remove a material.
|
||
/// 移除材质。
|
||
pub fn remove_material(&mut self, material_id: u32) -> bool {
|
||
self.renderer.remove_material(material_id)
|
||
}
|
||
|
||
/// Set a material's float uniform.
|
||
/// 设置材质的浮点uniform。
|
||
pub fn set_material_float(&mut self, material_id: u32, name: &str, value: f32) -> bool {
|
||
self.renderer.set_material_float(material_id, name, value)
|
||
}
|
||
|
||
/// Set a material's vec2 uniform.
|
||
/// 设置材质的vec2 uniform。
|
||
pub fn set_material_vec2(&mut self, material_id: u32, name: &str, x: f32, y: f32) -> bool {
|
||
if let Some(material) = self.renderer.get_material_mut(material_id) {
|
||
material.uniforms.set_vec2(name, x, y);
|
||
true
|
||
} else {
|
||
false
|
||
}
|
||
}
|
||
|
||
/// Set a material's vec3 uniform.
|
||
/// 设置材质的vec3 uniform。
|
||
pub fn set_material_vec3(&mut self, material_id: u32, name: &str, x: f32, y: f32, z: f32) -> bool {
|
||
if let Some(material) = self.renderer.get_material_mut(material_id) {
|
||
material.uniforms.set_vec3(name, x, y, z);
|
||
true
|
||
} else {
|
||
false
|
||
}
|
||
}
|
||
|
||
/// Set a material's vec4 uniform.
|
||
/// 设置材质的vec4 uniform。
|
||
pub fn set_material_vec4(&mut self, material_id: u32, name: &str, x: f32, y: f32, z: f32, w: f32) -> bool {
|
||
self.renderer.set_material_vec4(material_id, name, x, y, z, w)
|
||
}
|
||
|
||
/// Set a material's color uniform.
|
||
/// 设置材质的颜色uniform。
|
||
pub fn set_material_color(&mut self, material_id: u32, name: &str, r: f32, g: f32, b: f32, a: f32) -> bool {
|
||
if let Some(material) = self.renderer.get_material_mut(material_id) {
|
||
material.uniforms.set_color(name, r, g, b, a);
|
||
true
|
||
} else {
|
||
false
|
||
}
|
||
}
|
||
|
||
/// Set a material's blend mode.
|
||
/// 设置材质的混合模式。
|
||
pub fn set_material_blend_mode(&mut self, material_id: u32, blend_mode: u8) -> bool {
|
||
use crate::renderer::material::BlendMode;
|
||
|
||
let blend = match blend_mode {
|
||
0 => BlendMode::None,
|
||
1 => BlendMode::Alpha,
|
||
2 => BlendMode::Additive,
|
||
3 => BlendMode::Multiply,
|
||
4 => BlendMode::Screen,
|
||
5 => BlendMode::PremultipliedAlpha,
|
||
_ => return false,
|
||
};
|
||
|
||
if let Some(material) = self.renderer.get_material_mut(material_id) {
|
||
material.blend_mode = blend;
|
||
true
|
||
} else {
|
||
false
|
||
}
|
||
}
|
||
}
|