diff --git a/SpineViewer/MainForm.cs b/SpineViewer/MainForm.cs index 525e81f..3453916 100644 --- a/SpineViewer/MainForm.cs +++ b/SpineViewer/MainForm.cs @@ -43,7 +43,64 @@ namespace SpineViewer private void ExportPng_Work(object? sender, DoWorkEventArgs e) { + var worker = sender as BackgroundWorker; + var arguments = e.Argument as Dialogs.ExportPngDialog; + var outputDir = arguments.OutputDir; + var duration = arguments.Duration; + var fps = arguments.Fps; + var timestamp = DateTime.Now.ToString("yyMMddHHmmss"); + var resolution = spinePreviewer.Resolution; + var tex = new SFML.Graphics.RenderTexture((uint)resolution.Width, (uint)resolution.Height); + tex.SetView(spinePreviewer.View); + var delta = 1f / fps; + var frameCount = 1 + (int)(duration / delta); // 零帧开始导出 + + spinePreviewer.StopPreview(); + + lock (spineListView.Spines) + { + var spinesReverse = spineListView.Spines.Reverse(); + + // 重置动画时间 + foreach (var spine in spinesReverse) + spine.CurrentAnimation = spine.CurrentAnimation; + + Program.Logger.Info( + "Begin exporting png frames to output dir {}, duration: {}, fps: {}, totally {} spines", + [outputDir, duration, fps, spinesReverse.Count()] + ); + + // 逐帧导出 + var success = 0; + worker.ReportProgress(0, $"已处理 0/{frameCount}"); + for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) + { + if (worker.CancellationPending) + break; + + tex.Clear(SFML.Graphics.Color.Transparent); + + foreach(var spine in spinesReverse) + { + tex.Draw(spine); + spine.Update(delta); + } + + tex.Display(); + using (var img = tex.Texture.CopyToImage()) + { + img.SaveToFile(Path.Combine(outputDir, $"{timestamp}_{fps}_{frameIndex:d6}.png")); + } + + success++; + worker.ReportProgress((int)((frameIndex + 1) * 100.0) / frameCount, $"已处理 {frameIndex + 1}/{frameCount}"); + } + + Program.Logger.Info("Exporting done: {}/{}", success, frameCount); + } + + spinePreviewer.StartPreview(); } private void MainForm_Load(object sender, EventArgs e) @@ -77,14 +134,14 @@ namespace SpineViewer } } - //var openDialog = new BatchOpenSpineDialog(); - //if (openDialog.ShowDialog() != DialogResult.OK) - // return; + var exportDialog = new Dialogs.ExportPngDialog(); + if (exportDialog.ShowDialog() != DialogResult.OK) + return; - //var progressDialog = new ProgressDialog(); - //progressDialog.DoWork += ExportPng_Work; - //progressDialog.RunWorkerAsync(new { openDialog.SkelPaths, openDialog.Version }); - //progressDialog.ShowDialog(); + var progressDialog = new Dialogs.ProgressDialog(); + progressDialog.DoWork += ExportPng_Work; + progressDialog.RunWorkerAsync(exportDialog); + progressDialog.ShowDialog(); } private void toolStripMenuItem_Exit_Click(object sender, EventArgs e)