From 2784ec4955f60a256df7923c38a924f3e423c159 Mon Sep 17 00:00:00 2001 From: ww-rm Date: Thu, 27 Feb 2025 00:04:57 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=89=B9=E9=87=8F=E6=89=93?= =?UTF-8?q?=E5=BC=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/BatchOpenSpineDialog.Designer.cs | 206 +++++++++++++++++- SpineViewer/src/BatchOpenSpineDialog.cs | 53 ++++- SpineViewer/src/BatchOpenSpineDialog.resx | 57 ++--- SpineViewer/src/Spine/Spine.cs | 2 +- SpineViewer/src/SpineListView.cs | 62 ++++-- 5 files changed, 330 insertions(+), 50 deletions(-) diff --git a/SpineViewer/src/BatchOpenSpineDialog.Designer.cs b/SpineViewer/src/BatchOpenSpineDialog.Designer.cs index 5d58bad..540aacb 100644 --- a/SpineViewer/src/BatchOpenSpineDialog.Designer.cs +++ b/SpineViewer/src/BatchOpenSpineDialog.Designer.cs @@ -1,4 +1,4 @@ -namespace SpineViewer.src +namespace SpineViewer { partial class BatchOpenSpineDialog { @@ -28,12 +28,208 @@ /// private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(800, 450); - this.Text = "SkelBatchSelectForm"; + panel = new Panel(); + tableLayoutPanel1 = new TableLayoutPanel(); + label3 = new Label(); + comboBox_Version = new ComboBox(); + tableLayoutPanel2 = new TableLayoutPanel(); + button_Ok = new Button(); + button_Cancel = new Button(); + listBox_FilePath = new ListBox(); + button_SelectSkel = new Button(); + label_Tip = new Label(); + openFileDialog_Skel = new OpenFileDialog(); + label4 = new Label(); + panel.SuspendLayout(); + tableLayoutPanel1.SuspendLayout(); + tableLayoutPanel2.SuspendLayout(); + SuspendLayout(); + // + // panel + // + panel.Controls.Add(tableLayoutPanel1); + panel.Dock = DockStyle.Fill; + panel.Location = new Point(0, 0); + panel.Name = "panel"; + panel.Padding = new Padding(50, 15, 50, 10); + panel.Size = new Size(1126, 449); + panel.TabIndex = 1; + // + // tableLayoutPanel1 + // + tableLayoutPanel1.ColumnCount = 2; + tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle()); + tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F)); + tableLayoutPanel1.Controls.Add(label4, 0, 0); + tableLayoutPanel1.Controls.Add(label3, 0, 3); + tableLayoutPanel1.Controls.Add(comboBox_Version, 1, 3); + tableLayoutPanel1.Controls.Add(tableLayoutPanel2, 0, 4); + tableLayoutPanel1.Controls.Add(listBox_FilePath, 0, 2); + tableLayoutPanel1.Controls.Add(button_SelectSkel, 0, 1); + tableLayoutPanel1.Controls.Add(label_Tip, 1, 1); + tableLayoutPanel1.Dock = DockStyle.Fill; + tableLayoutPanel1.Location = new Point(50, 15); + tableLayoutPanel1.Name = "tableLayoutPanel1"; + tableLayoutPanel1.RowCount = 5; + tableLayoutPanel1.RowStyles.Add(new RowStyle()); + tableLayoutPanel1.RowStyles.Add(new RowStyle()); + tableLayoutPanel1.RowStyles.Add(new RowStyle()); + tableLayoutPanel1.RowStyles.Add(new RowStyle()); + tableLayoutPanel1.RowStyles.Add(new RowStyle()); + tableLayoutPanel1.Size = new Size(1026, 424); + tableLayoutPanel1.TabIndex = 1; + // + // label3 + // + label3.Anchor = AnchorStyles.Right; + label3.AutoSize = true; + label3.Location = new Point(90, 307); + label3.Name = "label3"; + label3.Size = new Size(50, 24); + label3.TabIndex = 12; + label3.Text = "版本:"; + // + // comboBox_Version + // + comboBox_Version.Anchor = AnchorStyles.Left; + comboBox_Version.DropDownStyle = ComboBoxStyle.DropDownList; + comboBox_Version.FormattingEnabled = true; + comboBox_Version.Location = new Point(146, 303); + comboBox_Version.Name = "comboBox_Version"; + comboBox_Version.Size = new Size(182, 32); + comboBox_Version.Sorted = true; + comboBox_Version.TabIndex = 13; + // + // tableLayoutPanel2 + // + tableLayoutPanel2.AutoSize = true; + tableLayoutPanel2.AutoSizeMode = AutoSizeMode.GrowAndShrink; + tableLayoutPanel2.ColumnCount = 2; + tableLayoutPanel1.SetColumnSpan(tableLayoutPanel2, 4); + tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F)); + tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F)); + tableLayoutPanel2.Controls.Add(button_Ok, 0, 0); + tableLayoutPanel2.Controls.Add(button_Cancel, 1, 0); + tableLayoutPanel2.Dock = DockStyle.Bottom; + tableLayoutPanel2.Location = new Point(3, 381); + tableLayoutPanel2.Name = "tableLayoutPanel2"; + tableLayoutPanel2.RowCount = 1; + tableLayoutPanel2.RowStyles.Add(new RowStyle()); + tableLayoutPanel2.Size = new Size(1020, 40); + tableLayoutPanel2.TabIndex = 11; + // + // button_Ok + // + button_Ok.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; + button_Ok.Location = new Point(368, 3); + button_Ok.Margin = new Padding(3, 3, 30, 3); + button_Ok.Name = "button_Ok"; + button_Ok.Size = new Size(112, 34); + button_Ok.TabIndex = 7; + button_Ok.Text = "确认"; + button_Ok.UseVisualStyleBackColor = true; + button_Ok.Click += button_Ok_Click; + // + // button_Cancel + // + button_Cancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Left; + button_Cancel.Location = new Point(540, 3); + button_Cancel.Margin = new Padding(30, 3, 3, 3); + button_Cancel.Name = "button_Cancel"; + button_Cancel.Size = new Size(112, 34); + button_Cancel.TabIndex = 8; + button_Cancel.Text = "取消"; + button_Cancel.UseVisualStyleBackColor = true; + button_Cancel.Click += button_Cancel_Click; + // + // listBox_FilePath + // + tableLayoutPanel1.SetColumnSpan(listBox_FilePath, 2); + listBox_FilePath.Dock = DockStyle.Fill; + listBox_FilePath.FormattingEnabled = true; + listBox_FilePath.ItemHeight = 24; + listBox_FilePath.Location = new Point(3, 97); + listBox_FilePath.Name = "listBox_FilePath"; + listBox_FilePath.Size = new Size(1020, 200); + listBox_FilePath.TabIndex = 2; + // + // button_SelectSkel + // + button_SelectSkel.Anchor = AnchorStyles.None; + button_SelectSkel.Location = new Point(3, 57); + button_SelectSkel.Name = "button_SelectSkel"; + button_SelectSkel.Size = new Size(137, 34); + button_SelectSkel.TabIndex = 1; + button_SelectSkel.Text = "选择文件..."; + button_SelectSkel.UseVisualStyleBackColor = true; + button_SelectSkel.Click += button_SelectSkel_Click; + // + // label_Tip + // + label_Tip.AutoSize = true; + label_Tip.Dock = DockStyle.Fill; + label_Tip.Location = new Point(146, 54); + label_Tip.Name = "label_Tip"; + label_Tip.Size = new Size(877, 40); + label_Tip.TabIndex = 0; + label_Tip.Text = "已选择 0 个文件"; + label_Tip.TextAlign = ContentAlignment.MiddleLeft; + // + // openFileDialog_Skel + // + openFileDialog_Skel.AddExtension = false; + openFileDialog_Skel.AddToRecent = false; + openFileDialog_Skel.Filter = "skel 文件 (*.skel; *.json)|*.skel;*.json"; + openFileDialog_Skel.Multiselect = true; + // + // label4 + // + label4.AutoSize = true; + tableLayoutPanel1.SetColumnSpan(label4, 4); + label4.Dock = DockStyle.Fill; + label4.Location = new Point(15, 15); + label4.Margin = new Padding(15); + label4.Name = "label4"; + label4.Size = new Size(996, 24); + label4.TabIndex = 14; + label4.Text = "说明:批量导入只需要选择skel文件,atlas文件需要在同目录下并且与skel文件名相同"; + label4.TextAlign = ContentAlignment.MiddleCenter; + // + // BatchOpenSpineDialog + // + AcceptButton = button_Ok; + AutoScaleDimensions = new SizeF(11F, 24F); + AutoScaleMode = AutoScaleMode.Font; + CancelButton = button_Cancel; + ClientSize = new Size(1126, 449); + Controls.Add(panel); + FormBorderStyle = FormBorderStyle.FixedDialog; + MaximizeBox = false; + MinimizeBox = false; + Name = "BatchOpenSpineDialog"; + ShowIcon = false; + ShowInTaskbar = false; + StartPosition = FormStartPosition.CenterScreen; + Text = "批量打开骨骼"; + panel.ResumeLayout(false); + tableLayoutPanel1.ResumeLayout(false); + tableLayoutPanel1.PerformLayout(); + tableLayoutPanel2.ResumeLayout(false); + ResumeLayout(false); } #endregion + private Panel panel; + private TableLayoutPanel tableLayoutPanel1; + private Label label_Tip; + private ListBox listBox_FilePath; + private Button button_SelectSkel; + private TableLayoutPanel tableLayoutPanel2; + private Button button_Ok; + private Button button_Cancel; + private Label label3; + private ComboBox comboBox_Version; + private OpenFileDialog openFileDialog_Skel; + private Label label4; } } \ No newline at end of file diff --git a/SpineViewer/src/BatchOpenSpineDialog.cs b/SpineViewer/src/BatchOpenSpineDialog.cs index 30e9d94..47b6633 100644 --- a/SpineViewer/src/BatchOpenSpineDialog.cs +++ b/SpineViewer/src/BatchOpenSpineDialog.cs @@ -1,4 +1,5 @@ -using System; +using SpineViewer.Spine; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; @@ -8,13 +9,59 @@ using System.Text; using System.Threading.Tasks; using System.Windows.Forms; -namespace SpineViewer.src +namespace SpineViewer { - public partial class BatchOpenSpineDialog: Form + public partial class BatchOpenSpineDialog : Form { + public string[] SkelPaths { get; private set; } + public Spine.Version Version { get; private set; } + public BatchOpenSpineDialog() { InitializeComponent(); + comboBox_Version.DataSource = VersionHelper.Versions.ToList(); + comboBox_Version.DisplayMember = "Value"; + comboBox_Version.ValueMember = "Key"; + comboBox_Version.SelectedValue = Spine.Version.V38; + } + + private void button_SelectSkel_Click(object sender, EventArgs e) + { + if (openFileDialog_Skel.ShowDialog() == DialogResult.OK) + { + listBox_FilePath.Items.Clear(); + foreach (var p in openFileDialog_Skel.FileNames) + listBox_FilePath.Items.Add(Path.GetFullPath(p)); + label_Tip.Text = $"已选择 {listBox_FilePath.Items.Count} 个文件"; + } + } + + private void button_Ok_Click(object sender, EventArgs e) + { + if (listBox_FilePath.Items.Count <= 0) + { + MessageBox.Show("未选择任何文件", "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + } + + foreach (string p in listBox_FilePath.Items) + { + if (!File.Exists(p)) + { + MessageBox.Show($"{p}", "skel文件不存在", MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + } + } + + SkelPaths = listBox_FilePath.Items.Cast().ToArray(); + Version = (Spine.Version)comboBox_Version.SelectedValue; + + DialogResult = DialogResult.OK; + } + + private void button_Cancel_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; } } } diff --git a/SpineViewer/src/BatchOpenSpineDialog.resx b/SpineViewer/src/BatchOpenSpineDialog.resx index 1af7de1..bfd4d3a 100644 --- a/SpineViewer/src/BatchOpenSpineDialog.resx +++ b/SpineViewer/src/BatchOpenSpineDialog.resx @@ -1,17 +1,17 @@  - @@ -117,4 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 92, 26 + \ No newline at end of file diff --git a/SpineViewer/src/Spine/Spine.cs b/SpineViewer/src/Spine/Spine.cs index b6f5332..ca9d1d6 100644 --- a/SpineViewer/src/Spine/Spine.cs +++ b/SpineViewer/src/Spine/Spine.cs @@ -73,7 +73,7 @@ namespace SpineViewer.Spine ImplementationTypes[attr.Version] = type; } } - Program.Logger.Debug($"Find Spine implementations: [{string.Join(", ", ImplementationTypes.Keys)}]"); + Program.Logger.Debug("Find Spine implementations: [{}]", string.Join(", ", ImplementationTypes.Keys)); // 加载 FragmentShader try diff --git a/SpineViewer/src/SpineListView.cs b/SpineViewer/src/SpineListView.cs index adb4589..13c2f88 100644 --- a/SpineViewer/src/SpineListView.cs +++ b/SpineViewer/src/SpineListView.cs @@ -42,20 +42,20 @@ namespace SpineViewer index = spines.Count; var dialog = new OpenSpineDialog(); - if (dialog.ShowDialog() == DialogResult.OK) + if (dialog.ShowDialog() != DialogResult.OK) + return; + + try { - try - { - var spine = Spine.Spine.New(dialog.Version, dialog.SkelPath, dialog.AtlasPath); - spines.Insert(index, spine); - listView.Items.Insert(index, new ListViewItem([spine.Name, spine.Version.String()], -1) { ToolTipText = spine.SkelPath }); - } - catch (Exception ex) - { - Program.Logger.Error(ex.ToString()); - Program.Logger.Error($"Failed to load {dialog.SkelPath} {dialog.AtlasPath}"); - MessageBox.Show(ex.ToString(), "骨骼加载失败", MessageBoxButtons.OK, MessageBoxIcon.Error); - } + var spine = Spine.Spine.New(dialog.Version, dialog.SkelPath, dialog.AtlasPath); + spines.Insert(index, spine); + listView.Items.Insert(index, new ListViewItem([spine.Name, spine.Version.String()], -1) { ToolTipText = spine.SkelPath }); + } + catch (Exception ex) + { + Program.Logger.Error(ex.ToString()); + Program.Logger.Error("Failed to load {} {}", dialog.SkelPath, dialog.AtlasPath); + MessageBox.Show(ex.ToString(), "骨骼加载失败", MessageBoxButtons.OK, MessageBoxIcon.Error); } } @@ -72,7 +72,41 @@ namespace SpineViewer /// public void BatchAdd() { - throw new NotImplementedException(); + var dialog = new BatchOpenSpineDialog(); + if (dialog.ShowDialog() != DialogResult.OK) + return; + + int totalCount = dialog.SkelPaths.Length; + int errorCount = 0; + + var version = dialog.Version; + for (int i = 0; i < totalCount; i++) + { + var skelPath = dialog.SkelPaths[i]; + Program.Logger.Info("[{}/{}] loading {}", i + 1, totalCount, skelPath); + try + { + var spine = Spine.Spine.New(version, skelPath); + spines.Add(spine); + listView.Items.Add(new ListViewItem([spine.Name, spine.Version.String()], -1) { ToolTipText = spine.SkelPath }); + } + catch (Exception ex) + { + Program.Logger.Error(ex.ToString()); + Program.Logger.Error("Failed to load {}", skelPath); + errorCount++; + } + } + + if (errorCount > 0) + { + Program.Logger.Warn("Batch load {} successfully, {} failed", totalCount - errorCount, errorCount); + MessageBox.Show($"{totalCount - errorCount}成功,{errorCount}失败", "部分骨骼加载失败", MessageBoxButtons.OK, MessageBoxIcon.Warning); + } + else + { + Program.Logger.Info("{} skel loaded successfully", totalCount); + } } private void listView_SelectedIndexChanged(object sender, EventArgs e)