Compare commits

..

No commits in common. "256d86aca58acea835a45d88038a777b18b0d806" and "75c507be4e5ba0499d6fc71e8cbcc6f0260d99f8" have entirely different histories.

49 changed files with 499 additions and 2829 deletions

View File

@ -22,12 +22,6 @@
<local:SubclassFilterConverter x:Key="SubclassFilterConverterosVMMotor" TargetType="{x:Type os:osVMmotorSim}" />
<local:UnsavedChangesConverter x:Key="UnsavedChangesConverter"/>
<local:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<!-- Estilo global para TreeViewItem para evitar errores de binding -->
<Style TargetType="TreeViewItem">
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
</Style>
</Application.Resources>
</Application>

View File

@ -18,7 +18,6 @@
</PropertyGroup>
<ItemGroup>
<Compile Remove="Documentation\PlantillaEstandarizacion.cs" />
<Compile Remove="ObjetosSim\ucBasicExample.xaml.cs" />
<Compile Remove="ObjetosSim\ucTransporteCurva.xaml.cs" />
<Compile Remove="Simulacion\FPhysics.cs" />
@ -71,7 +70,6 @@
</ItemGroup>
<ItemGroup>
<None Include="Documentation\PlantillaEstandarizacion.cs" />
<None Include="ObjetosSim\ucBasicExample.xaml" />
<None Include="ObjetosSim\ucBasicExample.xaml.cs" />
<None Include="Simulacion\FPhysics.cs" />
@ -87,9 +85,8 @@
<PackageReference Include="Emgu.CV.UI" Version="4.9.0.5494" />
<PackageReference Include="Extended.Wpf.Toolkit" Version="4.7.25104.5739" />
<PackageReference Include="LanguageDetection" Version="1.2.0" />
<PackageReference Include="LiveChartsCore.SkiaSharpView.WPF" Version="2.0.0-rc3.3" />
<PackageReference Include="LiveChartsCore.SkiaSharpView.WPF" Version="2.0.0-rc4.5" />
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.135" />
<PackageReference Include="SkiaSharp.Views.WPF" Version="2.88.8" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Ookii.Dialogs.Wpf" Version="5.0.1" />
<PackageReference Include="PaddleOCRSharp" Version="4.5.0.1" />

View File

@ -1,145 +0,0 @@
# Estandarización de Objetos derivados de osBase
## Criterios para NombreClase()
### Categorías de Objetos:
1. **Transporte**: Transportadores, cintas, curvas
2. **Sensores**: Fotocélulas, encoders, botones
3. **Actuadores**: Motores, válvulas
4. **Elementos Estáticos**: Guías, descartes, barreras
5. **Emuladores**: Generadores, llenadores, tanques
6. **Señales**: Tags analógicos, digitales
7. **Datos**: Extracción, búsqueda
8. **Decorativos**: Imágenes, marcos, textos
9. **Fluidos**: Tuberías, válvulas, sistemas
### Formato de Nombres:
- **Español**: Usar nombres descriptivos en español
- **Específico**: Incluir característica principal (ej: "Motor VetroMeccanica", "Transporte con Guías")
- **Consistente**: Mantener formato similar por categoría
## Categorías Estandarizadas para Propiedades
### 1. "Identificación"
- Nombre del objeto
- Etiquetas de clasificación
### 2. "Posición y Tamaño"
- Coordenadas (Left, Top)
- Dimensiones (Ancho, Alto, Ángulo)
- Bloqueo de movimiento
### 3. "Configuración"
- Parámetros principales del objeto
- Configuraciones específicas por tipo
### 4. "Simulación"
- Velocidades, fuerzas, coeficientes
- Parámetros físicos
### 5. "Enlace PLC"
- Tags de entrada y salida
- Conexiones con motores/sensores
### 6. "Información"
- Valores calculados
- Estados actuales
- Datos de depuración
### 7. "Apariencia"
- Colores, tamaños visuales
- Aspectos gráficos
## Ejemplos de Aplicación
### Motor VetroMeccanica:
```csharp
[ObservableProperty]
[property: Description("Velocidad actual del motor en Hz")]
[property: Category("Información")]
[property: Name("Velocidad Actual")]
public float velocidad;
[ObservableProperty]
[property: Description("Tiempo de rampa para acelerar/desacelerar")]
[property: Category("Configuración")]
[property: Name("Tiempo de Rampa")]
public float tiempoRampa;
```
### Fotocélula:
```csharp
[ObservableProperty]
[property: Description("Indica si la luz está cortada por un objeto")]
[property: Category("Información")]
[property: Name("Luz Cortada")]
bool luzCortada;
[ObservableProperty]
[property: Description("Ancho del haz de luz del sensor")]
[property: Category("Configuración")]
[property: Name("Ancho del Haz")]
float ancho_Haz_De_Luz;
```
## Plan de Implementación
### ✅ Fase 1: Estandarizar métodos `NombreClase()`
- [x] Crear mapeo de nombres descriptivos
- [x] Implementar ejemplos: TransporteTTop, Motor VetroMeccanica, Fotocélula, Tag Analógico
- [x] Generar script de automatización PowerShell
### ✅ Fase 2: Aplicar categorías y descripciones estándar
- [x] Definir 8 categorías estándar
- [x] Crear plantilla de implementación
- [x] Aplicar en objetos de ejemplo
### ✅ Fase 3: Implementación Clase por Clase (COMPLETADO)
- [x] **ucTransporteTTop** - Transporte TTOP
- [x] **ucVMmotorSim** - Motor VetroMeccanica
- [x] **ucPhotocell** - Fotocélula
- [x] **ucAnalogTag** - Tag Analógico
- [x] **ucCustomImage** - Imagen Personalizada
- [x] **ucBoolTag** - Tag Digital
- [x] **ucGuia** - Guía
- [x] **ucBotella** - Botella
- [x] **ucTransporteCurva** - Transporte Curva 90°
- [x] **ucBoton** - Botón
- [x] **ucBottGenerator** - Generador de Botellas
- [x] **ucDescarte** - Descarte
- [x] **ucFramePlate** - Marco de Panel (parcial)
### 📊 Estadísticas de Progreso
- **Clases procesadas**: 13
- **`using System.ComponentModel;` agregados**: 6 clases
- **Nombres de clase mejorados**: 13
- **Propiedades estandarizadas**: ~85 propiedades
## Archivos Generados
1. **`Scripts/EstandarizarObjetos.ps1`**: Script para automatizar cambios
2. **`Documentation/PlantillaEstandarizacion.cs`**: Plantilla con ejemplos
3. **`Documentation/EstandarizacionObjetos.md`**: Esta documentación
## Instrucciones de Uso
### Para aplicar automáticamente:
```powershell
cd CtrEditor
.\Scripts\EstandarizarObjetos.ps1
```
### Para aplicar manualmente:
1. Consultar `PlantillaEstandarizacion.cs`
2. Seguir el patrón de categorías establecido
3. Usar nombres descriptivos en español
## Objetos Ya Actualizados
- ✅ `ucTransporteTTop` → "Transporte TTOP"
- ✅ `ucVMmotorSim` → "Motor VetroMeccanica"
- ✅ `ucPhotocell` → "Fotocélula"
- ✅ `ucAnalogTag` → "Tag Analógico"
---
*Documento generado para estandarización del proyecto CtrEditor*

View File

@ -1,172 +0,0 @@
/*
PLANTILLA DE ESTANDARIZACIÓN PARA OBJETOS osBase
Usar esta plantilla como guía para estandarizar cualquier objeto derivado de osBase
*/
namespace CtrEditor.ObjetosSim
{
public partial class osEjemplo : osBase, IosBase
{
// 1. MÉTODO NOMBRECLASE - Usar nombres descriptivos en español
public static string NombreClase()
{
return "Nombre Descriptivo del Objeto"; // Ej: "Motor VetroMeccanica", "Fotocélula", "Transporte TTOP"
}
private string nombre = NombreClase();
// 2. PROPIEDAD NOMBRE - Siempre en categoría "Identificación"
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
set => SetProperty(ref nombre, value);
}
// 3. CATEGORÍAS ESTÁNDAR:
// IDENTIFICACIÓN - Información básica del objeto
[ObservableProperty]
[property: Category("Identificación")]
[property: Description("Descripción o comentario del objeto")]
[property: Name("Descripción")]
public string descripcion;
// POSICIÓN Y TAMAÑO - Heredadas de osBase (Left, Top, Ancho, Alto, Angulo)
// No necesitan redefinirse, ya están en osBase
// CONFIGURACIÓN - Parámetros principales del objeto
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Velocidad máxima del objeto")]
[property: Name("Velocidad Máxima")]
public float velocidadMaxima;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Habilita/deshabilita funcionalidad específica")]
[property: Name("Habilitar Función")]
public bool habilitarFuncion;
// SIMULACIÓN - Parámetros físicos y de simulación
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Velocidad actual en la simulación")]
[property: Name("Velocidad Actual")]
public float velocidadActual;
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Coeficiente de fricción")]
[property: Name("Coeficiente de Fricción")]
public float coeficienteFriccion;
// ENLACE PLC - Conexiones con PLC y otros objetos
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Dirección del tag en el PLC")]
[property: Name("Tag Principal")]
public string tagPrincipal;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Seleccionar motor para enlazar")]
[property: Name("Motor Enlazado")]
[property: ItemsSource(typeof(osBaseItemsSource<osVMmotorSim>))]
public string motorEnlazado;
// INFORMACIÓN - Valores calculados, estados, debug
[ObservableProperty]
[property: Category("Información")]
[property: Description("Estado actual del objeto")]
[property: Name("Estado")]
public bool estado;
[ObservableProperty]
[property: Category("Información")]
[property: Description("Último valor calculado")]
[property: Name("Último Valor")]
public float ultimoValor;
// APARIENCIA - Aspectos visuales
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Tamaño visual del objeto")]
[property: Name("Tamaño")]
public float tamano;
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Color del objeto")]
[property: Name("Color")]
public Brush color;
// ENCODER - Específico para motores con encoder
[ObservableProperty]
[property: Category("Encoder")]
[property: Description("Habilita el encoder")]
[property: Name("Con Encoder")]
public bool conEncoder;
[ObservableProperty]
[property: Category("Encoder")]
[property: Description("Posición actual del encoder")]
[property: Name("Posición Encoder")]
public float posicionEncoder;
}
}
/*
GUÍA DE CATEGORÍAS:
1. "Identificación"
- Nombre del objeto
- Descripción
- Etiquetas de clasificación
2. "Posición y Tamaño"
- Ya heredadas de osBase: Left, Top, Ancho, Alto, Angulo, Lock_movement
3. "Configuración"
- Parámetros principales del objeto
- Configuraciones específicas por tipo
- Valores que el usuario configura
4. "Simulación"
- Velocidades, fuerzas, coeficientes
- Parámetros físicos
- Comportamiento en simulación
5. "Enlace PLC"
- Tags de entrada y salida
- Conexiones con motores/sensores
- Direcciones de PLC
6. "Información"
- Valores calculados
- Estados actuales
- Datos de depuración
- Información de solo lectura
7. "Apariencia"
- Colores, tamaños visuales
- Aspectos gráficos
- Elementos de UI
8. "Encoder" (solo para motores)
- Configuración del encoder
- Valores del encoder
FORMATO DE DESCRIPCIONES:
- Usar español
- Ser descriptivo y claro
- Explicar qué hace la propiedad
- Evitar términos técnicos innecesarios
FORMATO DE NOMBRES:
- Usar español
- Formato "Título" (primera letra mayúscula)
- Ser conciso pero descriptivo
- Ej: "Velocidad Actual", "Tag Principal", "Con Encoder"
*/

View File

@ -1337,8 +1337,6 @@ namespace CtrEditor
// Mostrar como modeless (no modal)
libraryWindow.Show();
}
}
public class SimulationData

View File

