找回密码
 立即注册
查看: 344|回复: 0

Unity3D插件开发教程(三):制作拾色器ColorPicker

[复制链接]
发表于 2022-1-31 17:25 | 显示全部楼层 |阅读模式
声明:


  • 题图来自于unsplash.com
  • 欢迎分享本文
  • 本文未经允许不能以任何形式转载。

Unity有一个自带的Color拾色器面板,只有16进制(例如D5B1B1FF)显示,而32位显示(213, 177, 177, 255)的颜色值是分开四个输入框的,复制起来很不方便。可是我们项目开发时,使用的ColorColor32类却不能使用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<ColorPickerWindow>("ColorPicker");
    }
}
然后是在ColorPickerWindow内定义四个属性,用于记录四种颜色表示方式的数据。
/// <summary>
/// 16进制颜色
/// </summary>
private string _hexColor = "FFFFFFFF";

/// <summary>
/// 归一化颜色值
/// </summary>
private string _normalColor = "1f, 1f, 1f, 1f";

/// <summary>
/// 32位颜色值显示
/// </summary>
private string _color32 = "255, 255, 255, 255";

/// <summary>
/// unity颜色值
/// </summary>
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()
接下来分别添加转换方法。
/// <summary>
/// 16进制转Color类
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
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的引用传入方法。
/// <summary>
/// 归一化转Color
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
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, out numbers);

            numbers = Mathf.Clamp(numbers, 0.0f, 1.0f);
        }
        else
        {
            numbers = 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之间。
/// <summary>
/// Color32转Color
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
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, out numbers);
        }
        else
        {
            numbers = 255;
        }
    }

    color.r = numbers[0];
    color.g = numbers[1];
    color.b = numbers[2];
    color.a = numbers[3];

    return color;
}
Color32ToColorNormalToColor方法差不多,只是把float变成了byte
/// <summary>
/// 更新颜色值
/// 把color转成各种颜色表示方式
/// </summary>
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);
}最后,我们使用UpdateColorColor格式化一遍,变成各种字符串,这就大功告成了。ColorUtility.ToHtmlStringRGBA方法可以直接把Color转成16进制颜色,很方便。
最后,你就可以用它看看效果了。

源码:L-Lawliet/UnityEditorTutorial
==========================分割线==========================
如果大家有什么意见和建议,或者是有什么疑问,或者是有想看的知识点内容,都欢迎到评论区发上你们的评论。

最后我希望有更多人参与到插件开发的队伍里。也欢迎大家投稿。
QQ群:234204968

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-5-6 19:15 , Processed in 0.104074 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表