支持动画使用不同的形状

This commit is contained in:
艾竹
2023-05-01 00:10:55 +08:00
parent 4a3f278a97
commit 48555edbc6
13 changed files with 183 additions and 29 deletions

View File

@@ -1,4 +1,5 @@
using AIStudio.Wpf.DiagramDesigner; using AIStudio.Wpf.DiagramDesigner;
using Newtonsoft.Json.Linq;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -39,6 +40,17 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
return logicalConnectorInfo.ConnectorValue.ToString("f3"); return logicalConnectorInfo.ConnectorValue.ToString("f3");
} }
else if (logicalConnectorInfo.ConnectorValueType == ConnectorValueType.JsonString)
{
if (logicalConnectorInfo.ConnectorString != null)
{
JObject obj = JObject.Parse(logicalConnectorInfo.ConnectorString);
if (obj.ContainsKey("Text"))
{
return obj["Text"].ToString();
}
}
}
else else
{ {
return logicalConnectorInfo.ConnectorString; return logicalConnectorInfo.ConnectorString;

View File

@@ -12,5 +12,6 @@ namespace AIStudio.Wpf.DiagramDesigner
Bool = 2, Bool = 2,
ValueType = 99, ValueType = 99,
String = 100, String = 100,
JsonString = 101,
} }
} }

View File

@@ -70,6 +70,16 @@ namespace AIStudio.Wpf.DiagramDesigner
return JsonConvert.SerializeObject(obj); return JsonConvert.SerializeObject(obj);
} }
public static T ToObject<T>(this string str)
{
return JsonConvert.DeserializeObject<T>(str);
}
public static object ToObject(this string str, Type type)
{
return JsonConvert.DeserializeObject(str, type);
}
public static JsonSerializerSettings Settings { get; set; } = new JsonSerializerSettings public static JsonSerializerSettings Settings { get; set; } = new JsonSerializerSettings
{ {
DateFormatString = "yyyy-MM-dd HH:mm:ss.fff", DateFormatString = "yyyy-MM-dd HH:mm:ss.fff",

View File

@@ -470,6 +470,22 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
} }
[XmlAttribute]
public bool Repeat
{
get; set;
}
public bool Start
{
get; set;
}
public int Completed
{
get;set;
}
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
} }

View File

@@ -109,7 +109,7 @@
Data="{Binding AnimationViewModel.AnimationPath.Path}" Data="{Binding AnimationViewModel.AnimationPath.Path}"
Fill="{Binding AnimationViewModel.Color,Converter={StaticResource ColorBrushConverter}}" Fill="{Binding AnimationViewModel.Color,Converter={StaticResource ColorBrushConverter}}"
Width="{Binding AnimationViewModel.AnimationPath.Width}" Width="{Binding AnimationViewModel.AnimationPath.Width}"
Height="{Binding ColorViewModel.AnimationPath.Height}" Height="{Binding AnimationViewModel.AnimationPath.Height}"
Panel.ZIndex="1" /> Panel.ZIndex="1" />
</Canvas> </Canvas>
</Grid> </Grid>

View File

