From b8d3c953e623eee1b038df2ba5dc1563d2037ba0 Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 13 Jun 2025 19:52:43 +0200 Subject: [PATCH] =?UTF-8?q?Actualizaci=C3=B3n=20de=20la=20simulaci=C3=B3n?= =?UTF-8?q?=20de=20fluidos:=20se=20han=20agregado=20nuevos=20comandos=20pa?= =?UTF-8?q?ra=20iniciar=20y=20detener=20la=20simulaci=C3=B3n=20de=20fluido?= =?UTF-8?q?s,=20as=C3=AD=20como=20m=C3=A9todos=20para=20manejar=20su=20ini?= =?UTF-8?q?cio,=20detenci=C3=B3n=20y=20actualizaci=C3=B3n.=20Se=20han=20mo?= =?UTF-8?q?dificado=20las=20referencias=20de=20Emgu.CV=20a=20una=20versi?= =?UTF-8?q?=C3=B3n=20anterior=20y=20se=20han=20realizado=20ajustes=20en=20?= =?UTF-8?q?los=20archivos=20XAML=20para=20reflejar=20cambios=20en=20los=20?= =?UTF-8?q?espacios=20de=20nombres.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CtrEditor.csproj | 6 +- Icons/fluid.svg | 9 ++ MainViewModel.cs | 48 ++++++-- ObjetosSim/osSistemaFluidos.cs | 33 +++++ ObjetosSim/ucTuberiaFluido.xaml | 9 +- ObjetosSim/ucValvulaFluido.xaml | 4 +- Simulacion/FluidSimulationManager.cs | 177 +++++++++++++++++++++++++++ SimulationFluidsViewModel.cs | 126 +++++++++++++++++++ 8 files changed, 394 insertions(+), 18 deletions(-) create mode 100644 Icons/fluid.svg create mode 100644 Simulacion/FluidSimulationManager.cs create mode 100644 SimulationFluidsViewModel.cs diff --git a/CtrEditor.csproj b/CtrEditor.csproj index f3ac5a4..0ee2c26 100644 --- a/CtrEditor.csproj +++ b/CtrEditor.csproj @@ -80,9 +80,9 @@ - - - + + + diff --git a/Icons/fluid.svg b/Icons/fluid.svg new file mode 100644 index 0000000..a80b99e --- /dev/null +++ b/Icons/fluid.svg @@ -0,0 +1,9 @@ + + + Fluid + + + + + + diff --git a/MainViewModel.cs b/MainViewModel.cs index 6b976a5..e3342b8 100644 --- a/MainViewModel.cs +++ b/MainViewModel.cs @@ -1,4 +1,5 @@ -using System.ComponentModel; +using CtrEditor; +using System.ComponentModel; using System.Windows.Controls; using System.Windows.Input; using Ookii.Dialogs.Wpf; @@ -83,8 +84,12 @@ namespace CtrEditor public ICommand StopSimulationCommand { get; } public ICommand ItemDoubleClickCommand { get; private set; } + public SimulationFluidsViewModel FluidSimulation { get; private set; } + public ICommand TBStartSimulationCommand { get; } public ICommand TBStopSimulationCommand { get; } + public ICommand TBStartFluidSimulationCommand { get; } + public ICommand TBStopFluidSimulationCommand { get; } public ICommand TBSaveCommand { get; } public ICommand TBExtractTagsCommand { get; } @@ -358,6 +363,11 @@ namespace CtrEditor TBStartSimulationCommand = new RelayCommand(StartSimulation, () => !IsSimulationRunning); TBStopSimulationCommand = new RelayCommand(StopSimulation, () => IsSimulationRunning); + + // Inicializar simulación de fluidos + FluidSimulation = new SimulationFluidsViewModel(this); + TBStartFluidSimulationCommand = new RelayCommand(StartFluidSimulation, () => !FluidSimulation.IsFluidSimulationRunning); + TBStopFluidSimulationCommand = new RelayCommand(StopFluidSimulation, () => FluidSimulation.IsFluidSimulationRunning); TBSaveCommand = new RelayCommand(Save); TBEliminarUserControlCommand = new RelayCommand(EliminarUserControl, () => habilitarEliminarUserControl); @@ -749,7 +759,10 @@ namespace CtrEditor private void StartSimulation() { - IsSimulationRunning = true; + // Detener simulación de fluidos si está ejecutándose + StopFluidSimulation(); + + IsSimulationRunning = true; // Ocultar rectángulos de selección antes de iniciar la simulación _objectManager.UpdateSelectionVisuals(); @@ -776,12 +789,33 @@ namespace CtrEditor { simulationManager.Debug_ClearSimulationShapes(); Debug_SimulacionCreado = false; - } - _timerSimulacion.Stop(); + } + _timerSimulacion.Stop(); - // Restaurar los rectángulos de selección si hay objetos seleccionados - _objectManager.UpdateSelectionVisuals(); - } + // Restaurar los rectángulos de selección si hay objetos seleccionados + _objectManager.UpdateSelectionVisuals(); + } + + /// + /// Inicia la simulación de fluidos independiente + /// + public void StartFluidSimulation() + { + // Detener simulación física si está ejecutándose + StopSimulation(); + + FluidSimulation.StartFluidSimulation(); + CommandManager.InvalidateRequerySuggested(); + } + + /// + /// Detiene la simulación de fluidos independiente + /// + public void StopFluidSimulation() + { + FluidSimulation.StopFluidSimulation(); + CommandManager.InvalidateRequerySuggested(); + } private void OnTickSimulacion(object sender, EventArgs e) { diff --git a/ObjetosSim/osSistemaFluidos.cs b/ObjetosSim/osSistemaFluidos.cs index 5456730..a01042f 100644 --- a/ObjetosSim/osSistemaFluidos.cs +++ b/ObjetosSim/osSistemaFluidos.cs @@ -223,6 +223,39 @@ namespace CtrEditor.ObjetosSim } } + /// + /// Llamado cuando se inicia la simulación de fluidos + /// + public void OnFluidSimulationStart() + { + // Crear la simulación de fluidos si es necesario + UpdateGeometryStart(); + } + + /// + /// Llamado cuando se detiene la simulación de fluidos + /// + public void OnFluidSimulationStop() + { + // Detener recursos si es necesario + SimulationStop(); + } + + /// + /// Actualiza la simulación de fluidos + /// + public void UpdateFluidSimulation(float deltaTime) + { + // Actualizar la simulación con el delta time + if (_simFluidos != null) + { + _simFluidos.Actualizar(deltaTime); + + // Actualizar el control visual + UpdateControl((int)(deltaTime * 1000)); + } + } + public override void SimulationStop() { // Limpiar recursos si es necesario cuando se detiene la simulación diff --git a/ObjetosSim/ucTuberiaFluido.xaml b/ObjetosSim/ucTuberiaFluido.xaml index cf5e2d7..9582049 100644 --- a/ObjetosSim/ucTuberiaFluido.xaml +++ b/ObjetosSim/ucTuberiaFluido.xaml @@ -1,16 +1,15 @@ + xmlns:local="clr-namespace:CtrEditor.ObjetosSim" + xmlns:ctr="clr-namespace:CtrEditor"> - + + xmlns:local="clr-namespace:CtrEditor.ObjetosSim"> - + diff --git a/Simulacion/FluidSimulationManager.cs b/Simulacion/FluidSimulationManager.cs new file mode 100644 index 0000000..41bd12d --- /dev/null +++ b/Simulacion/FluidSimulationManager.cs @@ -0,0 +1,177 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using nkast.Aether.Physics2D.Common; +using CtrEditor.Simulacion.Fluids; +using CtrEditor.ObjetosSim; + +namespace CtrEditor.Simulacion +{ + /// + /// Gestor para la simulación de fluidos independiente de la simulación física principal + /// + public class FluidSimulationManager + { + private SimulacionFluidos _simulacion; + private readonly List _deferredActions = new List(); + private readonly List _sistemasRegistrados = new List(); + private float _defaultWidth = 10.0f; + private float _defaultHeight = 10.0f; + + private bool _isRunning = false; + private Stopwatch _stopwatch; + private double _lastUpdateTime; + + public bool IsRunning => _isRunning; + + /// + /// Constructor + /// + public FluidSimulationManager() + { + _stopwatch = new Stopwatch(); + } + + /// + /// Inicializa la simulación de fluidos + /// + public void Initialize() + { + if (_simulacion == null) + { + _simulacion = new SimulacionFluidos( + _defaultWidth, + _defaultHeight, + 10000, // max partículas + new Vector2(0, 9.8f) // gravedad por defecto + ); + } + } + + /// + /// Inicia la simulación de fluidos + /// + public void Start() + { + if (!_isRunning) + { + _isRunning = true; + _stopwatch.Start(); + _lastUpdateTime = _stopwatch.Elapsed.TotalMilliseconds; + + // Notificar a los sistemas de fluidos + foreach (var sistema in _sistemasRegistrados) + { + sistema.OnFluidSimulationStart(); + } + } + } + + /// + /// Detiene la simulación de fluidos + /// + public void Stop() + { + if (_isRunning) + { + _isRunning = false; + _stopwatch.Stop(); + _stopwatch.Reset(); + + // Notificar a los sistemas de fluidos + foreach (var sistema in _sistemasRegistrados) + { + sistema.OnFluidSimulationStop(); + } + } + } + + /// + /// Actualiza un paso de la simulación de fluidos + /// + public void Step() + { + if (!_isRunning) return; + + // Calcular delta time + double currentTime = _stopwatch.Elapsed.TotalMilliseconds; + float deltaTime = (float)(currentTime - _lastUpdateTime) / 1000.0f; + _lastUpdateTime = currentTime; + + // Asegurar que deltaTime no es demasiado grande (evita inestabilidades) + if (deltaTime > 0.05f) deltaTime = 0.05f; + + // Procesar acciones diferidas + foreach (var action in _deferredActions) + { + action(); + } + _deferredActions.Clear(); + + // Actualizar la simulación + _simulacion?.Actualizar(deltaTime); + + // Notificar a los sistemas de fluidos + foreach (var sistema in _sistemasRegistrados) + { + sistema.UpdateFluidSimulation(deltaTime); + } + } + + /// + /// Registra un sistema de fluidos para ser actualizado + /// + public void RegisterFluidSystem(osSistemaFluidos sistema) + { + if (!_sistemasRegistrados.Contains(sistema)) + { + _sistemasRegistrados.Add(sistema); + + // Si el sistema ya está corriendo, notificar al nuevo sistema + if (_isRunning) + { + sistema.OnFluidSimulationStart(); + } + } + } + + /// + /// Elimina un sistema de fluidos del registro + /// + public void UnregisterFluidSystem(osSistemaFluidos sistema) + { + _sistemasRegistrados.Remove(sistema); + } + + /// + /// Añade una acción para ser ejecutada en el próximo paso de simulación + /// + public void AddDeferredAction(Action action) + { + _deferredActions.Add(action); + } + + /// + /// Obtiene la instancia de simulación de fluidos + /// + public SimulacionFluidos GetSimulacion() + { + if (_simulacion == null) + { + Initialize(); + } + return _simulacion; + } + + /// + /// Limpia los recursos de la simulación + /// + public void Clear() + { + Stop(); + _simulacion = null; + _sistemasRegistrados.Clear(); + _deferredActions.Clear(); + } + } +} diff --git a/SimulationFluidsViewModel.cs b/SimulationFluidsViewModel.cs new file mode 100644 index 0000000..21f3a60 --- /dev/null +++ b/SimulationFluidsViewModel.cs @@ -0,0 +1,126 @@ +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; + } + } +}