diff --git a/CtrEditor.csproj b/CtrEditor.csproj index 014de43..acafe06 100644 --- a/CtrEditor.csproj +++ b/CtrEditor.csproj @@ -20,6 +20,7 @@ + @@ -64,6 +65,7 @@ + diff --git a/Icons/duplicate.png b/Icons/duplicate.png new file mode 100644 index 0000000..51669f8 Binary files /dev/null and b/Icons/duplicate.png differ diff --git a/MainViewModel.cs b/MainViewModel.cs index 669bdc4..8b898b6 100644 --- a/MainViewModel.cs +++ b/MainViewModel.cs @@ -58,7 +58,9 @@ namespace CtrEditor public ICommand TBDisconnectPLCCommand { get; } public ICommand TBEliminarUserControlCommand { get; } + public ICommand TBDuplicarUserControlCommand { get; } + public ICommand OpenWorkDirectoryCommand { get; } // Evento que se dispara cuando se selecciona una nueva imagen @@ -246,6 +248,7 @@ namespace CtrEditor TBDisconnectPLCCommand = new RelayCommand(DisconnectPLC, () => IsConnected); TBEliminarUserControlCommand = new RelayCommand(EliminarUserControl, () => habilitarEliminarUserControl); + TBDuplicarUserControlCommand = new RelayCommand(DuplicarUserControl, () => habilitarEliminarUserControl); stopwatch_PLCRefresh = new Stopwatch(); stopwatch_SimRefresh = new Stopwatch(); @@ -320,6 +323,45 @@ namespace CtrEditor } } + private void DuplicarUserControl() + { + if (SelectedItemOsList is osBase objDuplicar) + { + StopSimulation(); + DisconnectPLC(); + + objDuplicar.SalvarDatosNoSerializables(); + + var settings = new JsonSerializerSettings + { + Formatting = Formatting.Indented, + NullValueHandling = NullValueHandling.Ignore, + TypeNameHandling = TypeNameHandling.All + }; + + try + { + // Serializar + var serializedData = JsonConvert.SerializeObject(objDuplicar, settings); + // Duplicar + var NuevoObjetoDuplicado = JsonConvert.DeserializeObject(serializedData, settings); + if (NuevoObjetoDuplicado != null) + { + NuevoObjetoDuplicado.Nombre += "_Duplicado"; + ObjetosSimulables.Add(NuevoObjetoDuplicado); + CrearUserControlDesdeObjetoSimulable(NuevoObjetoDuplicado); + } + } + catch + { + // Log error or handle it accordingly + } + finally { + objDuplicar.RestaurarDatosNoSerializables(); + } + } + } + private void EliminarUserControl() { if (SelectedItemOsList is osBase objEliminar) @@ -458,25 +500,21 @@ namespace CtrEditor if (_selectedImage != null) { StopSimulation(); - PLCViewModel.Disconnect(); + DisconnectPLC(); - // Crear copias temporales de las propiedades que serán anuladas - var tempVisualRepresentations = new Dictionary(); - var tempSimulationManagers = new Dictionary(); - var tempMainViewModels = new Dictionary(); + // Ruta del archivo a ser guardado + var path = datosDeTrabajo.ObtenerPathImagenConExtension(_selectedImage, ".json"); + + // Verificar si el archivo ya existe y crear un respaldo + if (File.Exists(path)) + { + var backupPath = Path.ChangeExtension(path, ".bak"); + File.Copy(path, backupPath, true); // Copia el archivo existente a un nuevo archivo .bak, sobrescribiendo si es necesario + } foreach (var obj in ObjetosSimulables) - { // Guardar referencias temporales - tempVisualRepresentations[obj] = obj.VisualRepresentation; - tempSimulationManagers[obj] = obj.simulationManager; - tempMainViewModels[obj] = obj._mainViewModel; - - // Anular propiedades para la serialización - obj.VisualRepresentation = null; - obj.simulationManager = null; - obj._mainViewModel = null; - } + obj.SalvarDatosNoSerializables(); var settings = new JsonSerializerSettings { @@ -495,26 +533,20 @@ namespace CtrEditor // Serializar var serializedData = JsonConvert.SerializeObject(dataToSerialize, settings); - File.WriteAllText(datosDeTrabajo.ObtenerPathImagenConExtension(_selectedImage, ".json"), serializedData); + File.WriteAllText(path, serializedData); // Escribir el nuevo archivo JSON // Restaurar las propiedades originales de los objetos foreach (var obj in ObjetosSimulables) - { - obj.VisualRepresentation = tempVisualRepresentations[obj]; - obj.simulationManager = tempSimulationManagers[obj]; - obj._mainViewModel = tempMainViewModels[obj]; - } + obj.RestaurarDatosNoSerializables(); } } - - public void LoadStateObjetosSimulables() { try { StopSimulation(); - PLCViewModel.Disconnect(); + DisconnectPLC(); ObjetosSimulables.Clear(); simulationManager.Clear(); if (_selectedImage != null) diff --git a/MainWindow.xaml b/MainWindow.xaml index 74aa1f3..1adaa0e 100644 --- a/MainWindow.xaml +++ b/MainWindow.xaml @@ -54,8 +54,8 @@ - - + + @@ -177,6 +177,12 @@ + diff --git a/ObjetosSim/UserControls/ucFiller.xaml.cs b/ObjetosSim/UserControls/ucFiller.xaml.cs index af5ef81..7ff7e0f 100644 --- a/ObjetosSim/UserControls/ucFiller.xaml.cs +++ b/ObjetosSim/UserControls/ucFiller.xaml.cs @@ -207,18 +207,40 @@ namespace CtrEditor.ObjetosSim { TiempoRestante = 3600 / (Botellas_hora * (Velocidad_actual_percentual / 100.0f)); - var UltimaBotellla = GetLastElement(Botellas); - if (UltimaBotellla == null || (UltimaBotellla != null && !(UltimaBotellla.Left == Left && UltimaBotellla.Top == Top))) + var X = Left + OffsetLeftSalida; + var Y = Top + OffsetTopSalida; + + var UltimaBotella = GetLastElement(Botellas); + if (UltimaBotella == null) { - var Botella = _mainViewModel.CrearObjetoSimulable(typeof(osBotella), Left + OffsetLeftSalida, Top + OffsetTopSalida); - Botella.AutoCreated = true; - Botellas.Add((osBotella)Botella); + // No hay botellas, se puede crear una nueva directamente + var nuevaBotella = _mainViewModel.CrearObjetoSimulable(typeof(osBotella), X, Y); + ((osBotella)nuevaBotella).Diametro = Diametro_botella; + nuevaBotella.AutoCreated = true; + Botellas.Add((osBotella)nuevaBotella); + } + else + { + // Calcular la distancia entre el centro de la última botella y la nueva posición + float distancia = (float)Math.Sqrt(Math.Pow(UltimaBotella.Left - X, 2) + Math.Pow(UltimaBotella.Top - Y, 2)); + float distanciaMinima = Diametro_botella / 2; // Asumiendo que el diámetro de la nueva botella es similar + + if (distancia > distanciaMinima) + { + var nuevaBotella = _mainViewModel.CrearObjetoSimulable(typeof(osBotella), X, Y); + ((osBotella)nuevaBotella).Diametro = Diametro_botella; + nuevaBotella.AutoCreated = true; + Botellas.Add((osBotella)nuevaBotella); + } } } } else + { TiempoRestante = 0; + } } + public override void ucLoaded() { // El UserControl ya se ha cargado y podemos obtener las coordenadas para diff --git a/ObjetosSim/osBase.cs b/ObjetosSim/osBase.cs index 34e5c4c..b10e2cc 100644 --- a/ObjetosSim/osBase.cs +++ b/ObjetosSim/osBase.cs @@ -19,6 +19,7 @@ using Microsoft.Xna.Framework; using FarseerPhysics.Dynamics; using Siemens.Simatic.Simulation.Runtime; using System.Windows.Media.Imaging; +using System.Windows.Input; namespace CtrEditor.ObjetosSim { @@ -41,6 +42,28 @@ namespace CtrEditor.ObjetosSim int ZIndex(); } + public class DataSaveToSerialize + { + private MainViewModel? _mainViewModel; + private UserControl? VisualRepresentation; + private SimulationManagerFP? simulationManager; + + public DataSaveToSerialize(MainViewModel a, UserControl b, SimulationManagerFP c ) + { + _mainViewModel = a; + VisualRepresentation = b; + simulationManager = c; + } + + public void DataRestoreAfterSerialize(out MainViewModel a, out UserControl b, out SimulationManagerFP c) + { + a = _mainViewModel; + b = VisualRepresentation; + c = simulationManager; + } + } + + public abstract class osBase : INotifyPropertyChanged { public virtual string Nombre { get; set; } = "osBase"; @@ -52,6 +75,9 @@ namespace CtrEditor.ObjetosSim public bool AutoCreated = false; public bool RemoverDesdeSimulacion = false; // La simulacion indica que se debe remover + [JsonIgnore] + private DataSaveToSerialize DataSave; + [JsonIgnore] protected UserControl? _visualRepresentation = null; @@ -74,6 +100,19 @@ namespace CtrEditor.ObjetosSim [JsonIgnore] public SimulationManagerFP simulationManager; + public void SalvarDatosNoSerializables() + { + DataSave = new DataSaveToSerialize(_mainViewModel,_visualRepresentation,simulationManager); + _mainViewModel = null; + _visualRepresentation = null; + simulationManager = null; + } + public void RestaurarDatosNoSerializables() + { + if (DataSave == null) return; + DataSave.DataRestoreAfterSerialize(out _mainViewModel,out _visualRepresentation,out simulationManager); + } + protected osBase ObtenerLink(string NameLink, Type tipoOsBase) { if (!string.IsNullOrEmpty(NameLink) && _mainViewModel != null)