using System; using System.Diagnostics; using System.Windows.Threading; using CommunityToolkit.Mvvm.ComponentModel; using CtrEditor.Simulacion.Fluids; using nkast.Aether.Physics2D.Common; using CtrEditor.ObjetosSim; namespace CtrEditor { /// /// ViewModel para controlar la simulación de fluidos de forma independiente /// public partial class SimulationFluidsViewModel : ObservableObject { private MainViewModel _mainViewModel; private readonly DispatcherTimer _timerSimulacionFluidos; private Stopwatch _stopwatch; private double _lastUpdateTime; // Propiedades observables [ObservableProperty] private bool isFluidSimulationRunning; [ObservableProperty] private float fps; [ObservableProperty] private int particulasCount; /// /// Constructor /// /// Referencia al ViewModel principal public SimulationFluidsViewModel(MainViewModel mainViewModel) { _mainViewModel = mainViewModel; // Inicializar timer para simulación de fluidos _timerSimulacionFluidos = new DispatcherTimer(); _timerSimulacionFluidos.Interval = TimeSpan.FromMilliseconds(16); // ~60fps _timerSimulacionFluidos.Tick += OnTickSimulacionFluidos; _stopwatch = new Stopwatch(); _stopwatch.Start(); } /// /// Inicia la simulación de fluidos /// public void StartFluidSimulation() { if (IsFluidSimulationRunning) return; IsFluidSimulationRunning = true; // Notificar a todos los objetos que usan fluidos que inicie su simulación foreach (var objetoSimulable in _mainViewModel.ObjetosSimulables) { if (objetoSimulable is osSistemaFluidos sistemaFluidos) { sistemaFluidos.UpdateGeometryStart(); } } _lastUpdateTime = _stopwatch.Elapsed.TotalMilliseconds; _timerSimulacionFluidos.Start(); } /// /// Detiene la simulación de fluidos /// public void StopFluidSimulation() { if (!IsFluidSimulationRunning) return; IsFluidSimulationRunning = false; _timerSimulacionFluidos.Stop(); // Notificar a todos los objetos que usan fluidos que detenga su simulación foreach (var objetoSimulable in _mainViewModel.ObjetosSimulables) { if (objetoSimulable is osSistemaFluidos sistemaFluidos) { sistemaFluidos.SimulationStop(); } } } /// /// Evento que se dispara cada tick de la simulación de fluidos /// private void OnTickSimulacionFluidos(object sender, EventArgs e) { // Calcular delta time double currentTime = _stopwatch.Elapsed.TotalMilliseconds; float deltaTime = (float)(currentTime - _lastUpdateTime) / 1000.0f; // convertir a segundos _lastUpdateTime = currentTime; int totalParticleCount = 0; // Actualizar todos los sistemas de fluidos foreach (var objetoSimulable in _mainViewModel.ObjetosSimulables) { if (objetoSimulable is osSistemaFluidos sistemaFluidos && sistemaFluidos.Show_On_This_Page) { // Actualizar la simulación con el deltaTime calculado if (sistemaFluidos._simFluidos != null) { sistemaFluidos._simFluidos.Actualizar(deltaTime); totalParticleCount += sistemaFluidos._simFluidos.ParticlesCount; } // Actualizar controles visuales sistemaFluidos.UpdateControl((int)(deltaTime * 1000)); } } // Actualizar estadísticas Fps = 1.0f / Math.Max(deltaTime, 0.001f); ParticulasCount = totalParticleCount; } } }