@@ -42,7 +42,7 @@ namespace AIStudio.Wpf.DiagramDesigner
if (this.DataContext is ConnectionViewModel connector && connector.AnimationViewModel != null) if (this.DataContext is ConnectionViewModel connector && connector.AnimationViewModel != null)
{ {
connector.AnimationViewModel.PropertyChanged -= Connector_PropertyChanged; connector.AnimationViewModel.PropertyChanged -= Connector_PropertyChanged;
connector.AnimationViewModel.PropertyChanged += Connector_PropertyChanged; connector.AnimationViewModel.PropertyChanged += Connector_PropertyChanged;
} }
this.ball.Visibility = Visibility.Collapsed; this.ball.Visibility = Visibility.Collapsed;
await DoAnimation(); await DoAnimation();
@@ -56,6 +56,11 @@ namespace AIStudio.Wpf.DiagramDesigner
case nameof(AnimationViewModel.Duration): case nameof(AnimationViewModel.Duration):
await DoAnimation(); await DoAnimation();
break; break;
case nameof(AnimationViewModel.Start):
await Application.Current.Dispatcher.BeginInvoke(async () => {
await DoAnimation();
});
break;
} }
} }
@@ -64,26 +69,36 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
if (this.DataContext is ConnectionViewModel connector && connector.IsFullConnection) if (this.DataContext is ConnectionViewModel connector && connector.IsFullConnection)
{ {
await System.Threading.Tasks.Task.Delay(100); if (connector.AnimationViewModel.Repeat == false)
{
if (connector.AnimationViewModel.Start == false || connector.AnimationViewModel.Completed == 1)
{
return;
}
connector.AnimationViewModel.Completed = 1;
connector.AnimationViewModel.Start = false;
}
await System.Threading.Tasks.Task.Delay(10);
switch (connector.AnimationViewModel.Animation) switch (connector.AnimationViewModel.Animation)
{ {
case LineAnimation.None: case LineAnimation.None:
_story?.Stop(this); _story?.Stop(this);
ball.Visibility = Visibility.Collapsed; ball.Visibility = Visibility.Collapsed;
break; break;
case LineAnimation.PathAnimation: case LineAnimation.PathAnimation:
if (connector.ColorViewModel.FillColor.BrushType == BrushType.SolidColorBrush && connector.ColorViewModel.FillColor.Color == Colors.White) if (connector.ColorViewModel.FillColor.BrushType == BrushType.SolidColorBrush && connector.ColorViewModel.FillColor.Color == Colors.White)
{ {
connector.ColorViewModel.FillColor.Color = Colors.Red; connector.ColorViewModel.FillColor.Color = Colors.Red;
} }
PathAnimation(connector.AnimationViewModel.Duration); PathAnimation(connector.AnimationViewModel);
break; break;
case LineAnimation.DashAnimation: case LineAnimation.DashAnimation:
if (connector.ColorViewModel.LineDashStyle == LineDashStyle.None) if (connector.ColorViewModel.LineDashStyle == LineDashStyle.None)
{ {
connector.ColorViewModel.LineDashStyle = LineDashStyle.Dash1; connector.ColorViewModel.LineDashStyle = LineDashStyle.Dash1;
} }
DashAnimation(connector.AnimationViewModel.Duration); DashAnimation(connector.AnimationViewModel);
break; break;
} }
} }
@@ -91,14 +106,14 @@ namespace AIStudio.Wpf.DiagramDesigner
Storyboard _story; Storyboard _story;
private void PathAnimation(double second) private void PathAnimation(IAnimationViewModel animationViewModel)
{ {
this.ball.Visibility = Visibility.Visible; this.ball.Visibility = Visibility.Visible;
Canvas.SetTop(this.ball, -this.ball.ActualHeight / 2); Canvas.SetTop(this.ball, -this.ball.ActualHeight / 2);
Canvas.SetLeft(this.ball, -this.ball.ActualWidth / 2); Canvas.SetLeft(this.ball, -this.ball.ActualWidth / 2);
this.ball.RenderTransformOrigin = new Point(0.5, 0.5); this.ball.RenderTransformOrigin = new Point(0.5, 0.5);
TranslateTransform translate = new TranslateTransform(); TranslateTransform translate = new TranslateTransform();
RotateTransform rotate = new RotateTransform(); RotateTransform rotate = new RotateTransform();
@@ -114,7 +129,7 @@ namespace AIStudio.Wpf.DiagramDesigner
DoubleAnimationUsingPath animationX = new DoubleAnimationUsingPath(); DoubleAnimationUsingPath animationX = new DoubleAnimationUsingPath();
animationX.PathGeometry = this.line.Data?.GetFlattenedPathGeometry(); animationX.PathGeometry = this.line.Data?.GetFlattenedPathGeometry();
animationX.Source = PathAnimationSource.X; animationX.Source = PathAnimationSource.X;
animationX.Duration = new Duration(TimeSpan.FromSeconds(second)); animationX.Duration = new Duration(TimeSpan.FromSeconds(animationViewModel.Duration));
DoubleAnimationUsingPath animationY = new DoubleAnimationUsingPath(); DoubleAnimationUsingPath animationY = new DoubleAnimationUsingPath();
animationY.PathGeometry = this.line.Data?.GetFlattenedPathGeometry(); animationY.PathGeometry = this.line.Data?.GetFlattenedPathGeometry();
@@ -134,7 +149,15 @@ namespace AIStudio.Wpf.DiagramDesigner
_story.Children.Add(animationY); _story.Children.Add(animationY);
_story.Children.Add(animationAngle); _story.Children.Add(animationAngle);
_story.Completed += (s, d) => { _story.Completed += (s, d) => {
_story.Begin(this, true); if (animationViewModel.Repeat)
{
_story.Begin(this, true);
}
else
{
this.ball.Visibility = Visibility.Collapsed;
animationViewModel.Completed = 100;
}
}; };
Storyboard.SetTargetName(animationX, "translate"); Storyboard.SetTargetName(animationX, "translate");
Storyboard.SetTargetName(animationY, "translate"); Storyboard.SetTargetName(animationY, "translate");
@@ -147,12 +170,12 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
private void DashAnimation(double second) private void DashAnimation(IAnimationViewModel animationViewModel)
{ {
this.ball.Visibility = Visibility.Collapsed; this.ball.Visibility = Visibility.Collapsed;
var animation = new DoubleAnimation(0, -10, new Duration(TimeSpan.FromSeconds(second))) var animation = new DoubleAnimation(0, -10, new Duration(TimeSpan.FromSeconds(animationViewModel.Duration)))
{ {
RepeatBehavior = RepeatBehavior.Forever, RepeatBehavior = RepeatBehavior.Forever,
}; };
@@ -163,6 +186,17 @@ namespace AIStudio.Wpf.DiagramDesigner
_story = new Storyboard(); _story = new Storyboard();
_story.RepeatBehavior = RepeatBehavior.Forever; _story.RepeatBehavior = RepeatBehavior.Forever;
_story.Children.Add(animation); _story.Children.Add(animation);
_story.Completed += (s, d) => {
if (animationViewModel.Repeat)
{
_story.Begin(this, true);
}
else
{
this.ball.Visibility = Visibility.Collapsed;
animationViewModel.Completed = 100;
}
};
_story.Begin(this, true); _story.Begin(this, true);
} }

View File

@@ -79,6 +79,37 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
} }
private bool _repeat = true;
public bool Repeat
{
get
{
return _repeat;
}
set
{
SetProperty(ref _repeat, value);
}
}
private bool _start;
public bool Start
{
get
{
return _start;
}
set
{
SetProperty(ref _start, value);
}
}
public int Completed
{
get; set;
}
private void AnimationViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) private void AnimationViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{ {
if (sender == AnimationPath) if (sender == AnimationPath)

View File

@@ -26,6 +26,21 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
get; set; get; set;
} }
bool Repeat
{
get; set;
}
bool Start
{
get; set;
}
int Completed
{
get; set;
}
event PropertyChangedEventHandler PropertyChanged; event PropertyChangedEventHandler PropertyChanged;
} }
} }

