增加背景颜色参数
This commit is contained in:
@@ -67,10 +67,12 @@ namespace SpineViewer.Exporter
|
||||
public bool RenderSelectedOnly { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 背景颜色 TODO: 提供颜色编辑
|
||||
/// 背景颜色
|
||||
/// </summary>
|
||||
[Editor(typeof(SFMLColorEditor), typeof(UITypeEditor))]
|
||||
[TypeConverter(typeof(SFMLColorConverter))]
|
||||
[Category("[0] 导出"), DisplayName("背景颜色"), Description("要使用的背景色, 格式为 #RRGGBBAA")]
|
||||
public SFML.Graphics.Color BackgroundColor { get; set; } = SFML.Graphics.Color.Transparent;
|
||||
public SFML.Graphics.Color BackgroundColor { get; set; } = new(0, 255, 0, 0);
|
||||
|
||||
/// <summary>
|
||||
/// 检查参数是否合法并规范化参数值, 否则返回用户错误原因
|
||||
|
||||
@@ -23,4 +23,81 @@ namespace SpineViewer.Exporter
|
||||
return new StandardValuesCollection(supportedFileSuffix);
|
||||
}
|
||||
}
|
||||
|
||||
public class SFMLColorConverter : ExpandableObjectConverter
|
||||
{
|
||||
private class SFMLColorPropertyDescriptor : SimplePropertyDescriptor
|
||||
{
|
||||
public SFMLColorPropertyDescriptor(Type componentType, string name, Type propertyType) : base(componentType, name, propertyType) { }
|
||||
|
||||
public override object? GetValue(object? component)
|
||||
{
|
||||
return component?.GetType().GetField(Name)?.GetValue(component) ?? default;
|
||||
}
|
||||
|
||||
public override void SetValue(object? component, object? value)
|
||||
{
|
||||
component?.GetType().GetField(Name)?.SetValue(component, value);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
|
||||
{
|
||||
return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
|
||||
}
|
||||
|
||||
public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
|
||||
{
|
||||
if (value is string s)
|
||||
{
|
||||
s = s.Trim();
|
||||
if (s.StartsWith("#") && s.Length == 9)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 解析 R, G, B, A 分量,注意16进制解析
|
||||
byte r = byte.Parse(s.Substring(1, 2), NumberStyles.HexNumber);
|
||||
byte g = byte.Parse(s.Substring(3, 2), NumberStyles.HexNumber);
|
||||
byte b = byte.Parse(s.Substring(5, 2), NumberStyles.HexNumber);
|
||||
byte a = byte.Parse(s.Substring(7, 2), NumberStyles.HexNumber);
|
||||
return new SFML.Graphics.Color(r, g, b, a);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new FormatException("无法解析颜色,确保格式为 #RRGGBBAA", ex);
|
||||
}
|
||||
}
|
||||
throw new FormatException("格式错误,正确格式为 #RRGGBBAA");
|
||||
}
|
||||
return base.ConvertFrom(context, culture, value);
|
||||
}
|
||||
|
||||
public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType)
|
||||
{
|
||||
return destinationType == typeof(string) || base.CanConvertTo(context, destinationType);
|
||||
}
|
||||
|
||||
public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType)
|
||||
{
|
||||
if (destinationType == typeof(string) && value is SFML.Graphics.Color color)
|
||||
return $"#{color.R:X2}{color.G:X2}{color.B:X2}{color.A:X2}";
|
||||
return base.ConvertTo(context, culture, value, destinationType);
|
||||
}
|
||||
|
||||
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext? context, object value, Attribute[]? attributes)
|
||||
{
|
||||
// 自定义属性集合
|
||||
var properties = new List<PropertyDescriptor>
|
||||
{
|
||||
// 定义 R, G, B, A 四个字段的描述器
|
||||
new SFMLColorPropertyDescriptor(typeof(SFML.Graphics.Color), "R", typeof(byte)),
|
||||
new SFMLColorPropertyDescriptor(typeof(SFML.Graphics.Color), "G", typeof(byte)),
|
||||
new SFMLColorPropertyDescriptor(typeof(SFML.Graphics.Color), "B", typeof(byte)),
|
||||
new SFMLColorPropertyDescriptor(typeof(SFML.Graphics.Color), "A", typeof(byte))
|
||||
};
|
||||
|
||||
// 返回自定义属性集合
|
||||
return new PropertyDescriptorCollection(properties.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
66
SpineViewer/Exporter/UITypeEditor.cs
Normal file
66
SpineViewer/Exporter/UITypeEditor.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing.Design;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SpineViewer.Exporter
|
||||
{
|
||||
class SFMLColorEditor : UITypeEditor
|
||||
{
|
||||
public override bool GetPaintValueSupported(ITypeDescriptorContext? context) => true;
|
||||
|
||||
public override void PaintValue(PaintValueEventArgs e)
|
||||
{
|
||||
if (e.Value is SFML.Graphics.Color color)
|
||||
{
|
||||
// 定义颜色和透明度的绘制区域
|
||||
var colorBox = new Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Width / 2, e.Bounds.Height);
|
||||
var alphaBox = new Rectangle(e.Bounds.X + e.Bounds.Width / 2, e.Bounds.Y, e.Bounds.Width / 2, e.Bounds.Height);
|
||||
|
||||
// 转换为 System.Drawing.Color
|
||||
var drawColor = Color.FromArgb(color.A, color.R, color.G, color.B);
|
||||
|
||||
// 绘制纯颜色(RGB 部分)
|
||||
using (var brush = new SolidBrush(Color.FromArgb(color.R, color.G, color.B)))
|
||||
{
|
||||
e.Graphics.FillRectangle(brush, colorBox);
|
||||
e.Graphics.DrawRectangle(Pens.Black, colorBox);
|
||||
}
|
||||
|
||||
// 绘制带透明度效果的颜色
|
||||
using (var checkerBrush = CreateTransparencyBrush())
|
||||
{
|
||||
e.Graphics.FillRectangle(checkerBrush, alphaBox); // 背景棋盘格
|
||||
}
|
||||
using (var brush = new SolidBrush(drawColor))
|
||||
{
|
||||
e.Graphics.FillRectangle(brush, alphaBox); // 叠加透明颜色
|
||||
e.Graphics.DrawRectangle(Pens.Black, alphaBox);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
base.PaintValue(e);
|
||||
}
|
||||
}
|
||||
|
||||
// 创建一个透明背景的棋盘格图案画刷
|
||||
private static TextureBrush CreateTransparencyBrush()
|
||||
{
|
||||
var bitmap = new Bitmap(8, 8);
|
||||
using (var g = Graphics.FromImage(bitmap))
|
||||
{
|
||||
g.Clear(Color.White);
|
||||
using (var grayBrush = new SolidBrush(Color.LightGray))
|
||||
{
|
||||
g.FillRectangle(grayBrush, 0, 0, 4, 4);
|
||||
g.FillRectangle(grayBrush, 4, 4, 4, 4);
|
||||
}
|
||||
}
|
||||
return new TextureBrush(bitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user