增加预览图
This commit is contained in:
65
SpineViewer/Controls/SpineListView.Designer.cs
generated
65
SpineViewer/Controls/SpineListView.Designer.cs
generated
@@ -41,6 +41,13 @@
|
||||
toolStripSeparator2 = new ToolStripSeparator();
|
||||
toolStripMenuItem_BatchAdd = new ToolStripMenuItem();
|
||||
toolStripMenuItem_RemoveAll = new ToolStripMenuItem();
|
||||
toolStripSeparator3 = new ToolStripSeparator();
|
||||
toolStripMenuItem_ChangeView = new ToolStripMenuItem();
|
||||
toolStripMenuItem_LargeIconView = new ToolStripMenuItem();
|
||||
toolStripMenuItem_SmallIconView = new ToolStripMenuItem();
|
||||
toolStripMenuItem_DetailsView = new ToolStripMenuItem();
|
||||
imageList_LargeIcon = new ImageList(components);
|
||||
imageList_SmallIcon = new ImageList(components);
|
||||
contextMenuStrip.SuspendLayout();
|
||||
SuspendLayout();
|
||||
//
|
||||
@@ -52,10 +59,12 @@
|
||||
listView.Dock = DockStyle.Fill;
|
||||
listView.FullRowSelect = true;
|
||||
listView.GridLines = true;
|
||||
listView.LargeImageList = imageList_LargeIcon;
|
||||
listView.Location = new Point(0, 0);
|
||||
listView.Name = "listView";
|
||||
listView.ShowItemToolTips = true;
|
||||
listView.Size = new Size(336, 445);
|
||||
listView.SmallImageList = imageList_SmallIcon;
|
||||
listView.TabIndex = 1;
|
||||
listView.UseCompatibleStateImageBehavior = false;
|
||||
listView.View = View.Details;
|
||||
@@ -73,9 +82,9 @@
|
||||
// contextMenuStrip
|
||||
//
|
||||
contextMenuStrip.ImageScalingSize = new Size(24, 24);
|
||||
contextMenuStrip.Items.AddRange(new ToolStripItem[] { toolStripMenuItem_Add, toolStripMenuItem_Insert, toolStripMenuItem_Remove, toolStripSeparator1, toolStripMenuItem_MoveUp, toolStripMenuItem_MoveDown, toolStripSeparator2, toolStripMenuItem_BatchAdd, toolStripMenuItem_RemoveAll });
|
||||
contextMenuStrip.Items.AddRange(new ToolStripItem[] { toolStripMenuItem_Add, toolStripMenuItem_Insert, toolStripMenuItem_Remove, toolStripSeparator1, toolStripMenuItem_MoveUp, toolStripMenuItem_MoveDown, toolStripSeparator2, toolStripMenuItem_BatchAdd, toolStripMenuItem_RemoveAll, toolStripSeparator3, toolStripMenuItem_ChangeView });
|
||||
contextMenuStrip.Name = "contextMenuStrip";
|
||||
contextMenuStrip.Size = new Size(188, 226);
|
||||
contextMenuStrip.Size = new Size(188, 262);
|
||||
contextMenuStrip.Opening += contextMenuStrip_Opening;
|
||||
//
|
||||
// toolStripMenuItem_Add
|
||||
@@ -140,6 +149,51 @@
|
||||
toolStripMenuItem_RemoveAll.Text = "移除全部(&X)";
|
||||
toolStripMenuItem_RemoveAll.Click += toolStripMenuItem_RemoveAll_Click;
|
||||
//
|
||||
// toolStripSeparator3
|
||||
//
|
||||
toolStripSeparator3.Name = "toolStripSeparator3";
|
||||
toolStripSeparator3.Size = new Size(184, 6);
|
||||
//
|
||||
// toolStripMenuItem_ChangeView
|
||||
//
|
||||
toolStripMenuItem_ChangeView.DropDownItems.AddRange(new ToolStripItem[] { toolStripMenuItem_LargeIconView, toolStripMenuItem_SmallIconView, toolStripMenuItem_DetailsView });
|
||||
toolStripMenuItem_ChangeView.Name = "toolStripMenuItem_ChangeView";
|
||||
toolStripMenuItem_ChangeView.Size = new Size(187, 30);
|
||||
toolStripMenuItem_ChangeView.Text = "切换视图";
|
||||
//
|
||||
// toolStripMenuItem_LargeIconView
|
||||
//
|
||||
toolStripMenuItem_LargeIconView.Name = "toolStripMenuItem_LargeIconView";
|
||||
toolStripMenuItem_LargeIconView.Size = new Size(164, 34);
|
||||
toolStripMenuItem_LargeIconView.Text = "大图标";
|
||||
toolStripMenuItem_LargeIconView.Click += toolStripMenuItem_LargeIconView_Click;
|
||||
//
|
||||
// toolStripMenuItem_SmallIconView
|
||||
//
|
||||
toolStripMenuItem_SmallIconView.Name = "toolStripMenuItem_SmallIconView";
|
||||
toolStripMenuItem_SmallIconView.Size = new Size(164, 34);
|
||||
toolStripMenuItem_SmallIconView.Text = "小图标";
|
||||
toolStripMenuItem_SmallIconView.Click += toolStripMenuItem_SmallIconView_Click;
|
||||
//
|
||||
// toolStripMenuItem_DetailsView
|
||||
//
|
||||
toolStripMenuItem_DetailsView.Name = "toolStripMenuItem_DetailsView";
|
||||
toolStripMenuItem_DetailsView.Size = new Size(164, 34);
|
||||
toolStripMenuItem_DetailsView.Text = "列表";
|
||||
toolStripMenuItem_DetailsView.Click += toolStripMenuItem_DetailsView_Click;
|
||||
//
|
||||
// imageList_LargeIcon
|
||||
//
|
||||
imageList_LargeIcon.ColorDepth = ColorDepth.Depth32Bit;
|
||||
imageList_LargeIcon.ImageSize = new Size(96, 96);
|
||||
imageList_LargeIcon.TransparentColor = Color.Transparent;
|
||||
//
|
||||
// imageList_SmallIcon
|
||||
//
|
||||
imageList_SmallIcon.ColorDepth = ColorDepth.Depth32Bit;
|
||||
imageList_SmallIcon.ImageSize = new Size(48, 48);
|
||||
imageList_SmallIcon.TransparentColor = Color.Transparent;
|
||||
//
|
||||
// SpineListView
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(11F, 24F);
|
||||
@@ -164,5 +218,12 @@
|
||||
private ToolStripMenuItem toolStripMenuItem_MoveDown;
|
||||
private ToolStripSeparator toolStripSeparator2;
|
||||
private ColumnHeader columnHeader_Name;
|
||||
private ImageList imageList_SmallIcon;
|
||||
private ImageList imageList_LargeIcon;
|
||||
private ToolStripSeparator toolStripSeparator3;
|
||||
private ToolStripMenuItem toolStripMenuItem_ChangeView;
|
||||
private ToolStripMenuItem toolStripMenuItem_LargeIconView;
|
||||
private ToolStripMenuItem toolStripMenuItem_SmallIconView;
|
||||
private ToolStripMenuItem toolStripMenuItem_DetailsView;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,8 +58,13 @@ namespace SpineViewer.Controls
|
||||
index = listView.Items.Count;
|
||||
|
||||
// 锁定外部的读操作
|
||||
lock (Spines) { spines.Insert(index, spine); }
|
||||
listView.Items.Insert(index, new ListViewItem(spine.Name) { ToolTipText = spine.SkelPath });
|
||||
lock (Spines)
|
||||
{
|
||||
spines.Insert(index, spine);
|
||||
listView.SmallImageList.Images.Add(spine.ID, spine.Preview);
|
||||
listView.LargeImageList.Images.Add(spine.ID, spine.Preview);
|
||||
}
|
||||
listView.Items.Insert(index, new ListViewItem(spine.Name, spine.ID) { ToolTipText = spine.SkelPath });
|
||||
|
||||
// 选中新增项
|
||||
listView.SelectedIndices.Clear();
|
||||
@@ -123,8 +128,14 @@ namespace SpineViewer.Controls
|
||||
try
|
||||
{
|
||||
var spine = Spine.Spine.New(version, skelPath);
|
||||
var preview = spine.Preview;
|
||||
lock (Spines) { spines.Add(spine); }
|
||||
listView.Invoke(() => listView.Items.Add(new ListViewItem(spine.Name) { ToolTipText = spine.SkelPath }));
|
||||
listView.Invoke(() =>
|
||||
{
|
||||
listView.SmallImageList.Images.Add(spine.ID, preview);
|
||||
listView.LargeImageList.Images.Add(spine.ID, preview);
|
||||
listView.Items.Add(new ListViewItem(spine.Name, spine.ID) { ToolTipText = spine.SkelPath });
|
||||
});
|
||||
success++;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -255,6 +266,11 @@ namespace SpineViewer.Controls
|
||||
toolStripMenuItem_MoveUp.Enabled = selectedCount == 1 && listView.SelectedIndices[0] != 0;
|
||||
toolStripMenuItem_MoveDown.Enabled = selectedCount == 1 && listView.SelectedIndices[0] != itemsCount - 1;
|
||||
toolStripMenuItem_RemoveAll.Enabled = itemsCount > 0;
|
||||
|
||||
// 视图选项
|
||||
toolStripMenuItem_LargeIconView.Checked = listView.View == View.LargeIcon;
|
||||
toolStripMenuItem_SmallIconView.Checked = listView.View == View.SmallIcon;
|
||||
toolStripMenuItem_DetailsView.Checked = listView.View == View.Details;
|
||||
}
|
||||
|
||||
private void toolStripMenuItem_Add_Click(object sender, EventArgs e)
|
||||
@@ -288,8 +304,11 @@ namespace SpineViewer.Controls
|
||||
{
|
||||
lock (Spines)
|
||||
{
|
||||
spines[i].Dispose();
|
||||
var spine = spines[i];
|
||||
spines.RemoveAt(i);
|
||||
listView.SmallImageList.Images.RemoveByKey(spine.ID);
|
||||
listView.LargeImageList.Images.RemoveByKey(spine.ID);
|
||||
spine.Dispose();
|
||||
}
|
||||
listView.Items.RemoveAt(i);
|
||||
}
|
||||
@@ -338,10 +357,27 @@ namespace SpineViewer.Controls
|
||||
foreach (var spine in spines)
|
||||
spine.Dispose();
|
||||
spines.Clear();
|
||||
listView.SmallImageList.Images.Clear();
|
||||
listView.LargeImageList.Images.Clear();
|
||||
}
|
||||
listView.Items.Clear();
|
||||
if (PropertyGrid is not null)
|
||||
PropertyGrid.SelectedObject = null;
|
||||
}
|
||||
|
||||
private void toolStripMenuItem_LargeIconView_Click(object sender, EventArgs e)
|
||||
{
|
||||
listView.View = View.LargeIcon;
|
||||
}
|
||||
|
||||
private void toolStripMenuItem_SmallIconView_Click(object sender, EventArgs e)
|
||||
{
|
||||
listView.View = View.SmallIcon;
|
||||
}
|
||||
|
||||
private void toolStripMenuItem_DetailsView_Click(object sender, EventArgs e)
|
||||
{
|
||||
listView.View = View.Details;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,4 +120,10 @@
|
||||
<metadata name="contextMenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<metadata name="imageList_LargeIcon.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>552, 29</value>
|
||||
</metadata>
|
||||
<metadata name="imageList_SmallIcon.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>267, 34</value>
|
||||
</metadata>
|
||||
</root>
|
||||
@@ -41,6 +41,16 @@ namespace SpineViewer.Spine
|
||||
/// </summary>
|
||||
public const string EMPTY_ANIMATION = "<Empty>";
|
||||
|
||||
/// <summary>
|
||||
/// 预览图大小
|
||||
/// </summary>
|
||||
public static readonly Size PREVIEW_SIZE = new(256, 256);
|
||||
|
||||
/// <summary>
|
||||
/// 缩放最小值
|
||||
/// </summary>
|
||||
public const float SCALE_MIN = 0.001f;
|
||||
|
||||
/// <summary>
|
||||
/// 实现类缓存
|
||||
/// </summary>
|
||||
@@ -108,6 +118,11 @@ namespace SpineViewer.Spine
|
||||
return (Spine)Activator.CreateInstance(spineType, skelPath, atlasPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 标识符
|
||||
/// </summary>
|
||||
public readonly string ID = Guid.NewGuid().ToString();
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
@@ -132,13 +147,7 @@ namespace SpineViewer.Spine
|
||||
|
||||
~Spine() { Dispose(false); }
|
||||
public void Dispose() { Dispose(true); GC.SuppressFinalize(this); }
|
||||
protected virtual void Dispose(bool disposing) { }
|
||||
|
||||
/// <summary>
|
||||
/// 缩放最小值
|
||||
/// </summary>
|
||||
[Browsable(false)]
|
||||
public const float SCALE_MIN = 0.001f;
|
||||
protected virtual void Dispose(bool disposing) { preview?.Dispose(); }
|
||||
|
||||
/// <summary>
|
||||
/// 获取所属版本
|
||||
@@ -231,6 +240,48 @@ namespace SpineViewer.Spine
|
||||
[Browsable(false)]
|
||||
public abstract RectangleF Bounds { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 骨骼预览图
|
||||
/// </summary>
|
||||
[Browsable(false)]
|
||||
public Image Preview { get => preview ??= GetPreview(PREVIEW_SIZE); }
|
||||
private Image preview = null;
|
||||
|
||||
public Image GetPreview(Size size)
|
||||
{
|
||||
var curAnimation = CurrentAnimation;
|
||||
CurrentAnimation = EMPTY_ANIMATION;
|
||||
var bounds = Bounds;
|
||||
|
||||
float viewX = size.Width;
|
||||
float viewY = size.Height;
|
||||
float sizeX = bounds.Width;
|
||||
float sizeY = bounds.Height;
|
||||
|
||||
var scale = 1f;
|
||||
if ((sizeY / sizeX) < (viewY / viewX))
|
||||
scale = sizeX / viewX;// 相同的 X, 视窗 Y 更大
|
||||
else
|
||||
scale = sizeY / viewY;// 相同的 Y, 视窗 X 更大
|
||||
|
||||
viewX *= scale;
|
||||
viewY *= scale;
|
||||
|
||||
var tex = new SFML.Graphics.RenderTexture((uint)size.Width, (uint)size.Height);
|
||||
var view = tex.GetView();
|
||||
view.Center = new(bounds.X + viewX / 2, bounds.Y + viewY / 2);
|
||||
view.Size = new(viewX, -viewY);
|
||||
tex.SetView(view);
|
||||
tex.Clear(SFML.Graphics.Color.Transparent);
|
||||
tex.Draw(this);
|
||||
tex.Display();
|
||||
CurrentAnimation = curAnimation;
|
||||
using var img = tex.Texture.CopyToImage();
|
||||
img.SaveToMemory(out var imgBuffer, "bmp");
|
||||
using var stream = new MemoryStream(imgBuffer);
|
||||
return new Bitmap(stream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取动画时长, 如果动画不存在则返回 0
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user