* feat(platform-common): 添加WASM加载器和环境检测API * feat(rapier2d): 新增Rapier2D WASM绑定包 * feat(physics-rapier2d): 添加跨平台WASM加载器 * feat(asset-system): 添加运行时资产目录和bundle格式 * feat(asset-system-editor): 新增编辑器资产管理包 * feat(editor-core): 添加构建系统和模块管理 * feat(editor-app): 重构浏览器预览使用import maps * feat(platform-web): 添加BrowserRuntime和资产读取 * feat(engine): 添加材质系统和着色器管理 * feat(material): 新增材质系统和着色器编辑器 * feat(tilemap): 增强tilemap编辑器和动画系统 * feat(modules): 添加module.json配置 * feat(core): 添加module.json和类型定义更新 * chore: 更新依赖和构建配置 * refactor(plugins): 更新插件模板使用ModuleManifest * chore: 添加第三方依赖库 * chore: 移除BehaviourTree-ai和ecs-astar子模块 * docs: 更新README和文档主题样式 * fix: 修复Rust文档测试和添加rapier2d WASM绑定 * fix(tilemap-editor): 修复画布高DPI屏幕分辨率适配问题 * feat(ui): 添加UI屏幕适配系统(CanvasScaler/SafeArea) * fix(ecs-engine-bindgen): 添加缺失的ecs-framework-math依赖 * fix: 添加缺失的包依赖修复CI构建 * fix: 修复CodeQL检测到的代码问题 * fix: 修复构建错误和缺失依赖 * fix: 修复类型检查错误 * fix(material-system): 修复tsconfig配置支持TypeScript项目引用 * fix(editor-core): 修复Rollup构建配置添加tauri external * fix: 修复CodeQL检测到的代码问题 * fix: 修复CodeQL检测到的代码问题
208 lines
7.0 KiB
Rust
208 lines
7.0 KiB
Rust
//! Material manager for storing and retrieving materials.
|
||
//! 材质管理器,用于存储和检索材质。
|
||
|
||
use std::collections::HashMap;
|
||
use web_sys::WebGl2RenderingContext;
|
||
|
||
use super::material::{Material, BlendMode};
|
||
|
||
/// Reserved material IDs for built-in materials.
|
||
/// 内置材质的保留ID。
|
||
pub const MATERIAL_ID_DEFAULT: u32 = 0;
|
||
pub const MATERIAL_ID_ADDITIVE: u32 = 1;
|
||
pub const MATERIAL_ID_MULTIPLY: u32 = 2;
|
||
pub const MATERIAL_ID_UNLIT: u32 = 3;
|
||
|
||
/// Material manager for creating and caching materials.
|
||
/// 材质管理器,用于创建和缓存材质。
|
||
pub struct MaterialManager {
|
||
/// Stored materials indexed by ID.
|
||
/// 按ID索引的存储材质。
|
||
materials: HashMap<u32, Material>,
|
||
|
||
/// Next available material ID for custom materials.
|
||
/// 下一个可用的自定义材质ID。
|
||
next_material_id: u32,
|
||
}
|
||
|
||
impl MaterialManager {
|
||
/// Create a new material manager with built-in materials.
|
||
/// 创建带有内置材质的新材质管理器。
|
||
pub fn new() -> Self {
|
||
let mut manager = Self {
|
||
materials: HashMap::new(),
|
||
next_material_id: 100, // Reserve 0-99 for built-in materials
|
||
};
|
||
|
||
// Register built-in materials | 注册内置材质
|
||
manager.materials.insert(MATERIAL_ID_DEFAULT, Material::sprite());
|
||
manager.materials.insert(MATERIAL_ID_ADDITIVE, Material::additive());
|
||
manager.materials.insert(MATERIAL_ID_MULTIPLY, Material::multiply());
|
||
manager.materials.insert(MATERIAL_ID_UNLIT, Material::unlit());
|
||
|
||
log::info!("MaterialManager initialized with {} built-in materials | 材质管理器初始化完成,内置材质数量: {}",
|
||
manager.materials.len(), manager.materials.len());
|
||
|
||
manager
|
||
}
|
||
|
||
/// Register a custom material.
|
||
/// 注册自定义材质。
|
||
///
|
||
/// # Returns | 返回
|
||
/// The material ID for referencing this material | 用于引用此材质的ID
|
||
pub fn register_material(&mut self, material: Material) -> u32 {
|
||
let material_id = self.next_material_id;
|
||
self.next_material_id += 1;
|
||
|
||
log::debug!("Registered material '{}' with ID: {} | 注册材质 '{}' ID: {}",
|
||
material.name, material_id, material.name, material_id);
|
||
|
||
self.materials.insert(material_id, material);
|
||
material_id
|
||
}
|
||
|
||
/// Register a material with a specific ID.
|
||
/// 使用特定ID注册材质。
|
||
pub fn register_material_with_id(&mut self, material_id: u32, material: Material) {
|
||
log::debug!("Registered material '{}' with ID: {} | 注册材质 '{}' ID: {}",
|
||
material.name, material_id, material.name, material_id);
|
||
|
||
self.materials.insert(material_id, material);
|
||
|
||
// Update next_material_id if necessary
|
||
if material_id >= self.next_material_id {
|
||
self.next_material_id = material_id + 1;
|
||
}
|
||
}
|
||
|
||
/// Get a material by ID.
|
||
/// 按ID获取材质。
|
||
#[inline]
|
||
pub fn get_material(&self, material_id: u32) -> Option<&Material> {
|
||
self.materials.get(&material_id)
|
||
}
|
||
|
||
/// Get a mutable material by ID.
|
||
/// 按ID获取可变材质。
|
||
#[inline]
|
||
pub fn get_material_mut(&mut self, material_id: u32) -> Option<&mut Material> {
|
||
self.materials.get_mut(&material_id)
|
||
}
|
||
|
||
/// Get the default material.
|
||
/// 获取默认材质。
|
||
#[inline]
|
||
pub fn get_default_material(&self) -> &Material {
|
||
self.materials.get(&MATERIAL_ID_DEFAULT)
|
||
.expect("Default material should always exist | 默认材质应该始终存在")
|
||
}
|
||
|
||
/// Check if a material exists.
|
||
/// 检查材质是否存在。
|
||
#[inline]
|
||
pub fn has_material(&self, material_id: u32) -> bool {
|
||
self.materials.contains_key(&material_id)
|
||
}
|
||
|
||
/// Remove a material.
|
||
/// 移除材质。
|
||
///
|
||
/// Note: Cannot remove built-in materials (ID < 100).
|
||
/// 注意:无法移除内置材质(ID < 100)。
|
||
pub fn remove_material(&mut self, material_id: u32) -> bool {
|
||
if material_id < 100 {
|
||
log::warn!("Cannot remove built-in material: {} | 无法移除内置材质: {}", material_id, material_id);
|
||
return false;
|
||
}
|
||
|
||
self.materials.remove(&material_id).is_some()
|
||
}
|
||
|
||
/// Update a material's uniform value.
|
||
/// 更新材质的uniform值。
|
||
pub fn set_material_float(&mut self, material_id: u32, name: &str, value: f32) -> bool {
|
||
if let Some(material) = self.materials.get_mut(&material_id) {
|
||
material.uniforms.set_float(name, value);
|
||
true
|
||
} else {
|
||
false
|
||
}
|
||
}
|
||
|
||
/// Update 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 {
|
||
if let Some(material) = self.materials.get_mut(&material_id) {
|
||
material.uniforms.set_vec4(name, x, y, z, w);
|
||
true
|
||
} else {
|
||
false
|
||
}
|
||
}
|
||
|
||
/// Apply blend mode to WebGL context.
|
||
/// 将混合模式应用到WebGL上下文。
|
||
pub fn apply_blend_mode(gl: &WebGl2RenderingContext, blend_mode: BlendMode) {
|
||
match blend_mode {
|
||
BlendMode::None => {
|
||
gl.disable(WebGl2RenderingContext::BLEND);
|
||
}
|
||
BlendMode::Alpha => {
|
||
gl.enable(WebGl2RenderingContext::BLEND);
|
||
gl.blend_func(
|
||
WebGl2RenderingContext::SRC_ALPHA,
|
||
WebGl2RenderingContext::ONE_MINUS_SRC_ALPHA,
|
||
);
|
||
}
|
||
BlendMode::Additive => {
|
||
gl.enable(WebGl2RenderingContext::BLEND);
|
||
gl.blend_func(
|
||
WebGl2RenderingContext::SRC_ALPHA,
|
||
WebGl2RenderingContext::ONE,
|
||
);
|
||
}
|
||
BlendMode::Multiply => {
|
||
gl.enable(WebGl2RenderingContext::BLEND);
|
||
gl.blend_func(
|
||
WebGl2RenderingContext::DST_COLOR,
|
||
WebGl2RenderingContext::ZERO,
|
||
);
|
||
}
|
||
BlendMode::Screen => {
|
||
gl.enable(WebGl2RenderingContext::BLEND);
|
||
gl.blend_func(
|
||
WebGl2RenderingContext::ONE,
|
||
WebGl2RenderingContext::ONE_MINUS_SRC_COLOR,
|
||
);
|
||
}
|
||
BlendMode::PremultipliedAlpha => {
|
||
gl.enable(WebGl2RenderingContext::BLEND);
|
||
gl.blend_func(
|
||
WebGl2RenderingContext::ONE,
|
||
WebGl2RenderingContext::ONE_MINUS_SRC_ALPHA,
|
||
);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// Get all material IDs.
|
||
/// 获取所有材质ID。
|
||
pub fn material_ids(&self) -> Vec<u32> {
|
||
self.materials.keys().copied().collect()
|
||
}
|
||
|
||
/// Get material count.
|
||
/// 获取材质数量。
|
||
#[inline]
|
||
pub fn material_count(&self) -> usize {
|
||
self.materials.len()
|
||
}
|
||
}
|
||
|
||
impl Default for MaterialManager {
|
||
fn default() -> Self {
|
||
Self::new()
|
||
}
|
||
}
|