Compare commits

...

10 Commits

Author SHA1 Message Date
Miguel 256d86aca5 Se realizaron actualizaciones en múltiples clases para mejorar la legibilidad y la organización de las propiedades. Se añadieron nuevos atributos de descripción y nombre en varias clases, como ucBasicExample, ucTransporteCurva, y ucTransporteGuias, facilitando la identificación de los elementos en la interfaz de usuario. Además, se eliminaron archivos innecesarios del proyecto y se ajustaron las categorías de propiedades para una mejor clasificación. Estas mejoras optimizan la experiencia del usuario y la gestión de los objetos en la simulación. 2025-06-24 21:35:17 +02:00
Miguel 3bc314182c Se realizaron mejoras en la clase MainViewModel al agregar espacios en blanco para mejorar la legibilidad. En TagEditorAttribute, se añadieron nuevos atributos y se implementó la lógica para manejar nombres personalizados de propiedades. En UserControlFactory, se optimizó la obtención de nombres de propiedades y se eliminaron espacios en blanco innecesarios. Finalmente, se añadió un atributo Name en ucTransporteTTop para el coeficiente de fricción, mejorando la claridad en la interfaz de usuario. 2025-06-24 17:45:47 +02:00
Miguel 6928088691 Se añadieron nuevas propiedades y métodos en el control CircularSegment para gestionar guías visuales, incluyendo la distancia, grosor y color de las guías. Se implementó la lógica para dibujar las guías en el segmento circular, mejorando la visualización y personalización del control. 2025-06-24 17:32:17 +02:00
Miguel 81329e4c09 Se añadieron nuevas propiedades y métodos en la clase ucTransporteCurvaGuias para gestionar guías curvas, incluyendo la creación y actualización de segmentos de guías. Se implementaron validaciones para el número de segmentos y se mejoró la lógica de actualización de geometrías al cambiar propiedades relevantes. 2025-06-24 17:07:37 +02:00
Miguel b6f616f6cc Agregado del control TransportCurva con Guias 2025-06-24 16:53:03 +02:00
Miguel 1449544d71 Se actualizaron las propiedades en las clases osBase, ucCustomImage y ucVMmotorSim para utilizar el nuevo atributo [property: JsonIgnore], mejorando la gestión de la serialización JSON. Además, se ajustó la configuración del serializador en StateSerializer.cs para respetar los atributos JsonIgnore, optimizando la deserialización de objetos. 2025-06-24 11:17:34 +02:00
Miguel 5c2daaeb98 Se añadió un estilo global para TreeViewItem en App.xaml para evitar errores de binding. Se actualizaron las referencias de paquetes en CtrEditor.csproj, cambiando la versión de LiveChartsCore.SkiaSharpView.WPF y añadiendo SkiaSharp.Views.WPF. Se mejoró la gestión de carga de imágenes en osBase.cs y ucCustomImage.xaml.cs, implementando un manejo de errores más robusto y estableciendo imágenes por defecto en caso de fallos. Se ajustó el XAML de ucBoolTag para mejorar la conversión de color. Se implementó un convertidor seguro para ImageSource en StateSerializer.cs, mejorando la deserialización de imágenes. 2025-06-24 10:59:58 +02:00
Miguel 3af9ad99d8 Se añadió un nuevo parámetro de ángulo en el método CrearAnimacionStoryBoardTrasnporteCircular en la clase osBase, permitiendo ajustar la dirección de la animación según el valor del ángulo. Se actualizaron las llamadas a este método en ucTransporteCurva para incluir el nuevo parámetro, mejorando la lógica de animación en función de la dirección y el ángulo proporcionado. 2025-06-23 23:40:48 +02:00
Miguel da8d0516cb Se añadió la funcionalidad para crear y actualizar animaciones de transporte circular en la clase osBase y se integró en ucTransporteCurva. Se implementaron métodos para gestionar la dirección de las animaciones y se mejoró la lógica de actualización de geometrías. Además, se realizaron ajustes en el XAML de CircularSegment para incluir un patrón visual en el Path. 2025-06-23 22:10:00 +02:00
Miguel ac8773ebc7 Se realizaron mejoras en la gestión de objetos visuales en la clase ObjectManipulationManager. Se optimizó la lógica para purgar objetos eliminados y se mejoró la rotación de objetos, permitiendo rotaciones en incrementos de 45 grados al mantener presionada la tecla Shift. Además, se ajustaron espacios en blanco y se mejoró la legibilidad del código en varias secciones. 2025-06-23 21:36:53 +02:00
49 changed files with 2829 additions and 499 deletions

