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 @@
+
+
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;
+ }
+ }
+}