View File

@@ -9,6 +9,11 @@ namespace AIStudio.Wpf.DiagramDesigner
public static SharpPath Arrow { get; } = new SharpPath("M 0 -5 10 0 0 5 z", 10, 10, PathStyle.Arrow, SizeStyle.Middle); public static SharpPath Arrow { get; } = new SharpPath("M 0 -5 10 0 0 5 z", 10, 10, PathStyle.Arrow, SizeStyle.Middle);
public static SharpPath Circle { get; } = new SharpPath("M 0, 0 a 5,5 0 1,0 10,0 a 5,5 0 1,0 -10,0", 10, 10, PathStyle.Circle, SizeStyle.Middle); public static SharpPath Circle { get; } = new SharpPath("M 0, 0 a 5,5 0 1,0 10,0 a 5,5 0 1,0 -10,0", 10, 10, PathStyle.Circle, SizeStyle.Middle);
public static SharpPath Square { get; } = new SharpPath("M 0 -5 10 -5 10 5 0 5 z", 10, 10, PathStyle.Square, SizeStyle.Middle); public static SharpPath Square { get; } = new SharpPath("M 0 -5 10 -5 10 5 0 5 z", 10, 10, PathStyle.Square, SizeStyle.Middle);
public static SharpPath Triangle { get; } = new SharpPath("M1,21H23L12,2", 10, 10, PathStyle.Square, SizeStyle.Middle);
public static SharpPath Rhombus { get; } = new SharpPath("M 0,20 L 30 0 L 60,20 L 30,40 Z", 10, 10, PathStyle.Square, SizeStyle.Middle);
public static SharpPath Trapezoid { get; } = new SharpPath("M 0 0 H 60 L 50 40 H 10 Z", 10, 10, PathStyle.Square, SizeStyle.Middle);
public static SharpPath Pentagram { get; } = new SharpPath("M 9,2 11,7 17,7 12,10 14,15 9,12 4,15 6,10 1,7 7,7 Z", 10, 10, PathStyle.Square, SizeStyle.Middle);
public static SharpPath Hexagon { get; } = new SharpPath("M 0,20 L 10,0 H 50 L 60,20 L 50,40 H10 Z", 10, 10, PathStyle.Square, SizeStyle.Middle);
public static readonly Dictionary<PathStyle, string> ArrowDictionary = new Dictionary<PathStyle, string>() public static readonly Dictionary<PathStyle, string> ArrowDictionary = new Dictionary<PathStyle, string>()
{ {

View File

@@ -144,6 +144,10 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
return true; return true;
} }
else if (logical.ConnectorValueType == ConnectorValueType.JsonString && this.ConnectorValueType == logical.ConnectorValueType)
{
return true;
}
else if (logical.ConnectorValueType <= ConnectorValueType.ValueType && this.ConnectorValueType <= ConnectorValueType.ValueType) else if (logical.ConnectorValueType <= ConnectorValueType.ValueType && this.ConnectorValueType <= ConnectorValueType.ValueType)
{ {
return true; return true;

View File

@@ -1403,9 +1403,9 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
var logical = item as LogicalGateItemViewModelBase; var logical = item as LogicalGateItemViewModelBase;
if (logical != null && logical.LogicalType > 0) if (logical != null)
{ {
logical.OrderNumber = Items.OfType<LogicalGateItemViewModelBase>().Count(p => (int)p.LogicalType > 0) + 1; logical.OrderNumber = Items.OfType<LogicalGateItemViewModelBase>().Count() + 1;
} }
var designerItemViewModelBase = item as DesignerItemViewModelBase; var designerItemViewModelBase = item as DesignerItemViewModelBase;

View File

@@ -5,6 +5,7 @@ using System.ComponentModel.DataAnnotations;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using AIStudio.Wpf.DiagramDesigner.Enums; using AIStudio.Wpf.DiagramDesigner.Enums;
@@ -253,14 +254,16 @@ namespace AIStudio.Wpf.DiagramDesigner
continue; continue;
} }
if (connector.SourceConnectorInfo.DataItem is LogicalGateItemViewModelBase) if (connector.SourceConnectorInfo.DataItem is LogicalGateItemViewModelBase sourceItem)
{ {
var output = (connector.SourceConnectorInfo as LogicalConnectorInfo); var output = (connector.SourceConnectorInfo as LogicalConnectorInfo);
connector.ColorViewModel.LineColor.Color = output.ColorViewModel.FillColor.Color;
connector.ColorViewModel.FillColor.Color = output.ColorViewModel.FillColor.Color;
if (input.Value.CanAttachTo(output)) if (EnableInputValue(connector, input.Value, output))
{ {
connector.ColorViewModel.LineColor.Color = output.ColorViewModel.FillColor.Color;
connector.ColorViewModel.FillColor.Color = output.ColorViewModel.FillColor.Color;
connector.AnimationViewModel.Color = output.ColorViewModel.FillColor.Color;
input.Value.ConnectorValue = output.ConnectorValue; input.Value.ConnectorValue = output.ConnectorValue;
input.Value.ConnectorString = output.ConnectorString; input.Value.ConnectorString = output.ConnectorString;
input.Value.ColorViewModel.FillColor.Color = connector.SourceConnectorInfo.ColorViewModel.FillColor.Color; input.Value.ColorViewModel.FillColor.Color = connector.SourceConnectorInfo.ColorViewModel.FillColor.Color;
@@ -272,13 +275,10 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
input.Value.ConnectorValueType = ((connector.SourceConnectorInfo as LogicalConnectorInfo).ConnectorValueType == ConnectorValueType.Bool) ? ConnectorValueType.Bool : ConnectorValueType.Int; input.Value.ConnectorValueType = ((connector.SourceConnectorInfo as LogicalConnectorInfo).ConnectorValueType == ConnectorValueType.Bool) ? ConnectorValueType.Bool : ConnectorValueType.Int;
} }
sourceItem.ClearOutputValue(connector, output);
} }
else sourceItem.StartAnimation(output);
{
input.Value.ErrorCode = ConnectorErrorCode.ConnErr;
input.Value.ErrorMessage = "连接类型不匹配";
input.Value.ColorViewModel.FillColor.Color = Colors.DarkRed;
}
} }
} }
} }
@@ -310,16 +310,44 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
} }
} }
else else if (output.Value.ConnectorValueType <= ConnectorValueType.ValueType)
{ {
output.Value.ColorViewModel.FillColor.Color = Colors.Green; output.Value.ColorViewModel.FillColor.Color = Colors.Green;
} }
} }
} }
public virtual bool EnableInputValue(ConnectionViewModel connector, LogicalConnectorInfo input, LogicalConnectorInfo output)
{
if (!input.CanAttachTo(output))
{
input.ErrorCode = ConnectorErrorCode.ConnErr;
input.ErrorMessage = "连接类型不匹配";
input.ColorViewModel.FillColor.Color = Colors.DarkRed;
return false;
}
return true;
}
public virtual void ClearOutputValue(ConnectionViewModel connector, LogicalConnectorInfo output)
{
}
public virtual void StartAnimation(LogicalConnectorInfo output)
{
}
protected ConnectionViewModel GetSourceItem(FullyCreatedConnectorInfo sinkConnector) protected ConnectionViewModel GetSourceItem(FullyCreatedConnectorInfo sinkConnector)
{ {
return Root?.Items.OfType<ConnectionViewModel>().FirstOrDefault(p => p.SinkConnectorInfo == sinkConnector); return Root?.Items.OfType<ConnectionViewModel>().FirstOrDefault(p => p.SinkConnectorInfo == sinkConnector);
} }
protected ConnectionViewModel GetSinkItem(FullyCreatedConnectorInfo sourceConnector)
{
return Root?.Items.OfType<ConnectionViewModel>().FirstOrDefault(p => p.SourceConnectorInfo == sourceConnector);
}
} }
} }

