添加预览画面
This commit is contained in:
68
SpineViewer/src/MainForm.Designer.cs
generated
68
SpineViewer/src/MainForm.Designer.cs
generated
@@ -49,13 +49,11 @@
|
|||||||
splitContainer_Config = new SplitContainer();
|
splitContainer_Config = new SplitContainer();
|
||||||
groupBox_SkelConfig = new GroupBox();
|
groupBox_SkelConfig = new GroupBox();
|
||||||
groupBox_PreviewConfig = new GroupBox();
|
groupBox_PreviewConfig = new GroupBox();
|
||||||
|
propertyGrid_Previewer = new PropertyGrid();
|
||||||
groupBox_Preview = new GroupBox();
|
groupBox_Preview = new GroupBox();
|
||||||
panel_PreviewContainer = new Panel();
|
spinePreviewer = new SpinePreviewer();
|
||||||
panel_Preview = new Panel();
|
|
||||||
panel_MainForm = new Panel();
|
panel_MainForm = new Panel();
|
||||||
openFileDialog_Skel = new OpenFileDialog();
|
toolTip = new ToolTip(components);
|
||||||
openFileDialog_Atlas = new OpenFileDialog();
|
|
||||||
toolTip1 = new ToolTip(components);
|
|
||||||
menuStrip.SuspendLayout();
|
menuStrip.SuspendLayout();
|
||||||
((System.ComponentModel.ISupportInitialize)splitContainer_MainForm).BeginInit();
|
((System.ComponentModel.ISupportInitialize)splitContainer_MainForm).BeginInit();
|
||||||
splitContainer_MainForm.Panel1.SuspendLayout();
|
splitContainer_MainForm.Panel1.SuspendLayout();
|
||||||
@@ -75,8 +73,8 @@
|
|||||||
splitContainer_Config.Panel2.SuspendLayout();
|
splitContainer_Config.Panel2.SuspendLayout();
|
||||||
splitContainer_Config.SuspendLayout();
|
splitContainer_Config.SuspendLayout();
|
||||||
groupBox_SkelConfig.SuspendLayout();
|
groupBox_SkelConfig.SuspendLayout();
|
||||||
|
groupBox_PreviewConfig.SuspendLayout();
|
||||||
groupBox_Preview.SuspendLayout();
|
groupBox_Preview.SuspendLayout();
|
||||||
panel_PreviewContainer.SuspendLayout();
|
|
||||||
panel_MainForm.SuspendLayout();
|
panel_MainForm.SuspendLayout();
|
||||||
SuspendLayout();
|
SuspendLayout();
|
||||||
//
|
//
|
||||||
@@ -266,6 +264,7 @@
|
|||||||
propertyGrid_Skel.Size = new Size(369, 506);
|
propertyGrid_Skel.Size = new Size(369, 506);
|
||||||
propertyGrid_Skel.TabIndex = 0;
|
propertyGrid_Skel.TabIndex = 0;
|
||||||
propertyGrid_Skel.ToolbarVisible = false;
|
propertyGrid_Skel.ToolbarVisible = false;
|
||||||
|
propertyGrid_Skel.PropertyValueChanged += propertyGrid_PropertyValueChanged;
|
||||||
//
|
//
|
||||||
// splitContainer_Config
|
// splitContainer_Config
|
||||||
//
|
//
|
||||||
@@ -304,6 +303,7 @@
|
|||||||
//
|
//
|
||||||
// groupBox_PreviewConfig
|
// groupBox_PreviewConfig
|
||||||
//
|
//
|
||||||
|
groupBox_PreviewConfig.Controls.Add(propertyGrid_Previewer);
|
||||||
groupBox_PreviewConfig.Dock = DockStyle.Fill;
|
groupBox_PreviewConfig.Dock = DockStyle.Fill;
|
||||||
groupBox_PreviewConfig.Location = new Point(0, 0);
|
groupBox_PreviewConfig.Location = new Point(0, 0);
|
||||||
groupBox_PreviewConfig.Name = "groupBox_PreviewConfig";
|
groupBox_PreviewConfig.Name = "groupBox_PreviewConfig";
|
||||||
@@ -312,9 +312,20 @@
|
|||||||
groupBox_PreviewConfig.TabStop = false;
|
groupBox_PreviewConfig.TabStop = false;
|
||||||
groupBox_PreviewConfig.Text = "画面参数";
|
groupBox_PreviewConfig.Text = "画面参数";
|
||||||
//
|
//
|
||||||
|
// propertyGrid_Previewer
|
||||||
|
//
|
||||||
|
propertyGrid_Previewer.Dock = DockStyle.Fill;
|
||||||
|
propertyGrid_Previewer.HelpVisible = false;
|
||||||
|
propertyGrid_Previewer.Location = new Point(3, 26);
|
||||||
|
propertyGrid_Previewer.Name = "propertyGrid_Previewer";
|
||||||
|
propertyGrid_Previewer.Size = new Size(369, 227);
|
||||||
|
propertyGrid_Previewer.TabIndex = 1;
|
||||||
|
propertyGrid_Previewer.ToolbarVisible = false;
|
||||||
|
propertyGrid_Previewer.PropertyValueChanged += propertyGrid_PropertyValueChanged;
|
||||||
|
//
|
||||||
// groupBox_Preview
|
// groupBox_Preview
|
||||||
//
|
//
|
||||||
groupBox_Preview.Controls.Add(panel_PreviewContainer);
|
groupBox_Preview.Controls.Add(spinePreviewer);
|
||||||
groupBox_Preview.Dock = DockStyle.Fill;
|
groupBox_Preview.Dock = DockStyle.Fill;
|
||||||
groupBox_Preview.Location = new Point(0, 0);
|
groupBox_Preview.Location = new Point(0, 0);
|
||||||
groupBox_Preview.Name = "groupBox_Preview";
|
groupBox_Preview.Name = "groupBox_Preview";
|
||||||
@@ -323,23 +334,14 @@
|
|||||||
groupBox_Preview.TabStop = false;
|
groupBox_Preview.TabStop = false;
|
||||||
groupBox_Preview.Text = "预览画面";
|
groupBox_Preview.Text = "预览画面";
|
||||||
//
|
//
|
||||||
// panel_PreviewContainer
|
// spinePreviewer
|
||||||
//
|
//
|
||||||
panel_PreviewContainer.Controls.Add(panel_Preview);
|
spinePreviewer.Dock = DockStyle.Fill;
|
||||||
panel_PreviewContainer.Dock = DockStyle.Fill;
|
spinePreviewer.Location = new Point(3, 26);
|
||||||
panel_PreviewContainer.Location = new Point(3, 26);
|
spinePreviewer.Name = "spinePreviewer";
|
||||||
panel_PreviewContainer.Margin = new Padding(0);
|
spinePreviewer.Size = new Size(986, 766);
|
||||||
panel_PreviewContainer.Name = "panel_PreviewContainer";
|
spinePreviewer.TabIndex = 0;
|
||||||
panel_PreviewContainer.Size = new Size(986, 766);
|
spinePreviewer.RenderFrame += spinePreviewer_RenderFrame;
|
||||||
panel_PreviewContainer.TabIndex = 1;
|
|
||||||
//
|
|
||||||
// panel_Preview
|
|
||||||
//
|
|
||||||
panel_Preview.BackColor = SystemColors.ControlDark;
|
|
||||||
panel_Preview.Location = new Point(107, 95);
|
|
||||||
panel_Preview.Name = "panel_Preview";
|
|
||||||
panel_Preview.Size = new Size(256, 256);
|
|
||||||
panel_Preview.TabIndex = 0;
|
|
||||||
//
|
//
|
||||||
// panel_MainForm
|
// panel_MainForm
|
||||||
//
|
//
|
||||||
@@ -351,17 +353,9 @@
|
|||||||
panel_MainForm.Size = new Size(1741, 973);
|
panel_MainForm.Size = new Size(1741, 973);
|
||||||
panel_MainForm.TabIndex = 4;
|
panel_MainForm.TabIndex = 4;
|
||||||
//
|
//
|
||||||
// openFileDialog_Skel
|
// toolTip
|
||||||
//
|
//
|
||||||
openFileDialog_Skel.AddExtension = false;
|
toolTip.ShowAlways = true;
|
||||||
openFileDialog_Skel.AddToRecent = false;
|
|
||||||
openFileDialog_Skel.Filter = "skel 文件 (*.skel; *.json)|*.skel;*.json";
|
|
||||||
//
|
|
||||||
// openFileDialog_Atlas
|
|
||||||
//
|
|
||||||
openFileDialog_Atlas.AddExtension = false;
|
|
||||||
openFileDialog_Atlas.AddToRecent = false;
|
|
||||||
openFileDialog_Atlas.Filter = "atlas 文件 (*.atlas)|*.atlas";
|
|
||||||
//
|
//
|
||||||
// MainForm
|
// MainForm
|
||||||
//
|
//
|
||||||
@@ -395,8 +389,8 @@
|
|||||||
((System.ComponentModel.ISupportInitialize)splitContainer_Config).EndInit();
|
((System.ComponentModel.ISupportInitialize)splitContainer_Config).EndInit();
|
||||||
splitContainer_Config.ResumeLayout(false);
|
splitContainer_Config.ResumeLayout(false);
|
||||||
groupBox_SkelConfig.ResumeLayout(false);
|
groupBox_SkelConfig.ResumeLayout(false);
|
||||||
|
groupBox_PreviewConfig.ResumeLayout(false);
|
||||||
groupBox_Preview.ResumeLayout(false);
|
groupBox_Preview.ResumeLayout(false);
|
||||||
panel_PreviewContainer.ResumeLayout(false);
|
|
||||||
panel_MainForm.ResumeLayout(false);
|
panel_MainForm.ResumeLayout(false);
|
||||||
ResumeLayout(false);
|
ResumeLayout(false);
|
||||||
PerformLayout();
|
PerformLayout();
|
||||||
@@ -424,12 +418,12 @@
|
|||||||
private ToolStripMenuItem toolStripMenuItem_About;
|
private ToolStripMenuItem toolStripMenuItem_About;
|
||||||
private ToolStripMenuItem toolStripMenuItem_BatchOpen;
|
private ToolStripMenuItem toolStripMenuItem_BatchOpen;
|
||||||
private GroupBox groupBox_Preview;
|
private GroupBox groupBox_Preview;
|
||||||
private Panel panel_Preview;
|
|
||||||
private Panel panel_PreviewContainer;
|
|
||||||
private OpenFileDialog openFileDialog_Skel;
|
private OpenFileDialog openFileDialog_Skel;
|
||||||
private OpenFileDialog openFileDialog_Atlas;
|
private OpenFileDialog openFileDialog_Atlas;
|
||||||
private ToolTip toolTip1;
|
private ToolTip toolTip;
|
||||||
private PropertyGrid propertyGrid_Skel;
|
private PropertyGrid propertyGrid_Skel;
|
||||||
private SpineListView spineListView;
|
private SpineListView spineListView;
|
||||||
|
private PropertyGrid propertyGrid_Previewer;
|
||||||
|
private SpinePreviewer spinePreviewer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,11 @@ namespace SpineViewer
|
|||||||
public MainForm()
|
public MainForm()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
propertyGrid_Previewer.SelectedObject = spinePreviewer.Property;
|
||||||
|
|
||||||
InitializeLogConfiguration();
|
InitializeLogConfiguration();
|
||||||
|
spinePreviewer.Property.Resolution = new(1280, 720);
|
||||||
|
spinePreviewer.StartPreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -31,10 +35,10 @@ namespace SpineViewer
|
|||||||
};
|
};
|
||||||
|
|
||||||
rtbTarget.WordColoringRules.Add(new("[D]", "Gray", "Empty", FontStyle.Bold));
|
rtbTarget.WordColoringRules.Add(new("[D]", "Gray", "Empty", FontStyle.Bold));
|
||||||
rtbTarget.WordColoringRules.Add(new("[I]", "Gray", "Empty", FontStyle.Bold));
|
rtbTarget.WordColoringRules.Add(new("[I]", "DimGray", "Empty", FontStyle.Bold));
|
||||||
rtbTarget.WordColoringRules.Add(new("[W]", "DarkOrange", "Empty", FontStyle.Bold));
|
rtbTarget.WordColoringRules.Add(new("[W]", "DarkOrange", "Empty", FontStyle.Bold));
|
||||||
rtbTarget.WordColoringRules.Add(new("[E]", "Red", "Empty", FontStyle.Bold));
|
rtbTarget.WordColoringRules.Add(new("[E]", "Red", "Empty", FontStyle.Bold));
|
||||||
rtbTarget.WordColoringRules.Add(new("[F]", "Red", "Empty", FontStyle.Bold));
|
rtbTarget.WordColoringRules.Add(new("[F]", "DarkRed", "Empty", FontStyle.Bold));
|
||||||
|
|
||||||
LogManager.Configuration.AddTarget(rtbTarget);
|
LogManager.Configuration.AddTarget(rtbTarget);
|
||||||
LogManager.Configuration.AddRule(LogLevel.Debug, LogLevel.Fatal, rtbTarget);
|
LogManager.Configuration.AddRule(LogLevel.Debug, LogLevel.Fatal, rtbTarget);
|
||||||
@@ -55,8 +59,11 @@ namespace SpineViewer
|
|||||||
|
|
||||||
private void toolStripMenuItem_Export_Click(object sender, EventArgs e)
|
private void toolStripMenuItem_Export_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
var a = new SizeF(10, 100);
|
Program.Logger.Debug("Debug Test");
|
||||||
spineListView.Spines[0].Position = spineListView.Spines[0].Position + a;
|
Program.Logger.Info("Info Test");
|
||||||
|
Program.Logger.Warn("Warn Test");
|
||||||
|
Program.Logger.Error("Error Test");
|
||||||
|
Program.Logger.Fatal("Fatal Test");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void toolStripMenuItem_Exit_Click(object sender, EventArgs e)
|
private void toolStripMenuItem_Exit_Click(object sender, EventArgs e)
|
||||||
@@ -70,6 +77,26 @@ namespace SpineViewer
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Ԥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
#region Ԥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
|
||||||
|
private void spinePreviewer_RenderFrame(object sender, RenderFrameEventArgs e)
|
||||||
|
{
|
||||||
|
var target = e.RenderTarget;
|
||||||
|
var delta = e.Delta;
|
||||||
|
Spine.Spine[] spines = null;
|
||||||
|
|
||||||
|
// <20><>Ҫ<EFBFBD>ڿؼ<DABF><D8BC>߳<EFBFBD><DFB3>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD>dz<EFBFBD><C7B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
if (spineListView.InvokeRequired)
|
||||||
|
spineListView.Invoke(() => spines = spineListView.Spines.ToArray());
|
||||||
|
else
|
||||||
|
spines = spineListView.Spines.ToArray();
|
||||||
|
|
||||||
|
foreach (var spine in spines.Reverse())
|
||||||
|
{
|
||||||
|
spine.Update(delta);
|
||||||
|
target.Draw(spine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
#region <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
@@ -84,6 +111,11 @@ namespace SpineViewer
|
|||||||
ActiveControl = null;
|
ActiveControl = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void propertyGrid_PropertyValueChanged(object sender, PropertyValueChangedEventArgs e)
|
||||||
|
{
|
||||||
|
(sender as PropertyGrid).Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,14 +120,8 @@
|
|||||||
<metadata name="menuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
<metadata name="menuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
<value>17, 17</value>
|
<value>17, 17</value>
|
||||||
</metadata>
|
</metadata>
|
||||||
<metadata name="openFileDialog_Skel.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
<metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
<value>156, 25</value>
|
<value>187, 20</value>
|
||||||
</metadata>
|
|
||||||
<metadata name="openFileDialog_Atlas.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>404, 23</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>651, 23</value>
|
|
||||||
</metadata>
|
</metadata>
|
||||||
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
<value>89</value>
|
<value>89</value>
|
||||||
|
|||||||
@@ -157,33 +157,33 @@ namespace SpineViewer.Spine
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 缩放比例
|
/// 缩放比例
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Category("空间变换"), DisplayName("缩放比例")]
|
[Category("变换"), DisplayName("缩放比例")]
|
||||||
public abstract float Scale { get; set; }
|
public abstract float Scale { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 位置
|
/// 位置
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[TypeConverter(typeof(PointFTypeConverter))]
|
[TypeConverter(typeof(PointFTypeConverter))]
|
||||||
[Category("空间变换"), DisplayName("位置")]
|
[Category("变换"), DisplayName("位置")]
|
||||||
public abstract PointF Position { get; set; }
|
public abstract PointF Position { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 水平翻转
|
/// 水平翻转
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Category("空间变换"), DisplayName("水平翻转")]
|
[Category("变换"), DisplayName("水平翻转")]
|
||||||
public abstract bool FlipX { get; set; }
|
public abstract bool FlipX { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 垂直翻转
|
/// 垂直翻转
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Category("空间变换"), DisplayName("垂直翻转")]
|
[Category("变换"), DisplayName("垂直翻转")]
|
||||||
public abstract bool FlipY { get; set; }
|
public abstract bool FlipY { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否使用预乘Alpha
|
/// 是否使用预乘Alpha
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Category("其他"), DisplayName("预乘Alpha通道")]
|
[Category("画面"), DisplayName("预乘Alpha通道")]
|
||||||
public bool UsePremultipliedAlpha { get; set; }
|
public bool UsePremultipliedAlpha { get; set; } = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 包含的所有动画名称
|
/// 包含的所有动画名称
|
||||||
@@ -202,9 +202,15 @@ namespace SpineViewer.Spine
|
|||||||
/// 当前动画名称
|
/// 当前动画名称
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[TypeConverter(typeof(AnimationTypeConverter))]
|
[TypeConverter(typeof(AnimationTypeConverter))]
|
||||||
[Category("其他"), DisplayName("当前播放动画"), PropertyTab()]
|
[Category("动画"), DisplayName("当前动画")]
|
||||||
public abstract string CurrentAnimation { get; set; }
|
public abstract string CurrentAnimation { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前动画时长
|
||||||
|
/// </summary>
|
||||||
|
[Category("动画"), DisplayName("当前动画时长")]
|
||||||
|
public float CurrentAnimationDuration { get => GetAnimationDuration(CurrentAnimation); }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 骨骼包围盒
|
/// 骨骼包围盒
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
67
SpineViewer/src/SpinePreviewer.Designer.cs
generated
Normal file
67
SpineViewer/src/SpinePreviewer.Designer.cs
generated
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
namespace SpineViewer
|
||||||
|
{
|
||||||
|
partial class SpinePreviewer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 必需的设计器变量。
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清理所有正在使用的资源。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region 组件设计器生成的代码
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设计器支持所需的方法 - 不要修改
|
||||||
|
/// 使用代码编辑器修改此方法的内容。
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
panel = new Panel();
|
||||||
|
backgroundWorker = new System.ComponentModel.BackgroundWorker();
|
||||||
|
SuspendLayout();
|
||||||
|
//
|
||||||
|
// panel
|
||||||
|
//
|
||||||
|
panel.BackColor = SystemColors.ControlDark;
|
||||||
|
panel.Location = new Point(115, 75);
|
||||||
|
panel.Margin = new Padding(0);
|
||||||
|
panel.Name = "panel";
|
||||||
|
panel.Size = new Size(513, 446);
|
||||||
|
panel.TabIndex = 1;
|
||||||
|
panel.MouseDown += panel_MouseDown;
|
||||||
|
panel.MouseMove += panel_MouseMove;
|
||||||
|
panel.MouseUp += panel_MouseUp;
|
||||||
|
//
|
||||||
|
// backgroundWorker
|
||||||
|
//
|
||||||
|
backgroundWorker.DoWork += backgroundWorker_DoWork;
|
||||||
|
//
|
||||||
|
// SpinePreviewer
|
||||||
|
//
|
||||||
|
AutoScaleDimensions = new SizeF(11F, 24F);
|
||||||
|
AutoScaleMode = AutoScaleMode.Font;
|
||||||
|
Controls.Add(panel);
|
||||||
|
Name = "SpinePreviewer";
|
||||||
|
Size = new Size(637, 534);
|
||||||
|
SizeChanged += SpinePreviewer_SizeChanged;
|
||||||
|
ResumeLayout(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private Panel panel;
|
||||||
|
private System.ComponentModel.BackgroundWorker backgroundWorker;
|
||||||
|
}
|
||||||
|
}
|
||||||
288
SpineViewer/src/SpinePreviewer.cs
Normal file
288
SpineViewer/src/SpinePreviewer.cs
Normal file
@@ -0,0 +1,288 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Security.Policy;
|
||||||
|
|
||||||
|
namespace SpineViewer
|
||||||
|
{
|
||||||
|
public partial class SpinePreviewer : UserControl
|
||||||
|
{
|
||||||
|
public class PreviewerProperty
|
||||||
|
{
|
||||||
|
public const float ZOOM_MAX = 1000f;
|
||||||
|
public const float ZOOM_MIN = 0.001f;
|
||||||
|
|
||||||
|
private readonly SFML.Graphics.RenderWindow RenderWindow;
|
||||||
|
private readonly Control ContainerControl;
|
||||||
|
|
||||||
|
public PreviewerProperty(SFML.Graphics.RenderWindow renderWindow, Control containerControl)
|
||||||
|
{
|
||||||
|
RenderWindow = renderWindow;
|
||||||
|
ContainerControl = containerControl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 导出画面分辨率
|
||||||
|
/// </summary>
|
||||||
|
[TypeConverter(typeof(SizeTypeConverter))]
|
||||||
|
[Category("属性"), DisplayName("分辨率")]
|
||||||
|
public Size Resolution
|
||||||
|
{
|
||||||
|
get => resolution;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value.Width <= 0) value.Width = 100;
|
||||||
|
if (value.Height <= 0) value.Height = 100;
|
||||||
|
|
||||||
|
float parentX = ContainerControl.Width;
|
||||||
|
float parentY = ContainerControl.Height;
|
||||||
|
float sizeX = value.Width;
|
||||||
|
float sizeY = value.Height;
|
||||||
|
|
||||||
|
if ((sizeY / sizeX) < (parentY / parentX))
|
||||||
|
{
|
||||||
|
// 相同的 X, 子窗口 Y 更小
|
||||||
|
sizeY = parentX * sizeY / sizeX;
|
||||||
|
sizeX = parentX;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 相同的 Y, 子窗口 X 更小
|
||||||
|
sizeX = parentY * sizeX / sizeY;
|
||||||
|
sizeY = parentY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 必须通过 SFML 的方法调整窗口
|
||||||
|
RenderWindow.Position = new((int)(parentX - sizeX) / 2, (int)(parentY - sizeY) / 2);
|
||||||
|
RenderWindow.Size = new((uint)sizeX, (uint)sizeY);
|
||||||
|
|
||||||
|
// 将 view 的大小设置成于 resolution 相同的大小, 其余属性都不变
|
||||||
|
var view = RenderWindow.GetView();
|
||||||
|
var signX = Math.Sign(view.Size.X);
|
||||||
|
var signY = Math.Sign(view.Size.Y);
|
||||||
|
view.Size = new(value.Width * signX, value.Height * signY);
|
||||||
|
RenderWindow.SetView(view);
|
||||||
|
|
||||||
|
resolution = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private Size resolution = new(0, 0);
|
||||||
|
|
||||||
|
[TypeConverter(typeof(PointFTypeConverter))]
|
||||||
|
[Category("属性"), DisplayName("画面中心点")]
|
||||||
|
public PointF Center
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var center = RenderWindow.GetView().Center;
|
||||||
|
return new(center.X, center.Y);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
var view = RenderWindow.GetView();
|
||||||
|
view.Center = new(value.X, value.Y);
|
||||||
|
RenderWindow.SetView(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 画面缩放
|
||||||
|
/// </summary>
|
||||||
|
[Category("属性"), DisplayName("缩放")]
|
||||||
|
public float Zoom
|
||||||
|
{
|
||||||
|
get => resolution.Width / Math.Abs(RenderWindow.GetView().Size.X);
|
||||||
|
set
|
||||||
|
{
|
||||||
|
value = Math.Clamp(value, ZOOM_MIN, ZOOM_MAX);
|
||||||
|
var view = RenderWindow.GetView();
|
||||||
|
var signX = Math.Sign(view.Size.X);
|
||||||
|
var signY = Math.Sign(view.Size.Y);
|
||||||
|
view.Size = new(resolution.Width / value * signX, resolution.Height / value * signY);
|
||||||
|
RenderWindow.SetView(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 画面旋转
|
||||||
|
/// </summary>
|
||||||
|
[Category("属性"), DisplayName("旋转")]
|
||||||
|
public float Rotation
|
||||||
|
{
|
||||||
|
get => RenderWindow.GetView().Rotation;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
var view = RenderWindow.GetView();
|
||||||
|
view.Rotation = value;
|
||||||
|
RenderWindow.SetView(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 画面旋转
|
||||||
|
/// </summary>
|
||||||
|
[Category("属性"), DisplayName("水平翻转")]
|
||||||
|
public bool FlipX
|
||||||
|
{
|
||||||
|
get => RenderWindow.GetView().Size.X < 0;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
var view = RenderWindow.GetView();
|
||||||
|
var size = view.Size;
|
||||||
|
if (size.X > 0 && value || size.X < 0 && !value)
|
||||||
|
size.X *= -1;
|
||||||
|
view.Size = size;
|
||||||
|
RenderWindow.SetView(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 画面旋转
|
||||||
|
/// </summary>
|
||||||
|
[Category("属性"), DisplayName("垂直翻转")]
|
||||||
|
public bool FlipY
|
||||||
|
{
|
||||||
|
get => RenderWindow.GetView().Size.Y < 0;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
var view = RenderWindow.GetView();
|
||||||
|
var size = view.Size;
|
||||||
|
if (size.Y > 0 && value || size.Y < 0 && !value)
|
||||||
|
size.Y *= -1;
|
||||||
|
view.Size = size;
|
||||||
|
RenderWindow.SetView(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 帧渲染事件
|
||||||
|
/// </summary>
|
||||||
|
[Category("自定义"), Description("帧渲染事件")]
|
||||||
|
public event EventHandler<RenderFrameEventArgs>? RenderFrame;
|
||||||
|
private void OnRenderFrame(float delta) { RenderFrame?.Invoke(this, new(RenderWindow, delta)); }
|
||||||
|
|
||||||
|
private readonly SFML.Graphics.RenderWindow RenderWindow;
|
||||||
|
private readonly SFML.System.Clock Clock = new();
|
||||||
|
private readonly SFML.Graphics.Color BackgroundColor = SFML.Graphics.Color.Green;
|
||||||
|
|
||||||
|
[Browsable(false)]
|
||||||
|
public PreviewerProperty Property { get; }
|
||||||
|
|
||||||
|
public SpinePreviewer()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
RenderWindow = new(panel.Handle);
|
||||||
|
RenderWindow.SetFramerateLimit(30);
|
||||||
|
RenderWindow.SetActive(false);
|
||||||
|
Property = new(RenderWindow, this)
|
||||||
|
{
|
||||||
|
Resolution = new(1280, 720),
|
||||||
|
Center = new(0, 0),
|
||||||
|
FlipY = true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StartPreview()
|
||||||
|
{
|
||||||
|
if (!backgroundWorker.IsBusy)
|
||||||
|
backgroundWorker.RunWorkerAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StopPreview()
|
||||||
|
{
|
||||||
|
if (backgroundWorker.IsBusy)
|
||||||
|
backgroundWorker.CancelAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SpinePreviewer_SizeChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (RenderWindow is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
float parentX = Width;
|
||||||
|
float parentY = Height;
|
||||||
|
float sizeX = panel.Width;
|
||||||
|
float sizeY = panel.Height;
|
||||||
|
|
||||||
|
if ((sizeY / sizeX) < (parentY / parentX))
|
||||||
|
{
|
||||||
|
// 相同的 X, 子窗口 Y 更小
|
||||||
|
sizeY = parentX * sizeY / sizeX;
|
||||||
|
sizeX = parentX;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 相同的 Y, 子窗口 X 更小
|
||||||
|
sizeX = parentY * sizeX / sizeY;
|
||||||
|
sizeY = parentY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 必须通过 SFML 的方法调整窗口
|
||||||
|
RenderWindow.Position = new((int)(parentX - sizeX) / 2, (int)(parentY - sizeY) / 2);
|
||||||
|
RenderWindow.Size = new((uint)sizeX, (uint)sizeY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void panel_MouseDown(object sender, MouseEventArgs e)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void panel_MouseMove(object sender, MouseEventArgs e)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void panel_MouseUp(object sender, MouseEventArgs e)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
|
||||||
|
{
|
||||||
|
RenderWindow.SetActive(true);
|
||||||
|
|
||||||
|
while (!backgroundWorker.CancellationPending)
|
||||||
|
{
|
||||||
|
var delta = Clock.ElapsedTime.AsSeconds();
|
||||||
|
Clock.Restart();
|
||||||
|
|
||||||
|
// TODO: 绘制网格线
|
||||||
|
RenderWindow.Clear(BackgroundColor);
|
||||||
|
|
||||||
|
OnRenderFrame(delta);
|
||||||
|
RenderWindow.Display();
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderWindow.SetActive(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// RenderFrame 事件参数
|
||||||
|
/// </summary>
|
||||||
|
public class RenderFrameEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 渲染目标
|
||||||
|
/// </summary>
|
||||||
|
public SFML.Graphics.RenderTarget RenderTarget { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 距离上一帧经过的时间, 单位秒
|
||||||
|
/// </summary>
|
||||||
|
public float Delta { get; }
|
||||||
|
|
||||||
|
public RenderFrameEventArgs(SFML.Graphics.RenderTarget renderTarget, float delta)
|
||||||
|
{
|
||||||
|
RenderTarget = renderTarget;
|
||||||
|
Delta = delta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
123
SpineViewer/src/SpinePreviewer.resx
Normal file
123
SpineViewer/src/SpinePreviewer.resx
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<metadata name="backgroundWorker.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>17, 17</value>
|
||||||
|
</metadata>
|
||||||
|
</root>
|
||||||
Reference in New Issue
Block a user