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.

This commit is contained in:
Miguel 2025-06-23 22:10:00 +02:00
parent ac8773ebc7
commit da8d0516cb
4 changed files with 90 additions and 22 deletions

View File

@ -46,6 +46,11 @@ namespace CtrEditor.ObjetosSim
partial void OnInvertirDireccionChanged(bool value)
{
SetSpeed();
if (_visualRepresentation is ucTransporteCurva uc)
{
CrearAnimacionStoryBoardTrasnporteCircular(uc.Transporte.TransportePath, InvertirDireccion);
ActualizarAnimacionStoryBoardTransporte(VelocidadActual);
}
}
void SetSpeed()
@ -54,6 +59,7 @@ namespace CtrEditor.ObjetosSim
Simulation_TransporteCurva?.SetSpeed(-VelocidadActual);
else
Simulation_TransporteCurva?.SetSpeed(VelocidadActual);
ActualizarAnimacionStoryBoardTransporte(VelocidadActual);
}
[ObservableProperty]
@ -64,13 +70,13 @@ namespace CtrEditor.ObjetosSim
// Update ancho and alto based on radioExterno
Ancho = value * 2;
Alto = value * 2;
// Ensure radioInterno maintains proper proportion if needed
if (RadioInterno >= value)
{
RadioInterno = value * 0.75f; // Default proportion
}
ActualizarGeometrias();
}
@ -84,7 +90,7 @@ namespace CtrEditor.ObjetosSim
[property: Category("PLC link:")]
string tag_ReleActivatedMotor;
[ObservableProperty]
[ObservableProperty]
[property: Description("Link to Motor")]
[property: Category("PLC link:")]
[property: ItemsSource(typeof(osBaseItemsSource<osVMmotorSim>))]
@ -115,8 +121,8 @@ namespace CtrEditor.ObjetosSim
}
}
public override void AnguloChanged(float value)
{
public override void AnguloChanged(float value)
{
OnPropertyChanged(nameof(AnguloFinal));
}
@ -127,14 +133,14 @@ namespace CtrEditor.ObjetosSim
[Hidden]
public float AnguloFinal
{
get => Angulo+Arco_en_grados;
get => Angulo + Arco_en_grados;
}
private void ActualizarGeometrias()
{
if (_visualRepresentation is ucTransporteCurva uc)
{
UpdateCurve(Simulation_TransporteCurva, RadioInterno, RadioExterno, Angulo, Angulo+Arco_en_grados);
UpdateCurve(Simulation_TransporteCurva, RadioInterno, RadioExterno, Angulo, Angulo + Arco_en_grados);
SetSpeed();
}
}
@ -158,32 +164,32 @@ namespace CtrEditor.ObjetosSim
// Calculate the proportional change factor
float widthChangeFactor = (Ancho + Delta_Width) / Ancho;
float heightChangeFactor = (Alto + Delta_Height) / Alto;
// Use the average or minimum change factor to maintain aspect ratio
float changeFactor = Math.Min(widthChangeFactor, heightChangeFactor);
// Save the original radiuses for calculating position adjustments
float originalRadioExterno = RadioExterno;
// Apply the change factor to both radios
RadioExterno *= changeFactor;
RadioInterno *= changeFactor;
// Calculate position adjustment to keep the component centered
float radiusDifference = RadioExterno - originalRadioExterno;
// Adjust Left and Top to maintain center position
// We move by negative half the difference because the component expands outward
Left -= radiusDifference;
Top -= radiusDifference;
// Ensure minimums
if (RadioExterno < 0.1f)
RadioExterno = 0.1f;
if (RadioInterno < 0.05f)
RadioInterno = 0.05f;
// Ensure radioInterno is always less than radioExterno
if (RadioInterno >= RadioExterno)
RadioInterno = RadioExterno * 0.75f;
@ -205,9 +211,14 @@ namespace CtrEditor.ObjetosSim
{
// Se llama antes de la simulacion
ActualizarGeometrias();
}
public override void SimulationStop()
{
// Se llama al detener la simulacion
ActualizarAnimacionStoryBoardTransporte(VelocidadActual);
}
public override void UpdatePLC(PLCViewModel plc, int elapsedMilliseconds)
{
if (Motor != null)
@ -225,13 +236,13 @@ namespace CtrEditor.ObjetosSim
// El UserControl ya se ha cargado y podemos obtener las coordenadas para
// crear el objeto de simulacion
base.ucLoaded();
OnId_MotorChanged(Id_Motor); // Link Id_Motor = Motor
if (_visualRepresentation is ucTransporteCurva uc)
Simulation_TransporteCurva = AddCurve(RadioInterno,RadioExterno, Angulo, Angulo + Arco_en_grados);
// AddCurve(float innerRadius, float outerRadius, float startAngle, float endAngle, Vector2 position)
{
Simulation_TransporteCurva = AddCurve(RadioInterno, RadioExterno, Angulo, Angulo + Arco_en_grados);
CrearAnimacionStoryBoardTrasnporteCircular(uc.Transporte.TransportePath, InvertirDireccion);
}
}
public override void ucUnLoaded()
{

View File

@ -6,7 +6,23 @@
xmlns:local="clr-namespace:CtrEditor.ObjetosSim.UserControls"
mc:Ignorable="d" Name="circularSegmentControl">
<Canvas>
<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>
<RotateTransform Angle="{Binding Angle, ElementName=circularSegmentControl}"/>
</Path.RenderTransform>

View File

@ -59,6 +59,9 @@ namespace CtrEditor.ObjetosSim.UserControls
InitializeComponent();
}
// Propiedad pública para acceder al Path desde código externo
public System.Windows.Shapes.Path TransportePath => path;
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as CircularSegment)?.DrawSegment();