View File

@@ -29,12 +29,10 @@ namespace AIStudio.Wpf.DiagramDesigner.Demo.ViewModels
DiagramViewModel.Add(node3); DiagramViewModel.Add(node3);
ConnectionViewModel connector1 = new ConnectionViewModel(DiagramViewModel, node1.RightConnector, node2.LeftConnector, DrawMode.ConnectingLineSmooth, RouterMode.RouterNormal); ConnectionViewModel connector1 = new ConnectionViewModel(DiagramViewModel, node1.RightConnector, node2.LeftConnector, DrawMode.ConnectingLineSmooth, RouterMode.RouterNormal);
connector1.ColorViewModel.FillColor.Color = Colors.Red;
connector1.AnimationViewModel.Animation = LineAnimation.PathAnimation; connector1.AnimationViewModel.Animation = LineAnimation.PathAnimation;
DiagramViewModel.Add(connector1); DiagramViewModel.Add(connector1);
ConnectionViewModel connector2 = new ConnectionViewModel(DiagramViewModel, node2.RightConnector, node3.RightConnector, DrawMode.ConnectingLineStraight, RouterMode.RouterOrthogonal); ConnectionViewModel connector2 = new ConnectionViewModel(DiagramViewModel, node2.RightConnector, node3.RightConnector, DrawMode.ConnectingLineStraight, RouterMode.RouterOrthogonal);
connector2.ColorViewModel.FillColor.Color = Colors.Red;
connector2.AnimationViewModel.Animation = LineAnimation.PathAnimation; connector2.AnimationViewModel.Animation = LineAnimation.PathAnimation;
DiagramViewModel.Add(connector2); DiagramViewModel.Add(connector2);
} }