using LinePutScript; using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Media.Imaging; using static VPet_Simulator.Core.IGraph; using static VPet_Simulator.Core.Picture; namespace VPet_Simulator.Core { /// /// PNGAnimation.xaml 的交互逻辑 /// public partial class PNGAnimation : IImageRun { /// /// 所有动画帧 /// public List Animations; /// /// 是否循环播放 /// public bool IsLoop { get; set; } /// /// 动画信息 /// public GraphInfo GraphInfo { get; private set; } /// /// 是否准备完成 /// public bool IsReady { get; private set; } = false; public TaskControl Control { get; set; } int nowid; /// /// 图片资源 /// public string Path; private GraphCore GraphCore; /// /// 反正一次性生成太多导致闪退 /// public static int NowLoading = 0; /// /// 新建 PNG 动画 /// /// 文件夹位置 /// 文件内容列表 /// 是否循环 public PNGAnimation(GraphCore graphCore, string path, FileInfo[] paths, GraphInfo graphinfo, bool isLoop = false) { Animations = new List(); IsLoop = isLoop; //StoreMemory = storemem; GraphInfo = graphinfo; GraphCore = graphCore; if (!GraphCore.CommConfig.ContainsKey("PA_Setup")) { GraphCore.CommConfig["PA_Setup"] = true; GraphCore.CommUIElements["Image1.PNGAnimation"] = new System.Windows.Controls.Image() { Height = 500 }; GraphCore.CommUIElements["Image2.PNGAnimation"] = new System.Windows.Controls.Image() { Height = 500 }; GraphCore.CommUIElements["Image3.PNGAnimation"] = new System.Windows.Controls.Image() { Height = 500 }; // 多整个, 防止动画闪烁 } Task.Run(() => startup(path, paths)); } public static void LoadGraph(GraphCore graph, FileSystemInfo path, ILine info) { if (!(path is DirectoryInfo p)) { Picture.LoadGraph(graph, path, info); return; } var paths = p.GetFiles(); bool isLoop = info[(gbol)"loop"]; PNGAnimation pa = new PNGAnimation(graph, path.FullName, paths, new GraphInfo(path, info), isLoop); graph.AddGraph(pa); } public double Width; /// /// 最大同时加载数 /// public static int MaxLoadNumber = 40; private void startup(string path, FileInfo[] paths) { while (NowLoading > MaxLoadNumber) { Thread.Sleep(100); } Interlocked.Increment(ref NowLoading); //新方法:加载大图片 //生成大文件加载非常慢,先看看有没有缓存能用 Path = System.IO.Path.Combine(GraphCore.CachePath, $"{GraphCore.Resolution}_{Math.Abs(Sub.GetHashCode(path))}_{paths.Length}.png"); Width = 500 * (paths.Length + 1); if (!File.Exists(Path) && !((List)GraphCore.CommConfig["Cache"]).Contains(path)) { ((List)GraphCore.CommConfig["Cache"]).Add(path); int w = 0; int h = 0; FileInfo firstImage = paths[0]; var img = System.Drawing.Image.FromFile(firstImage.FullName); w = img.Width; h = img.Height; if (w > GraphCore.Resolution) { w = GraphCore.Resolution; h = (int)(h * (GraphCore.Resolution / (double)img.Width)); } if (paths.Length * w >= 60000) {//修复大长动画导致过长分辨率导致可能的报错 w = 60000 / paths.Length; h = (int)(img.Height * (w / (double)img.Width)); } using (Bitmap joinedBitmap = new Bitmap(w * paths.Length, h)) using (Graphics graph = Graphics.FromImage(joinedBitmap)) { using (img) graph.DrawImage(img, 0, 0, w, h); Parallel.For(1, paths.Length, i => { using (var img = System.Drawing.Image.FromFile(paths[i].FullName)) { lock (graph) graph.DrawImage(img, w * i, 0, w, h); } }); if (!File.Exists(Path)) joinedBitmap.Save(Path); } } for (int i = 0; i < paths.Length; i++) { var noExtFileName = System.IO.Path.GetFileNameWithoutExtension(paths[i].Name); int time = int.Parse(noExtFileName.Substring(noExtFileName.LastIndexOf('_') + 1)); Animations.Add(new Animation(this, time, -500 * i)); } //stream = new MemoryStream(File.ReadAllBytes(cp)); IsReady = true; Interlocked.Decrement(ref NowLoading); } /// /// 单帧动画 /// public class Animation { private PNGAnimation parent; public int MarginWIX; ///// ///// 显示 ///// //public Action Visible; ///// ///// 隐藏 ///// //public Action Hidden; /// /// 帧时间 /// public int Time; public Animation(PNGAnimation parent, int time, int wxi)//, Action hidden) { this.parent = parent; Time = time; //Visible = visible; //Hidden = hidden; MarginWIX = wxi; } /// /// 运行该图层 /// /// 动画控制 /// 显示的图层 public void Run(FrameworkElement This, TaskControl Control) { //先显示该图层 This.Dispatcher.Invoke(() => This.Margin = new Thickness(MarginWIX, 0, 0, 0)); //然后等待帧时间毫秒 Thread.Sleep(Time); //判断是否要下一步 switch (Control.Type) { case TaskControl.ControlType.Stop: Control.EndAction?.Invoke(); return; case TaskControl.ControlType.Status_Stoped: return; case TaskControl.ControlType.Status_Quo: case TaskControl.ControlType.Continue: if (++parent.nowid >= parent.Animations.Count) if (parent.IsLoop) parent.nowid = 0; else if (Control.Type == TaskControl.ControlType.Continue) { Control.Type = TaskControl.ControlType.Status_Quo; parent.nowid = 0; } else { Control.Type = TaskControl.ControlType.Status_Stoped; Control.EndAction?.Invoke(); //运行结束动画时事件 return; } //要下一步 parent.Animations[parent.nowid].Run(This, Control); return; } } } /// /// 从0开始运行该动画 /// public void Run(Decorator parant, Action EndAction = null) { if (!IsReady) { EndAction?.Invoke(); return; } if (Control?.PlayState == true) {//如果当前正在运行,重置状态 Control.Stop(() => Run(parant, EndAction)); return; } nowid = 0; Control = new TaskControl(EndAction); parant.Dispatcher.Invoke(() => { if (parant.Tag == this) { Task.Run(() => Animations[0].Run((System.Windows.Controls.Image)parant.Child, Control)); return; } System.Windows.Controls.Image img; if (parant.Child == GraphCore.CommUIElements["Image1.PNGAnimation"]) { img = (System.Windows.Controls.Image)GraphCore.CommUIElements["Image1.PNGAnimation"]; } else if (parant.Child == GraphCore.CommUIElements["Image3.PNGAnimation"]) { img = (System.Windows.Controls.Image)GraphCore.CommUIElements["Image3.PNGAnimation"]; } else { img = (System.Windows.Controls.Image)GraphCore.CommUIElements["Image2.PNGAnimation"]; if (parant.Child != GraphCore.CommUIElements["Image2.PNGAnimation"]) { if (img.Parent == null) { parant.Child = img; } else { img = (System.Windows.Controls.Image)GraphCore.CommUIElements["Image1.PNGAnimation"]; if (img.Parent != null) ((Decorator)img.Parent).Child = null; parant.Child = img; } } } parant.Tag = this; img.Source = new BitmapImage(new Uri(Path)); img.Width = Width; Task.Run(() => Animations[0].Run((System.Windows.Controls.Image)parant.Child, Control)); }); } /// /// 指定图像图像控件准备运行该动画 /// /// 用于显示的Image /// 结束动画 /// 准备好的线程 public Task Run(System.Windows.Controls.Image img, Action EndAction = null) { if (!IsReady) { EndAction?.Invoke(); return Task.CompletedTask; } if (Control?.PlayState == true) {//如果当前正在运行,重置状态 Control.EndAction = null; Control.Type = TaskControl.ControlType.Stop; } nowid = 0; Control = new TaskControl(EndAction); return img.Dispatcher.Invoke(() => { if (img.Tag == this) { return new Task(() => Animations[0].Run(img, Control)); } img.Tag = this; img.Source = new BitmapImage(new Uri(Path)); img.Width = Width; return new Task(() => Animations[0].Run(img, Control)); }); } } }