diff --git a/SpineViewer/Extensions/SFMLExtension.cs b/SpineViewer/Extensions/SFMLExtension.cs index dcfb9ce..a4b9fc7 100644 --- a/SpineViewer/Extensions/SFMLExtension.cs +++ b/SpineViewer/Extensions/SFMLExtension.cs @@ -8,6 +8,39 @@ namespace SpineViewer.Extensions { public static class SFMLExtension { + /// + /// 获取适合指定画布参数下能够覆盖包围盒的画布视区包围盒 + /// + public static RectangleF GetCanvasBounds(this RectangleF bounds, Size resolution) => GetCanvasBounds(bounds, resolution, new(0), new(0)); + + /// + /// 获取适合指定画布参数下能够覆盖包围盒的画布视区包围盒 + /// + public static RectangleF GetCanvasBounds(this RectangleF bounds, Size resolution, Padding margin) => GetCanvasBounds(bounds, resolution, margin, new(0)); + + /// + /// 获取适合指定画布参数下能够覆盖包围盒的画布视区包围盒 + /// + public static RectangleF GetCanvasBounds(this RectangleF bounds, Size resolution, Padding margin, Padding padding) + { + float sizeW = bounds.Width; + float sizeH = bounds.Height; + float innerW = resolution.Width - padding.Horizontal; + float innerH = resolution.Height - padding.Vertical; + float scale = Math.Max(Math.Abs(sizeW / innerW), Math.Abs(sizeH / innerH)); // 取两方向上较大的缩放比, 以此让画布可以覆盖内容 + float scaleW = scale * Math.Sign(sizeW); + float scaleH = scale * Math.Sign(sizeH); + + innerW *= scaleW; + innerH *= scaleH; + + var x = bounds.X - (innerW - sizeW) / 2 - (margin.Left + padding.Left) * scaleW; + var y = bounds.Y - (innerH - sizeH) / 2 - (margin.Top + padding.Top) * scaleH; + var w = (resolution.Width + margin.Horizontal) * scaleW; + var h = (resolution.Height + margin.Vertical) * scaleH; + return new(x, y, w, h); + } + /// /// 获取 Winforms Bitmap 对象, 需要使用 Dispose 释放对象 /// @@ -29,26 +62,33 @@ namespace SpineViewer.Extensions } /// - /// 获取适合指定画布参数下能够覆盖包围盒的视区包围盒 + /// 获取视图的包围盒 /// - public static RectangleF GetResolutionBounds(this RectangleF bounds, Size resolution, Padding margin, Padding padding) + public static RectangleF GetBounds(this SFML.Graphics.View view) + => new(view.Center.X - view.Size.X / 2, view.Center.Y - view.Size.Y / 2, view.Size.X, view.Size.Y); + + /// + /// 按画布设置视区, 边缘和填充区域将不会出现内容 + /// + public static void SetViewport(this SFML.Graphics.View view, Size resolution, Padding margin, Padding padding) { - float sizeW = bounds.Width; - float sizeH = bounds.Height; - float innerW = resolution.Width - padding.Horizontal; - float innerH = resolution.Height - padding.Vertical; - float scale = Math.Max(Math.Abs(sizeW / innerW), Math.Abs(sizeH / innerH)); // 取两方向上较大的缩放比, 以此让画布可以覆盖内容 - float scaleW = scale * Math.Sign(sizeW); - float scaleH = scale * Math.Sign(sizeH); + var innerW = resolution.Width - padding.Horizontal; + var innerH = resolution.Height - padding.Vertical; - innerW *= scaleW; - innerH *= scaleH; + float width = resolution.Width + margin.Horizontal; + float height = resolution.Height + margin.Vertical; - var x = bounds.X - (innerW - sizeW) / 2 - (margin.Left + padding.Left) * scaleW; - var y = bounds.Y - (innerH - sizeH) / 2 - (margin.Top + padding.Top) * scaleH; - var w = (resolution.Width + margin.Horizontal) * scaleW; - var h = (resolution.Height + margin.Vertical) * scaleH; - return new(x, y, w, h); + view.Viewport = new( + (margin.Left + padding.Left) / width, + (margin.Top + padding.Top) / height, + innerW / width, + innerH / height + ); + + var bounds = view.GetBounds().GetCanvasBounds(new(innerW, innerH)); + + view.Center = new(bounds.X + bounds.Width / 2, bounds.Y + bounds.Height / 2); + view.Size = new(bounds.Width, bounds.Height); } } }