moltrun 1.7.2

High-performance game engine library with AI capabilities, built on wgpu for modern 3D graphics and physics simulation
Documentation
use std::any::Any;
use std::sync::Arc;
use crate::{
    core::{Entity, System, SystemContext, SystemError, SystemId},
    runtime::AssetManager,
};
use super::{
    gpu::{GraphicsContext, RenderPipeline},
    pipeline::{SpriteBatch, RenderCommands},
    resources::TextureCache,
};

pub struct RenderSystem {
    id: SystemId,
    graphics: Option<GraphicsContext>,
    render_pipeline: Option<RenderPipeline>,
    sprite_batch: SpriteBatch,
    texture_cache: Option<TextureCache>,
    initialized: bool,
}

impl RenderSystem {
    pub fn new() -> Self {
        Self {
            id: SystemId::from_str("RenderSystem"),
            graphics: None,
            render_pipeline: None,
            sprite_batch: SpriteBatch::new(800.0, 600.0),  // 기본 크기
            texture_cache: None,
            initialized: false,
        }
    }
    
    pub async fn initialize(&mut self, window: Arc<winit::window::Window>) -> Result<(), SystemError> {
        let graphics = GraphicsContext::new(window).await
            .map_err(|e| SystemError::InitializationFailed(e))?;
        
        // 렌더 파이프라인 생성
        let render_pipeline = RenderPipeline::new_sprite_pipeline(
            graphics.device(),
            graphics.config().format
        );
        
        // TextureCache 초기화
        let texture_cache = TextureCache::new(
            Arc::new(graphics.device().clone()),
            Arc::new(graphics.queue().clone()),
        );
        
        self.graphics = Some(graphics);
        self.render_pipeline = Some(render_pipeline);
        self.texture_cache = Some(texture_cache);
        self.initialized = true;
        
        println!("✅ RenderSystem 초기화 완료");
        Ok(())
    }

    fn render_entities_with_textures(
        &mut self, 
        entities: &[Entity],
        camera: &crate::runtime::Camera,
        asset_manager: &mut AssetManager,
    ) -> Result<(), SystemError> {
        if !self.initialized {
            return Err(SystemError::RuntimeError("RenderSystem not initialized. Call initialize() first.".to_string()));
        }
        
        let Some(graphics) = &self.graphics else {
            return Err(SystemError::RuntimeError("Graphics not initialized".to_string()));
        };
        
        let Some(render_pipeline) = &self.render_pipeline else {
            return Err(SystemError::RuntimeError("Render pipeline not initialized".to_string()));
        };
        
        let Some(texture_cache) = &mut self.texture_cache else {
            return Err(SystemError::RuntimeError("Texture cache not initialized".to_string()));
        };

        // 스프라이트 배치 수집 (카메라 전달)
        self.sprite_batch.begin_frame();
        self.sprite_batch.collect_sprites(entities, camera);
        
        if self.sprite_batch.is_empty() {
            return Ok(());
        }

        let output = graphics.get_current_frame()
            .map_err(|e| SystemError::RuntimeError(format!("Surface texture: {}", e)))?;
        
        let view = output.texture.create_view(&wgpu::TextureViewDescriptor::default());
        let mut encoder = graphics.device().create_command_encoder(&wgpu::CommandEncoderDescriptor {
            label: Some("Render Encoder"),
        });

        let render_commands = RenderCommands::new(
            graphics,
            render_pipeline,
        );

        // 텍스처와 함께 렌더링
        render_commands.execute_render_pass_with_textures(
            &mut encoder, 
            &view, 
            &self.sprite_batch,
            texture_cache,
            asset_manager,
        );

        graphics.queue().submit(std::iter::once(encoder.finish()));
        output.present();

        Ok(())
    }
}

impl System for RenderSystem {
    fn id(&self) -> SystemId {
        self.id
    }
    
    fn update(&mut self, context: &mut SystemContext) -> Result<(), SystemError> {
        self.render_entities_with_textures(
            context.entities,
            context.camera,
            context.asset_manager,
        )
    }
    
    fn name(&self) -> &'static str {
        "RenderSystem"
    }
    
    fn as_any(&self) -> &dyn Any {
        self
    }
    
    fn as_any_mut(&mut self) -> &mut dyn Any {
        self
    }
}