土屋つかさの技術ブログは今か無しか

土屋つかさが主にプログラミングについて語るブログです。

ダミーボタンUI素材ジェネレーターを作りたかった

 ゲームに限らないんですが、メニュー画面を実装する際、ひとまず仮で使うボタン画像の素材が欲しいという時がよくあります(……ありますよね?)。プロトタイプ制作時とか、まだレイアウトの仕様が決まっていないので各ボタンのサイズが決まっていないのだけど、ひとまず配置して、かつそのボタンを押せるようにしたいという時です(……ありますよね?)。

 画像はひとまず仮のサイズで、背景は単色で文字のみ書いてあれば良いのですが、ボタンが5個を超えたあたりで、この「仮のサイズで、背景は単色で文字のみ」の画像をいちいち作るのが土屋は非常にめんどくさい。しかも、このサイズをちょこちょこ変えたくなる。ついでにいえば、ボタン1つごとに、最低でも「通常時」「マウスオーバー時」「プッシュ時」の3種類が欲しいのです。

 以前からこれをバッチ処理で出来るようにしたいと思っていて、コマンドラインで動くツールを作ってみました。

using System.IO;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;

namespace ConsoleApp5
{
    [DataContract]
    internal class BoxData
    {
        [DataMember]
        internal string folder_path;
        [DataMember]
        internal string file_name;
        [DataMember]
        internal string[] text;

        [DataMember]
        internal int[] size;
        [DataMember]
        internal int[] color;

        public static BoxData[] ReadToObject(string json)
        {
            return deserializeJson<BoxData[]>(json);
        }

        public static T deserializeJson<T>(string result)
        {
            DataContractJsonSerializer jsonSer = new DataContractJsonSerializer(typeof(T));
            using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(result)))
            {
                ms.Position = 0;
                return (T)jsonSer.ReadObject(ms);
            }
        }
    }

    public class Program
    {
        static void Main(string[] args)
        {
            //テキストファイルの中身をすべて読み込む
            System.Text.Encoding enc = System.Text.Encoding.GetEncoding("utf-8");
            string str = System.IO.File.ReadAllText(args[0], enc);

            //JSONを解析してBoxData構造体配列を構築
            BoxData[] boxDataList = BoxData.ReadToObject(str);

            //BoxData構造体配列を巡回して画像を生成する
            foreach (var boxData in boxDataList)
            {
                int index = 0;
                foreach (var text in boxData.text)
                {
                    CreateBoxPng(
                        boxData.size[0], 
                        boxData.size[1],
                        text, 
                        boxData.file_name + "_" + index.ToString(), 
                        boxData.folder_path, 
                        boxData.color);
                    index++;
                }
            }
        }

        public static void CreateBoxPng(
            int width, 
            int height, 
            string text, 
            string file_name, 
            string folder_path, 
            int[] color)
        {
            //bitmapとDCを獲得
            Bitmap bmp = new Bitmap(width, height);
            var context = Graphics.FromImage(bmp);

            //塗りつぶす
            Color customColor = Color.FromArgb(color[0], color[1], color[2], color[3]);
            SolidBrush shadowBrush = new SolidBrush(customColor);
            context.FillRectangle(shadowBrush, 0, 0, width, height);

            //センタリング指定
            StringFormat stringFormat = new StringFormat();
            stringFormat.Alignment = StringAlignment.Center;
            stringFormat.LineAlignment = StringAlignment.Center;

            //フォントオブジェクトの作成
            Font fnt = new Font("MS UI Gothic", 20);
            //文字列をセンタリング、黒色で表示
            context.DrawString(text, fnt, Brushes.Black, width/2, height/2, stringFormat);

            //保存
            bmp.Save(folder_path + @"\" + file_name + ".png", ImageFormat.Png);


        }

    }
}

 幾つかの参照設定について、プロジェクトエクスプローラーから設定する必要があるみたいです(これたまにしかやらないのでちゃんと覚えない。いかんな……)。
 下記のようなjsonファイルを作って、引数として与えると画像が自動生成されます。

[
{
	"size": [512, 120],
	"color": [255, 255, 0, 0],
	"folder_path": "C:/Users/tsuchiya_tsukasa/source/repos/ConsoleApp5/ConsoleApp5/image",
	"file_name": "cross_mark1",
	"text": ["ボタン1", "ボタン2", "ボタン3", "ボタン4", "ボタン5"]
},
{
	"size": [512, 120],
	"color": [255, 0, 255, 0],
	"folder_path": "C:/Users/tsuchiya_tsukasa/source/repos/ConsoleApp5/ConsoleApp5/image",
	"file_name": "cross_mark2",
	"text": ["ボタン1", "ボタン2", "ボタン3", "ボタン4", "ボタン5"]
}
]

 本当は、ボタンにフチ取りしたり、テキストのサイズを変えられるようにしようとか考えていたんですが、作っている途中で「これjsonじゃなくて、csvに1ボタン=1行で、サイズやファイル名も愚直に1行ごとに書いた方が、トータルでは楽だな……?」と気づき、モチベが消失したのでここまでです。csv版も作るつもりですが、汎用性が低すぎるので公開はしない予定。