sevenx_engine 0.2.11

Engine de jogos 2D/3D completa com suporte Android, física, áudio, partículas, tilemap, UI, eventos e sistema 3D avançado com PBR.
Documentation
// Sistema de configurações gráficas e otimizações
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum GraphicsQuality {
    VeryLow,    // Para PCs muito fracos
    Low,        // Para PCs fracos
    Medium,     // Padrão balanceado
    High,       // Para PCs bons
    Ultra,      // Máxima qualidade
}

impl GraphicsQuality {
    pub fn from_index(index: usize) -> Self {
        match index {
            0 => GraphicsQuality::VeryLow,
            1 => GraphicsQuality::Low,
            2 => GraphicsQuality::Medium,
            3 => GraphicsQuality::High,
            4 => GraphicsQuality::Ultra,
            _ => GraphicsQuality::VeryLow,
        }
    }

    pub fn to_index(&self) -> usize {
        match self {
            GraphicsQuality::VeryLow => 0,
            GraphicsQuality::Low => 1,
            GraphicsQuality::Medium => 2,
            GraphicsQuality::High => 3,
            GraphicsQuality::Ultra => 4,
        }
    }

    pub fn name(&self) -> &str {
        match self {
            GraphicsQuality::VeryLow => "Muito Baixo",
            GraphicsQuality::Low => "Baixo",
            GraphicsQuality::Medium => "Médio",
            GraphicsQuality::High => "Alto",
            GraphicsQuality::Ultra => "Ultra",
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GraphicsSettings {
    pub quality: GraphicsQuality,
    pub vsync: bool,
    pub target_fps: u32,
    pub render_distance: f32,
    pub shadow_quality: u32,
    pub particle_limit: usize,
    pub texture_quality: u32,
    pub anti_aliasing: bool,
    pub post_processing: bool,
    pub bloom: bool,
    pub motion_blur: bool,
    pub ambient_occlusion: bool,
    pub lod_enabled: bool,
    pub culling_enabled: bool,
    pub resolution_scale: f32,
}

impl Default for GraphicsSettings {
    fn default() -> Self {
        Self::very_low() // Padrão para PCs fracos
    }
}

impl GraphicsSettings {
    // Preset: Muito Baixo (para PCs muito fracos)
    pub fn very_low() -> Self {
        Self {
            quality: GraphicsQuality::VeryLow,
            vsync: false,
            target_fps: 30,
            render_distance: 20.0,
            shadow_quality: 0,
            particle_limit: 50,
            texture_quality: 0,
            anti_aliasing: false,
            post_processing: false,
            bloom: false,
            motion_blur: false,
            ambient_occlusion: false,
            lod_enabled: true,
            culling_enabled: true,
            resolution_scale: 0.5, // 50% da resolução
        }
    }

    // Preset: Baixo (para PCs fracos)
    pub fn low() -> Self {
        Self {
            quality: GraphicsQuality::Low,
            vsync: false,
            target_fps: 60,
            render_distance: 40.0,
            shadow_quality: 1,
            particle_limit: 100,
            texture_quality: 1,
            anti_aliasing: false,
            post_processing: false,
            bloom: false,
            motion_blur: false,
            ambient_occlusion: false,
            lod_enabled: true,
            culling_enabled: true,
            resolution_scale: 0.75, // 75% da resolução
        }
    }

    // Preset: Médio (balanceado)
    pub fn medium() -> Self {
        Self {
            quality: GraphicsQuality::Medium,
            vsync: true,
            target_fps: 60,
            render_distance: 60.0,
            shadow_quality: 2,
            particle_limit: 200,
            texture_quality: 2,
            anti_aliasing: false,
            post_processing: true,
            bloom: false,
            motion_blur: false,
            ambient_occlusion: false,
            lod_enabled: true,
            culling_enabled: true,
            resolution_scale: 1.0, // 100% da resolução
        }
    }

    // Preset: Alto (para PCs bons)
    pub fn high() -> Self {
        Self {
            quality: GraphicsQuality::High,
            vsync: true,
            target_fps: 60,
            render_distance: 100.0,
            shadow_quality: 3,
            particle_limit: 500,
            texture_quality: 3,
            anti_aliasing: true,
            post_processing: true,
            bloom: true,
            motion_blur: false,
            ambient_occlusion: true,
            lod_enabled: true,
            culling_enabled: true,
            resolution_scale: 1.0,
        }
    }

    // Preset: Ultra (máxima qualidade)
    pub fn ultra() -> Self {
        Self {
            quality: GraphicsQuality::Ultra,
            vsync: true,
            target_fps: 120,
            render_distance: 200.0,
            shadow_quality: 4,
            particle_limit: 1000,
            texture_quality: 4,
            anti_aliasing: true,
            post_processing: true,
            bloom: true,
            motion_blur: true,
            ambient_occlusion: true,
            lod_enabled: false, // Sem LOD em ultra
            culling_enabled: true,
            resolution_scale: 1.0,
        }
    }

    // Aplica preset baseado na qualidade
    pub fn apply_preset(&mut self, quality: GraphicsQuality) {
        *self = match quality {
            GraphicsQuality::VeryLow => Self::very_low(),
            GraphicsQuality::Low => Self::low(),
            GraphicsQuality::Medium => Self::medium(),
            GraphicsQuality::High => Self::high(),
            GraphicsQuality::Ultra => Self::ultra(),
        };
    }

    // Salva configurações em arquivo
    pub fn save(&self, path: &str) -> Result<(), Box<dyn std::error::Error>> {
        let json = serde_json::to_string_pretty(self)?;
        std::fs::write(path, json)?;
        Ok(())
    }

    // Carrega configurações de arquivo
    pub fn load(path: &str) -> Result<Self, Box<dyn std::error::Error>> {
        let json = std::fs::read_to_string(path)?;
        let settings = serde_json::from_str(&json)?;
        Ok(settings)
    }

    // Detecta automaticamente a melhor qualidade baseado no FPS
    pub fn auto_detect(current_fps: f32) -> GraphicsQuality {
        if current_fps >= 120.0 {
            GraphicsQuality::Ultra
        } else if current_fps >= 60.0 {
            GraphicsQuality::High
        } else if current_fps >= 45.0 {
            GraphicsQuality::Medium
        } else if current_fps >= 30.0 {
            GraphicsQuality::Low
        } else {
            GraphicsQuality::VeryLow
        }
    }

    // Ajusta dinamicamente baseado no FPS
    pub fn dynamic_adjust(&mut self, current_fps: f32) {
        if current_fps < 25.0 && self.quality != GraphicsQuality::VeryLow {
            // FPS muito baixo, reduz qualidade
            let new_quality = GraphicsQuality::from_index(self.quality.to_index().saturating_sub(1));
            self.apply_preset(new_quality);
        } else if current_fps > 70.0 && self.quality != GraphicsQuality::Ultra {
            // FPS alto, pode aumentar qualidade
            let new_quality = GraphicsQuality::from_index((self.quality.to_index() + 1).min(4));
            self.apply_preset(new_quality);
        }
    }

    // Retorna o limite de partículas baseado na qualidade
    pub fn get_particle_limit(&self) -> usize {
        self.particle_limit
    }

    // Retorna a distância de renderização
    pub fn get_render_distance(&self) -> f32 {
        self.render_distance
    }

    // Verifica se deve usar LOD
    pub fn should_use_lod(&self) -> bool {
        self.lod_enabled
    }

    // Verifica se deve usar culling
    pub fn should_use_culling(&self) -> bool {
        self.culling_enabled
    }

    // Retorna o fator de escala de resolução
    pub fn get_resolution_scale(&self) -> f32 {
        self.resolution_scale
    }
}

// Sistema de otimização automática
pub struct PerformanceMonitor {
    fps_history: Vec<f32>,
    max_history: usize,
    last_adjustment: f32,
    adjustment_cooldown: f32,
}

impl PerformanceMonitor {
    pub fn new() -> Self {
        Self {
            fps_history: Vec::new(),
            max_history: 60, // 1 segundo de histórico a 60 FPS
            last_adjustment: 0.0,
            adjustment_cooldown: 5.0, // 5 segundos entre ajustes
        }
    }

    pub fn update(&mut self, fps: f32, elapsed_time: f32) {
        self.fps_history.push(fps);
        if self.fps_history.len() > self.max_history {
            self.fps_history.remove(0);
        }
        self.last_adjustment += elapsed_time;
    }

    pub fn average_fps(&self) -> f32 {
        if self.fps_history.is_empty() {
            return 60.0;
        }
        self.fps_history.iter().sum::<f32>() / self.fps_history.len() as f32
    }

    pub fn should_adjust(&self) -> bool {
        self.last_adjustment >= self.adjustment_cooldown && self.fps_history.len() >= self.max_history
    }

    pub fn reset_adjustment_timer(&mut self) {
        self.last_adjustment = 0.0;
    }

    pub fn is_stable(&self) -> bool {
        if self.fps_history.len() < 10 {
            return false;
        }
        let avg = self.average_fps();
        let variance: f32 = self.fps_history.iter()
            .map(|fps| (fps - avg).powi(2))
            .sum::<f32>() / self.fps_history.len() as f32;
        variance < 100.0 // Variância baixa = estável
    }
}

// Configurações de otimização específicas
#[derive(Debug, Clone)]
pub struct OptimizationSettings {
    pub batch_rendering: bool,
    pub frustum_culling: bool,
    pub occlusion_culling: bool,
    pub texture_streaming: bool,
    pub mesh_simplification: bool,
    pub dynamic_lod: bool,
    pub particle_pooling: bool,
    pub shader_caching: bool,
}

impl OptimizationSettings {
    pub fn for_quality(quality: GraphicsQuality) -> Self {
        match quality {
            GraphicsQuality::VeryLow => Self {
                batch_rendering: true,
                frustum_culling: true,
                occlusion_culling: true,
                texture_streaming: true,
                mesh_simplification: true,
                dynamic_lod: true,
                particle_pooling: true,
                shader_caching: true,
            },
            GraphicsQuality::Low => Self {
                batch_rendering: true,
                frustum_culling: true,
                occlusion_culling: true,
                texture_streaming: true,
                mesh_simplification: true,
                dynamic_lod: true,
                particle_pooling: true,
                shader_caching: true,
            },
            GraphicsQuality::Medium => Self {
                batch_rendering: true,
                frustum_culling: true,
                occlusion_culling: false,
                texture_streaming: true,
                mesh_simplification: false,
                dynamic_lod: true,
                particle_pooling: true,
                shader_caching: true,
            },
            GraphicsQuality::High => Self {
                batch_rendering: true,
                frustum_culling: true,
                occlusion_culling: false,
                texture_streaming: false,
                mesh_simplification: false,
                dynamic_lod: true,
                particle_pooling: false,
                shader_caching: true,
            },
            GraphicsQuality::Ultra => Self {
                batch_rendering: false,
                frustum_culling: true,
                occlusion_culling: false,
                texture_streaming: false,
                mesh_simplification: false,
                dynamic_lod: false,
                particle_pooling: false,
                shader_caching: true,
            },
        }
    }
}