编者按
本文已于作者 @Lawliet 授权转载,原载于知乎,如需转载请务必联系原作者。
正文
Unity有一个自带的 Color 拾色器面板,只有16进制(例如D5B1B1FF)显示,而 32位 显示(213, 177, 177, 255)的颜色值是分开四个输入框的,复制起来很不方便。可是我们项目开发时,使用的 Color 和 Color32 类却不能使用16进制,所以有时候拾取的颜色值要用到代码里需要大费周章。
所以今天要做一个颜色拾取器,用于同时显示16进制,归一化颜色值,32位颜色值
知识要点:
- EditorWindow
- EditorGUILayout.TextField
- EditorGUILayout.ColorField
- ColorUtility
使用版本:
- Unity3D 5.3.3
目标:
- 继续深入学习 EditorGUILayout 类其他功能。
整个插件的结构:
像上一节教程一样,我们要先创建一个 EditorWindow 面板类。 怎么样创建 Editor 目录的内容就不再这多说,有疑惑可以看回前两章的教程内容。
public class ColorPickerWindow : EditorWindow { [MenuItem("Tools/ColorPicker")] public static void ShowWindow() { //调用GetWindow创建一个面板 EditorWindow.GetWindow("ColorPicker"); } }
然后是在 ColorPickerWindow 内定义四个属性,用于记录四种颜色表示方式的数据。
////// 16进制颜色 /// private string _hexColor = "FFFFFFFF"; ////// 归一化颜色值 /// private string _normalColor = "1f, 1f, 1f, 1f"; ////// 32位颜色值显示 /// private string _color32 = "255, 255, 255, 255"; ////// unity颜色值 /// private Color _color = new Color(1, 1, 1, 1);
接下来就是定义OnGUI方法,并且写入我们绘制面板的代码。
string tempHexColor = EditorGUILayout.TextField("HexColor:", _hexColor); string tempNormalColor = EditorGUILayout.TextField("NormalColor:", _normalColor); string tempColor32 = EditorGUILayout.TextField("Color32:", _color32); Color tempColorValue = EditorGUILayout.ColorField(_color);
这里重点说一下 EditorGUILayout.TextField,因为它是比较常用的输入框组件,它显示的是字符串,返回的是用户输入的字符串结果。第一个参数为输入框的 Label(可忽略),第二个参数是输入框显示的字符串内容。
接着是 EditorGUILayout.ColorField,这是我们常用来显示颜色的 Color 组件,Color组件也可以显示 Label,不过这里忽略掉,只使用第一个参数(Color类型)。
EditorGUILayout 下的组件用法大致相同,而且基本都有几种重载方法。使用的时候,可以先看看方法的定义。如果有必要,可能会另外开一节课讲GUI的绘制原理。
上面我们把四个输入框组件绘制出来,并保存下来,为的是之后的转换。
if (tempHexColor != _hexColor) { _hexColor = tempHexColor; _color = HexToColor(_hexColor); UpdateColor(); this.Repaint(); } else if (tempNormalColor != _normalColor) { _normalColor = tempNormalColor; _color = NormalToColor(_normalColor); UpdateColor(); this.Repaint(); } else if (tempColor32 != _color32) { _color32 = tempColor32; _color = Color32ToColor(_color32); UpdateColor(); this.Repaint(); } else if(tempColorValue != _color) { _color = tempColorValue; UpdateColor(); this.Repaint(); }
这里分别对四个属性进行判断,然后分别调用相应的转换函数,把数值转换成Color类,然后再分别格式化显示各种数值,最后调用Repaint()方法刷新界面。
注意:这里要先判断是否修改的做法,第一,是提高效率。第二,Repaint()方法会触发一次OnGUI(),这样可以防止一直刷新OnGUI()
接下来分别添加转换方法。
////// 16进制转Color类 /// /// /// private Color HexToColor(string value) { Color color; value = value.Replace("0x", ""); value = value.Replace("0X", ""); if (value.IndexOf("#") != 0) { value = "#" + value; } ColorUtility.TryParseHtmlString(value, out color); return color; }
首先是16进制转 Color,16进制颜色通常会使用“0xFFFFFFFF”、“#FFFFFFFF”、“FFFFFFFF”。由于后面用到ColorUtility.TryParseHtmlString方法要使用“#FFFFFFFF”样式,所以,先要把“0x”替换掉,然后加上“#”。
ColorUtility 是 Editor 的颜色工具类,这里的 TryParseHtmlString 方法能把16进制字符串转换成 Color 类。很方便使用。
由于第二个参数是 out,所以要加上 out 关键字,把 color 的引用传入方法。
////// 归一化转Color /// /// /// private Color NormalToColor(string value) { Color color = new Color(); value = value.Replace(" ",""); value = value.Replace("f", ""); string[] values = value.Split(','); float[] numbers = new float[4]; for (int i = 0; i < 4; i++) { if (i < values.Length) { float.TryParse(values[i], out numbers[i]); numbers[i] = Mathf.Clamp(numbers[i], 0.0f, 1.0f); } else { numbers[i] = 1.0f; } } color.r = numbers[0]; color.g = numbers[1]; color.b = numbers[2]; color.a = numbers[3]; return color; }
归一化颜色值(0f-1f)我们可能并不少见,在着色器 shader 编写上就有用到。这里的显示我们会在数字后面加上“f”,以便我们能直接复制到代码里面使用。
当然,转换的时候要把空格和“f”替换掉,然后进行分割字符,再使用 float.TryParse 把字符串转变成 float 类型。这里还要使用Mathf.Clamp 方法对数值进行一个限制,限制到 0f-1f 之间。
////// Color32转Color /// /// /// private Color Color32ToColor(string value) { Color32 color = new Color32(); value = value.Replace(" ", ""); string[] values = value.Split(','); byte[] numbers = new byte[4]; for (int i = 0; i < 4; i++) { if (i < values.Length) { byte.TryParse(values[i], out numbers[i]); } else { numbers[i] = 255; } } color.r = numbers[0]; color.g = numbers[1]; color.b = numbers[2]; color.a = numbers[3]; return color; }
Color32ToColor 和 NormalToColor 方法差不多,只是把 float 变成了 byte
////// 更新颜色值 /// 把color转成各种颜色表示方式 /// private void UpdateColor() { _hexColor = ColorUtility.ToHtmlStringRGBA(_color); _normalColor = string.Format("{0}f, {1}f, {2}f, {3}f", _color.r, _color.g, _color.b, _color.a); Color32 color32 = _color; _color32 = string.Format("{0}, {1}, {2}, {3}", color32.r, color32.g, color32.b, color32.a); }
最后,我们使用 UpdateColor 把 Color 格式化一遍,变成各种字符串,这就大功告成了。ColorUtility.ToHtmlStringRGBA 方法可以直接把 Color 转成16进制颜色,很方便。
最后,你就可以用它看看效果了。
后记
如果大家有什么意见和建议,或者是有什么疑问,或者是有想看的知识点内容,都欢迎到评论区发上你们的评论。
最后我希望有更多人参与到插件开发的队伍里。也欢迎大家投稿。
- 源码:L-Lawliet/UnityEditorTutorial
- 题图来自于unsplash.com
- 欢迎分享本文
- QQ群:234204968
这个系列的题图都很神。