@ -173,8 +173,8 @@ namespace CtrEditor
private void PurgeDeletedObjects()
{
var deletedObjects = _selectedObjects.Where(obj =>
obj.VisualRepresentation == null ||
var deletedObjects = _selectedObjects.Where(obj =>
obj.VisualRepresentation == null ||
!_canvas.Children.Contains(obj.VisualRepresentation)).ToList();
foreach (var obj in deletedObjects)
@ -202,7 +202,7 @@ namespace CtrEditor
PurgeDeletedObjects();
// Asegurarse de que el canvas haya actualizado su layout
_canvas.UpdateLayout();
RemoveResizeRectangles();
if (_selectedObjects.Any())
{
@ -253,15 +253,14 @@ namespace CtrEditor
public void AddResizeRectangles(IEnumerable<osBase> selectedObjects)
{
double rectHighlightSize = 1;
RemoveResizeRectangles();
RemoveResizeRectangles();
// Verificar si hay objetos bloqueados
bool hasLockedObjects = selectedObjects.Any(obj => obj.Lock_movement);
// Calcular el bounding box que contenga todos los objetos seleccionados
Rect boundingBox = CalculateTotalBoundingBox(selectedObjects);
if (_selectedObjectsAreVisible)
{
if (_selectedObjectsAreVisible) {
FuncionesBase.MutableRect rectBox = new FuncionesBase.MutableRect(boundingBox);
rectBox.Left -= (float)rectHighlightSize;
@ -304,7 +303,7 @@ namespace CtrEditor
foreach (var obj in selectedObjects)
{
if (obj.VisualRepresentation != null && obj.VisualRepresentation.Visibility != Visibility.Collapsed)
if (obj.VisualRepresentation != null && obj.VisualRepresentation.Visibility!=Visibility.Collapsed)
{
// Obtener el bounding box del objeto actual
Rect objectBounds = VisualTreeHelper.GetDescendantBounds(obj.VisualRepresentation);
@ -337,7 +336,7 @@ namespace CtrEditor
// Cambiar el estilo visual dependiendo si hay objetos bloqueados
Brush strokeBrush;
DoubleCollection dashArray;
if (hasLockedObjects)
{
// Estilo para objetos bloqueados (rojo/naranja con líneas más separadas)
@ -378,10 +377,10 @@ namespace CtrEditor
// Calcular el tamaño apropiado para los manejadores basado en el tamaño del objeto
double minObjectDimension = Math.Min(rectBox.Width, rectBox.Height);
double rectSize = Math.Min(defaultRectSize, minObjectDimension / 3);
// Asegurar un tamaño mínimo para los manejadores
rectSize = Math.Max(rectSize, 6);
// Calcular el offset para posicionar los manejadores fuera del rectángulo
double offset = rectSize / 2;
@ -420,9 +419,9 @@ namespace CtrEditor
return (Cursors.SizeWE, Cursors.SizeNS, Cursors.SizeNWSE);
double angle = Math.Abs(firstObject.Angulo % 360);
// Si el objeto no está significativamente rotado, usar cursores estándar
if (angle < 15 || (angle > 345 && angle < 360) ||
if (angle < 15 || (angle > 345 && angle < 360) ||
(angle > 165 && angle < 195))
{
return (Cursors.SizeWE, Cursors.SizeNS, Cursors.SizeNWSE);
@ -570,7 +569,7 @@ namespace CtrEditor
}
UpdateSelectionVisuals();
// Update the view model's selection state
vm.NotifySelectionChanged();
}
@ -584,7 +583,7 @@ namespace CtrEditor
_selectedObjects.Remove(obj);
obj.IsSelected = false;
RemoveSelectionHighlight(obj.VisualRepresentation);
// Update the view model's selection state
if (_mainWindow.DataContext is MainViewModel vm)
{
@ -653,7 +652,7 @@ namespace CtrEditor
Width = transformedBoundingBox.Width,
Height = transformedBoundingBox.Height,
Fill = Brushes.Transparent,
Stroke = new SolidColorBrush(isReference ?
Stroke = new SolidColorBrush(isReference ?
Color.FromArgb(180, 128, 0, 128) : // Purple for reference
Color.FromArgb(180, 255, 0, 0)), // Red for others
StrokeThickness = isReference ? 3 : 2, // Más grueso para el de referencia
@ -716,7 +715,7 @@ namespace CtrEditor
{
// Verificar si hay objetos bloqueados en la selección actual
bool hasLockedObjects = _selectedObjects.Any(obj => obj.Lock_movement);
if (_resizeRectangles != null && _resizeRectangles.Contains(sender))
{
// Si hay objetos bloqueados, no permitir redimensionamiento
@ -725,10 +724,10 @@ namespace CtrEditor
e.Handled = true;
return;
}
// Capturar estado antes de iniciar redimensionamiento
CaptureUndoState();
_currentDraggingRectangle = sender as Rectangle;
_lastMousePosition = e.GetPosition(_canvas);
_currentDraggingRectangle.CaptureMouse();
@ -742,10 +741,10 @@ namespace CtrEditor
if (userControl != null && userControl.DataContext is osBase datos)
{
bool isControlPressed = Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl);
// Determinar qué objetos serán afectados por el movimiento
List<osBase> objectsToMove = new List<osBase>();
if (!isControlPressed)
{
// Si no está Ctrl presionado y vamos a hacer dragging
@ -759,28 +758,28 @@ namespace CtrEditor
// Si no está seleccionado, solo vamos a mover este objeto
objectsToMove.Add(datos);
}
// Verificar si alguno de los objetos a mover está bloqueado
bool willMoveLockedObjects = objectsToMove.Any(obj => obj.Lock_movement);
if (!willMoveLockedObjects)
{
// Capturar estado antes de iniciar movimiento
CaptureUndoStateForObjects(objectsToMove);
userControl.CaptureMouse();
_currentDraggingControl = userControl;
_isMovingUserControl = true;
InitializeDrag(e);
}
}
// Manejar la selección después de capturar el estado
HandleObjectSelection(userControl, datos);
// Actualizar el estado de objetos bloqueados después de la selección
hasLockedObjects = _selectedObjects.Any(obj => obj.Lock_movement);
if (hasLockedObjects && !isControlPressed)
{
// Si hay objetos bloqueados, no permitir el inicio del arrastre
@ -832,14 +831,14 @@ namespace CtrEditor
private void HandleDrag(Point currentPosition)
{
PurgeDeletedObjects();
// Verificar si hay objetos bloqueados antes de mover
bool hasLockedObjects = _selectedObjects.Any(obj => obj.Lock_movement);
if (hasLockedObjects)
{
return; // No mover si hay objetos bloqueados
}
var dx = currentPosition.X - _startPointUserControl.X;
var dy = currentPosition.Y - _startPointUserControl.Y;
@ -993,11 +992,11 @@ namespace CtrEditor
return HandleMode.None;
double angle = Math.Abs(firstObject.Angulo % 360);
// Si el objeto no está significativamente rotado, usar el comportamiento por defecto
if (angle < 15 || (angle > 345 && angle < 360) ||
(angle > 75 && angle < 105) ||
(angle > 165 && angle < 195) ||
if (angle < 15 || (angle > 345 && angle < 360) ||
(angle > 75 && angle < 105) ||
(angle > 165 && angle < 195) ||
(angle > 255 && angle < 285))
{
return DetermineHandleModeDefault(resizeDirection);
@ -1039,14 +1038,14 @@ namespace CtrEditor
private void HandleResize(Point currentPosition, HandleMode mode)
{
PurgeDeletedObjects();
// Verificar si hay objetos bloqueados antes de redimensionar
bool hasLockedObjects = _selectedObjects.Any(obj => obj.Lock_movement);
if (hasLockedObjects)
{
return; // No redimensionar si hay objetos bloqueados
}
RemoveAllSelectionHighlights(); // Remover antes de redimensionar
foreach (var selectedObject in _selectedObjects)
@ -1081,13 +1080,13 @@ namespace CtrEditor
// Para objetos rotados, transformar los cambios del mouse según la orientación del objeto
// Convertir ángulo de grados a radianes
double angleRad = obj.Angulo * Math.PI / 180.0;
// Calcular los componentes de cambio transformados según la rotación
// Rotar el vector de cambio por el ángulo negativo del objeto para obtener
// los cambios en el sistema de coordenadas local del objeto
double cos = Math.Cos(-angleRad);
double sin = Math.Sin(-angleRad);
double localDeltaX = deltaX * cos - deltaY * sin;
double localDeltaY = deltaX * sin + deltaY * cos;
@ -1116,19 +1115,16 @@ namespace CtrEditor
private void HandleRotation(Point currentPosition)
{
PurgeDeletedObjects();
// Verificar si hay objetos bloqueados antes de rotar
bool hasLockedObjects = _selectedObjects.Any(obj => obj.Lock_movement);
if (hasLockedObjects)
{
return; // No rotar si hay objetos bloqueados
}
RemoveAllSelectionHighlights(); // Remover antes de rotar
// Verificar si la tecla Shift está presionada para rotación en incrementos de 45 grados
bool isShiftPressed = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift);
// Calcular el ángulo respecto al centro del bounding box que contiene todos los objetos seleccionados
double deltaX = currentPosition.X - _transformedBoundingBoxCenter.X;
double deltaY = currentPosition.Y - _transformedBoundingBoxCenter.Y;
@ -1141,48 +1137,11 @@ namespace CtrEditor
else
{
double deltaAngle = angle - _lastAngle;
if (isShiftPressed)
foreach (var selectedObject in _selectedObjects)
{
// Rotación en incrementos de 45 grados
// Calcular el ángulo total acumulado desde el inicio de la rotación
double totalAngleChange = angle - _lastAngle;
// Determinar a qué incremento de 45 grados corresponde
double snapAngle = Math.Round(totalAngleChange / 45.0) * 45.0;
// Solo aplicar la rotación si hay un cambio significativo (al menos 22.5 grados de movimiento)
if (Math.Abs(totalAngleChange) > 22.5)
{
// Calcular el cambio real que necesitamos aplicar
double actualRotationChange = snapAngle;
foreach (var selectedObject in _selectedObjects)
{
// Obtener el ángulo actual del objeto
double currentObjectAngle = selectedObject.Angulo;
// Calcular el nuevo ángulo alineado a incrementos de 45 grados
double targetAngle = Math.Round((currentObjectAngle + actualRotationChange) / 45.0) * 45.0;
// Aplicar la rotación necesaria para llegar al ángulo objetivo
double rotationNeeded = targetAngle - currentObjectAngle;
selectedObject.Rotate(rotationNeeded);
}
// Actualizar el ángulo de referencia para evitar aplicar la misma rotación múltiples veces
_lastAngle = (float)angle;
}
}
else
{
// Rotación libre (comportamiento original)
foreach (var selectedObject in _selectedObjects)
{
selectedObject.Rotate(deltaAngle);
}
_lastAngle = (float)angle;
selectedObject.Rotate(deltaAngle);
}
_lastAngle = (float)angle;
}
UpdateAllSelectionHighlights();
@ -1278,10 +1237,10 @@ namespace CtrEditor
ClearSelection();
RemoveResizeRectangles();
RemoveAllSelectionHighlights();
// Ensure the property panel is cleared by explicitly setting SelectedItemOsList to null
viewModel.SelectedItemOsList = null;
// Actualizar el estado de cambios sin guardar
if (viewModel != null)
{
@ -1380,7 +1339,7 @@ namespace CtrEditor
{
// Capturar solo el estado de los objetos seleccionados
var undoState = new UndoState(_selectedObjects);
// Mantener solo los últimos MaxUndoSteps estados
if (_undoHistory.Count >= MaxUndoSteps)
{
@ -1394,7 +1353,7 @@ namespace CtrEditor
_undoHistory.Push(state);
}
}
_undoHistory.Push(undoState);
Console.WriteLine($"Estado capturado para undo de {_selectedObjects.Count} objetos. Historial: {_undoHistory.Count} estados");
}
@ -1415,7 +1374,7 @@ namespace CtrEditor
{
// Capturar solo el estado de los objetos especificados
var undoState = new UndoState(objectsList);
// Mantener solo los últimos MaxUndoSteps estados
if (_undoHistory.Count >= MaxUndoSteps)
{
@ -1429,7 +1388,7 @@ namespace CtrEditor
_undoHistory.Push(state);
}
}
_undoHistory.Push(undoState);
Console.WriteLine($"Estado capturado para undo de {objectsList.Count} objetos específicos. Historial: {_undoHistory.Count} estados");
}
@ -1458,7 +1417,7 @@ namespace CtrEditor
if (_mainWindow.DataContext is MainViewModel viewModel)
{
_isApplyingUndo = true;
try
{
var undoState = _undoHistory.Pop();
@ -1484,10 +1443,10 @@ namespace CtrEditor
// Actualizar los visuales de selección
UpdateSelectionVisuals();
// Marcar como cambios sin guardar
viewModel.HasUnsavedChanges = true;
Console.WriteLine("Undo aplicado exitosamente");
}
finally

View File

@ -16,103 +16,48 @@ namespace CtrEditor.ObjetosSim
{
public static string NombreClase()
{
return "Imagen Personalizada";
return "Custom Image";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
set => SetProperty(ref nombre, value);
}
private string _imagePath;
[Description("Ruta del archivo de imagen")]
[Category("Configuración")]
[property: Name("Ruta de Imagen")]
public string ImagePath
{
get => _imagePath;
set
{
try
{
if (SetProperty(ref _imagePath, value))
{
OnImagePathChanged(value);
OnPropertyChanged(nameof(ImageSource_oculta));
}
}
catch
{
// Si hay error al establecer la propiedad, simplemente ignorarlo
// y establecer la imagen por defecto
try
{
SetProperty(ref _imagePath, value);
ImageSource_oculta = ImageFromPath("/Icons/unselect.png");
OnPropertyChanged(nameof(ImageSource_oculta));
}
catch
{
// En caso de error total, establecer valores seguros
_imagePath = value;
ImageSource_oculta = null;
}
}
}
}
[ObservableProperty]
[property: Description("Voltear la imagen horizontalmente")]
[property: Category("Configuración")]
[property: Name("Voltear Horizontal")]
[NotifyPropertyChangedFor(nameof(ImageSource_oculta))]
[property: Description("Path to the image file")]
[property: Category("Image:")]
private string imagePath;
[ObservableProperty]
[property: Description("Flip the image horizontally")]
[property: Category("Image:")]
private bool horizontal_Flip;
[ObservableProperty]
[property: Description("Voltear la imagen verticalmente")]
[property: Category("Configuración")]
[property: Name("Voltear Vertical")]
[property: Description("Flip the image vertically")]
[property: Category("Image:")]
private bool vertical_Flip;
[JsonIgnore]
[ObservableProperty]
[property: JsonIgnore]
[property: Category("Apariencia")]
[property: Description("Imagen visual del objeto")]
[property: Name("Imagen")]
public ImageSource imageSource_oculta;
private void OnImagePathChanged(string value)
partial void OnImagePathChanged(string value)
{
try
if (!string.IsNullOrEmpty(value))
{
if (!string.IsNullOrEmpty(value))
{
ImageSource_oculta = ImageFromPath(value);
}
else
{
// Si no hay path, usar la imagen por defecto
ImageSource_oculta = ImageFromPath("/Icons/unselect.png");
}
ImageSource_oculta = ImageFromPath(value);
}
catch
else
{
// Si hay cualquier error, usar la imagen por defecto
try
{
ImageSource_oculta = ImageFromPath("/Icons/unselect.png");
}
catch
{
// Si incluso la imagen por defecto falla, establecer como null
ImageSource_oculta = null;
}
// Si no hay path, usar la imagen por defecto
ImageSource_oculta = ImageFromPath("/Icons/unselect.png");
}
}
@ -137,30 +82,14 @@ namespace CtrEditor.ObjetosSim
public override void ucLoaded()
{
base.ucLoaded();
try
if (!string.IsNullOrEmpty(ImagePath))
{
if (!string.IsNullOrEmpty(ImagePath))
{
ImageSource_oculta = ImageFromPath(ImagePath);
}
else
{
// Si no hay path al cargar, usar la imagen por defecto
ImageSource_oculta = ImageFromPath("/Icons/unselect.png");
}
ImageSource_oculta = ImageFromPath(ImagePath);
}
catch
else
{
// Si hay cualquier error, usar la imagen por defecto
try
{
ImageSource_oculta = ImageFromPath("/Icons/unselect.png");
}
catch
{
// Si incluso la imagen por defecto falla, establecer como null
ImageSource_oculta = null;
}
// Si no hay path al cargar, usar la imagen por defecto
ImageSource_oculta = ImageFromPath("/Icons/unselect.png");
}
}
}

View File

@ -29,13 +29,9 @@ namespace CtrEditor.ObjetosSim
public static string NombreClase()
{
return "Marco de Panel";
return "Frame Plate";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
@ -43,9 +39,8 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Description("Índice de capa para objetos en el marco")]
[property: Category("Configuración")]
[property: Name("Índice Z del Marco")]
[property: Description("Layer index to add to Objects on the Frame")]
[property: Category("Layer:")]
int zindex_FramePlate;
partial void OnZindex_FramePlateChanged(int value)
@ -54,33 +49,19 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Color de fondo del marco")]
[property: Name("Color")]
Color color;
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Color del texto del título")]
[property: Name("Color del Título")]
Color color_Titulo;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Texto del título del marco")]
[property: Name("Título")]
string titulo;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Alto del área del título")]
[property: Name("Alto del Título")]
public float alto_Titulo;
// Encoder X
[ObservableProperty]
[property: Description("This is a link to a Encoder for X.")]
[property: Category("Encoders:")]
[property: Category("Encoders:")]
[property: ItemsSource(typeof(osBaseItemsSource<osEncoderMotorLineal>))]
private string encoder_X;
@ -104,7 +85,7 @@ namespace CtrEditor.ObjetosSim
// Encoder Y
[ObservableProperty]
[property: Description("This is a link to a Encoder for Y.")]
[property: Category("Encoders:")]
[property: Category("Encoders:")]
[property: ItemsSource(typeof(osBaseItemsSource<osEncoderMotorLineal>))]
private string encoder_Y;
@ -127,7 +108,7 @@ namespace CtrEditor.ObjetosSim
// Encoder Rotation
[ObservableProperty]
[property: Description("This is a link to a Encoder for Rotation.")]
[property: Category("Encoders:")]
[property: Category("Encoders:")]
[property: ItemsSource(typeof(osBaseItemsSource<osEncoderMotorLineal>))]
private string encoder_Rotation;
@ -416,8 +397,8 @@ namespace CtrEditor.ObjetosSim
[JsonIgnore]
public double RenderTransformCenterX
{
get
{
get
{
if (PivotCenterX)
{
// Centro horizontal del rectángulo principal
@ -437,12 +418,12 @@ namespace CtrEditor.ObjetosSim
[JsonIgnore]
public double RenderTransformCenterY
{
get
{
get
{
// Altura del título y del rectángulo principal
double titleHeight = PixelToMeter.Instance.calc.MetersToPixels(Alto_Titulo);
double frameHeight = PixelToMeter.Instance.calc.MetersToPixels(Alto);
if (PivotCenterY)
{
// Centro vertical de todo el control (título + rectángulo)

View File

@ -4,7 +4,6 @@ using System.Windows.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using CtrEditor.FuncionesBase;
using Newtonsoft.Json;
using System.ComponentModel;
namespace CtrEditor.ObjetosSim
@ -23,13 +22,9 @@ namespace CtrEditor.ObjetosSim
public static string NombreClase()
{
return "Placa de Texto";
return "Plate";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
@ -37,32 +32,17 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Color de fondo de la placa")]
[property: Name("Color")]
Color color;
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Color del texto del título")]
[property: Name("Color Título")]
Color color_Titulo;
[ObservableProperty]
[property: Category("Identificación")]
[property: Description("Texto del título")]
[property: Name("Título")]
string titulo;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Alto del área del título")]
[property: Name("Alto Título")]
public float alto_Titulo;
public override void TopChanging(float oldValue, float newValue)
{
public override void TopChanging(float oldValue, float newValue) {
offsetY = newValue - oldValue;
}
public override void LeftChanging(float oldValue, float newValue)

View File

@ -8,7 +8,6 @@ using CommunityToolkit.Mvvm.ComponentModel;
using nkast.Aether.Physics2D.Common;
using System.Windows.Media;
using CtrEditor.FuncionesBase;
using System.ComponentModel;
namespace CtrEditor.ObjetosSim
{
@ -28,36 +27,26 @@ namespace CtrEditor.ObjetosSim
return "Botella";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
set => SetProperty(ref nombre, value);
}
public override void OnMove(float LeftPixels, float TopPixels)
public override void OnMove(float LeftPixels, float TopPixels)
{
UpdateAfterMove();
}
public override void OnResize(float Delta_Width, float Delta_Height)
public override void OnResize(float Delta_Width, float Delta_Height)
{
Diametro += Delta_Width;
}
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Color visual de la botella")]
[property: Name("Color")]
private Brush colorButton_oculto;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Diámetro de la botella en metros")]
[property: Name("Diámetro")]
private float diametro;
partial void OnDiametroChanged(float value)
@ -72,33 +61,17 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Información")]
[property: Description("Velocidad actual desde la simulación")]
[property: Name("Velocidad de Simulación")]
private string velocidad_desde_simulacion;
[ObservableProperty]
[property: Category("Información")]
[property: Description("Inercia actual desde la simulación")]
[property: Name("Inercia de Simulación")]
private float inercia_desde_simulacion;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Conservar objeto cuando sale de transporte")]
[property: Name("Conservar Fuera de Transporte")]
private bool preserve_Outside_Transport;
[ObservableProperty]
[property: Category("Información")]
[property: Description("Porcentaje de tracción con transporte")]
[property: Name("Porcentaje de Tracción")]
private float porcentaje_Traccion;
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Masa del objeto en kg")]
[property: Name("Masa")]
private float mass;
partial void OnMassChanged(float value)
{
@ -107,22 +80,22 @@ namespace CtrEditor.ObjetosSim
public Vector2 GetCentro()
{
return new Vector2(Left + Diametro / 2, Top + Diametro / 2);
return new Vector2 (Left+Diametro/2,Top+Diametro/2);
}
public void SetCentro(float x, float y)
{ Left = x; Top = y; }
public void SetCentro(Vector2 centro)
{
{
Left = centro.X - Diametro / 2;
Top = centro.Y - Diametro / 2;
Top = centro.Y - Diametro / 2;
}
private void ActualizarGeometrias()
{
if (SimGeometria != null && !RemoverDesdeSimulacion)
{
{
SimGeometria.SetPosition(GetCentro());
}
}
@ -169,7 +142,7 @@ namespace CtrEditor.ObjetosSim
}
// Ha sido marcada para remover
if (SimGeometria.Descartar)
if (SimGeometria.Descartar)
RemoverDesdeSimulacion = true;
// Eliminar la botella si esta fuera de un transporte

View File

@ -8,7 +8,6 @@ using CommunityToolkit.Mvvm.ComponentModel;
using nkast.Aether.Physics2D.Common;
using System.Windows.Media;
using CtrEditor.FuncionesBase;
using System.ComponentModel;
namespace CtrEditor.ObjetosSim
{
@ -26,10 +25,6 @@ namespace CtrEditor.ObjetosSim
return "Botella con Cuello";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
@ -52,15 +47,9 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Color del botón visual")]
[property: Name("Color")]
private Brush colorButton_oculto;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Diámetro de la botella")]
[property: Name("Diámetro")]
private float diametro;
partial void OnDiametroChanged(float value)
@ -69,21 +58,12 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Información")]
[property: Description("Velocidad desde simulación")]
[property: Name("Velocidad Simulación")]
private string velocidad_desde_simulacion;
[ObservableProperty]
[property: Category("Información")]
[property: Description("Inercia desde simulación")]
[property: Name("Inercia Simulación")]
private float inercia_desde_simulacion;
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Masa de la botella")]
[property: Name("Masa")]
private float mass;
partial void OnMassChanged(float value)
{

View File

@ -17,43 +17,27 @@ namespace CtrEditor.ObjetosSim
private float TiempoRestante;
public static string NombreClase()
{
return "Generador de Botellas";
return "BottGenerator";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre { get => nombre; set => SetProperty(ref nombre, value); }
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Desplazamiento horizontal del punto de salida")]
[property: Name("Offset Horizontal")]
private float offsetLeftSalida;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Desplazamiento vertical del punto de salida")]
[property: Name("Offset Vertical")]
private float offsetTopSalida;
[ObservableProperty]
[property: Description("Las botellas se destruirán si caen fuera del transporte")]
[property: Category("Configuración")]
[property: Name("Conservar Fuera de Transporte")]
[property: Description("The bottle will be destroyed if fall outside transport.")]
[property: Category("Enable to Run:")]
private bool preserve_Outside_Transport;
[ObservableProperty]
[property: Description("Tag PLC para habilitar funcionamiento. 1 => siempre activo")]
[property: Category("Enlace PLC")]
[property: Name("Tag Consenso")]
[property: Description("PLC tag for consense to run. 1 => always")]
[property: Category("Enable to Run:")]
private string tag_consenso;
[ObservableProperty]
[property: Description("Estado de consenso para funcionamiento")]
[property: Category("Simulación")]
[property: Name("Consenso")]
[property: Description("Consense to run.")]
[property: Category("Enable to Run:")]
private bool consenso;
partial void OnConsensoChanged(bool value)
{
@ -61,38 +45,26 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Description("Consenso normalmente cerrado")]
[property: Category("Configuración")]
[property: Name("Consenso NC")]
[property: Description("Consense is Normally close.")]
[property: Category("Enable to Run:")]
private bool consenso_NC;
[ObservableProperty]
[property: Description("Habilitar filtro de consenso")]
[property: Category("Configuración")]
[property: Name("Filtro Habilitado")]
[property: Description("Enable filter.")]
[property: Category("Enable to Run:")]
private bool consenso_Filtrado;
[ObservableProperty]
[property: Description("Tiempo de activación del filtro en segundos")]
[property: Category("Configuración")]
[property: Name("Tiempo ON (s)")]
[property: Description("Time ON in s.")]
[property: Category("Enable to Run:")]
float filtro_consenso_ON_s;
[ObservableProperty]
[property: Description("Tiempo de desactivación del filtro en segundos")]
[property: Category("Configuración")]
[property: Name("Tiempo OFF (s)")]
[property: Description("Time OFF in s.")]
[property: Category("Enable to Run:")]
float filtro_consenso_OFF_s;
[ObservableProperty]
[property: Description("Señal de salida del filtro")]
[property: Category("Información")]
[property: Name("Salida Filtro")]
[property: Description("Filter OUT signal.")]
[property: Category("Enable to Run:")]
bool filter_Output;
[ObservableProperty]
[property: Description("Cantidad de botellas generadas por hora")]
[property: Category("Configuración")]
[property: Name("Botellas por Hora")]
private float botellas_hora;
partial void OnBotellas_horaChanged(float value)
{
@ -100,9 +72,6 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Description("Cantidad de botellas generadas por segundo")]
[property: Category("Configuración")]
[property: Name("Botellas por Segundo")]
private float botellas_segundo;
partial void OnBotellas_segundoChanged(float value)
{
@ -110,15 +79,8 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Description("Velocidad actual como porcentaje")]
[property: Category("Simulación")]
[property: Name("Velocidad Actual (%)")]
private float velocidad_actual_percentual;
[ObservableProperty]
[property: Description("Diámetro de las botellas generadas")]
[property: Category("Configuración")]
[property: Name("Diámetro Botella")]
private float diametro_botella;
public override void UpdatePLC(PLCViewModel plc, int elapsedMilliseconds)
{

View File

@ -5,7 +5,6 @@ using System.Windows.Controls;
using CommunityToolkit.Mvvm.ComponentModel;
using System.Diagnostics;
using CtrEditor.FuncionesBase;
using System.ComponentModel;
namespace CtrEditor.ObjetosSim
{
@ -22,13 +21,9 @@ namespace CtrEditor.ObjetosSim
public static string NombreClase()
{
return "Llenadora";
return "Filler";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
@ -36,27 +31,13 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Offset horizontal para salida de botellas")]
[property: Name("Offset Left Salida")]
private float offsetLeftSalida;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Offset vertical para salida de botellas")]
[property: Name("Offset Top Salida")]
private float offsetTopSalida;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Tag PLC para consenso")]
[property: Name("Tag Consenso")]
private string tag_consenso;
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Estado del consenso")]
[property: Name("Consenso")]
private bool consenso;
partial void OnConsensoChanged(bool value)
@ -64,27 +45,13 @@ namespace CtrEditor.ObjetosSim
_TON_TOFF.Senal = value;
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Consenso normalmente cerrado")]
[property: Name("Consenso NC")]
private bool consenso_NC;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Aplicar filtrado al consenso")]
[property: Name("Consenso Filtrado")]
private bool consenso_Filtrado;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Tiempo de filtro en segundos")]
[property: Name("Filtro Consenso (s)")]
float filtro_consenso_s;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Producción en botellas por hora")]
[property: Name("Botellas/Hora")]
private float botellas_hora;
partial void OnBotellas_horaChanged(float value)
@ -93,9 +60,6 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Información")]
[property: Description("Producción en botellas por segundo")]
[property: Name("Botellas/Segundo")]
private float botellas_segundo;
partial void OnBotellas_segundoChanged(float value)
@ -104,15 +68,8 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Velocidad actual en porcentaje")]
[property: Name("Velocidad (%)")]
private float velocidad_actual_percentual;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Diámetro de las botellas generadas")]
[property: Name("Diámetro Botella")]
private float diametro_botella;
public osFiller()

View File

@ -3,7 +3,6 @@ using LibS7Adv;
using System.Windows;
using System.Windows.Controls;
using CtrEditor.FuncionesBase;
using System.ComponentModel;
namespace CtrEditor.ObjetosSim
{
@ -19,10 +18,6 @@ namespace CtrEditor.ObjetosSim
return "Tanque";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
@ -30,68 +25,26 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Capacidad total del tanque en litros")]
[property: Name("Capacidad (L)")]
public float capacidad_Litros;
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Estado de apertura del ingreso")]
[property: Name("Ingreso Abierto")]
public bool ingreso_Abierto;
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Estado de apertura de la salida")]
[property: Name("Salida Abierta")]
public bool salida_Abierta;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Tag PLC para nivel del tanque")]
[property: Name("Tag Nivel")]
public string tagNivel_Word;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Tag PLC para control de ingreso")]
[property: Name("Tag Ingreso")]
public string tagIngresoAbierto_Bool;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Tag PLC para control de salida")]
[property: Name("Tag Salida")]
public string tagSalidaAbierta_Bool;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Velocidad de llenado en L/min")]
[property: Name("Velocidad Ingreso")]
public float velocidad_Ingreso;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Velocidad de vaciado en L/min")]
[property: Name("Velocidad Salida")]
public float velocidad_Salida;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Valor mínimo escalado para salida PLC")]
[property: Name("Mínimo Escalado")]
public float min_OUT_Scaled;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Valor máximo escalado para salida PLC")]
[property: Name("Máximo Escalado")]
public float max_OUT_Scaled;
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Nivel actual del tanque en porcentaje")]
[property: Name("Nivel (%)")]
public float level;
public osTanque()

View File

@ -7,7 +7,6 @@ using nkast.Aether.Physics2D.Common;
using System.Windows.Media.Animation;
using CommunityToolkit.Mvvm.ComponentModel;
using CtrEditor.FuncionesBase;
using System.ComponentModel;
namespace CtrEditor.ObjetosSim
{
/// <summary>
@ -23,10 +22,6 @@ namespace CtrEditor.ObjetosSim
return "Descarte";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
@ -34,9 +29,6 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Diámetro del área de descarte en metros")]
[property: Name("Diámetro")]
private float diametro;
partial void OnDiametroChanged(float value)

View File

@ -1,10 +1,10 @@
using System.Windows;
using System.Windows.Controls;
using CommunityToolkit.Mvvm.ComponentModel;
using LibS7Adv;
using CtrEditor.Simulacion;
using CtrEditor.FuncionesBase;
using System.ComponentModel;
namespace CtrEditor.ObjetosSim
{
@ -17,13 +17,9 @@ namespace CtrEditor.ObjetosSim
public static string NombreClase()
{
return "Guía";
return "Guia";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
private string nombre = "Guia";
public override string Nombre
{
get => nombre;
@ -31,9 +27,6 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Alto de la guía en metros")]
[property: Name("Alto de la Guía")]
public float altoGuia;
private void ActualizarGeometrias()
@ -42,7 +35,7 @@ namespace CtrEditor.ObjetosSim
UpdateOrCreateLine(SimGeometria, uc.Guia);
}
public override void OnMoveResizeRotate()
public override void OnMoveResizeRotate()
{
ActualizarGeometrias();
}

View File

@ -23,13 +23,9 @@ namespace CtrEditor.ObjetosSim
public static string NombreClase()
{
return "Transporte Curva 90°";
return "Transporte Curva 90";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
private string nombre = "Transporte Curva 90";
public override string Nombre
{
get => nombre;
@ -37,9 +33,6 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Velocidad actual del transporte en m/s")]
[property: Name("Velocidad Actual")]
public float velocidadActual;
partial void OnVelocidadActualChanged(float value)
@ -48,19 +41,11 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Invierte el sentido de movimiento del transporte")]
[property: Name("Invertir Dirección")]
bool invertirDireccion;
partial void OnInvertirDireccionChanged(bool value)
{
SetSpeed();
if (_visualRepresentation is ucTransporteCurva uc)
{
CrearAnimacionStoryBoardTrasnporteCircular(uc.Transporte.TransportePath, InvertirDireccion, Angulo);
ActualizarAnimacionStoryBoardTransporte(VelocidadActual);
}
}
void SetSpeed()
@ -69,13 +54,9 @@ namespace CtrEditor.ObjetosSim
Simulation_TransporteCurva?.SetSpeed(-VelocidadActual);
else
Simulation_TransporteCurva?.SetSpeed(VelocidadActual);
ActualizarAnimacionStoryBoardTransporte(VelocidadActual);
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Radio exterior de la curva en metros")]
[property: Name("Radio Exterior")]
private float radioExterno;
partial void OnRadioExternoChanged(float value)
@ -83,32 +64,29 @@ namespace CtrEditor.ObjetosSim
// Update ancho and alto based on radioExterno
Ancho = value * 2;
Alto = value * 2;
// Ensure radioInterno maintains proper proportion if needed
if (RadioInterno >= value)
{
RadioInterno = value * 0.75f; // Default proportion
}
ActualizarGeometrias();
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Radio interior de la curva en metros")]
[property: Name("Radio Interior")]
private float radioInterno;
[ObservableProperty]
[property: Description("Tag de bit para activar enlace con motor")]
[property: Category("Enlace PLC")]
[property: Name("Tag Activación Motor")]
string tag_ReleActivatedMotor;
[ObservableProperty]
[property: Description("Seleccionar motor para enlazar")]
[property: Category("Enlace PLC")]
[property: Name("Motor Enlazado")]
[property: Description("Bit to enable Link to Motor")]
[property: Category("PLC link:")]
string tag_ReleActivatedMotor;
[ObservableProperty]
[property: Description("Link to Motor")]
[property: Category("PLC link:")]
[property: ItemsSource(typeof(osBaseItemsSource<osVMmotorSim>))]
string id_Motor;
@ -137,8 +115,8 @@ namespace CtrEditor.ObjetosSim
}
}
public override void AnguloChanged(float value)
{
public override void AnguloChanged(float value)
{
OnPropertyChanged(nameof(AnguloFinal));
}
@ -149,14 +127,14 @@ namespace CtrEditor.ObjetosSim
[Hidden]
public float AnguloFinal
{
get => Angulo + Arco_en_grados;
get => Angulo+Arco_en_grados;
}
private void ActualizarGeometrias()
{
if (_visualRepresentation is ucTransporteCurva uc)
{
UpdateCurve(Simulation_TransporteCurva, RadioInterno, RadioExterno, Angulo, Angulo + Arco_en_grados);
UpdateCurve(Simulation_TransporteCurva, RadioInterno, RadioExterno, Angulo, Angulo+Arco_en_grados);
SetSpeed();
}
}
@ -180,32 +158,32 @@ namespace CtrEditor.ObjetosSim
// Calculate the proportional change factor
float widthChangeFactor = (Ancho + Delta_Width) / Ancho;
float heightChangeFactor = (Alto + Delta_Height) / Alto;
// Use the average or minimum change factor to maintain aspect ratio
float changeFactor = Math.Min(widthChangeFactor, heightChangeFactor);
// Save the original radiuses for calculating position adjustments
float originalRadioExterno = RadioExterno;
// Apply the change factor to both radios
RadioExterno *= changeFactor;
RadioInterno *= changeFactor;
// Calculate position adjustment to keep the component centered
float radiusDifference = RadioExterno - originalRadioExterno;
// Adjust Left and Top to maintain center position
// We move by negative half the difference because the component expands outward
Left -= radiusDifference;
Top -= radiusDifference;
// Ensure minimums
if (RadioExterno < 0.1f)
RadioExterno = 0.1f;
if (RadioInterno < 0.05f)
RadioInterno = 0.05f;
// Ensure radioInterno is always less than radioExterno
if (RadioInterno >= RadioExterno)
RadioInterno = RadioExterno * 0.75f;
@ -227,14 +205,9 @@ namespace CtrEditor.ObjetosSim
{
// Se llama antes de la simulacion
ActualizarGeometrias();
}
public override void SimulationStop()
{
// Se llama al detener la simulacion
ActualizarAnimacionStoryBoardTransporte(VelocidadActual);
}
}
public override void UpdatePLC(PLCViewModel plc, int elapsedMilliseconds)
{
if (Motor != null)
@ -252,13 +225,13 @@ namespace CtrEditor.ObjetosSim
// El UserControl ya se ha cargado y podemos obtener las coordenadas para
// crear el objeto de simulacion
base.ucLoaded();
OnId_MotorChanged(Id_Motor); // Link Id_Motor = Motor
if (_visualRepresentation is ucTransporteCurva uc)
{
Simulation_TransporteCurva = AddCurve(RadioInterno, RadioExterno, Angulo, Angulo + Arco_en_grados);
CrearAnimacionStoryBoardTrasnporteCircular(uc.Transporte.TransportePath, InvertirDireccion, Angulo);
}
Simulation_TransporteCurva = AddCurve(RadioInterno,RadioExterno, Angulo, Angulo + Arco_en_grados);
// AddCurve(float innerRadius, float outerRadius, float startAngle, float endAngle, Vector2 position)
}
public override void ucUnLoaded()
{

View File

@ -1,24 +0,0 @@
<UserControl x:Class="CtrEditor.ObjetosSim.ucTransporteCurvaGuias"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:localuc="clr-namespace:CtrEditor.ObjetosSim.UserControls" xmlns:vm="clr-namespace:CtrEditor.ObjetosSim"
mc:Ignorable="d">
<UserControl.DataContext>
<vm:osTransporteCurvaGuias />
</UserControl.DataContext>
<Canvas x:Name="MainCanvas">
<localuc:CircularSegment x:Name="Transporte" Angle="0"
OuterRadius="{Binding RadioExterno, Converter={StaticResource MeterToPixelConverter}}"
InnerRadius="{Binding RadioInterno, Converter={StaticResource MeterToPixelConverter}}"
StartAngle="{Binding Angulo}" EndAngle="{Binding AnguloFinal}"
ShowGuides="{Binding MostrarGuias}"
GuideDistance="{Binding DistanciaGuias, Converter={StaticResource MeterToPixelConverter}}"
GuideThickness="{Binding GrosorGuias, Converter={StaticResource MeterToPixelConverter}}"
GuideStroke="{Binding ColorGuiasBrush}" />
</Canvas>
</UserControl>

View File

@ -1,510 +0,0 @@
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using CommunityToolkit.Mvvm.ComponentModel;
using LibS7Adv;
using CtrEditor.Simulacion;
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
using CtrEditor.FuncionesBase;
using System.Text.Json.Serialization;
using System.Windows.Media;
namespace CtrEditor.ObjetosSim
{
/// <summary>
/// Interaction logic for ucTransporteCurvaGuias.xaml
/// </summary>
public partial class osTransporteCurvaGuias : osBase, IosBase
{
private osBase Motor = null;
private simCurve Simulation_TransporteCurvaGuias;
// Listas para almacenar los segmentos de las guías curvas
private List<simGuia> GuiasSuperiores = new List<simGuia>();
private List<simGuia> GuiasInferiores = new List<simGuia>();
private float _velocidadActual;
public static string NombreClase()
{
return "Transporte Curva con Guías";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
set => SetProperty(ref nombre, value);
}
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Velocidad actual del transporte")]
[property: Name("Velocidad Actual")]
public float velocidadActual;
partial void OnVelocidadActualChanged(float value)
{
SetSpeed();
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Invierte el sentido de movimiento")]
[property: Name("Invertir Dirección")]
bool invertirDireccion;
partial void OnInvertirDireccionChanged(bool value)
{
SetSpeed();
if (_visualRepresentation is ucTransporteCurvaGuias uc)
{
CrearAnimacionStoryBoardTrasnporteCircular(uc.Transporte.TransportePath, InvertirDireccion, Angulo);
ActualizarAnimacionStoryBoardTransporte(VelocidadActual);
}
}
void SetSpeed()
{
if (InvertirDireccion)
Simulation_TransporteCurvaGuias?.SetSpeed(-VelocidadActual);
else
Simulation_TransporteCurvaGuias?.SetSpeed(VelocidadActual);
ActualizarAnimacionStoryBoardTransporte(VelocidadActual);
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Radio externo de la curva")]
[property: Name("Radio Externo")]
private float radioExterno;
partial void OnRadioExternoChanged(float value)
{
// Update ancho and alto based on radioExterno
Ancho = value * 2;
Alto = value * 2;
// Ensure radioInterno maintains proper proportion if needed
if (RadioInterno >= value)
{
RadioInterno = value * 0.75f; // Default proportion
}
ActualizarGeometrias();
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Radio interno de la curva")]
[property: Name("Radio Interno")]
private float radioInterno;
partial void OnRadioInternoChanged(float value)
{
ActualizarGeometrias();
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Número de segmentos para las guías (máximo 20)")]
[property: Name("Segmentos Guías")]
private int numeroSegmentosGuias;
partial void OnNumeroSegmentosGuiasChanged(int value)
{
// Limitar entre 4 y 20 segmentos
if (value < 4) NumeroSegmentosGuias = 4;
if (value > 20) NumeroSegmentosGuias = 20;
ActualizarGeometrias();
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Grosor de las guías")]
[property: Name("Grosor Guías")]
private float grosorGuias;
partial void OnGrosorGuiasChanged(float value)
{
ActualizarGeometrias();
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Distancia de separación de las guías desde el borde")]
[property: Name("Distancia Guías")]
private float distanciaGuias;
partial void OnDistanciaGuiasChanged(float value)
{
ActualizarGeometrias();
}
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Mostrar guías visuales")]
[property: Name("Mostrar Guías")]
private bool mostrarGuias;
// Propiedad interna Brush para el binding
private Brush _colorGuiasBrush = new SolidColorBrush(Colors.DarkBlue);
[JsonIgnore]
public Brush ColorGuiasBrush
{
get => _colorGuiasBrush;
set
{
if (_colorGuiasBrush != value)
{
_colorGuiasBrush = value;
OnPropertyChanged(nameof(ColorGuiasBrush));
// Extraer el color del brush y actualizar la propiedad Color
if (value is SolidColorBrush solidBrush)
{
colorGuias = solidBrush.Color;
OnPropertyChanged(nameof(ColorGuias));
}
}
}
}
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Color de las guías")]
[property: Name("Color Guías")]
private Color colorGuias = Colors.DarkBlue;
partial void OnColorGuiasChanged(Color value)
{
// Sincronizar con la propiedad Brush
ColorGuiasBrush = new SolidColorBrush(value);
}
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Tag para activar enlace con motor")]
[property: Name("Tag Activación Motor")]
string tag_ReleActivatedMotor;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Motor enlazado al transporte")]
[property: Name("Motor Enlazado")]
[property: ItemsSource(typeof(osBaseItemsSource<osVMmotorSim>))]
string id_Motor;
[JsonIgnore]
private PropertyChangedEventHandler motorPropertyChangedHandler;
partial void OnId_MotorChanged(string value)
{
if (Motor != null && motorPropertyChangedHandler != null)
Motor.PropertyChanged -= motorPropertyChangedHandler;
if (_mainViewModel != null && !string.IsNullOrEmpty(value))
{
Motor = (osVMmotorSim)_mainViewModel.ObjetosSimulables.FirstOrDefault(s => s is osVMmotorSim motor && motor.Nombre == value);
if (Motor != null)
{
motorPropertyChangedHandler = (sender, e) =>
{
if (e.PropertyName == nameof(osVMmotorSim.Nombre))
{
Id_Motor = ((osVMmotorSim)sender).Nombre;
}
};
Motor.PropertyChanged += motorPropertyChangedHandler;
}
}
}
public override void AnguloChanged(float value)
{
OnPropertyChanged(nameof(AnguloFinal));
ActualizarGeometrias();
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Arco de la curva en grados")]
[property: Name("Arco (grados)")]
[NotifyPropertyChangedFor(nameof(AnguloFinal))]
private float arco_en_grados;
partial void OnArco_en_gradosChanged(float value)
{
ActualizarGeometrias();
}
[Hidden]
public float AnguloFinal
{
get => Angulo + Arco_en_grados;
}
private void ActualizarGeometrias()
{
if (_visualRepresentation is ucTransporteCurvaGuias uc)
{
UpdateCurve(Simulation_TransporteCurvaGuias, RadioInterno, RadioExterno, Angulo, Angulo + Arco_en_grados);
ActualizarGuiasCurvas();
SetSpeed();
}
}
private void ActualizarGuiasCurvas()
{
// Limpiar guías existentes
EliminarGuiasExistentes();
// Crear nuevas guías
CrearGuiasCurvas();
}
private void EliminarGuiasExistentes()
{
foreach (var guia in GuiasSuperiores)
{
simulationManager?.Remove(guia);
}
foreach (var guia in GuiasInferiores)
{
simulationManager?.Remove(guia);
}
GuiasSuperiores.Clear();
GuiasInferiores.Clear();
}
private void CrearGuiasCurvas()
{
if (NumeroSegmentosGuias < 4 || simulationManager == null)
return;
float radioGuiaSuperior = RadioExterno + DistanciaGuias;
float radioGuiaInferior = RadioInterno - DistanciaGuias;
// Asegurar que el radio interior de la guía no sea negativo
if (radioGuiaInferior < 0.01f)
radioGuiaInferior = 0.01f;
// Convertir ángulos a radianes
float anguloInicioRad = simBase.GradosARadianes(Angulo);
float anguloFinalRad = simBase.GradosARadianes(AnguloFinal);
float rangoAngular = anguloFinalRad - anguloInicioRad;
// Calcular el paso angular entre segmentos
float pasoAngular = rangoAngular / NumeroSegmentosGuias;
// Obtener el centro una vez para todo el método
nkast.Aether.Physics2D.Common.Vector2 centro = GetCurveCenterInMeter(RadioExterno);
// Crear segmentos para guía superior (externa)
for (int i = 0; i < NumeroSegmentosGuias; i++)
{
float angulo1 = anguloInicioRad + i * pasoAngular;
float angulo2 = anguloInicioRad + (i + 1) * pasoAngular;
nkast.Aether.Physics2D.Common.Vector2 punto1 = new nkast.Aether.Physics2D.Common.Vector2(
radioGuiaSuperior * (float)Math.Cos(angulo1),
radioGuiaSuperior * (float)Math.Sin(angulo1)
);
nkast.Aether.Physics2D.Common.Vector2 punto2 = new nkast.Aether.Physics2D.Common.Vector2(
radioGuiaSuperior * (float)Math.Cos(angulo2),
radioGuiaSuperior * (float)Math.Sin(angulo2)
);
// Ajustar por la posición del objeto
punto1 += centro;
punto2 += centro;
simGuia guiaSegmento = simulationManager.AddLine(punto1, punto2);
GuiasSuperiores.Add(guiaSegmento);
}
// Crear segmentos para guía inferior (interna)
for (int i = 0; i < NumeroSegmentosGuias; i++)
{
float angulo1 = anguloInicioRad + i * pasoAngular;
float angulo2 = anguloInicioRad + (i + 1) * pasoAngular;
nkast.Aether.Physics2D.Common.Vector2 punto1 = new nkast.Aether.Physics2D.Common.Vector2(
radioGuiaInferior * (float)Math.Cos(angulo1),
radioGuiaInferior * (float)Math.Sin(angulo1)
);
nkast.Aether.Physics2D.Common.Vector2 punto2 = new nkast.Aether.Physics2D.Common.Vector2(
radioGuiaInferior * (float)Math.Cos(angulo2),
radioGuiaInferior * (float)Math.Sin(angulo2)
);
// Ajustar por la posición del objeto
punto1 += centro;
punto2 += centro;
simGuia guiaSegmento = simulationManager.AddLine(punto1, punto2);
GuiasInferiores.Add(guiaSegmento);
}
}
public override void OnMoveResizeRotate()
{
ActualizarGeometrias();
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Coeficiente de fricción")]
[property: Name("Coeficiente Fricción")]
public float frictionCoefficient;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Velocidad máxima a 50Hz")]
[property: Name("Velocidad Max 50Hz")]
public float velMax50hz;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Tiempo de rampa")]
[property: Name("Tiempo Rampa")]
public float tiempoRampa;
[ObservableProperty]
[property: Category("Información")]
[property: Description("Estado de marcha")]
[property: Name("En Marcha")]
public bool esMarcha;
public override void OnResize(float Delta_Width, float Delta_Height)
{
// Calculate the proportional change factor
float widthChangeFactor = (Ancho + Delta_Width) / Ancho;
float heightChangeFactor = (Alto + Delta_Height) / Alto;
// Use the average or minimum change factor to maintain aspect ratio
float changeFactor = Math.Min(widthChangeFactor, heightChangeFactor);
// Save the original radiuses for calculating position adjustments
float originalRadioExterno = RadioExterno;
// Apply the change factor to both radios
RadioExterno *= changeFactor;
RadioInterno *= changeFactor;
// Calculate position adjustment to keep the component centered
float radiusDifference = RadioExterno - originalRadioExterno;
// Adjust Left and Top to maintain center position
// We move by negative half the difference because the component expands outward
Left -= radiusDifference;
Top -= radiusDifference;
// Ensure minimums
if (RadioExterno < 0.1f)
RadioExterno = 0.1f;
if (RadioInterno < 0.05f)
RadioInterno = 0.05f;
// Ensure radioInterno is always less than radioExterno
if (RadioInterno >= RadioExterno)
RadioInterno = RadioExterno * 0.75f;
}
public osTransporteCurvaGuias()
{
RadioExterno = 1.3f;
RadioInterno = 1f;
Ancho = RadioExterno * 2; // Set initial width based on external radius
Alto = RadioExterno * 2; // Set initial height based on external radius
Arco_en_grados = 90;
Tag_ReleActivatedMotor = "1";
NumeroSegmentosGuias = 12; // Valor por defecto
GrosorGuias = 0.03f;
DistanciaGuias = 0.05f;
MostrarGuias = true; // Mostrar guías por defecto
}
public override void UpdateGeometryStart()
{
// Se llama antes de la simulacion
ActualizarGeometrias();
}
public override void SimulationStop()
{
// Se llama al detener la simulacion
ActualizarAnimacionStoryBoardTransporte(VelocidadActual);
}
public override void UpdatePLC(PLCViewModel plc, int elapsedMilliseconds)
{
if (Motor != null)
{
if (Motor is osVMmotorSim motor)
if (LeerBitTag(Tag_ReleActivatedMotor))
VelocidadActual = motor.Velocidad;
else
VelocidadActual = 0;
}
}
public override void ucLoaded()
{
// El UserControl ya se ha cargado y podemos obtener las coordenadas para
// crear el objeto de simulacion
base.ucLoaded();
OnId_MotorChanged(Id_Motor); // Link Id_Motor = Motor
if (_visualRepresentation is ucTransporteCurvaGuias uc)
{
Simulation_TransporteCurvaGuias = AddCurve(RadioInterno, RadioExterno, Angulo, Angulo + Arco_en_grados);
CrearGuiasCurvas(); // Crear las guías curvas
CrearAnimacionStoryBoardTrasnporteCircular(uc.Transporte.TransportePath, InvertirDireccion, Angulo);
}
}
public override void ucUnLoaded()
{
// El UserControl se esta eliminando
// eliminar el objeto de simulacion
simulationManager?.Remove(Simulation_TransporteCurvaGuias);
EliminarGuiasExistentes();
}
}
public partial class ucTransporteCurvaGuias : UserControl, IDataContainer
{
public osBase? Datos { get; set; }
public int zIndex_fromFrames { get; set; }
public ucTransporteCurvaGuias()
{
InitializeComponent();
this.Loaded += OnLoaded;
this.Unloaded += OnUnloaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
Datos?.ucLoaded();
}
private void OnUnloaded(object sender, RoutedEventArgs e)
{
Datos?.ucUnLoaded();
}
public void Highlight(bool State) { }
public ZIndexEnum ZIndex_Base()
{
return ZIndexEnum.Estaticos;
}
}
}

View File

@ -25,13 +25,10 @@ namespace CtrEditor.ObjetosSim
public static string NombreClase()
{
return "Transporte con Guías";
return "Transporte Guias";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
@ -39,9 +36,6 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Velocidad actual del transporte")]
[property: Name("Velocidad Actual")]
public float velocidadActual;
partial void OnVelocidadActualChanged(float value)
@ -50,9 +44,6 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Invierte el sentido de movimiento")]
[property: Name("Invertir Dirección")]
bool invertirDireccion;
partial void OnInvertirDireccionChanged(bool value)
@ -76,21 +67,16 @@ namespace CtrEditor.ObjetosSim
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Color del transporte")]
[property: Name("Color")]
Color color = Colors.Blue;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Tag para activar enlace con motor")]
[property: Name("Tag Activación Motor")]
[property: Description("Bit to enable Link to Motor")]
[property: Category("PLC link:")]
string tag_ReleActivatedMotor;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Motor enlazado al transporte")]
[property: Name("Motor Enlazado")]
[property: Description("Link to Motor")]
[property: Category("PLC link:")]
[property: ItemsSource(typeof(osBaseItemsSource<osVMmotorSim>))]
string id_Motor;
@ -119,15 +105,12 @@ namespace CtrEditor.ObjetosSim
}
}
public override void AltoChanged(float value)
public override void AltoChanged(float value)
{
ActualizarGeometrias();
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Actuar como freno")]
[property: Name("Es Freno")]
public bool esFreno;
partial void OnEsFrenoChanged(bool value)
@ -137,39 +120,16 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Coeficiente de fricción")]
[property: Name("Coeficiente Fricción")]
public float frictionCoefficient;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Velocidad máxima a 50Hz")]
[property: Name("Velocidad Max 50Hz")]
public float velMax50hz;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Tiempo de rampa")]
[property: Name("Tiempo Rampa")]
public float tiempoRampa;
[ObservableProperty]
[property: Category("Información")]
[property: Description("Estado de marcha")]
[property: Name("En Marcha")]
public bool esMarcha;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Distancia entre guías")]
[property: Name("Distancia")]
private float distance;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Alto de las guías")]
[property: Name("Alto Guía")]
private float altoGuia;
private void ActualizarGeometrias()
@ -216,7 +176,7 @@ namespace CtrEditor.ObjetosSim
{
if (Motor != null)
if (Motor is osVMmotorSim id_motor)
if (LeerBitTag(Tag_ReleActivatedMotor))
if (LeerBitTag(Tag_ReleActivatedMotor))
VelocidadActual = id_motor.Velocidad;
else
VelocidadActual = 0;

View File

@ -28,13 +28,10 @@ namespace CtrEditor.ObjetosSim
public static string NombreClase()
{
return "Transporte Guías Unión";
return "Transporte Guias Union";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
@ -42,21 +39,16 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Color del transporte")]
[property: Name("Color")]
Color color;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Tag para activar enlace con motor")]
[property: Name("Tag Activación Motor")]
[property: Description("Bit to enable Link to Motor")]
[property: Category("PLC link:")]
string tag_ReleActivatedMotor;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Motor A enlazado")]
[property: Name("Motor A")]
[property: Description("Link to Motor A")]
[property: Category("PLC link:")]
[property: ItemsSource(typeof(osBaseItemsSource<osVMmotorSim>))]
string id_MotorA;
@ -82,9 +74,8 @@ namespace CtrEditor.ObjetosSim
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Motor B enlazado")]
[property: Name("Motor B")]
[property: Description("Link to Motor B")]
[property: Category("PLC link:")]
[property: ItemsSource(typeof(osBaseItemsSource<osVMmotorSim>))]
string id_MotorB;
@ -110,9 +101,6 @@ namespace CtrEditor.ObjetosSim
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Velocidad actual del motor A")]
[property: Name("Velocidad A")]
public float velocidadActualA;
partial void OnVelocidadActualAChanged(float value)
@ -125,9 +113,6 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Invertir dirección del motor A")]
[property: Name("Invertir A")]
bool invertirDireccionA;
partial void OnInvertirDireccionAChanged(bool value)
@ -143,9 +128,6 @@ namespace CtrEditor.ObjetosSim
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Velocidad actual del motor B")]
[property: Name("Velocidad B")]
public float velocidadActualB;
partial void OnVelocidadActualBChanged(float value)
@ -158,9 +140,6 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Invertir dirección del motor B")]
[property: Name("Invertir B")]
bool invertirDireccionB;
partial void OnInvertirDireccionBChanged(bool value)
@ -174,21 +153,14 @@ namespace CtrEditor.ObjetosSim
}
}
public override void OnResize(float Delta_Width, float Delta_Height)
public override void OnResize(float Delta_Width, float Delta_Height)
{
AnchoRecto += Delta_Width;
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Ancho de las secciones rectas")]
[property: Name("Ancho Recto")]
public float anchoRecto;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Ancho de la sección central")]
[property: Name("Ancho Central")]
public float anchoCentral;
@ -203,45 +175,19 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Información")]
[property: Description("Ancho total del transporte calculado")]
[property: Name("Ancho Total")]
public float anchoTransporte_oculto;
public float anchoTransporte_oculto;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Coeficiente de fricción")]
[property: Name("Coeficiente Fricción")]
public float frictionCoefficient;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Velocidad máxima a 50Hz")]
[property: Name("Velocidad Max 50Hz")]
public float velMax50hz;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Tiempo de rampa")]
[property: Name("Tiempo Rampa")]
public float tiempoRampa;
[ObservableProperty]
[property: Category("Información")]
[property: Description("Estado de marcha")]
[property: Name("En Marcha")]
public bool esMarcha;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Distancia entre elementos")]
[property: Name("Distancia")]
private float distance;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Alto de las guías")]
[property: Name("Alto Guía")]
private float altoGuia;
void ActualizarStoryboards(Rectangle transporte)
@ -358,8 +304,8 @@ namespace CtrEditor.ObjetosSim
if (child is Rectangle rect)
if (rect.Name.StartsWith("Transporte"))
{
SimGeometriaT.Add(rect, AddRectangle(simulationManager, rect, Alto, AnchoTransporte_oculto, Angulo));
Storyboards.Add(rect, CrearAnimacionMultiStoryBoardTrasnporte(rect, false));
SimGeometriaT.Add(rect,AddRectangle(simulationManager, rect, Alto, AnchoTransporte_oculto, Angulo));
Storyboards.Add(rect,CrearAnimacionMultiStoryBoardTrasnporte(rect,false));
}
foreach (var child in uc.GuiaSuperior.Canvas.Children)

View File

@ -23,13 +23,11 @@ namespace CtrEditor.ObjetosSim
public static string NombreClase()
{
return "Transporte TTOP";
return "Transporte";
}
private string nombre = NombreClase();
private string nombre = "Transporte TTOP";
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
[property: Category("Id:")]
public override string Nombre
{
get => nombre;
@ -37,9 +35,7 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Velocidad actual del transporte en m/s")]
[property: Name("Velocidad Actual")]
[property: Category("Simulation:")]
public float velocidadActual;
partial void OnVelocidadActualChanged(float value)
@ -48,9 +44,7 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Invierte el sentido de movimiento del transporte")]
[property: Name("Invertir Dirección")]
[property: Category("Simulation:")]
bool invertirDireccion;
partial void OnInvertirDireccionChanged(bool value)
@ -73,15 +67,13 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Description("Tag de bit para activar enlace con motor")]
[property: Category("Enlace PLC")]
[property: Name("Tag Activación Motor")]
[property: Description("Bit to enable Link to Motor")]
[property: Category("PLC link:")]
string tag_ReleActivatedMotor;
[ObservableProperty]
[property: Description("Seleccionar motor para enlazar")]
[property: Category("Enlace PLC")]
[property: Name("Motor Enlazado")]
[property: Description("Link to Motor")]
[property: Category("PLC link:")]
[property: ItemsSource(typeof(osBaseItemsSource<osVMmotorSim>))]
string id_Motor;
@ -112,27 +104,16 @@ namespace CtrEditor.ObjetosSim
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Coeficiente de fricción entre objetos y superficie")]
[property: Name("Coeficiente de Fricción")]
[property: Category("Setup:")]
public float frictionCoefficient;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Velocidad máxima a 50Hz")]
[property: Name("Velocidad Máxima 50Hz")]
[property: Category("Setup:")]
public float velMax50hz;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Tiempo de rampa para acelerar/desacelerar")]
[property: Name("Tiempo de Rampa")]
[property: Category("Setup:")]
public float tiempoRampa;
[ObservableProperty]
[property: Category("Información")]
[property: Description("Indica si el transporte está en marcha")]
[property: Name("En Marcha")]
[property: Category("Setup:")]
public bool esMarcha;

View File

@ -26,13 +26,11 @@ namespace CtrEditor.ObjetosSim
public static string NombreClase()
{
return "Transporte TTOP Doble Inversor";
return "Transporte Dual Inverter";
}
private string nombre = NombreClase();
private string nombre = "Transporte TTOP Dual Inverter";
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
[property: Category("Id:")]
public override string Nombre
{
get => nombre;
@ -40,9 +38,7 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Velocidad actual del transporte")]
[property: Name("Velocidad Actual")]
[property: Category("Simulation:")]
public float velocidadActual;
partial void OnVelocidadActualChanged(float value)
@ -51,9 +47,7 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Invierte el sentido de movimiento")]
[property: Name("Invertir Dirección")]
[property: Category("Simulation:")]
bool invertirDireccion;
partial void OnInvertirDireccionChanged(bool value)
@ -76,28 +70,24 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Tag para activar enlace con inversor A")]
[property: Name("Tag Activación Motor A")]
[property: Description("Bit to enable Link to Inverter A")]
[property: Category("PLC link:")]
string tag_ReleActivatedMotor_A;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Tag para activar enlace con inversor B")]
[property: Name("Tag Activación Motor B")]
[property: Description("Bit to enable Link to Inverter B")]
[property: Category("PLC link:")]
string tag_ReleActivatedMotor_B;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Enlace a inversor A")]
[property: Name("Motor A")]
[property: Description("Link to Inverter A")]
[property: Category("PLC link:")]
[property: ItemsSource(typeof(osBaseItemsSource<osVMmotorSim>))]
string id_Motor_A;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Enlace a inversor B")]
[property: Name("Motor B")]
[property: Description("Link to Inverter B")]
[property: Category("PLC link:")]
[property: ItemsSource(typeof(osBaseItemsSource<osVMmotorSim>))]
string id_Motor_B;
@ -151,27 +141,16 @@ namespace CtrEditor.ObjetosSim
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Coeficiente de fricción")]
[property: Name("Coeficiente Fricción")]
[property: Category("Setup:")]
public float frictionCoefficient;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Velocidad máxima a 50Hz")]
[property: Name("Velocidad Max 50Hz")]
[property: Category("Setup:")]
public float velMax50hz;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Tiempo de rampa")]
[property: Name("Tiempo Rampa")]
[property: Category("Setup:")]
public float tiempoRampa;
[ObservableProperty]
[property: Category("Información")]
[property: Description("Estado de marcha")]
[property: Name("En Marcha")]
[property: Category("Setup:")]
public bool esMarcha;

View File

@ -25,30 +25,20 @@ namespace CtrEditor.ObjetosSim
public static string NombreClase()
{
return "Motor VetroMeccanica";
return "VetroMeccanica Motor";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
set => SetProperty(ref nombre, value);
}
[JsonIgnore]
[ObservableProperty]
[property: JsonIgnore]
[property: Category("Apariencia")]
[property: Description("Imagen visual del motor")]
[property: Name("Imagen")]
public ImageSource imageSource_oculta;
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Tamaño visual del motor")]
[property: Name("Tamaño")]
public float tamano;
public override void OnResize(float Delta_Width, float Delta_Height)
@ -57,45 +47,28 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Tiempo de actualización en milisegundos")]
[property: Name("Tiempo de Actualización")]
public float refresh_Time_ms;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Velocidad proporcional en porcentaje")]
[property: Name("Velocidad Proporcional")]
public float proporcional_Speed;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Velocidad máxima para rampa")]
[property: Name("Velocidad Máxima Rampa")]
public float max_Speed_for_Ramp;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Contacto normalmente cerrado de trip del VFD")]
[property: Name("VFD Trip NC")]
bool vFD_Trip_NC;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Tiempo de rampa para acelerar/desacelerar")]
[property: Name("Tiempo de Rampa")]
public float tiempoRampa;
[ObservableProperty]
[property: Description("Habilita lectura del encoder del motor simulado en PLC")]
[property: Category("Encoder")]
[property: Name("Motor con Encoder")]
[property: Description("Enable read of the Motor encoder simulated on PLC.")]
[property: Category("Encoder:")]
bool motor_With_Encoder;
[ObservableProperty]
[property: Description("Valor actual de la posición del encoder")]
[property: Category("Encoder")]
[property: Name("Posición Actual")]
[property: Description("Actual Value of the encoder position.")]
[property: Category("Encoder:")]
public float actual_Position;
partial void OnTiempoRampaChanged(float value)
@ -106,15 +79,8 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Información")]
[property: Description("Estado de encendido del motor")]
[property: Name("Encendido")]
bool encendido;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Número del motor en el PLC")]
[property: Name("Número de Motor PLC")]
int pLC_NumeroMotor;
partial void OnPLC_NumeroMotorChanged(int value)
@ -126,27 +92,16 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Bloque de datos del motor en el PLC")]
[property: Name("DB del Motor")]
int pLC_DB_Motor;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Relación de transmisión")]
[property: Name("Ratio")]
public float ratio;
[ObservableProperty]
[property: Category("Información")]
[property: Description("Velocidad actual del motor")]
[property: Name("Velocidad")]
public float velocidad;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Invierte el sentido de giro")]
[property: Name("Sentido Contrario")]
public bool sentido_contrario;
@ -267,9 +222,9 @@ namespace CtrEditor.ObjetosSim
else
Data.Actual_Position = 0;
// Read ControlWord and track the raw response
var rawResponse = plc.LeerTagDInt($"\"DB MotorSimulate\".Motors[{DB_Motor}].ControlWord");
int controlWord = rawResponse ?? 0;
// Read ControlWord and track the raw response
var rawResponse = plc.LeerTagDInt($"\"DB MotorSimulate\".Motors[{DB_Motor}].ControlWord");
int controlWord = rawResponse ?? 0;
var control = VMMotorBitPacker.UnpackControlWord(controlWord);

View File

@ -74,13 +74,10 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
public static string NombreClase()
{
return "Buscador de Plantillas";
return "Search Templates";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
@ -88,9 +85,7 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Ejecutar búsqueda de plantillas")]
[property: Name("Buscar Plantillas")]
[property: Category("Tag Extraction:")]
bool search_templates;
partial void OnSearch_templatesChanged(bool oldValue, bool newValue)
@ -101,22 +96,16 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Capturar imagen de referencia")]
[property: Name("Tomar Clip")]
[property: Category("Tag Extraction:")]
bool tomarClip;
// En lugar de almacenar Mat directamente, guardaremos una representación serializable
[ObservableProperty]
[property: Category("Información")]
[property: Description("Datos de región capturada")]
[property: Name("Datos Región")]
[property: Category("Tag Extraction:")]
byte[] capturedRegionData;
[ObservableProperty]
[property: Category("Información")]
[property: Description("Indica si la región fue capturada")]
[property: Name("Región Capturada")]
[property: Category("Tag Extraction:")]
[property: ReadOnly(true)]
bool regionCapturada;
@ -126,27 +115,19 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
// Propiedades para almacenar las dimensiones de la captura
[ObservableProperty]
[property: Category("Información")]
[property: Description("Ancho de región capturada")]
[property: Name("Ancho Capturado")]
[property: Category("Tag Extraction:")]
int capturedWidth;
[ObservableProperty]
[property: Category("Información")]
[property: Description("Alto de región capturada")]
[property: Name("Alto Capturado")]
[property: Category("Tag Extraction:")]
int capturedHeight;
[ObservableProperty]
[property: Category("Datos")]
[property: Description("Exportar datos OCR")]
[property: Name("Exportar OCR")]
[property: Category("Tag Extraction:")]
bool export_ocr;
[ObservableProperty]
[property: Category("Datos")]
[property: Description("Texto exportado OCR")]
[property: Name("Texto Export OCR")]
[property: Category("Tag Extraction:")]
string text_export_ocr;
@ -326,7 +307,7 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
public override void AltoChanged(float newValue)
{
base.AnchoChanged(newValue);
// LimpiarRegionCapturada();
// LimpiarRegionCapturada();
}
private void LimpiarRegionCapturada()

View File

@ -17,13 +17,9 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
{
public static string NombreClase()
{
return "Extractor de Tags";
return "Extraccion Tags";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
@ -36,28 +32,20 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Ejecutar extracción de tag")]
[property: Name("Extraer")]
[property: Category("Tag Extraction:")]
bool extraer;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Eliminar saltos de línea del texto extraído")]
[property: Name("Eliminar Enter")]
[property: Category("Tag Extraction:")]
bool eliminar_enters;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Idioma para reconocimiento OCR")]
[property: Name("Idioma OCR")]
[property: Category("Tag Extraction:")]
[property: ItemsSource(typeof(IdiomasItemsSource<Idiomas>))]
string idioma_Extraccion;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Patrón de extracción de texto")]
[property: Name("Tipo de Patrón")]
[property: Category("Tag Extraction:")]
[property: ItemsSource(typeof(TagPatternItemsSource<TagPattern>))]
string pattern_Type;
@ -109,9 +97,8 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
private osBuscarCoincidencias Search_Templates;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Plantillas de búsqueda asociadas")]
[property: Name("Plantillas Búsqueda")]
[property: Description("Link to Search Templates")]
[property: Category("Tag Extraction:")]
[property: ItemsSource(typeof(osBaseItemsSource<osBuscarCoincidencias>))]
string id_Search_Templates;
@ -136,46 +123,33 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
}
[ObservableProperty]
[property: Category("Datos")]
[property: Description("Texto extraído mediante OCR")]
[property: Name("Tag Extraído")]
[property: Category("Tag Extraction:")]
string tag_extract;
[ObservableProperty]
[property: Category("Datos")]
[property: Description("Clase del objeto para exportación")]
[property: Name("Clase")]
[property: Category("Export:")]
string clase;
[ObservableProperty]
[property: Category("Datos")]
[property: Description("Nombre de la columna para exportación")]
[property: Name("Nombre Columna")]
[property: Category("Export:")]
string collumn_name;
[ObservableProperty]
[property: Category("Datos")]
[property: Description("Número de columna Excel")]
[property: Name("Número Columna")]
[property: Description("Excel collumn.")]
[property: Category("Export:")]
int collumn_number;
[ObservableProperty]
[property: Category("Información")]
[property: Description("Número de copia del objeto")]
[property: Name("Número de Copia")]
[property: Category("Tag Extraction:")]
[property: ReadOnly(true)]
int copy_Number;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Mostrar ventana de depuración OCR")]
[property: Name("Mostrar Debug")]
[property: Category("Tag Extraction:")]
bool show_Debug_Window;
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Opacidad del objeto")]
[property: Name("Opacidad")]
float opacity_oculto;
public osExtraccionTag()
@ -192,7 +166,7 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
public void CaptureImageAreaAndDoOCR()
{
string extractedText = CaptureImageAreaAndDoOCRPPaddle(Left, Top, Ancho, Alto, Angulo, Show_Debug_Window);
// Clean up the extracted text if eliminar_enters is true
if (Eliminar_enters && !string.IsNullOrEmpty(extractedText))
{

View File

@ -1,11 +1,11 @@
using CommunityToolkit.Mvvm.ComponentModel;
using LibS7Adv;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using CtrEditor.FuncionesBase;
using System.ComponentModel;
namespace CtrEditor.ObjetosSim
{
@ -18,13 +18,9 @@ namespace CtrEditor.ObjetosSim
public static string NombreClase()
{
return "Botón";
return "Boton";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
@ -32,52 +28,31 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Texto mostrado en el botón")]
[property: Name("Texto del Botón")]
string button_Name;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Tipo normalmente cerrado")]
[property: Name("Normalmente Cerrado")]
public bool tipo_NC;
[ObservableProperty]
[property: Hidden]
[property: Category("Apariencia")]
[property: Description("Color cuando está presionado")]
[property: Name("Color Presionado")]
Color color_Pressed;
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Color del texto del botón")]
[property: Name("Color del Texto")]
Color color_Titulo;
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Color principal del botón")]
[property: Name("Color")]
Color color;
partial void OnColorChanged(Color value)
{
OnEstadoChanged(Estado);
}
[ObservableProperty]
[property: Hidden]
[property: Category("Apariencia")]
[property: Description("Color actual del botón")]
[property: Name("Color Actual")]
private Color colorButton;
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Tamaño visual del botón")]
[property: Name("Tamaño")]
public float tamano;
public override void OnResize(float Delta_Width, float Delta_Height)
@ -86,9 +61,6 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Estado actual del botón")]
[property: Name("Estado")]
public bool estado;
partial void OnEstadoChanged(bool value)
@ -104,15 +76,9 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Dirección del tag en el PLC")]
[property: Name("Tag PLC")]
public string tag;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Tag para controlar luz indicadora")]
[property: Name("Tag Luz")]
public string tag_Luz;
public void ButtonDownCommand()
@ -144,12 +110,11 @@ namespace CtrEditor.ObjetosSim
public override void UpdatePLC(PLCViewModel plc, int elapsedMilliseconds)
{
if (LeerBitTag(Tag_Luz))
ColorButton = ObtenerColorMasClaroYSaturado(Color, 0.3, 0.5);
ColorButton = ObtenerColorMasClaroYSaturado(Color, 0.3, 0.5);
else ColorButton = Color;
}
public override void UpdatePLCPrimerCiclo()
{
public override void UpdatePLCPrimerCiclo() {
// Escribimos el valor actual al iniciar la conexion
// Esto es util para NC principalmente

View File

@ -17,14 +17,10 @@ namespace CtrEditor.ObjetosSim
public static string NombreClase()
{
return "Encoder de Motor";
return "Encoder Motor";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
@ -32,46 +28,35 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Color visual del encoder")]
[property: Name("Color")]
private Brush color_oculto;
[ObservableProperty]
[property: Category("Información")]
[property: Description("Velocidad actual del motor")]
[property: Name("Velocidad Actual")]
public float velocidadActual;
[ObservableProperty]
[property: Category("Encoder")]
[property: Description("Pulsos por vuelta del encoder")]
[property: Name("Pulsos por Vuelta")]
[property: Category("Encoder Config:")]
public float pulsos_Por_Vuelta;
[ObservableProperty]
[property: Category("Encoder")]
[property: Description("Ratio de giros por 50Hz")]
[property: Name("Ratio Giros 50Hz")]
[property: Category("Encoder Config:")]
public float ratio_Giros_50hz;
[ObservableProperty]
[property: Category("Información")]
[property: Description("Valor actual del encoder")]
[property: Name("Valor Actual")]
[property: Category("Encoder Status:")]
public float valor_Actual;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Motor enlazado al encoder")]
[property: Name("Motor Enlazado")]
[property: Description("Link to Motor")]
[property: Category("PLC link:")]
[property: ItemsSource(typeof(osBaseItemsSource<osVMmotorSim>))]
string id_Motor;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Tag PLC para valor del encoder")]
[property: Name("Tag Valor")]
[property: Description("Tag para escribir el valor del encoder")]
[property: Category("PLC link:")]
string tag_Valor;
partial void OnId_MotorChanged(string value)

View File

@ -21,10 +21,6 @@ namespace CtrEditor.ObjetosSim
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
@ -32,46 +28,35 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Color visual del encoder")]
[property: Name("Color")]
private Brush color_oculto;
[ObservableProperty]
[property: Category("Información")]
[property: Description("Velocidad actual del motor")]
[property: Name("Velocidad Actual")]
public float velocidadActual;
[ObservableProperty]
[property: Category("Encoder")]
[property: Description("Pulsos por Hz por segundo (K)")]
[property: Name("Pulsos por Hz")]
[property: Description("Pulsos por Hz por segundo : K")]
[property: Category("Encoder Config:")]
public float pulsos_Por_Hz;
[ObservableProperty]
[property: Category("Información")]
[property: Description("Valor actual del encoder")]
[property: Name("Valor Actual")]
[property: Category("Encoder Status:")]
public float valor_Actual;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Motor enlazado al encoder")]
[property: Name("Motor Enlazado")]
[property: Description("Link to Motor")]
[property: Category("PLC link:")]
[property: ItemsSource(typeof(osBaseItemsSource<osVMmotorSim>))]
string id_Motor;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Tag PLC para escribir valor del encoder")]
[property: Name("Tag Valor Escritura")]
[property: Description("Tag para escribir el valor del encoder")]
[property: Category("PLC link:")]
string tag_Valor;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Tag PLC para leer valor del encoder (tiene prioridad sobre motor)")]
[property: Name("Tag Valor Lectura")]
[property: Description("Tag para leer el valor del encoder. Este tag tiene prioridad sobre el Motor. Si se usa solo se lee el tag para actualizar la posicion.")]
[property: Category("PLC link:")]
string tag_ReadValor;

View File

@ -24,14 +24,10 @@ namespace CtrEditor.ObjetosSim
public static string NombreClase()
{
return "Encoder de Engranaje";
return "Ruota Fonica";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
@ -39,15 +35,8 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Tag PLC para señal de pulso")]
[property: Name("Tag PLC")]
public string tag;
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Estado actual del pulso")]
[property: Name("Pulso")]
public bool pulso;
partial void OnPulsoChanged(bool value)
@ -67,33 +56,20 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Color visual del encoder")]
[property: Name("Color")]
private Brush color_oculto;
[ObservableProperty]
[property: Category("Información")]
[property: Description("Velocidad actual del encoder")]
[property: Name("Velocidad Actual")]
public float velocidadActual;
public override void AnguloChanged(float value)
public override void AnguloChanged(float value)
{
// Generar pulsos cuadrados en función del ángulo
Pulso = DetectarDiente();
}
[ObservableProperty]
[property: Category("Información")]
[property: Description("Tiempo entre pulsos en ms")]
[property: Name("Tiempo de Pulso")]
public float tiempo_Pulso;
[ObservableProperty]
[property: Category("Información")]
[property: Description("Pulsos generados por segundo")]
[property: Name("Pulsos por Segundo")]
public float pulsos_Por_Segundo;
partial void OnPulsos_Por_SegundoChanged(float value)
@ -102,9 +78,6 @@ namespace CtrEditor.ObjetosSim
Giros_segundo_a_100 = (float)((pulsos_Por_Segundo / Dientes) * 100 / VelocidadActual);
}
[ObservableProperty]
[property: Category("Encoder")]
[property: Description("Ejecutar homing del encoder")]
[property: Name("Homing")]
private bool homing;
partial void OnHomingChanged(bool value)
@ -114,33 +87,14 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Encoder")]
[property: Description("Número de dientes del encoder")]
[property: Name("Cantidad de Dientes")]
public float dientes;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Radio interno del encoder")]
[property: Name("Radio Interno")]
public float radio_Interno;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Radio externo del encoder")]
[property: Name("Radio Externo")]
public float radio_Externo;
[ObservableProperty]
[property: Category("Encoder")]
[property: Description("Ancho de los dientes (0-1)")]
[property: Name("Ancho de Dientes")]
public float ancho_Dientes;
[ObservableProperty]
[property: Category("Encoder")]
[property: Description("Giros por segundo al 100%")]
[property: Name("Giros/seg al 100%")]
public float giros_segundo_a_100;
public override void OnResize(float Delta_Width, float Delta_Height)
@ -150,9 +104,8 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Motor enlazado al encoder")]
[property: Name("Motor Enlazado")]
[property: Description("Link to Motor")]
[property: Category("PLC link:")]
[property: ItemsSource(typeof(osBaseItemsSource<osVMmotorSim>))]
string id_Motor;
@ -177,7 +130,7 @@ namespace CtrEditor.ObjetosSim
}
public osGearEncoder()
{
{
Ancho_Dientes = 0.5f;
Dientes = 10;
Radio_Interno = 0.5f;
@ -239,7 +192,7 @@ namespace CtrEditor.ObjetosSim
if (Motor != null)
{
if (Motor is osVMmotorSim motor)
{
{
if (motor.Sentido_contrario)
VelocidadActual = -motor.Velocidad;
else

View File

@ -1,4 +1,5 @@
using CtrEditor.Simulacion;

using CtrEditor.Simulacion;
using LibS7Adv;
using System.Windows;
using System.Windows.Controls;
@ -21,32 +22,26 @@ namespace CtrEditor.ObjetosSim
Stopwatch timer;
double timer_lastPositive;
double timer_lastNegative;
public static string NombreClase()
{
return "Fotocélula";
return "Photocell";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
set => SetProperty(ref nombre, value);
}
[ObservableProperty]
[property: Description("Color del sensor")]
[property: Category("Apariencia")]
[property: Name("Color")]
[ObservableProperty]
[property: Description("Color")]
[property: Category("Layout:")]
Brush color;
[ObservableProperty]
[property: Description("Indica si la luz está cortada por un objeto")]
[property: Category("Información")]
[property: Name("Luz Cortada")]
[property: Description("Light cut")]
[property: Category("Debug:")]
bool luzCortada;
partial void OnLuzCortadaChanged(bool value)
@ -65,12 +60,10 @@ namespace CtrEditor.ObjetosSim
Frecuency = 0;
}
if (!value)
{
Lenght_positive_pulse = (float)(timer.Elapsed.TotalMilliseconds - timer_lastPositive);
timer_lastNegative = timer.Elapsed.TotalMilliseconds;
}
else
if (!value) {
Lenght_positive_pulse = (float) (timer.Elapsed.TotalMilliseconds - timer_lastPositive);
timer_lastNegative = timer.Elapsed.TotalMilliseconds;
} else
{
Lenght_negative_pulse = (float)(timer.Elapsed.TotalMilliseconds - timer_lastNegative);
timer_lastPositive = timer.Elapsed.TotalMilliseconds;
@ -81,21 +74,18 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Description("Ancho del haz de luz del sensor")]
[property: Category("Configuración")]
[property: Name("Ancho del Haz")]
[property: Description("Size of the Light.")]
[property: Category("Setup:")]
float ancho_Haz_De_Luz;
[ObservableProperty]
[property: Description("Distancia al cuello de la botella")]
[property: Category("Información")]
[property: Name("Distancia al Cuello")]
[property: Description("Distance to the neck.")]
[property: Category("Debug:")]
float distancia_cuello;
[ObservableProperty]
[property: Description("Tipo de detección: cuello de botella o botella completa")]
[property: Category("Configuración")]
[property: Name("Detectar Cuello")]
[property: Description("Type of detection: Neck of the bottle or Complete bottle.")]
[property: Category("Setup:")]
bool detectarCuello;
partial void OnDetectarCuelloChanged(bool value)
@ -107,45 +97,35 @@ namespace CtrEditor.ObjetosSim
[ObservableProperty]
[property: Description("Filtro de frecuencia para la señal")]
[property: Category("Configuración")]
[property: Name("Filtro de Frecuencia")]
[property: Description("Filter signal.")]
[property: Category("Setup:")]
float filter_Frecuency;
partial void OnFilter_FrecuencyChanged(float value)
{
if (value <= 0)
if (value<=0)
Filter_Frecuency = 10;
}
[ObservableProperty]
[property: Category("Información")]
[property: Description("Frecuencia calculada")]
[property: Name("Frecuencia")]
[property: Category("Debug:")]
float frecuency;
[ObservableProperty]
[property: Category("Información")]
[property: Description("Duración del pulso positivo")]
[property: Name("Duración Pulso Positivo")]
[property: Category("Debug:")]
float lenght_positive_pulse;
[ObservableProperty]
[property: Category("Información")]
[property: Description("Duración del pulso negativo")]
[property: Name("Duración Pulso Negativo")]
[property: Category("Debug:")]
float lenght_negative_pulse;
[ObservableProperty]
[property: Category("Información")]
[property: Description("Tiempo de flanco positivo a flanco positivo")]
[property: Name("Tiempo FP a FP")]
[property: Category("Debug:")]
float lenght_FP_to_FP;
[ObservableProperty]
[property: Description("Tipo de contacto: Normalmente Cerrado")]
[property: Category("Configuración")]
[property: Name("Tipo NC")]
[property: Description("Type Filter signal.")]
[property: Category("Setup:")]
public bool tipo_NC;
partial void OnTipo_NCChanged(bool value)
@ -154,9 +134,6 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Tag de salida de la fotocélula")]
[property: Name("Tag de Salida")]
public string tagPhotocell_OUT;
@ -222,8 +199,7 @@ namespace CtrEditor.ObjetosSim
OnLuzCortadaChanged(LuzCortada);
}
public override void UpdatePLC(PLCViewModel plc, int elapsedMilliseconds)
{
public override void UpdatePLC(PLCViewModel plc, int elapsedMilliseconds) {
}
public override void ucLoaded()
{

View File

@ -17,13 +17,9 @@ namespace CtrEditor.ObjetosSim
public static string NombreClase()
{
return "Sensor de Temperatura";
return "Temperatura";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
@ -31,27 +27,13 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Tag PLC para valor de temperatura")]
[property: Name("Tag PLC")]
public string tag;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Valor mínimo escalado")]
[property: Name("Mínimo Escalado")]
public float min_OUT_Scaled;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Valor máximo escalado")]
[property: Name("Máximo Escalado")]
public float max_OUT_Scaled;
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Valor actual de temperatura")]
[property: Name("Temperatura")]
public float value;
partial void OnValueChanged(float value)
@ -69,7 +51,7 @@ namespace CtrEditor.ObjetosSim
public override void UpdatePLC(PLCViewModel plc, int elapsedMilliseconds)
{
}
public override void UpdatePLCPrimerCiclo()
{

View File

@ -1,4 +1,3 @@
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
@ -13,26 +12,9 @@ namespace CtrEditor.ObjetosSim
/// <summary>
/// Atributo para marcar propiedades que deben usar el editor de etiquetas
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class TagEditorAttribute : Attribute
{
public Type? EditorType { get; }
public TagEditorAttribute(Type? editorType = null)
{
EditorType = editorType;
}
}
[AttributeUsage(AttributeTargets.Property)]
public class NameAttribute : Attribute
{
public string DisplayName { get; }
public NameAttribute(string displayName)
{
DisplayName = displayName ?? throw new ArgumentNullException(nameof(displayName));
}
public TagEditorAttribute() { }
}
/// <summary>

View File

@ -1,11 +1,11 @@
using LibS7Adv;

using LibS7Adv;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using Newtonsoft.Json.Linq;
using CtrEditor.FuncionesBase;
using System.ComponentModel;
namespace CtrEditor.ObjetosSim
{
@ -21,13 +21,9 @@ namespace CtrEditor.ObjetosSim
public static string NombreClase()
{
return "Tag Analógico";
return "Analog Tag";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
@ -35,9 +31,6 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Tamaño visual del tag")]
[property: Name("Tamaño")]
public float tamano;
public override void OnResize(float Delta_Width, float Delta_Height)
@ -47,49 +40,23 @@ namespace CtrEditor.ObjetosSim
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(Value))]
[property: Category("Enlace PLC")]
[property: Description("Dirección del tag en el PLC")]
[property: Name("Tag")]
public string tag;
[ObservableProperty]
[property: Category("Identificación")]
[property: Description("Descripción del tag")]
[property: Name("Descripción")]
public string descripcion;
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(Value))]
[property: Category("Configuración")]
[property: Description("Valor mínimo de entrada escalado")]
[property: Name("Mínimo Entrada")]
public float min_IN_Scaled;
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(Value))]
[property: Category("Configuración")]
[property: Description("Valor máximo de entrada escalado")]
[property: Name("Máximo Entrada")]
public float max_IN_Scaled;
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(Value))]
[property: Category("Configuración")]
[property: Description("Valor mínimo de salida escalado")]
[property: Name("Mínimo Salida")]
public float min_OUT_Scaled;
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(Value))]
[property: Category("Configuración")]
[property: Description("Valor máximo de salida escalado")]
[property: Name("Máximo Salida")]
public float max_OUT_Scaled;
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Valor actual del tag")]
[property: Name("Valor")]
public float value;
partial void OnValueChanged(float value)

View File

@ -27,7 +27,7 @@
Width="16" Height="25" VerticalAlignment="Center" HorizontalAlignment="Center"
Background="{Binding Color, Converter={StaticResource ColorToBrushConverter}}" />
<Label Content="{Binding Descripcion}" Grid.Column="1" VerticalAlignment="Center"
Background="{Binding Color, Converter={StaticResource ColorToBrushConverter}}"
Background="{Binding Color}"
Visibility="{Binding Show_Description, Converter={StaticResource BooleanToVisibilityConverter}}" />
<CheckBox Grid.Column="2" VerticalAlignment="Center" IsChecked="{Binding Estado}"
Background="{Binding Color_oculto}" />

View File

@ -6,7 +6,6 @@ using System.Windows.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using Newtonsoft.Json.Linq;
using CtrEditor.FuncionesBase;
using System.ComponentModel;
namespace CtrEditor.ObjetosSim
{
@ -22,13 +21,9 @@ namespace CtrEditor.ObjetosSim
public static string NombreClase()
{
return "Tag Digital";
return "Bool Tag";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
@ -36,42 +31,27 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Color de fondo cuando está activo")]
[property: Name("Color de Fondo")]
private Brush color_oculto;
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Color del tag")]
[property: Name("Color")]
Color color;
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Estado actual del tag")]
[property: Name("Estado")]
public bool estado;
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Mostrar descripción en el objeto")]
[property: Name("Mostrar Descripción")]
public bool show_Description;
partial void OnEstadoChanged(bool value)
{
EscribirBitTag(Tag, value);
EscribirBitTag(Tag, value);
if (value)
Color_oculto = Brushes.LightGreen;
else
Color_oculto = Brushes.Transparent;
}
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Tamaño visual del tag")]
[property: Name("Tamaño")]
public float tamano;
public override void OnResize(float Delta_Width, float Delta_Height)
@ -80,17 +60,11 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Dirección del tag en el PLC")]
[property: Name("Tag PLC")]
[NotifyPropertyChangedFor(nameof(Estado))]
public string tag;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Descripción del tag")]
[property: Name("Descripción")]
public string descripcion;
public string descripcion;
public osBoolTag()
{

View File

@ -2,7 +2,6 @@
using System.Windows;
using System.Windows.Controls;
using CtrEditor.FuncionesBase;
using System.ComponentModel;
namespace CtrEditor.ObjetosSim
@ -16,22 +15,15 @@ namespace CtrEditor.ObjetosSim
public TagsConsensos Consensos = new TagsConsensos();
[ObservableProperty]
[property: Category("Datos")]
[property: Description("Lista de tags para consenso")]
[property: Name("Tags")]
public List<string> tags;
// Otros datos y métodos relevantes para la simulación
public static string NombreClase()
{
return "Consenso Genérico";
return "Consensi";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
@ -39,9 +31,6 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Tamaño del consenso")]
[property: Name("Tamaño")]
public float tamano;
public override void OnResize(float Delta_Width, float Delta_Height)

View File

@ -7,7 +7,6 @@ using System.Windows.Shapes;
using LibS7Adv;
using System.Runtime.Intrinsics;
using CtrEditor.FuncionesBase;
using System.ComponentModel;
namespace CtrEditor.ObjetosSim
{
@ -24,13 +23,9 @@ namespace CtrEditor.ObjetosSim
public static string NombreClase()
{
return "Trazador de 3 Señales";
return "Trace3";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
@ -38,75 +33,31 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Color de la serie 1")]
[property: Name("Color Serie 1")]
private Brush color_Serie_1;
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Color de la serie 2")]
[property: Name("Color Serie 2")]
private Brush color_Serie_2;
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Color de la serie 3")]
[property: Name("Color Serie 3")]
private Brush color_Serie_3;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Alto del trazador")]
[property: Name("Alto")]
float alto;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Ancho del trazador")]
[property: Name("Ancho")]
float ancho;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Serie 1 es tipo booleana")]
[property: Name("Serie 1 Bool")]
bool serie1_Tipo_Bool;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Tag PLC para serie 1")]
[property: Name("Tag Serie 1")]
string tag_Serie1;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Serie 2 es tipo booleana")]
[property: Name("Serie 2 Bool")]
bool serie2_Tipo_Bool;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Tag PLC para serie 2")]
[property: Name("Tag Serie 2")]
string tag_Serie2;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Serie 3 es tipo booleana")]
[property: Name("Serie 3 Bool")]
bool serie3_Tipo_Bool;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Tag PLC para serie 3")]
[property: Name("Tag Serie 3")]
string tag_Serie3;
[ObservableProperty]
[property: Category("Identificación")]
[property: Description("Título del trazador")]
[property: Name("Título")]
string titulo;
[ObservableProperty]
@ -138,9 +89,6 @@ namespace CtrEditor.ObjetosSim
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Máximo número de elementos a mostrar")]
[property: Name("Max Elementos")]
float max_Cantidad_Elementos;
public osTrace3()
@ -331,8 +279,7 @@ namespace CtrEditor.ObjetosSim
{
Datos?.ucUnLoaded();
}
public void Resize(float width, float height)
{
public void Resize(float width, float height) {
if (Datos is osTrace3 datos)
{
datos.Ancho += PixelToMeter.Instance.calc.PixelsToMeters(width);
@ -347,8 +294,7 @@ namespace CtrEditor.ObjetosSim
Datos.Top = PixelToMeter.Instance.calc.PixelsToMeters(TopPixels);
}
}
public float Angle() { return 0; }
public void Rotate(float Angle) { }
public float Angle() { return 0; } public void Rotate(float Angle) { }
public void Highlight(bool State) { }
public ZIndexEnum ZIndex_Base()
{

View File

@ -11,7 +11,6 @@ using LiveChartsCore.SkiaSharpView;
using LiveChartsCore.Defaults;
using System.Diagnostics;
using CtrEditor.FuncionesBase;
using System.ComponentModel;
namespace CtrEditor.ObjetosSim
{
@ -29,13 +28,9 @@ namespace CtrEditor.ObjetosSim
public static string NombreClase()
{
return "Trazador Simple";
return "Trace";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
@ -43,33 +38,18 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Alto del trazador")]
[property: Name("Alto")]
float alto;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Ancho del trazador")]
[property: Name("Ancho")]
float ancho;
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Tag PLC para la serie de datos")]
[property: Name("Tag Serie")]
string tag_serie;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Nombre del eje X")]
[property: Name("Nombre Eje X")]
string x_Series_Name;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Nombre del eje Y")]
[property: Name("Nombre Eje Y")]
string y_Series_Name;
private readonly ObservableCollection<ObservableValue> _observableValues;
@ -90,7 +70,7 @@ namespace CtrEditor.ObjetosSim
}
};
data = new List<float>();
stopwatch = new Stopwatch();
stopwatch = new Stopwatch();
YScale = 2.0;
Alto = 1;
@ -105,13 +85,12 @@ namespace CtrEditor.ObjetosSim
public override void UpdatePLCPrimerCiclo()
{
stopwatch.Start();
stopwatch.Start();
}
public override void UpdatePLC(PLCViewModel plc, int elapsedMilliseconds)
{
if (Tag_serie != null && Tag_serie.Length > 0)
{
if (Tag_serie != null && Tag_serie.Length > 0) {
var value = LeerBitTag(Tag_serie) == false ? 0 : 1;
data.Add(value);
}
@ -120,14 +99,14 @@ namespace CtrEditor.ObjetosSim
if (stopwatch.Elapsed.TotalMilliseconds > 1000)
{
stopwatch.Reset();
stopwatch.Start();
stopwatch.Start();
foreach (var v in data)
{
_observableValues.Add(new(v));
if (_observableValues.Count > 50)
if (_observableValues.Count > 50)
_observableValues.RemoveAt(0);
}
}
}
@ -165,8 +144,7 @@ namespace CtrEditor.ObjetosSim
{
Datos?.ucUnLoaded();
}
public void Resize(float width, float height)
{
public void Resize(float width, float height) {
if (Datos is osTraceSimple datos)
{
datos.Ancho += PixelToMeter.Instance.calc.PixelsToMeters(width);
@ -181,8 +159,7 @@ namespace CtrEditor.ObjetosSim
Datos.Top = PixelToMeter.Instance.calc.PixelsToMeters(TopPixels);
}
}
public float Angle() { return 0; }
public void Rotate(float Angle) { }
public float Angle() { return 0; } public void Rotate(float Angle) { }
public void Highlight(bool State) { }
public ZIndexEnum ZIndex_Base()
{

View File

@ -91,7 +91,7 @@ namespace CtrEditor.ObjetosSim
{
// Forzar la actualización de bindings pendientes antes de limpiar
ForzarActualizacionBindings(propertyGrid);
// Clear previous properties
propertyGrid.SelectedObject = null;
propertyGrid.PropertyDefinitions.Clear();
@ -129,7 +129,7 @@ namespace CtrEditor.ObjetosSim
// Pequeña pausa para permitir que se procesen los eventos
System.Windows.Threading.Dispatcher.CurrentDispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.Background,
System.Windows.Threading.DispatcherPriority.Background,
new Action(() => { }));
}
catch (Exception ex)
@ -144,7 +144,7 @@ namespace CtrEditor.ObjetosSim
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
// Buscar TextBox, ComboBox, y otros controles de edición comunes
if (child is TextBox textBox)
{
@ -163,7 +163,7 @@ namespace CtrEditor.ObjetosSim
var expression = checkBox.GetBindingExpression(CheckBox.IsCheckedProperty);
expression?.UpdateSource();
}
// Recursión para buscar en controles hijos
ForzarActualizacionControlesEditores(child);
}
@ -173,7 +173,7 @@ namespace CtrEditor.ObjetosSim
{
// Forzar la actualización de bindings pendientes antes de cambiar el objeto
ForzarActualizacionBindings(propertyGrid);
// Limpia las propiedades previas
propertyGrid.SelectedObject = null;
propertyGrid.PropertyDefinitions.Clear();
@ -190,26 +190,12 @@ namespace CtrEditor.ObjetosSim
continue;
var displayNameAttr = property.Attributes.OfType<DisplayNameAttribute>().FirstOrDefault();
var customNameAttr = property.Attributes.OfType<NameAttribute>().FirstOrDefault();
string displayName;
if (customNameAttr != null)
{
displayName = customNameAttr.DisplayName;
}
else if (displayNameAttr != null)
{
displayName = displayNameAttr.DisplayName;
}
else
{
displayName = property.Name.Replace("_", " ");
}
var propertyDefinition = new PropertyDefinition
{
TargetProperties = new[] { property.Name },
DisplayName = displayName
DisplayName = displayNameAttr != null
? displayNameAttr.DisplayName
: property.Name.Replace("_", " ")
};
// Aquí se añaden todas las propiedades; para "ImagePath" no se requiere

View File

@ -5,24 +5,8 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CtrEditor.ObjetosSim.UserControls"
mc:Ignorable="d" Name="circularSegmentControl">
<Canvas Name="mainCanvas">
<Path Name="path" Stroke="Black" StrokeThickness="1">
<Path.Fill>
<VisualBrush TileMode="Tile" Viewport="0,0,20,20" ViewportUnits="Absolute">
<VisualBrush.Transform>
<TransformGroup>
<TranslateTransform X="0" Y="0"/>
</TransformGroup>
</VisualBrush.Transform>
<VisualBrush.Visual>
<Canvas Width="20" Height="20">
<!-- Patrón de rayas radiales que simulan el movimiento tangencial -->
<Rectangle Fill="LightGray" Width="10" Height="10" Canvas.Left="0" Canvas.Top="0"/>
<Rectangle Fill="GhostWhite" Width="10" Height="10" Canvas.Left="0" Canvas.Top="10"/>
</Canvas>
</VisualBrush.Visual>
</VisualBrush>
</Path.Fill>
<Canvas>
<Path Name="path" Stroke="Black" Fill="LightBlue" StrokeThickness="1">
<Path.RenderTransform>
<RotateTransform Angle="{Binding Angle, ElementName=circularSegmentControl}"/>
</Path.RenderTransform>

View File

@ -1,7 +1,6 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
namespace CtrEditor.ObjetosSim.UserControls
{
@ -55,95 +54,21 @@ namespace CtrEditor.ObjetosSim.UserControls
public static readonly DependencyProperty EndAngleProperty =
DependencyProperty.Register("EndAngle", typeof(double), typeof(CircularSegment), new PropertyMetadata(90.0, OnPropertyChanged));
// Nuevas propiedades para las guías
public bool ShowGuides
{
get { return (bool)GetValue(ShowGuidesProperty); }
set { SetValue(ShowGuidesProperty, value); }
}
public static readonly DependencyProperty ShowGuidesProperty =
DependencyProperty.Register("ShowGuides", typeof(bool), typeof(CircularSegment), new PropertyMetadata(false, OnPropertyChanged));
public double GuideDistance
{
get { return (double)GetValue(GuideDistanceProperty); }
set { SetValue(GuideDistanceProperty, value); }
}
public static readonly DependencyProperty GuideDistanceProperty =
DependencyProperty.Register("GuideDistance", typeof(double), typeof(CircularSegment), new PropertyMetadata(5.0, OnPropertyChanged));
public double GuideThickness
{
get { return (double)GetValue(GuideThicknessProperty); }
set { SetValue(GuideThicknessProperty, value); }
}
public static readonly DependencyProperty GuideThicknessProperty =
DependencyProperty.Register("GuideThickness", typeof(double), typeof(CircularSegment), new PropertyMetadata(2.0, OnPropertyChanged));
public static readonly DependencyProperty GuideStrokeProperty =
DependencyProperty.Register("GuideStroke", typeof(Brush), typeof(CircularSegment), new PropertyMetadata(new SolidColorBrush(Colors.DarkBlue), OnGuidePropertyChanged));
public Brush GuideStroke
{
get { return (Brush)GetValue(GuideStrokeProperty); }
set { SetValue(GuideStrokeProperty, value); }
}
public CircularSegment()
{
InitializeComponent();
this.Loaded += CircularSegment_Loaded;
}
private void CircularSegment_Loaded(object sender, RoutedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("CircularSegment_Loaded called");
DrawSegment();
}
// Propiedad pública para acceder al Path desde código externo
public System.Windows.Shapes.Path TransportePath => path;
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as CircularSegment)?.DrawSegment();
}
private static void OnGuidePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as CircularSegment)?.DrawSegment();
}
private void DrawSegment()
{
System.Diagnostics.Debug.WriteLine($"DrawSegment called - ShowGuides: {ShowGuides}");
if (OuterRadius <= 0 || InnerRadius <= 0 || StartAngle == EndAngle)
return;
// Limpiar canvas existente - mantener solo el path principal
for (int i = mainCanvas.Children.Count - 1; i >= 0; i--)
{
if (mainCanvas.Children[i] != path)
{
mainCanvas.Children.RemoveAt(i);
}
}
DrawMainSegment();
if (ShowGuides)
{
System.Diagnostics.Debug.WriteLine("About to call DrawGuides()");
DrawGuides();
}
}
private void DrawMainSegment()
{
PathGeometry geometry = new PathGeometry();
PathFigure figure = new PathFigure();
@ -175,76 +100,5 @@ namespace CtrEditor.ObjetosSim.UserControls
geometry.Figures.Add(figure);
path.Data = geometry;
}
private void DrawGuides()
{
Point center = new Point(OuterRadius, OuterRadius);
// Calcular radios de las guías
double outerGuideRadius = OuterRadius + GuideDistance;
double innerGuideRadius = InnerRadius - GuideDistance;
System.Diagnostics.Debug.WriteLine($"DrawGuides - Creating guides with radii: Outer={outerGuideRadius}, Inner={innerGuideRadius}");
// Asegurar que el radio interior no sea negativo
if (innerGuideRadius < 1.0)
innerGuideRadius = 1.0;
// Crear guía exterior
CreateGuideArc(center, outerGuideRadius, "OuterGuide");
// Crear guía interior solo si el radio es válido
if (innerGuideRadius > 1.0)
{
CreateGuideArc(center, innerGuideRadius, "InnerGuide");
}
}
private void CreateGuideArc(Point center, double radius, string name)
{
var guidePath = new System.Windows.Shapes.Path
{
Name = name,
Stroke = GuideStroke,
StrokeThickness = GuideThickness,
Fill = null
};
// Crear geometría del arco
double radiansStart = StartAngle * Math.PI / 180.0;
double radiansEnd = EndAngle * Math.PI / 180.0;
Point startPoint = new Point(
center.X + radius * Math.Cos(radiansStart),
center.Y + radius * Math.Sin(radiansStart)
);
Point endPoint = new Point(
center.X + radius * Math.Cos(radiansEnd),
center.Y + radius * Math.Sin(radiansEnd)
);
// Crear el arco usando ArcSegment
var pathGeometry = new PathGeometry();
var pathFigure = new PathFigure
{
StartPoint = startPoint
};
var arcSegment = new ArcSegment
{
Point = endPoint,
Size = new Size(radius, radius),
SweepDirection = SweepDirection.Clockwise,
IsLargeArc = Math.Abs(EndAngle - StartAngle) > 180
};
pathFigure.Segments.Add(arcSegment);
pathGeometry.Figures.Add(pathFigure);
guidePath.Data = pathGeometry;
System.Diagnostics.Debug.WriteLine($"Adding guide {name} to canvas");
mainCanvas.Children.Add(guidePath);
}
}
}

View File

@ -71,8 +71,8 @@ namespace CtrEditor.ObjetosSim
[JsonIgnore]
private System.Threading.Timer timer = null;
[JsonIgnore]
[ObservableProperty]
[property: JsonIgnore]
[property: Hidden]
public bool isVisFilter;
@ -80,15 +80,13 @@ namespace CtrEditor.ObjetosSim
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Bloquear movimiento del objeto")]
[property: Name("Bloquear Movimiento")]
[property: Description("Lock object to mouse movement.")]
[property: Category("Layout:")]
private bool lock_movement;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Coordenada X del objeto")]
[property: Name("Izquierda")]
[property: Description("X coordinate.")]
[property: Category("Layout:")]
private float left;
public void CheckData()
@ -116,9 +114,8 @@ namespace CtrEditor.ObjetosSim
public virtual void LeftChanging(float oldValue, float newValue) { }
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Coordenada Y del objeto")]
[property: Name("Superior")]
[property: Description("Y coordinate.")]
[property: Category("Layout:")]
private float top;
partial void OnTopChanged(float value)
@ -140,9 +137,8 @@ namespace CtrEditor.ObjetosSim
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Ancho del objeto")]
[property: Name("Ancho")]
[property: Description("Widht.")]
[property: Category("Layout:")]
private float ancho;
partial void OnAnchoChanged(float value)
@ -152,9 +148,8 @@ namespace CtrEditor.ObjetosSim
public virtual void AnchoChanged(float value) { }
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Alto del objeto")]
[property: Name("Alto")]
[property: Description("Height.")]
[property: Category("Layout:")]
private float alto;
partial void OnAltoChanged(float value)
@ -165,9 +160,8 @@ namespace CtrEditor.ObjetosSim
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Ángulo de rotación del objeto")]
[property: Name("Ángulo")]
[property: Description("Angle.")]
[property: Category("Layout:")]
private float angulo;
partial void OnAnguloChanged(float value)
@ -183,9 +177,8 @@ namespace CtrEditor.ObjetosSim
public virtual void AnguloChanging(float oldValue, float newValue) { }
[ObservableProperty]
[property: Category("Identificación")]
[property: Description("Etiquetas para clasificar el objeto. Use # antes de cada etiqueta (ej: #motor #bomba #critico)")]
[property: Name("Etiquetas")]
[property: Category("General:")]
[property: Editor(typeof(TagPropertyEditor), typeof(TagPropertyEditor))]
[property: TagEditor]
private string etiquetas = "";
@ -297,9 +290,8 @@ namespace CtrEditor.ObjetosSim
// Group as FacePlate
[ObservableProperty]
[property: Category("Agrupación")]
[property: Description("Enlace a una placa de texto como ancla")]
[property: Name("Panel Grupo")]
[property: Description("This is a link to a faceplate. It works like an anchor.")]
[property: Category("Group:")]
[property: ItemsSource(typeof(osBaseItemsSource<osTextPlate>))]
private string group_Panel;
@ -341,9 +333,8 @@ namespace CtrEditor.ObjetosSim
// Group as FacePlate
[ObservableProperty]
[property: Category("Agrupación")]
[property: Description("Enlace a un marco que se mueve automáticamente como ancla")]
[property: Name("Panel Marco")]
[property: Description("This is a link to a FromPlate that moves automatically. It works like an anchor.")]
[property: Category("Group:")]
[property: ItemsSource(typeof(osBaseItemsSource<osFramePlate>))]
private string group_FramePanel;
@ -353,28 +344,28 @@ namespace CtrEditor.ObjetosSim
private bool isUpdatingFromFramePlate = false;
// Variables para rotación orbital alrededor del FramePlate
[JsonIgnore]
[ObservableProperty]
[property: JsonIgnore]
[property: Hidden]
private float framePlate_RelativeX;
[JsonIgnore]
[ObservableProperty]
[property: JsonIgnore]
[property: Hidden]
private float framePlate_RelativeY;
[JsonIgnore]
[ObservableProperty]
[property: JsonIgnore]
[property: Hidden]
private float framePlate_InitialAngle;
[JsonIgnore]
[ObservableProperty]
[property: JsonIgnore]
[property: Hidden]
private float framePlate_PivotX;
[JsonIgnore]
[ObservableProperty]
[property: JsonIgnore]
[property: Hidden]
private float framePlate_PivotY;
@ -763,9 +754,8 @@ namespace CtrEditor.ObjetosSim
// All Pages Objects
[NotifyPropertyChangedFor(nameof(Show_On_This_Page))]
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Habilitar este objeto para ser usado en todas las páginas")]
[property: Name("Habilitado en Todas Páginas")]
[property: Description("Enable this object to be used in all pages.")]
[property: Category("Layout:")]
private bool enable_On_All_Pages;
@ -789,9 +779,8 @@ namespace CtrEditor.ObjetosSim
// Local Data for Global Objects
[NotifyPropertyChangedFor(nameof(Show_On_This_Page))]
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Habilitar datos locales de este objeto global en todas las páginas")]
[property: Name("Datos Locales para Todas")]
[property: Description("Enable local data of this global Object on all pages.")]
[property: Category("Layout:")]
private bool enable_Local_Data_for_All;
partial void OnEnable_Local_Data_for_AllChanged(bool value)
@ -806,9 +795,8 @@ namespace CtrEditor.ObjetosSim
// Local Data for Global Objects
[NotifyPropertyChangedFor(nameof(Show_On_This_Page))]
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Habilitar datos locales de este objeto global en esta página")]
[property: Name("Datos Locales")]
[property: Description("Enable local data of this global Object on this page.")]
[property: Category("Layout:")]
[property: JsonIgnore]
private bool enable_Local_Data;
@ -922,9 +910,7 @@ namespace CtrEditor.ObjetosSim
private List<string> showOnThisPagesList;
private bool show_On_This_Page;
[property: Category("Información")]
[property: Description("Mostrar en esta página")]
[property: Name("Mostrar en Esta Página")]
[property: Category("Layout:")]
public bool Show_On_This_Page
{
get
@ -972,15 +958,13 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Datos")]
[property: Description("Creado automáticamente y clonado con plantillas de búsqueda")]
[property: Name("Clonado")]
[property: Description("Autocreated and cloned with Search Templates")]
[property: Category("Tag Extraction:")]
bool cloned;
[ObservableProperty]
[property: Category("Datos")]
[property: Description("ID del objeto del cual fue clonado")]
[property: Name("Clonado Desde")]
[property: Description("Autocreated and cloned with Search Templates")]
[property: Category("Tag Extraction:")]
[property: Hidden]
UniqueId cloned_from;
@ -1169,27 +1153,6 @@ namespace CtrEditor.ObjetosSim
return storyboard;
}
protected Storyboard CrearAnimacionMultiStoryBoardTrasnporteCircular(System.Windows.Shapes.Path transporte, bool invertirDireccion)
{
if (_visualRepresentation == null) return null;
if (transporte == null) return null;
Storyboard storyboard = new Storyboard();
var animation = new DoubleAnimation
{
From = invertirDireccion ? 20 : 0,
To = invertirDireccion ? 0 : 20, // Total Pixels Brush
Duration = TimeSpan.FromSeconds(PixelToMeter.Instance.calc.PixelsToMeters(20) * 60),
RepeatBehavior = RepeatBehavior.Forever
};
Storyboard.SetTarget(animation, transporte);
Storyboard.SetTargetProperty(animation, new PropertyPath("(Path.Fill).(VisualBrush.Transform).(TransformGroup.Children)[0].(TranslateTransform.Y)"));
storyboard.Children.Add(animation);
storyboard.Begin();
storyboard.SetSpeedRatio(0);
return storyboard;
}
protected Storyboard CrearAnimacionMultiStoryBoardTrasnporte(Storyboard storyboard, Rectangle transporte, bool invertirDireccion)
{
// Detener y eliminar el storyboard existente si hay uno
@ -1202,18 +1165,6 @@ namespace CtrEditor.ObjetosSim
return CrearAnimacionMultiStoryBoardTrasnporte(transporte, invertirDireccion);
}
protected Storyboard CrearAnimacionMultiStoryBoardTrasnporteCircular(Storyboard storyboard, System.Windows.Shapes.Path transporte, bool invertirDireccion)
{
// Detener y eliminar el storyboard existente si hay uno
if (storyboard != null)
{
storyboard.Stop();
storyboard.Children.Clear();
}
return CrearAnimacionMultiStoryBoardTrasnporteCircular(transporte, invertirDireccion);
}
protected void ActualizarAnimacionMultiStoryBoardTransporte(Storyboard storyboard, float velocidadActual)
{
if (_visualRepresentation == null) return;
@ -1230,14 +1181,6 @@ namespace CtrEditor.ObjetosSim
_storyboard = CrearAnimacionMultiStoryBoardTrasnporte(_storyboard, transporte, invertirDireccion);
}
protected void CrearAnimacionStoryBoardTrasnporteCircular(System.Windows.Shapes.Path transporte, bool invertirDireccion, float angulo)
{
if (angulo > 45 && angulo < 225)
_storyboard = CrearAnimacionMultiStoryBoardTrasnporteCircular(_storyboard, transporte, !invertirDireccion);
else
_storyboard = CrearAnimacionMultiStoryBoardTrasnporteCircular(_storyboard, transporte, invertirDireccion);
}
protected void ActualizarAnimacionStoryBoardTransporte(float velocidadActual)
{
ActualizarAnimacionMultiStoryBoardTransporte(_storyboard, velocidadActual);
@ -1658,31 +1601,7 @@ namespace CtrEditor.ObjetosSim
{
if (value is string stringValue)
{
try
{
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.UriSource = new Uri(stringValue, UriKind.RelativeOrAbsolute);
bitmapImage.EndInit();
return bitmapImage;
}
catch
{
// Si falla la carga de la imagen, usar imagen por defecto como fallback
try
{
var defaultImage = new BitmapImage();
defaultImage.BeginInit();
defaultImage.UriSource = new Uri("/Icons/unselect.png", UriKind.RelativeOrAbsolute);
defaultImage.EndInit();
return defaultImage;
}
catch
{
// Si incluso la imagen por defecto falla, devolver null
return null;
}
}
return new BitmapImage(new Uri(stringValue, UriKind.RelativeOrAbsolute));
}
return null;
}

View File

@ -20,97 +20,84 @@ namespace CtrEditor.ObjetosSim
{
// Referencia a la simulación de fluidos
public SimulacionFluidos _simFluidos;
// Tamaño del área de simulación
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Ancho del área de simulación en metros")]
[property: Name("Ancho Simulación")]
[property: Category("Simulación:")]
private float anchoSimulacion = 10.0f;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Alto del área de simulación en metros")]
[property: Name("Alto Simulación")]
[property: Category("Simulación:")]
private float altoSimulacion = 10.0f;
// Propiedades del fluido
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Tamaño visual de las partículas")]
[property: Name("Tamaño Partícula")]
[property: Category("Visual:")]
private float tamañoParticula = 0.01f;
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Color del fluido")]
[property: Name("Color Fluido")]
[property: Category("Visual:")]
private Color colorFluido = Colors.CornflowerBlue;
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Opacidad de las partículas")]
[property: Name("Opacidad Partículas")]
[property: Category("Visual:")]
private double opacidadParticulas = 0.7;
// Propiedades de gravedad
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Gravedad en X (m/s²)")]
[property: Name("Gravedad X")]
[property: Category("Física:")]
private float gravedadX = 0.0f;
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Gravedad en Y (m/s²)")]
[property: Name("Gravedad Y")]
[property: Category("Física:")]
private float gravedadY = 9.8f;
partial void OnGravedadXChanged(float value)
{
ActualizarGravedad();
}
partial void OnGravedadYChanged(float value)
{
ActualizarGravedad();
}
// Estadísticas de la simulación
[ObservableProperty]
[property: Category("Información")]
[property: Description("Número de partículas")]
[property: Name("Número Partículas")]
[property: Category("Estadísticas:")]
private int numeroParticulas;
[ObservableProperty]
[property: Category("Información")]
[property: Description("Rendimiento en FPS")]
[property: Name("FPS")]
[property: Category("Estadísticas:")]
private double fps;
// Referencia a componentes (solo para la función Add)
private List<IContenedorFluido> _contenedores = new List<IContenedorFluido>();
// Nombre de la clase para identificación
public static string NombreClase()
{
return "Sistema de Fluidos";
return "SistemaFluidos";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
set => SetProperty(ref nombre, value);
}
// Métodos para interactuar con la simulación
/// <summary>
/// Agrega partículas en un punto específico
/// </summary>
@ -118,7 +105,7 @@ namespace CtrEditor.ObjetosSim
{
_simFluidos?.AgregarParticula(posicion);
}
/// <summary>
/// Agrega múltiples partículas en un área
/// </summary>
@ -126,57 +113,57 @@ namespace CtrEditor.ObjetosSim
{
_simFluidos?.AgregarParticulasEnArea(centro, ancho, alto, cantidad);
}
/// <summary>
/// Crea un nuevo tanque y lo agrega a la simulación
/// </summary>
public Tanque CrearTanque(Vector2 posicion, float ancho, float alto)
{
if (_simFluidos == null) return null;
Tanque tanque = new Tanque(posicion, ancho, alto, (int)(AnchoSimulacion * 100));
_simFluidos.AgregarContenedor(tanque);
_contenedores.Add(tanque);
return tanque;
}
/// <summary>
/// Crea una nueva tubería
/// </summary>
public Tuberia CrearTuberia(float diametro)
{
if (_simFluidos == null) return null;
Tuberia tuberia = new Tuberia(diametro, (int)(AnchoSimulacion * 100));
_simFluidos.AgregarContenedor(tuberia);
_contenedores.Add(tuberia);
return tuberia;
}
/// <summary>
/// Crea una nueva válvula
/// </summary>
public Valvula CrearValvula(Vector2 posicion, float diametro, float apertura = 1.0f)
{
if (_simFluidos == null) return null;
Valvula valvula = new Valvula(posicion, diametro, apertura, (int)(AnchoSimulacion * 100));
_simFluidos.AgregarContenedor(valvula);
_contenedores.Add(valvula);
return valvula;
}
/// <summary>
/// Elimina un componente de la simulación
/// </summary>
public void EliminarComponente(IContenedorFluido componente)
{
if (_simFluidos == null || componente == null) return;
_simFluidos.RemoverContenedor(componente);
_contenedores.Remove(componente);
}
/// <summary>
/// Limpia todas las partículas de la simulación
/// </summary>
@ -184,7 +171,7 @@ namespace CtrEditor.ObjetosSim
{
_simFluidos?.LimpiarParticulas();
}
/// <summary>
/// Actualiza el vector de gravedad según las propiedades
/// </summary>
@ -195,7 +182,7 @@ namespace CtrEditor.ObjetosSim
_simFluidos.AjustarGravedad(new Vector2(GravedadX, GravedadY));
}
}
/// <summary>
/// Constructor de la clase
/// </summary>
@ -205,28 +192,28 @@ namespace CtrEditor.ObjetosSim
Ancho = 1.0f;
Alto = 1.0f;
}
// Métodos sobrescritos de osBase
public override void UpdateGeometryStart()
{
// Crear la simulación de fluidos si es necesario
if (_simFluidos == null)
{
_simFluidos = new SimulacionFluidos(
AnchoSimulacion,
AltoSimulacion,
AnchoSimulacion,
AltoSimulacion,
10000, // Máximo de partículas
new Vector2(GravedadX, GravedadY)
);
}
}
public override void UpdateGeometryStep()
{
// No es necesario actualizar en cada paso
}
public override void UpdateControl(int elapsedMilliseconds)
{
// Actualizar estadísticas
@ -235,7 +222,7 @@ namespace CtrEditor.ObjetosSim
NumeroParticulas = _simFluidos.ParticlesCount;
}
}
/// <summary>
/// Llamado cuando se inicia la simulación de fluidos
/// </summary>
@ -244,7 +231,7 @@ namespace CtrEditor.ObjetosSim
// Crear la simulación de fluidos si es necesario
UpdateGeometryStart();
}
/// <summary>
/// Llamado cuando se detiene la simulación de fluidos
/// </summary>
@ -253,7 +240,7 @@ namespace CtrEditor.ObjetosSim
// Detener recursos si es necesario
SimulationStop();
}
/// <summary>
/// Actualiza la simulación de fluidos
/// </summary>
@ -263,48 +250,48 @@ namespace CtrEditor.ObjetosSim
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
}
public override void ucLoaded()
{
base.ucLoaded();
// Inicializar la simulación de fluidos si es necesario
UpdateGeometryStart();
}
public override void ucUnLoaded()
{
// Limpiar recursos
_simFluidos = null;
_contenedores.Clear();
}
// Implementación para las conexiones con PLC
[ObservableProperty]
[property: Description("Tag de lectura/escritura del nivel del Tanque 1")]
[property: Category("PLC:")]
private string tagNivelTanque1;
[ObservableProperty]
[property: Description("Tag de lectura/escritura de la apertura de la Válvula 1")]
[property: Category("PLC:")]
private string tagAperturaValvula1;
// Referencia a componentes típicos para integración con PLC
private Tanque _tanque1;
private Valvula _valvula1;
public override void UpdatePLC(PLCViewModel plc, int elapsedMilliseconds)
{
// Ejemplo de integración con PLC para la válvula
@ -313,7 +300,7 @@ namespace CtrEditor.ObjetosSim
float aperturaValvula = LeerWordTagScaled(TagAperturaValvula1) / 100.0f;
_valvula1.Apertura = Math.Clamp(aperturaValvula, 0, 1);
}
// Ejemplo de escritura del nivel del tanque al PLC
if (_tanque1 != null && !string.IsNullOrEmpty(TagNivelTanque1))
{

View File

@ -7,7 +7,6 @@ using CommunityToolkit.Mvvm.ComponentModel;
using LibS7Adv;
using CtrEditor.Simulacion;
using System.Windows.Input;
using System.ComponentModel;
namespace CtrEditor.ObjetosSim
@ -25,13 +24,9 @@ namespace CtrEditor.ObjetosSim
public static string NombreClase()
{
return "Ejemplo Básico";
return "Example";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
private string nombre = "Transporte TTOP";
public override string Nombre
{
get => nombre;
@ -39,9 +34,6 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Velocidad actual del transporte")]
[property: Name("Velocidad Actual")]
public float velocidadActual;
partial void OnVelocidadActualChanged(float value)
@ -50,9 +42,6 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Invierte el sentido de movimiento")]
[property: Name("Invertir Dirección")]
bool invertirDireccion;
partial void OnInvertirDireccionChanged(bool value)
@ -76,9 +65,6 @@ namespace CtrEditor.ObjetosSim
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Motor enlazado al transporte")]
[property: Name("Motor")]
public string motor;
partial void OnMotorChanged(string value)
@ -87,45 +73,18 @@ namespace CtrEditor.ObjetosSim
}
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Ancho del transporte")]
[property: Name("Ancho")]
public float ancho;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Alto del transporte")]
[property: Name("Alto")]
public float alto;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Ángulo de rotación")]
[property: Name("Ángulo")]
public float angulo;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Coeficiente de fricción")]
[property: Name("Coeficiente Fricción")]
public float frictionCoefficient;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Velocidad máxima a 50Hz")]
[property: Name("Velocidad Max 50Hz")]
public float velMax50hz;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Tiempo de rampa")]
[property: Name("Tiempo Rampa")]
public float tiempoRampa;
[ObservableProperty]
[property: Category("Información")]
[property: Description("Estado de marcha")]
[property: Name("En Marcha")]
public bool esMarcha;

View File

@ -18,32 +18,32 @@ namespace CtrEditor.ObjetosSim
{
public osBase? Datos { get; set; }
public int zIndex_fromFrames { get; set; }
public ucTuberiaFluido()
{
InitializeComponent();
this.Loaded += OnLoaded;
this.Unloaded += OnUnloaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
Datos?.ucLoaded();
}
private void OnUnloaded(object sender, RoutedEventArgs e)
{
Datos?.ucUnLoaded();
}
public void Highlight(bool State) { }
public ZIndexEnum ZIndex_Base()
{
return ZIndexEnum.Estaticos;
}
}
/// <summary>
/// ViewModel para la tubería de fluidos
/// </summary>
@ -51,17 +51,16 @@ namespace CtrEditor.ObjetosSim
{
// Tubería en la simulación de fluidos
private Tuberia _tuberia;
// Referencia al sistema de fluidos
private osSistemaFluidos _sistemaFluidos;
// Propiedades visuales
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Diámetro de la tubería en metros")]
[property: Name("Diámetro")]
[property: Category("Dimensiones:")]
private float diametro = 0.05f;
partial void OnDiametroChanged(float value)
{
// Actualizar geometría si la tubería ya existe
@ -71,57 +70,48 @@ namespace CtrEditor.ObjetosSim
ReconstruirTuberia();
}
}
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Diámetro interno para visualización del fluido")]
[property: Name("Diámetro Interno")]
[property: Category("Visual:")]
private float diametroInterno;
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Color de la tubería")]
[property: Name("Color Tubería")]
[property: Category("Visual:")]
private System.Windows.Media.Color color = System.Windows.Media.Colors.Gray;
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Color del fluido")]
[property: Name("Color Fluido")]
[property: Category("Visual:")]
private System.Windows.Media.Color colorFluido = System.Windows.Media.Colors.CornflowerBlue;
[ObservableProperty]
[property: Category("Información")]
[property: Description("Datos del path para dibujar la tubería")]
[property: Name("Path Data")]
[property: Category("Interno:")]
private string pathData;
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Densidad del fluido (0-1)")]
[property: Name("Densidad Fluido")]
[property: Category("Simulación:")]
private double densidadFluido = 0.7;
// Lista de puntos que forman la tubería
private List<Vector2> _puntos = new List<Vector2>();
// Nombre de la clase para identificación
public static string NombreClase()
{
return "Tubería de Fluido";
return "TuberiaFluido";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
set => SetProperty(ref nombre, value);
}
/// <summary>
/// Agrega un punto a la tubería
/// </summary>
@ -129,36 +119,36 @@ namespace CtrEditor.ObjetosSim
{
_puntos.Add(new Vector2(x, y));
ActualizarPathData();
// Si la tubería ya está creada, agregar el punto a la simulación
if (_tuberia != null)
{
_tuberia.AgregarPunto(new Vector2(x, y));
}
}
/// <summary>
/// Actualiza la representación visual de la tubería
/// </summary>
private void ActualizarPathData()
{
if (_puntos.Count < 2) return;
var converter = new MeterToPixelConverter();
StringBuilder sb = new StringBuilder();
// Iniciar el path
sb.Append($"M {converter.Convert(_puntos[0].X, null, null, null)} {converter.Convert(_puntos[0].Y, null, null, null)} ");
// Añadir los demás puntos
for (int i = 1; i < _puntos.Count; i++)
{
sb.Append($"L {converter.Convert(_puntos[i].X, null, null, null)} {converter.Convert(_puntos[i].Y, null, null, null)} ");
}
PathData = sb.ToString();
}
/// <summary>
/// Reconstruye la tubería en la simulación
/// </summary>
@ -171,10 +161,10 @@ namespace CtrEditor.ObjetosSim
{
_sistemaFluidos.EliminarComponente(_tuberia);
}
// Crear nueva tubería
_tuberia = _sistemaFluidos.CrearTuberia(Diametro);
// Agregar todos los puntos existentes
foreach (var punto in _puntos)
{
@ -182,7 +172,7 @@ namespace CtrEditor.ObjetosSim
}
}
}
/// <summary>
/// Constructor
/// </summary>
@ -190,28 +180,28 @@ namespace CtrEditor.ObjetosSim
{
DiametroInterno = Diametro * 0.8f;
}
public override void OnMove(float LeftPixels, float TopPixels)
{
// Mover todos los puntos de la tubería
if (_puntos.Count > 0)
{
Vector2 delta = new Vector2(Left - CanvasGetLeftinMeter(), Top - CanvasGetTopinMeter());
for (int i = 0; i < _puntos.Count; i++)
{
_puntos[i] += delta;
}
ActualizarPathData();
ReconstruirTuberia();
}
}
public override void ucLoaded()
{
base.ucLoaded();
// Buscar el sistema de fluidos en la simulación
if (_mainViewModel?.ObjetosSimulables != null)
{
@ -224,7 +214,7 @@ namespace CtrEditor.ObjetosSim
}
}
}
// Si no hay puntos, agregar dos puntos iniciales
if (_puntos.Count == 0)
{
@ -232,11 +222,11 @@ namespace CtrEditor.ObjetosSim
_puntos.Add(new Vector2(Left + Ancho, Top));
ActualizarPathData();
}
// Crear la tubería en la simulación
ReconstruirTuberia();
}
public override void ucUnLoaded()
{
// Eliminar la tubería de la simulación
@ -246,7 +236,7 @@ namespace CtrEditor.ObjetosSim
_tuberia = null;
}
}
public override void UpdateControl(int elapsedMilliseconds)
{
// Actualizar la densidad del fluido basada en la simulación
@ -259,7 +249,7 @@ namespace CtrEditor.ObjetosSim
centro += punto;
}
centro /= _puntos.Count;
// Obtener densidad en esa posición
DensidadFluido = _sistemaFluidos._simFluidos.ObtenerDensidadEnPosicion(centro);
}

View File

@ -19,32 +19,32 @@ namespace CtrEditor.ObjetosSim
{
public osBase? Datos { get; set; }
public int zIndex_fromFrames { get; set; }
public ucValvulaFluido()
{
InitializeComponent();
this.Loaded += OnLoaded;
this.Unloaded += OnUnloaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
Datos?.ucLoaded();
}
private void OnUnloaded(object sender, RoutedEventArgs e)
{
Datos?.ucUnLoaded();
}
public void Highlight(bool State) { }
public ZIndexEnum ZIndex_Base()
{
return ZIndexEnum.Estaticos;
}
}
/// <summary>
/// ViewModel para la válvula de fluidos
/// </summary>
@ -52,72 +52,65 @@ namespace CtrEditor.ObjetosSim
{
// Válvula en la simulación de fluidos
private Valvula _valvula;
// Referencia al sistema de fluidos
private osSistemaFluidos _sistemaFluidos;
// Propiedades dimensionales
[ObservableProperty]
[property: Category("Configuración")]
[property: Category("Dimensiones:")]
[property: Description("Ancho de la válvula en metros")]
[property: Name("Ancho")]
private float ancho = 0.1f;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Alto de la válvula en metros")]
[property: Name("Alto")]
[property: Category("Dimensiones:")]
private float alto = 0.06f;
[ObservableProperty]
[property: Category("Configuración")]
[property: Description("Diámetro de la tubería conectada")]
[property: Name("Diámetro Tubería")]
[property: Category("Dimensiones:")]
private float diametroTuberia = 0.05f;
// Propiedades visuales
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Color de la válvula")]
[property: Name("Color")]
[property: Category("Visual:")]
private Color color = Colors.Silver;
[ObservableProperty]
[property: Category("Apariencia")]
[property: Description("Color del indicador de apertura")]
[property: Name("Color Indicador")]
[property: Category("Visual:")]
private Color colorIndicador = Colors.CornflowerBlue;
// Propiedades de funcionamiento
[ObservableProperty]
[property: Category("Simulación")]
[property: Description("Apertura de la válvula (0-1)")]
[property: Name("Apertura")]
[property: Category("Operación:")]
private float apertura = 1.0f;
partial void OnAperturaChanged(float value)
{
Apertura = Math.Clamp(value, 0, 1);
// Actualizar la válvula en la simulación
if (_valvula != null)
{
_valvula.Apertura = Apertura;
}
}
// Tag PLC para la válvula
[ObservableProperty]
[property: Category("Enlace PLC")]
[property: Description("Tag PLC para lectura/escritura de apertura (0-100%)")]
[property: Name("Tag Apertura")]
[property: Description("Tag de lectura/escritura de la apertura (0-100%)")]
[property: Category("PLC:")]
private string tagApertura;
// Propiedades calculadas para visualización
public float AperturaVisual => Ancho * 0.8f * Apertura;
public float GrosorIndicador => Alto * 0.2f;
public float ValorApertura => Apertura;
// Propiedades para posicionamiento de elementos
public float OffsetXRectangulo => -Ancho / 2;
public float OffsetYRectangulo => -Alto / 2;
@ -125,24 +118,20 @@ namespace CtrEditor.ObjetosSim
public float OffsetYIndicador => -GrosorIndicador / 2;
public float OffsetXTexto => -Ancho * 0.15f;
public float OffsetYTexto => Alto * 0.1f;
// Nombre de la clase para identificación
public static string NombreClase()
{
return "Válvula de Fluido";
return "ValvulaFluido";
}
private string nombre = NombreClase();
[property: Category("Identificación")]
[property: Description("Nombre identificativo del objeto")]
[property: Name("Nombre")]
public override string Nombre
{
get => nombre;
set => SetProperty(ref nombre, value);
}
/// <summary>
/// Constructor
/// </summary>
@ -150,7 +139,7 @@ namespace CtrEditor.ObjetosSim
{
// Constructor
}
public override void OnMove(float LeftPixels, float TopPixels)
{
if (_valvula != null)
@ -159,17 +148,17 @@ namespace CtrEditor.ObjetosSim
_valvula.ActualizarPosicion(new Vector2(Left, Top));
}
}
public override void OnRotate(float Delta_Angle)
{
// La rotación visual ya está manejada por el XAML
// No necesita actualizaciones adicionales en la simulación
}
public override void ucLoaded()
{
base.ucLoaded();
// Buscar el sistema de fluidos en la simulación
if (_mainViewModel?.ObjetosSimulables != null)
{
@ -182,7 +171,7 @@ namespace CtrEditor.ObjetosSim
}
}
}
// Crear la válvula en la simulación
if (_sistemaFluidos != null)
{
@ -193,7 +182,7 @@ namespace CtrEditor.ObjetosSim
);
}
}
public override void ucUnLoaded()
{
// Eliminar la válvula de la simulación
@ -203,7 +192,7 @@ namespace CtrEditor.ObjetosSim
_valvula = null;
}
}
public override void UpdatePLC(PLCViewModel plc, int elapsedMilliseconds)
{
// Manejar la comunicación con PLC

View File

@ -1,138 +0,0 @@
# Script para estandarizar objetos derivados de osBase
# Ejecutar desde la raíz del proyecto CtrEditor
Write-Host "=== Estandarización de Objetos osBase ===" -ForegroundColor Green
# Mapeo de nombres de clase mejorados
$nombresClase = @{
# Transportes
"ucTransporteTTop" = "Transporte TTOP"
"ucTransporteTTopDualInverter" = "Transporte TTOP Dual Inverter"
"ucTransporteGuias" = "Transporte con Guías"
"ucTransporteGuiasUnion" = "Transporte con Guías Unión"
"ucTransporteCurva" = "Transporte Curva"
"ucTransporteCurvaGuias" = "Transporte Curva con Guías"
# Sensores
"ucPhotocell" = "Fotocélula"
"ucGearEncoder" = "Encoder de Engranaje"
"ucEncoderMotor" = "Encoder Motor"
"ucEncoderMotorLineal" = "Encoder Motor Lineal"
"ucSensTemperatura" = "Sensor de Temperatura"
"ucBoton" = "Botón"
# Actuadores
"ucVMmotorSim" = "Motor VetroMeccanica"
"ucValvulaFluido" = "Válvula de Fluido"
# Elementos Estáticos
"ucGuia" = "Guía"
"ucDescarte" = "Descarte"
# Emuladores
"ucBottGenerator" = "Generador de Botellas"
"ucFiller" = "Llenadora"
"ucTanque" = "Tanque"
# Señales
"ucAnalogTag" = "Tag Analógico"
"ucBoolTag" = "Tag Digital"
"ucConsensGeneric" = "Consenso Genérico"
# Datos
"ucExtraccionTag" = "Extracción de Tag"
"ucBuscarCoincidencias" = "Búsqueda de Coincidencias"
# Decorativos
"ucCustomImage" = "Imagen Personalizada"
"ucFramePlate" = "Marco"
"ucTextPlate" = "Placa de Texto"
# Fluidos
"ucTuberiaFluido" = "Tubería de Fluido"
"osSistemaFluidos" = "Sistema de Fluidos"
# Trazas
"ucTrace3" = "Traza 3 Puntos"
"ucTraceSimple" = "Traza Simple"
# Dinámicos
"ucBotella" = "Botella"
"ucBotellaCuello" = "Botella con Cuello"
# Ejemplo
"ucBasicExample" = "Ejemplo Básico"
}
# Mapeo de categorías estándar
$categoriasEstandar = @{
"Id:" = "Identificación"
"Layout:" = "Posición y Tamaño"
"Setup:" = "Configuración"
"Simulation:" = "Simulación"
"PLC link:" = "Enlace PLC"
"Debug:" = "Información"
"Encoder:" = "Encoder"
"General:" = "Identificación"
}
function Actualizar-NombreClase {
param(
[string]$archivo,
[string]$nuevoNombre
)
$contenido = Get-Content $archivo -Raw
$patron = 'return\s+"[^"]*";'
$reemplazo = "return `"$nuevoNombre`";"
if ($contenido -match $patron) {
$contenido = $contenido -replace $patron, $reemplazo
Set-Content $archivo $contenido -NoNewline
Write-Host "✓ Actualizado NombreClase en $archivo" -ForegroundColor Yellow
}
}
function Estandarizar-Categorias {
param([string]$archivo)
$contenido = Get-Content $archivo -Raw
$modificado = $false
foreach ($categoria in $categoriasEstandar.Keys) {
$patron = [regex]::Escape("Category(`"$categoria`")")
$reemplazo = "Category(`"$($categoriasEstandar[$categoria])`")"
if ($contenido -match $patron) {
$contenido = $contenido -replace $patron, $reemplazo
$modificado = $true
}
}
if ($modificado) {
Set-Content $archivo $contenido -NoNewline
Write-Host "✓ Estandarizadas categorías en $archivo" -ForegroundColor Cyan
}
}
# Buscar todos los archivos .cs en ObjetosSim
$archivos = Get-ChildItem -Path "ObjetosSim" -Filter "*.cs" -Recurse | Where-Object {
$_.Name -like "uc*.cs" -or $_.Name -like "os*.cs"
}
Write-Host "Encontrados $($archivos.Count) archivos para procesar" -ForegroundColor Blue
foreach ($archivo in $archivos) {
$nombreArchivo = [System.IO.Path]::GetFileNameWithoutExtension($archivo.Name)
# Actualizar nombre de clase si está en el mapeo
if ($nombresClase.ContainsKey($nombreArchivo)) {
Actualizar-NombreClase -archivo $archivo.FullName -nuevoNombre $nombresClase[$nombreArchivo]
}
# Estandarizar categorías
Estandarizar-Categorias -archivo $archivo.FullName
}
Write-Host "=== Proceso completado ===" -ForegroundColor Green
Write-Host "Revise los cambios y verifique que la compilación sea exitosa" -ForegroundColor Yellow

View File

@ -6,7 +6,6 @@ using System.Windows;
using CtrEditor.Simulacion;
using System.IO;
using System.Linq;
using System.Windows.Media;
namespace CtrEditor.Serialization
{
@ -255,94 +254,8 @@ namespace CtrEditor.Serialization
NullValueHandling = NullValueHandling.Ignore,
TypeNameHandling = TypeNameHandling.Auto,
ObjectCreationHandling = ObjectCreationHandling.Replace,
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
Error = HandleDeserializationError,
Converters = { new SafeImageSourceConverter() },
// Configuración para respetar atributos JsonIgnore de Newtonsoft.Json
ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver
{
IgnoreSerializableAttribute = false
}
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
};
}
private void HandleDeserializationError(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs e)
{
// Si es un error relacionado con ImagePath, ImageSource o osCustomImage, simplemente ignorarlo y continuar
if (e.ErrorContext.Error.Message.Contains("ImagePath") ||
e.ErrorContext.Error.Message.Contains("osCustomImage") ||
e.ErrorContext.Error.Message.Contains("ImageSource") ||
e.ErrorContext.Error.Message.Contains("lmageSource") || // posible typo en el mensaje de error
(e.ErrorContext.Path != null && e.ErrorContext.Path.Contains("ImageSource")) ||
(e.ErrorContext.Path != null && e.ErrorContext.Path.Contains("imagePath")) ||
(e.ErrorContext.Member != null && e.ErrorContext.Member.ToString().Contains("Image")))
{
e.ErrorContext.Handled = true;
// Si el contexto actual es un objeto osCustomImage y hay un error,
// intentar establecer valores por defecto
if (e.ErrorContext.OriginalObject is osCustomImage customImage)
{
try
{
// Establecer valores seguros por defecto
if (e.ErrorContext.Member?.ToString() == "ImagePath" ||
e.ErrorContext.Member?.ToString() == "imagePath")
{
customImage.ImagePath = ""; // Esto activará el fallback a imagen por defecto
}
}
catch
{
// Si incluso esto falla, simplemente ignorar
}
}
}
}
}
/// <summary>
/// Convertidor JSON seguro para ImageSource que nunca lanza excepciones
/// </summary>
public class SafeImageSourceConverter : JsonConverter<ImageSource>
{
public override ImageSource ReadJson(JsonReader reader, Type objectType, ImageSource existingValue, bool hasExistingValue, JsonSerializer serializer)
{
try
{
// Si el valor es null o string vacío, devolver null
if (reader.Value == null || reader.Value.ToString() == "")
return null;
// Intentar crear ImageSource desde el valor
string value = reader.Value.ToString();
// Limpiar caracteres problemáticos
value = value.Trim();
if (value.Contains("•"))
value = value.Replace("•", "");
if (value.StartsWith("filet///"))
value = value.Replace("filet///", "file:///");
// Si el valor limpio está vacío, devolver null
if (string.IsNullOrWhiteSpace(value))
return null;
// No intentar crear ImageSource aquí, simplemente devolver null
// La lógica de carga de imagen se manejará en el código de la aplicación
return null;
}
catch
{
// En caso de cualquier error, devolver null silenciosamente
return null;
}
}
public override void WriteJson(JsonWriter writer, ImageSource value, JsonSerializer serializer)
{
// Nunca serializar ImageSource, siempre escribir null
writer.WriteNull();
}
}
}