From 1d2513cef513fbd0820a90704535aa2e0c78064f Mon Sep 17 00:00:00 2001 From: ww-rm Date: Wed, 16 Apr 2025 22:28:35 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0padding=E5=92=8Cmargin?= =?UTF-8?q?=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SpineViewer/Extensions/SFMLExtension.cs | 12 +-- SpineViewer/Spine/SpineExporter/Exporter.cs | 89 +++++++++++++++++++-- 2 files changed, 90 insertions(+), 11 deletions(-) diff --git a/SpineViewer/Extensions/SFMLExtension.cs b/SpineViewer/Extensions/SFMLExtension.cs index 4e8d3ad..2c28e05 100644 --- a/SpineViewer/Extensions/SFMLExtension.cs +++ b/SpineViewer/Extensions/SFMLExtension.cs @@ -37,12 +37,14 @@ namespace SpineViewer.Extensions float sizeH = bounds.Height; float innerW = resolution.Width - padding.Horizontal; float innerH = resolution.Height - padding.Vertical; - float scale = Math.Max(sizeW / innerW, sizeH / innerH); // 取两方向上较大的缩放比, 以此让画布可以覆盖内容 + float scale = Math.Max(Math.Abs(sizeW / innerW), Math.Abs(sizeH / innerH)); // 取两方向上较大的缩放比, 以此让画布可以覆盖内容 + float scaleW = scale * Math.Sign(sizeW); + float scaleH = scale * Math.Sign(sizeH); return new( - bounds.X + (padding.Left + margin.Left - padding.Right - margin.Right) * scale, - bounds.Y + (padding.Top + margin.Top - padding.Bottom - margin.Bottom) * scale, - (resolution.Width + margin.Horizontal) * scale, - (resolution.Height + margin.Vertical) * scale + bounds.X - (padding.Left + margin.Left - padding.Right - margin.Right) * scaleW, + bounds.Y - (padding.Top + margin.Top - padding.Bottom - margin.Bottom) * scaleH, + (resolution.Width + margin.Horizontal) * scaleW, + (resolution.Height + margin.Vertical) * scaleH ); } } diff --git a/SpineViewer/Spine/SpineExporter/Exporter.cs b/SpineViewer/Spine/SpineExporter/Exporter.cs index b17b178..cee487d 100644 --- a/SpineViewer/Spine/SpineExporter/Exporter.cs +++ b/SpineViewer/Spine/SpineExporter/Exporter.cs @@ -27,6 +27,11 @@ namespace SpineViewer.Spine.SpineExporter /// protected readonly string timestamp = DateTime.Now.ToString("yyMMddHHmmss"); + /// + /// 模型包围盒缓存 + /// + private readonly Dictionary boundsCache = []; + ~Exporter() { Dispose(false); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { View.Dispose(); } @@ -82,16 +87,74 @@ namespace SpineViewer.Spine.SpineExporter public SFML.Graphics.Color BackgroundColorPma { get; private set; } = SFML.Graphics.Color.Transparent; /// - /// 获取供渲染的 SFML.Graphics.RenderTexture + /// 四周填充距离, 单位为像素 + /// + public Padding Padding + { + get => padding; + set + { + if (value.Left < 0) value.Left = 0; + if (value.Right < 0) value.Right = 0; + if (value.Top < 0) value.Top = 0; + if (value.Bottom < 0) value.Bottom = 0; + padding = value; + } + } + private Padding padding = new(0); + + /// + /// 四周边缘距离, 单位为像素 + /// + public Padding Margin + { + get => margin; + set + { + if (value.Left < 0) value.Left = 0; + if (value.Right < 0) value.Right = 0; + if (value.Top < 0) value.Top = 0; + if (value.Bottom < 0) value.Bottom = 0; + margin = value; + } + } + private Padding margin = new(0); + + /// + /// 自动分辨率, 将会忽略预览画面的分辨率和视图, 使用模型自身的包围盒 + /// + public bool AutoResolution { get; set; } = true; + + /// + /// 按照预览画面的参数获取供渲染的 SFML.Graphics.RenderTexture /// private SFML.Graphics.RenderTexture GetRenderTexture() { - var tex = new SFML.Graphics.RenderTexture((uint)Resolution.Width, (uint)Resolution.Height); + var x = View.Center.X - View.Size.X / 2; + var y = View.Center.Y - View.Size.Y / 2; + var w = View.Size.X; + var h = View.Size.Y; + var currentBounds = new RectangleF(x, y, w, h); + var bounds = currentBounds.GetResolutionBounds(Resolution, new(0), Margin); + + using var view = new SFML.Graphics.View(View); + view.Center = new(bounds.X + bounds.Width / 2, bounds.Y + bounds.Height / 2); + view.Size = new(bounds.Width, bounds.Height); + + var tex = new SFML.Graphics.RenderTexture((uint)(Resolution.Width + Margin.Horizontal), (uint)(Resolution.Height + Margin.Vertical)); + tex.SetView(view); tex.Clear(SFML.Graphics.Color.Transparent); - tex.SetView(View); return tex; } + /// + /// 按照要被渲染的模型获取 SFML.Graphics.RenderTexture + /// + //private SFML.Graphics.RenderTexture GetRenderTexture(SpineObject[] spinesToRender) + //{ + + //} + /// /// 获取单个模型的单帧画面 /// @@ -179,11 +242,11 @@ namespace SpineViewer.Spine.SpineExporter /// public virtual void Export(SpineObject[] spines, BackgroundWorker? worker = null) { - if (Validate() is string err) - throw new ArgumentException(err); + if (Validate() is string err) throw new ArgumentException(err); + + boundsCache.Clear(); var spinesToRender = spines.Where(sp => !RenderSelectedOnly || sp.IsSelected).Reverse().ToArray(); - if (IsExportSingle) ExportSingle(spinesToRender, worker); else ExportIndividual(spinesToRender, worker); @@ -238,5 +301,19 @@ namespace SpineViewer.Spine.SpineExporter [TypeConverter(typeof(SFMLColorConverter))] [Category("[0] 导出"), DisplayName("背景颜色"), Description("要使用的背景色, 格式为 #RRGGBBAA")] public SFML.Graphics.Color BackgroundColor { get => Exporter.BackgroundColor; set => Exporter.BackgroundColor = value; } + + /// + /// 四周填充距离 + /// + [TypeConverter(typeof(PaddingConverter))] + [Category("[0] 导出"), DisplayName("四周填充距离"), Description("画布内部的填充距离 (Padding), 导出的分辨率大小不会发生变化, 但是会留有四周空间")] + public Padding Padding { get => Exporter.Padding; set => Exporter.Padding = value; } + + /// + /// 四周边缘距离 + /// + [TypeConverter(typeof(PaddingConverter))] + [Category("[0] 导出"), DisplayName("四周边缘距离"), Description("画布外部的边缘距离 (Margin), 最终导出的分辨率需要加上这个边距")] + public Padding Margin { get => Exporter.Margin; set => Exporter.Margin = value; } } }