diff --git a/SpineViewer/Controls/SpinePreviewer.Designer.cs b/SpineViewer/Controls/SpinePreviewer.Designer.cs
index b62a281..8ba3bd3 100644
--- a/SpineViewer/Controls/SpinePreviewer.Designer.cs
+++ b/SpineViewer/Controls/SpinePreviewer.Designer.cs
@@ -29,12 +29,21 @@
private void InitializeComponent()
{
panel = new Panel();
+ tableLayoutPanel1 = new TableLayoutPanel();
+ panel_Container = new Panel();
+ flowLayoutPanel1 = new FlowLayoutPanel();
+ button_Stop = new Button();
+ button_Start = new Button();
+ button_Pause = new Button();
+ tableLayoutPanel1.SuspendLayout();
+ panel_Container.SuspendLayout();
+ flowLayoutPanel1.SuspendLayout();
SuspendLayout();
//
// panel
//
panel.BackColor = SystemColors.ControlDarkDark;
- panel.Location = new Point(160, 160);
+ panel.Location = new Point(143, 124);
panel.Margin = new Padding(0);
panel.Name = "panel";
panel.Size = new Size(320, 320);
@@ -44,20 +53,100 @@
panel.MouseUp += panel_MouseUp;
panel.MouseWheel += panel_MouseWheel;
//
+ // tableLayoutPanel1
+ //
+ tableLayoutPanel1.ColumnCount = 1;
+ tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+ tableLayoutPanel1.Controls.Add(panel_Container, 0, 0);
+ tableLayoutPanel1.Controls.Add(flowLayoutPanel1, 0, 1);
+ tableLayoutPanel1.Dock = DockStyle.Fill;
+ tableLayoutPanel1.Location = new Point(0, 0);
+ tableLayoutPanel1.Margin = new Padding(0);
+ tableLayoutPanel1.Name = "tableLayoutPanel1";
+ tableLayoutPanel1.RowCount = 2;
+ tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+ tableLayoutPanel1.RowStyles.Add(new RowStyle());
+ tableLayoutPanel1.Size = new Size(641, 636);
+ tableLayoutPanel1.TabIndex = 2;
+ //
+ // panel_Container
+ //
+ panel_Container.BackColor = SystemColors.ControlDark;
+ panel_Container.Controls.Add(panel);
+ panel_Container.Dock = DockStyle.Fill;
+ panel_Container.Location = new Point(0, 0);
+ panel_Container.Margin = new Padding(0);
+ panel_Container.Name = "panel_Container";
+ panel_Container.Size = new Size(641, 596);
+ panel_Container.TabIndex = 0;
+ //
+ // flowLayoutPanel1
+ //
+ flowLayoutPanel1.Anchor = AnchorStyles.None;
+ flowLayoutPanel1.AutoSize = true;
+ flowLayoutPanel1.AutoSizeMode = AutoSizeMode.GrowAndShrink;
+ flowLayoutPanel1.Controls.Add(button_Stop);
+ flowLayoutPanel1.Controls.Add(button_Start);
+ flowLayoutPanel1.Controls.Add(button_Pause);
+ flowLayoutPanel1.Location = new Point(143, 596);
+ flowLayoutPanel1.Margin = new Padding(0);
+ flowLayoutPanel1.Name = "flowLayoutPanel1";
+ flowLayoutPanel1.Size = new Size(354, 40);
+ flowLayoutPanel1.TabIndex = 1;
+ //
+ // button_Stop
+ //
+ button_Stop.Location = new Point(3, 3);
+ button_Stop.Name = "button_Stop";
+ button_Stop.Size = new Size(112, 34);
+ button_Stop.TabIndex = 0;
+ button_Stop.Text = "停止";
+ button_Stop.UseVisualStyleBackColor = true;
+ button_Stop.Click += button_Stop_Click;
+ //
+ // button_Start
+ //
+ button_Start.Location = new Point(121, 3);
+ button_Start.Name = "button_Start";
+ button_Start.Size = new Size(112, 34);
+ button_Start.TabIndex = 1;
+ button_Start.Text = "开始";
+ button_Start.UseVisualStyleBackColor = true;
+ button_Start.Click += button_Start_Click;
+ //
+ // button_Pause
+ //
+ button_Pause.Location = new Point(239, 3);
+ button_Pause.Name = "button_Pause";
+ button_Pause.Size = new Size(112, 34);
+ button_Pause.TabIndex = 2;
+ button_Pause.Text = "暂停";
+ button_Pause.UseVisualStyleBackColor = true;
+ button_Pause.Click += button_Pause_Click;
+ //
// SpinePreviewer
//
AutoScaleDimensions = new SizeF(11F, 24F);
AutoScaleMode = AutoScaleMode.Font;
- BackColor = SystemColors.ControlDark;
- Controls.Add(panel);
+ Controls.Add(tableLayoutPanel1);
Name = "SpinePreviewer";
- Size = new Size(640, 640);
+ Size = new Size(641, 636);
SizeChanged += SpinePreviewer_SizeChanged;
+ tableLayoutPanel1.ResumeLayout(false);
+ tableLayoutPanel1.PerformLayout();
+ panel_Container.ResumeLayout(false);
+ flowLayoutPanel1.ResumeLayout(false);
ResumeLayout(false);
}
#endregion
private Panel panel;
+ private TableLayoutPanel tableLayoutPanel1;
+ private Panel panel_Container;
+ private FlowLayoutPanel flowLayoutPanel1;
+ private Button button_Stop;
+ private Button button_Start;
+ private Button button_Pause;
}
}
diff --git a/SpineViewer/Controls/SpinePreviewer.cs b/SpineViewer/Controls/SpinePreviewer.cs
index 2791bc9..5f298d9 100644
--- a/SpineViewer/Controls/SpinePreviewer.cs
+++ b/SpineViewer/Controls/SpinePreviewer.cs
@@ -15,6 +15,45 @@ namespace SpineViewer.Controls
{
public partial class SpinePreviewer : UserControl
{
+ ///
+ /// 画面拖放对象世界坐标源点
+ ///
+ private SFML.System.Vector2f? draggingSrc = null;
+
+ ///
+ /// 要绑定的 Spine 列表控件
+ ///
+ [Category("自定义"), Description("相关联的 SpineListView")]
+ public SpineListView? SpineListView { get; set; }
+
+ ///
+ /// 属性信息面板
+ ///
+ [Category("自定义"), Description("用于显示画面属性的属性页")]
+ public PropertyGrid? PropertyGrid
+ {
+ get => propertyGrid;
+ set
+ {
+ propertyGrid = value;
+ if (propertyGrid is not null)
+ propertyGrid.SelectedObject = new PreviewerProperty(this);
+ }
+ }
+ private PropertyGrid? propertyGrid;
+
+ #region 画面参数
+
+ ///
+ /// 画面缩放最大值
+ ///
+ public const float ZOOM_MAX = 1000f;
+
+ ///
+ /// 画面缩放最小值
+ ///
+ public const float ZOOM_MIN = 0.001f;
+
///
/// 包装类, 用于属性面板显示
///
@@ -50,74 +89,6 @@ namespace SpineViewer.Controls
public uint MaxFps { get => previewer.MaxFps; set => previewer.MaxFps = value; }
}
- ///
- /// 要绑定的 Spine 列表控件
- ///
- [Category("自定义"), Description("相关联的 SpineListView")]
- public SpineListView? SpineListView { get; set; }
-
- ///
- /// 属性信息面板
- ///
- [Category("自定义"), Description("用于显示画面属性的属性页")]
- public PropertyGrid? PropertyGrid
- {
- get => propertyGrid;
- set
- {
- propertyGrid = value;
- if (propertyGrid is not null)
- propertyGrid.SelectedObject = new PreviewerProperty(this);
- }
- }
- private PropertyGrid? propertyGrid;
-
- ///
- /// 画面缩放最大值
- ///
- public const float ZOOM_MAX = 1000f;
-
- ///
- /// 画面缩放最小值
- ///
- public const float ZOOM_MIN = 0.001f;
-
- ///
- /// 预览画面背景色
- ///
- private static readonly SFML.Graphics.Color BackgroundColor = new(105, 105, 105);
-
- ///
- /// 预览画面坐标轴颜色
- ///
- private static readonly SFML.Graphics.Color AxisColor = new(220, 220, 220);
-
- ///
- /// 坐标轴顶点缓冲区
- ///
- private readonly SFML.Graphics.VertexArray AxisVertex = new(SFML.Graphics.PrimitiveType.Lines, 2);
-
- ///
- /// 渲染窗口
- ///
- private readonly SFML.Graphics.RenderWindow RenderWindow;
-
- ///
- /// 帧间隔计时器
- ///
- private readonly SFML.System.Clock Clock = new();
-
- ///
- /// 画面拖放对象世界坐标源点
- ///
- private SFML.System.Vector2f? draggingSrc = null;
-
- ///
- /// 渲染任务
- ///
- private Task? task = null;
- private CancellationTokenSource? cancelToken = null;
-
///
/// 分辨率
///
@@ -280,6 +251,8 @@ namespace SpineViewer.Controls
public uint MaxFps { get => maxFps; set { RenderWindow.SetFramerateLimit(value); maxFps = value; } }
private uint maxFps = 60;
+ #endregion
+
public SpinePreviewer()
{
InitializeComponent();
@@ -294,14 +267,27 @@ namespace SpineViewer.Controls
}
///
- /// 预览画面帧参数
+ /// 预览画面帧参数, TODO: 转移到统一导出参数
///
public SpinePreviewerFrameArgs GetFrameArgs() => new(Resolution, RenderWindow.GetView(), RenderSelectedOnly);
+ #region 渲染线程管理
+
///
- /// 开始预览
+ /// 渲染窗口
///
- public void StartPreview()
+ private readonly SFML.Graphics.RenderWindow RenderWindow;
+
+ ///
+ /// 渲染任务
+ ///
+ private Task? task = null;
+ private CancellationTokenSource? cancelToken = null;
+
+ ///
+ /// 开始渲染
+ ///
+ public void StartRender()
{
if (task is not null)
return;
@@ -310,9 +296,9 @@ namespace SpineViewer.Controls
}
///
- /// 停止预览
+ /// 停止渲染
///
- public void StopPreview()
+ public void StopRender()
{
if (task is null || cancelToken is null)
return;
@@ -322,6 +308,56 @@ namespace SpineViewer.Controls
task = null;
}
+ #endregion
+
+ ///
+ /// 是否还在更新画面
+ ///
+ public bool IsUpdating { get; private set; } = true;
+
+ ///
+ /// 开始更新
+ ///
+ public void StartUpdate() => IsUpdating = true;
+
+ ///
+ /// 暂停更新
+ ///
+ public void PauseUpdate() => IsUpdating = false;
+
+ ///
+ /// 停止更新, 将所有模型动画时间重置到 0 时刻
+ ///
+ public void StopUpdate()
+ {
+ IsUpdating = false;
+ lock (SpineListView.Spines)
+ {
+ foreach (var spine in SpineListView.Spines)
+ spine.CurrentAnimation = spine.CurrentAnimation;
+ }
+ }
+
+ ///
+ /// 预览画面背景色
+ ///
+ private static readonly SFML.Graphics.Color BackgroundColor = new(105, 105, 105);
+
+ ///
+ /// 预览画面坐标轴颜色
+ ///
+ private static readonly SFML.Graphics.Color AxisColor = new(220, 220, 220);
+
+ ///
+ /// 坐标轴顶点缓冲区
+ ///
+ private readonly SFML.Graphics.VertexArray AxisVertex = new(SFML.Graphics.PrimitiveType.Lines, 2);
+
+ ///
+ /// 帧间隔计时器
+ ///
+ private readonly SFML.System.Clock Clock = new();
+
///
/// 渲染任务
///
@@ -362,7 +398,8 @@ namespace SpineViewer.Controls
break; // 提前中止
var spine = spines[i];
- spine.Update(delta);
+
+ spine.Update(IsUpdating ? delta : 0);
if (RenderSelectedOnly && !spine.IsSelected)
continue;
@@ -388,8 +425,8 @@ namespace SpineViewer.Controls
if (RenderWindow is null)
return;
- float parentX = Width;
- float parentY = Height;
+ float parentX = panel.Parent.Width;
+ float parentY = panel.Parent.Height;
float sizeX = panel.Width;
float sizeY = panel.Height;
@@ -538,6 +575,21 @@ namespace SpineViewer.Controls
Zoom *= (e.Delta > 0 ? 1.1f : 0.9f);
PropertyGrid?.Refresh();
}
+
+ private void button_Stop_Click(object sender, EventArgs e)
+ {
+ StopUpdate();
+ }
+
+ private void button_Start_Click(object sender, EventArgs e)
+ {
+ StartUpdate();
+ }
+
+ private void button_Pause_Click(object sender, EventArgs e)
+ {
+ PauseUpdate();
+ }
}
///
diff --git a/SpineViewer/MainForm.Designer.cs b/SpineViewer/MainForm.Designer.cs
index 8953ec0..476d91f 100644
--- a/SpineViewer/MainForm.Designer.cs
+++ b/SpineViewer/MainForm.Designer.cs
@@ -39,8 +39,6 @@
toolStripMenuItem_ExportPreview = new ToolStripMenuItem();
toolStripSeparator2 = new ToolStripSeparator();
toolStripMenuItem_Exit = new ToolStripMenuItem();
- toolStripMenuItem_Function = new ToolStripMenuItem();
- toolStripMenuItem_ResetAnimation = new ToolStripMenuItem();
toolStripMenuItem_Tool = new ToolStripMenuItem();
toolStripMenuItem_ConvertFileFormat = new ToolStripMenuItem();
toolStripMenuItem_Download = new ToolStripMenuItem();
@@ -92,7 +90,7 @@
//
menuStrip.BackColor = SystemColors.Control;
menuStrip.ImageScalingSize = new Size(24, 24);
- menuStrip.Items.AddRange(new ToolStripItem[] { toolStripMenuItem_File, toolStripMenuItem_Function, toolStripMenuItem_Tool, toolStripMenuItem_Download, toolStripMenuItem_Help });
+ menuStrip.Items.AddRange(new ToolStripItem[] { toolStripMenuItem_File, toolStripMenuItem_Tool, toolStripMenuItem_Download, toolStripMenuItem_Help });
menuStrip.Location = new Point(0, 0);
menuStrip.Name = "menuStrip";
menuStrip.Size = new Size(1748, 32);
@@ -154,20 +152,6 @@
toolStripMenuItem_Exit.Text = "退出(&X)";
toolStripMenuItem_Exit.Click += toolStripMenuItem_Exit_Click;
//
- // toolStripMenuItem_Function
- //
- toolStripMenuItem_Function.DropDownItems.AddRange(new ToolStripItem[] { toolStripMenuItem_ResetAnimation });
- toolStripMenuItem_Function.Name = "toolStripMenuItem_Function";
- toolStripMenuItem_Function.Size = new Size(87, 28);
- toolStripMenuItem_Function.Text = "功能(&G)";
- //
- // toolStripMenuItem_ResetAnimation
- //
- toolStripMenuItem_ResetAnimation.Name = "toolStripMenuItem_ResetAnimation";
- toolStripMenuItem_ResetAnimation.Size = new Size(242, 34);
- toolStripMenuItem_ResetAnimation.Text = "重置动画时间(&R)";
- toolStripMenuItem_ResetAnimation.Click += toolStripMenuItem_ResetAnimation_Click;
- //
// toolStripMenuItem_Tool
//
toolStripMenuItem_Tool.DropDownItems.AddRange(new ToolStripItem[] { toolStripMenuItem_ConvertFileFormat });
@@ -178,7 +162,7 @@
// toolStripMenuItem_ConvertFileFormat
//
toolStripMenuItem_ConvertFileFormat.Name = "toolStripMenuItem_ConvertFileFormat";
- toolStripMenuItem_ConvertFileFormat.Size = new Size(254, 34);
+ toolStripMenuItem_ConvertFileFormat.Size = new Size(270, 34);
toolStripMenuItem_ConvertFileFormat.Text = "转换文件格式(&C)...";
toolStripMenuItem_ConvertFileFormat.Click += toolStripMenuItem_ConvertFileFormat_Click;
//
@@ -408,7 +392,6 @@
//
// spinePreviewer
//
- spinePreviewer.BackColor = SystemColors.ControlDark;
spinePreviewer.Dock = DockStyle.Fill;
spinePreviewer.Location = new Point(3, 26);
spinePreviewer.Name = "spinePreviewer";
@@ -501,8 +484,6 @@
private Controls.SpineListView spineListView;
private PropertyGrid propertyGrid_Previewer;
private Controls.SpinePreviewer spinePreviewer;
- private ToolStripMenuItem toolStripMenuItem_Function;
- private ToolStripMenuItem toolStripMenuItem_ResetAnimation;
private ToolStripMenuItem toolStripMenuItem_Diagnostics;
private ToolStripSeparator toolStripSeparator3;
private ToolStripMenuItem toolStripMenuItem_Download;
diff --git a/SpineViewer/MainForm.cs b/SpineViewer/MainForm.cs
index e1c5095..f75f145 100644
--- a/SpineViewer/MainForm.cs
+++ b/SpineViewer/MainForm.cs
@@ -115,15 +115,6 @@ namespace SpineViewer
Close();
}
- private void toolStripMenuItem_ResetAnimation_Click(object sender, EventArgs e)
- {
- lock (spineListView.Spines)
- {
- foreach (var spine in spineListView.Spines)
- spine.CurrentAnimation = spine.CurrentAnimation;
- }
- }
-
private void toolStripMenuItem_ConvertFileFormat_Click(object sender, EventArgs e)
{
var openDialog = new Dialogs.ConvertFileFormatDialog();