【Unity拡張】Photoshopが無くても.acoファイルが使いたい

# はじめに
<a href = "https://dribbble.com">Dribbble</a> のようなデザイン系のWEBサイトを見ていると、配色データ(拡張子.aco)がダウンロードできることがあるのですが、これはPhotoshopがないと開くことができません。

「Photoshopが無くても.acoファイルを開きたいなぁ」と思ったので、.acoファイルをUnity上で確認できるようにするツールをサクッと作ってみました。

# 作ったもの
.acoファイルに含まれているカラーの一覧を表示するEditorWindowを作ってみました。
<img src = "https://qiita-image-store.s3.amazonaws.com/0/44288/7757866f-b24f-b3cd-a073-7a431bf71912.png">

# ソースコード
以下のスクリプトをプロジェクト内のEditorフォルダ以下へ入れてください。
ツールが使えるようになります。

```AcoImportWindow.cs
namespace AcoImporter
{
    using System.IO;
    using UnityEngine;
    using UnityEditor;
    using System.Collections.Generic;
    using System.Linq;

    public class AcoImportWindow : EditorWindow
    {
        private Vector2 scrollPosition = Vector2.zero;

        /// <summary>
        /// .acoファイル 
        /// </summary>
        [SerializeField]
        private Object aco;

        /// <summary>
        /// .acoから取り出した色
        /// </summary>
        [SerializeField]
        private ColorData[] colors;

        [MenuItem("Tools/Aco Importer")]
        static void Open()
        {
            var window = CreateInstance<AcoImportWindow>();
            window.titleContent.text = "Aco Importer";
            window.Show();
        }

        void OnGUI()
        {
            this.scrollPosition = EditorGUILayout.BeginScrollView(this.scrollPosition);
            EditorGUILayout.LabelField("*.aco");

            EditorGUI.BeginChangeCheck();
            this.aco = EditorGUILayout.ObjectField(this.aco, typeof(UnityEngine.Object), false);

            if (EditorGUI.EndChangeCheck())
            {
                this.colors = null;
            }

            EditorGUI.BeginDisabledGroup(this.aco == null);

            if (GUILayout.Button("Import"))
            {
                this.colors = GetColors(this.aco).ToArray();
            }
            EditorGUI.EndDisabledGroup();

            if (this.colors != null)
            {
                // 色の一覧を表示
                foreach (var color in this.colors)
                {
                    string rgb = color.R.ToString("X2") + color.G.ToString("X2") + color.B.ToString("X2");
                    EditorGUILayout.BeginVertical("Box");
                    GUILayout.Space(-1f);
                    EditorGUILayout.LabelField(rgb, GUILayout.Width(80f));

                    GUILayout.Space(-3f);
                    EditorGUI.BeginChangeCheck();
                    color.Color = EditorGUILayout.ColorField(color.Color);
                    if (EditorGUI.EndChangeCheck())
                    {
                        color.R = (byte)(color.Color.r * 255);
                        color.G = (byte)(color.Color.g * 255);
                        color.B = (byte)(color.Color.b * 255);
                    }

                    GUILayout.Space(2f);
                    EditorGUILayout.EndVertical();
                    GUILayout.Space(2f);
                }
            }

            EditorGUILayout.EndScrollView();
        }

        /// <summary>
        /// .acoファイルの色を取り出す
        /// </summary>
        static IEnumerable<ColorData> GetColors(Object aco)
        {
            // .acoのバイナリを取得
            byte[] b = ToBinary(aco);

            // 色の個数が入っている場所は b[3]
            int colorCount = b[3];

            // RGB値を取り出していく
            int pos = 6;
            for (int i = 0; i < colorCount; i++)
            {
                ColorData color = new ColorData();
                color.R = b[pos];
                color.G = b[pos + 2];
                color.B = b[pos + 4];
                color.Color = new Color(color.R, color.G, color.B, 255f) / 255f;
                yield return color;

                pos += 10;
            }
        }

        /// <summary>
        /// Assetをバイト列にする 
        /// </summary>
        static byte[] ToBinary(Object asset)
        {
            var split = AssetDatabase.GetAssetPath(asset).Split('/');
            var path = Application.dataPath + "/";
            for (int i = 1; i < split.Length - 1; i++)
            {
                path += split[i] + "/";
            }
            path += split[split.Length - 1];

            FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read);
            BinaryReader bin = new BinaryReader(fileStream);
            return bin.ReadBytes((int)bin.BaseStream.Length);
        }

        /// <summary>
        /// 色のデータ 
        /// </summary>
        [System.SerializableAttribute]
        public class ColorData
        {
            public byte R;
            public byte G;
            public byte B;
            public Color Color;
        }
    }
}
```

# ツールを動かす
画面上部のメニューの"Tools/Aco Importer"を選択するとウィンドウが開きます。
![image](https://qiita-image-store.s3.amazonaws.com/0/44288/7bf11024-726f-6b6c-13a7-3b71a5e181ed.png)


ウィンドウ上にacoファイルをドラッグアンドドロップしてImportボタンを押すと色のリストが表示されます。(完)
![aco_demo.gif](https://qiita-image-store.s3.amazonaws.com/0/44288/1d3ef6ed-3fd2-15e0-5b46-f495227020e0.gif)