View File

@ -1153,6 +1153,27 @@ namespace CtrEditor.ObjetosSim
return storyboard;
}
protected Storyboard CrearAnimacionMultiStoryBoardTrasnporteCircular(System.Windows.Shapes.Path transporte, bool invertirDireccion)
{
if (_visualRepresentation == null) return null;
if (transporte == null) return null;
Storyboard storyboard = new Storyboard();
var animation = new DoubleAnimation
{
From = invertirDireccion ? 20 : 0,
To = invertirDireccion ? 0 : 20, // Total Pixels Brush
Duration = TimeSpan.FromSeconds(PixelToMeter.Instance.calc.PixelsToMeters(20) * 60),
RepeatBehavior = RepeatBehavior.Forever
};
Storyboard.SetTarget(animation, transporte);
Storyboard.SetTargetProperty(animation, new PropertyPath("(Path.Fill).(VisualBrush.Transform).(TransformGroup.Children)[0].(TranslateTransform.Y)"));
storyboard.Children.Add(animation);
storyboard.Begin();
storyboard.SetSpeedRatio(0);
return storyboard;
}
protected Storyboard CrearAnimacionMultiStoryBoardTrasnporte(Storyboard storyboard, Rectangle transporte, bool invertirDireccion)
{
// Detener y eliminar el storyboard existente si hay uno
@ -1165,6 +1186,18 @@ namespace CtrEditor.ObjetosSim
return CrearAnimacionMultiStoryBoardTrasnporte(transporte, invertirDireccion);
}
protected Storyboard CrearAnimacionMultiStoryBoardTrasnporteCircular(Storyboard storyboard, System.Windows.Shapes.Path transporte, bool invertirDireccion)
{
// Detener y eliminar el storyboard existente si hay uno
if (storyboard != null)
{
storyboard.Stop();
storyboard.Children.Clear();
}
return CrearAnimacionMultiStoryBoardTrasnporteCircular(transporte, invertirDireccion);
}
protected void ActualizarAnimacionMultiStoryBoardTransporte(Storyboard storyboard, float velocidadActual)
{
if (_visualRepresentation == null) return;
@ -1181,6 +1214,11 @@ namespace CtrEditor.ObjetosSim
_storyboard = CrearAnimacionMultiStoryBoardTrasnporte(_storyboard, transporte, invertirDireccion);
}
protected void CrearAnimacionStoryBoardTrasnporteCircular(System.Windows.Shapes.Path transporte, bool invertirDireccion)
{
_storyboard = CrearAnimacionMultiStoryBoardTrasnporteCircular(_storyboard, transporte, invertirDireccion);
}
protected void ActualizarAnimacionStoryBoardTransporte(float velocidadActual)
{
ActualizarAnimacionMultiStoryBoardTransporte(_storyboard, velocidadActual);