View File

@ -22,6 +22,12 @@
<local:SubclassFilterConverter x:Key="SubclassFilterConverterosVMMotor" TargetType="{x:Type os:osVMmotorSim}" /> <local:SubclassFilterConverter x:Key="SubclassFilterConverterosVMMotor" TargetType="{x:Type os:osVMmotorSim}" />
<local:UnsavedChangesConverter x:Key="UnsavedChangesConverter"/> <local:UnsavedChangesConverter x:Key="UnsavedChangesConverter"/>
<local:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/> <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.Resources>
</Application> </Application>

View File

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

View File

@ -0,0 +1,145 @@
# 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

@ -0,0 +1,172 @@
/*
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,6 +1337,8 @@ namespace CtrEditor
// Mostrar como modeless (no modal) // Mostrar como modeless (no modal)
libraryWindow.Show(); libraryWindow.Show();
} }
} }
public class SimulationData public class SimulationData

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,24 @@
<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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,3 +1,4 @@
using System;
using System.ComponentModel; using System.ComponentModel;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
@ -12,9 +13,26 @@ namespace CtrEditor.ObjetosSim
/// <summary> /// <summary>
/// Atributo para marcar propiedades que deben usar el editor de etiquetas /// Atributo para marcar propiedades que deben usar el editor de etiquetas
/// </summary> /// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class TagEditorAttribute : Attribute public class TagEditorAttribute : Attribute
{ {
public TagEditorAttribute() { } 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));
}
} }
/// <summary> /// <summary>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,8 +5,24 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CtrEditor.ObjetosSim.UserControls" xmlns:local="clr-namespace:CtrEditor.ObjetosSim.UserControls"
mc:Ignorable="d" Name="circularSegmentControl"> mc:Ignorable="d" Name="circularSegmentControl">
<Canvas> <Canvas Name="mainCanvas">
<Path Name="path" Stroke="Black" Fill="LightBlue" StrokeThickness="1"> <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>
<Path.RenderTransform> <Path.RenderTransform>
<RotateTransform Angle="{Binding Angle, ElementName=circularSegmentControl}"/> <RotateTransform Angle="{Binding Angle, ElementName=circularSegmentControl}"/>
</Path.RenderTransform> </Path.RenderTransform>

View File

@ -1,6 +1,7 @@
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Shapes;
namespace CtrEditor.ObjetosSim.UserControls namespace CtrEditor.ObjetosSim.UserControls
{ {
@ -54,21 +55,95 @@ namespace CtrEditor.ObjetosSim.UserControls
public static readonly DependencyProperty EndAngleProperty = public static readonly DependencyProperty EndAngleProperty =
DependencyProperty.Register("EndAngle", typeof(double), typeof(CircularSegment), new PropertyMetadata(90.0, OnPropertyChanged)); 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() public CircularSegment()
{ {
InitializeComponent(); 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) private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{ {
(d as CircularSegment)?.DrawSegment(); (d as CircularSegment)?.DrawSegment();
} }
private static void OnGuidePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as CircularSegment)?.DrawSegment();
}
private void DrawSegment() private void DrawSegment()
{ {
System.Diagnostics.Debug.WriteLine($"DrawSegment called - ShowGuides: {ShowGuides}");
if (OuterRadius <= 0 || InnerRadius <= 0 || StartAngle == EndAngle) if (OuterRadius <= 0 || InnerRadius <= 0 || StartAngle == EndAngle)
return; 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(); PathGeometry geometry = new PathGeometry();
PathFigure figure = new PathFigure(); PathFigure figure = new PathFigure();
@ -100,5 +175,76 @@ namespace CtrEditor.ObjetosSim.UserControls
geometry.Figures.Add(figure); geometry.Figures.Add(figure);
path.Data = geometry; 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] [JsonIgnore]
private System.Threading.Timer timer = null; private System.Threading.Timer timer = null;
[JsonIgnore]
[ObservableProperty] [ObservableProperty]
[property: JsonIgnore]
[property: Hidden] [property: Hidden]
public bool isVisFilter; public bool isVisFilter;
@ -80,13 +80,15 @@ namespace CtrEditor.ObjetosSim
[ObservableProperty] [ObservableProperty]
[property: Description("Lock object to mouse movement.")] [property: Category("Configuración")]
[property: Category("Layout:")] [property: Description("Bloquear movimiento del objeto")]
[property: Name("Bloquear Movimiento")]
private bool lock_movement; private bool lock_movement;
[ObservableProperty] [ObservableProperty]
[property: Description("X coordinate.")] [property: Category("Configuración")]
[property: Category("Layout:")] [property: Description("Coordenada X del objeto")]
[property: Name("Izquierda")]
private float left; private float left;
public void CheckData() public void CheckData()
@ -114,8 +116,9 @@ namespace CtrEditor.ObjetosSim
public virtual void LeftChanging(float oldValue, float newValue) { } public virtual void LeftChanging(float oldValue, float newValue) { }
[ObservableProperty] [ObservableProperty]
[property: Description("Y coordinate.")] [property: Category("Configuración")]
[property: Category("Layout:")] [property: Description("Coordenada Y del objeto")]
[property: Name("Superior")]
private float top; private float top;
partial void OnTopChanged(float value) partial void OnTopChanged(float value)
@ -137,8 +140,9 @@ namespace CtrEditor.ObjetosSim
[ObservableProperty] [ObservableProperty]
[property: Description("Widht.")] [property: Category("Configuración")]
[property: Category("Layout:")] [property: Description("Ancho del objeto")]
[property: Name("Ancho")]
private float ancho; private float ancho;
partial void OnAnchoChanged(float value) partial void OnAnchoChanged(float value)
@ -148,8 +152,9 @@ namespace CtrEditor.ObjetosSim
public virtual void AnchoChanged(float value) { } public virtual void AnchoChanged(float value) { }
[ObservableProperty] [ObservableProperty]
[property: Description("Height.")] [property: Category("Configuración")]
[property: Category("Layout:")] [property: Description("Alto del objeto")]
[property: Name("Alto")]
private float alto; private float alto;
partial void OnAltoChanged(float value) partial void OnAltoChanged(float value)
@ -160,8 +165,9 @@ namespace CtrEditor.ObjetosSim
[ObservableProperty] [ObservableProperty]
[property: Description("Angle.")] [property: Category("Configuración")]
[property: Category("Layout:")] [property: Description("Ángulo de rotación del objeto")]
[property: Name("Ángulo")]
private float angulo; private float angulo;
partial void OnAnguloChanged(float value) partial void OnAnguloChanged(float value)
@ -177,8 +183,9 @@ namespace CtrEditor.ObjetosSim
public virtual void AnguloChanging(float oldValue, float newValue) { } public virtual void AnguloChanging(float oldValue, float newValue) { }
[ObservableProperty] [ObservableProperty]
[property: Category("Identificación")]
[property: Description("Etiquetas para clasificar el objeto. Use # antes de cada etiqueta (ej: #motor #bomba #critico)")] [property: Description("Etiquetas para clasificar el objeto. Use # antes de cada etiqueta (ej: #motor #bomba #critico)")]
[property: Category("General:")] [property: Name("Etiquetas")]
[property: Editor(typeof(TagPropertyEditor), typeof(TagPropertyEditor))] [property: Editor(typeof(TagPropertyEditor), typeof(TagPropertyEditor))]
[property: TagEditor] [property: TagEditor]
private string etiquetas = ""; private string etiquetas = "";
@ -290,8 +297,9 @@ namespace CtrEditor.ObjetosSim
// Group as FacePlate // Group as FacePlate
[ObservableProperty] [ObservableProperty]
[property: Description("This is a link to a faceplate. It works like an anchor.")] [property: Category("Agrupación")]
[property: Category("Group:")] [property: Description("Enlace a una placa de texto como ancla")]
[property: Name("Panel Grupo")]
[property: ItemsSource(typeof(osBaseItemsSource<osTextPlate>))] [property: ItemsSource(typeof(osBaseItemsSource<osTextPlate>))]
private string group_Panel; private string group_Panel;
@ -333,8 +341,9 @@ namespace CtrEditor.ObjetosSim
// Group as FacePlate // Group as FacePlate
[ObservableProperty] [ObservableProperty]
[property: Description("This is a link to a FromPlate that moves automatically. It works like an anchor.")] [property: Category("Agrupación")]
[property: Category("Group:")] [property: Description("Enlace a un marco que se mueve automáticamente como ancla")]
[property: Name("Panel Marco")]
[property: ItemsSource(typeof(osBaseItemsSource<osFramePlate>))] [property: ItemsSource(typeof(osBaseItemsSource<osFramePlate>))]
private string group_FramePanel; private string group_FramePanel;
@ -344,28 +353,28 @@ namespace CtrEditor.ObjetosSim
private bool isUpdatingFromFramePlate = false; private bool isUpdatingFromFramePlate = false;
// Variables para rotación orbital alrededor del FramePlate // Variables para rotación orbital alrededor del FramePlate
[JsonIgnore]
[ObservableProperty] [ObservableProperty]
[property: JsonIgnore]
[property: Hidden] [property: Hidden]
private float framePlate_RelativeX; private float framePlate_RelativeX;
[JsonIgnore]
[ObservableProperty] [ObservableProperty]
[property: JsonIgnore]
[property: Hidden] [property: Hidden]
private float framePlate_RelativeY; private float framePlate_RelativeY;
[JsonIgnore]
[ObservableProperty] [ObservableProperty]
[property: JsonIgnore]
[property: Hidden] [property: Hidden]
private float framePlate_InitialAngle; private float framePlate_InitialAngle;
[JsonIgnore]
[ObservableProperty] [ObservableProperty]
[property: JsonIgnore]
[property: Hidden] [property: Hidden]
private float framePlate_PivotX; private float framePlate_PivotX;
[JsonIgnore]
[ObservableProperty] [ObservableProperty]
[property: JsonIgnore]
[property: Hidden] [property: Hidden]
private float framePlate_PivotY; private float framePlate_PivotY;
@ -754,8 +763,9 @@ namespace CtrEditor.ObjetosSim
// All Pages Objects // All Pages Objects
[NotifyPropertyChangedFor(nameof(Show_On_This_Page))] [NotifyPropertyChangedFor(nameof(Show_On_This_Page))]
[ObservableProperty] [ObservableProperty]
[property: Description("Enable this object to be used in all pages.")] [property: Category("Configuración")]
[property: Category("Layout:")] [property: Description("Habilitar este objeto para ser usado en todas las páginas")]
[property: Name("Habilitado en Todas Páginas")]
private bool enable_On_All_Pages; private bool enable_On_All_Pages;
@ -779,8 +789,9 @@ namespace CtrEditor.ObjetosSim
// Local Data for Global Objects // Local Data for Global Objects
[NotifyPropertyChangedFor(nameof(Show_On_This_Page))] [NotifyPropertyChangedFor(nameof(Show_On_This_Page))]
[ObservableProperty] [ObservableProperty]
[property: Description("Enable local data of this global Object on all pages.")] [property: Category("Configuración")]
[property: Category("Layout:")] [property: Description("Habilitar datos locales de este objeto global en todas las páginas")]
[property: Name("Datos Locales para Todas")]
private bool enable_Local_Data_for_All; private bool enable_Local_Data_for_All;
partial void OnEnable_Local_Data_for_AllChanged(bool value) partial void OnEnable_Local_Data_for_AllChanged(bool value)
@ -795,8 +806,9 @@ namespace CtrEditor.ObjetosSim
// Local Data for Global Objects // Local Data for Global Objects
[NotifyPropertyChangedFor(nameof(Show_On_This_Page))] [NotifyPropertyChangedFor(nameof(Show_On_This_Page))]
[ObservableProperty] [ObservableProperty]
[property: Description("Enable local data of this global Object on this page.")] [property: Category("Configuración")]
[property: Category("Layout:")] [property: Description("Habilitar datos locales de este objeto global en esta página")]
[property: Name("Datos Locales")]
[property: JsonIgnore] [property: JsonIgnore]
private bool enable_Local_Data; private bool enable_Local_Data;
@ -910,7 +922,9 @@ namespace CtrEditor.ObjetosSim
private List<string> showOnThisPagesList; private List<string> showOnThisPagesList;
private bool show_On_This_Page; private bool show_On_This_Page;
[property: Category("Layout:")] [property: Category("Información")]
[property: Description("Mostrar en esta página")]
[property: Name("Mostrar en Esta Página")]
public bool Show_On_This_Page public bool Show_On_This_Page
{ {
get get
@ -958,13 +972,15 @@ namespace CtrEditor.ObjetosSim
} }
[ObservableProperty] [ObservableProperty]
[property: Description("Autocreated and cloned with Search Templates")] [property: Category("Datos")]
[property: Category("Tag Extraction:")] [property: Description("Creado automáticamente y clonado con plantillas de búsqueda")]
[property: Name("Clonado")]
bool cloned; bool cloned;
[ObservableProperty] [ObservableProperty]
[property: Description("Autocreated and cloned with Search Templates")] [property: Category("Datos")]
[property: Category("Tag Extraction:")] [property: Description("ID del objeto del cual fue clonado")]
[property: Name("Clonado Desde")]
[property: Hidden] [property: Hidden]
UniqueId cloned_from; UniqueId cloned_from;
@ -1153,6 +1169,27 @@ namespace CtrEditor.ObjetosSim
return storyboard; 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) protected Storyboard CrearAnimacionMultiStoryBoardTrasnporte(Storyboard storyboard, Rectangle transporte, bool invertirDireccion)
{ {
// Detener y eliminar el storyboard existente si hay uno // Detener y eliminar el storyboard existente si hay uno
@ -1165,6 +1202,18 @@ namespace CtrEditor.ObjetosSim
return CrearAnimacionMultiStoryBoardTrasnporte(transporte, invertirDireccion); 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) protected void ActualizarAnimacionMultiStoryBoardTransporte(Storyboard storyboard, float velocidadActual)
{ {
if (_visualRepresentation == null) return; if (_visualRepresentation == null) return;
@ -1181,6 +1230,14 @@ namespace CtrEditor.ObjetosSim
_storyboard = CrearAnimacionMultiStoryBoardTrasnporte(_storyboard, transporte, invertirDireccion); _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) protected void ActualizarAnimacionStoryBoardTransporte(float velocidadActual)
{ {
ActualizarAnimacionMultiStoryBoardTransporte(_storyboard, velocidadActual); ActualizarAnimacionMultiStoryBoardTransporte(_storyboard, velocidadActual);
@ -1601,7 +1658,31 @@ namespace CtrEditor.ObjetosSim
{ {
if (value is string stringValue) if (value is string stringValue)
{ {
return new BitmapImage(new Uri(stringValue, UriKind.RelativeOrAbsolute)); 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 null; return null;
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,138 @@
# 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,6 +6,7 @@ using System.Windows;
using CtrEditor.Simulacion; using CtrEditor.Simulacion;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Windows.Media;
namespace CtrEditor.Serialization namespace CtrEditor.Serialization
{ {
@ -254,8 +255,94 @@ namespace CtrEditor.Serialization
NullValueHandling = NullValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore,
TypeNameHandling = TypeNameHandling.Auto, TypeNameHandling = TypeNameHandling.Auto,
ObjectCreationHandling = ObjectCreationHandling.Replace, ObjectCreationHandling = ObjectCreationHandling.Replace,
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor 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
}
}; };
} }
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();
}
} }
} }