Spine ファイルを一括で自動書き出し出来るツールを Mac の Automator で作ったら、仕事が捗りすぎた [作り方のレシピ公開]

プログラミング IT・プログラミング

※ 本記事にはプロモーションが含まれています。

こんにちは! ねこです。

Automator の Spine ファイル一括書き出しイメージ

先日、会社から Spine という 2Dアニメーションツールのファイルを大量に自動書き出ししたいという要望がありました。

こちら結構便利で汎用的に出来たので、せっかくだから皆さんにシェアしようと思っています。

しかし、会社で作ったものなので、それをそのまま公開する訳にもいきません。

ですので、今回は Spine 一括書き出しツールの作り方のレシピ公開をしようと思っています。

Mac の Automator の使い方から、 JavaScript を利用したプログラムの内容について順を追って説明します。それを見ながら自分で作ってしまうという試みです。

プログラムは苦手だというクリエーターの皆さんにも、こういう身近なものからプログラムを触るきっかけのひとつになれば幸いです。

ちなみに、Automator というツール。何気に日頃のルーチンワークを自動化してくれる便利ツールですので、これを機に色々なものを自動化するのも良いかもしれません。

流れとしては、まず一通りの手順を説明し、その通りに作っていただいてから解説を読んでいただく形にしたいなと思っています。

今回制作するものは、Spine ファイルを複数含むフォルダをドラッグ&ロドップしたらエクスポートファイルが書き出されている。というものを目指します。

まずは、使い方から

今回制作したい内容の使用方法を記載します。この動作になることを目標に制作していきましょう。

  1. Spine アプリケーションを開き、左上メニュー -> Export から、書き出し設定を行い Save ボタンを押し、json ファイルを保存します。

  2. 今回用意する Autometor アプリケーションファイル(任意の名前)に、書き出したいSpineデータが入ったフォルダ(複数可)をドラッグ&ドロップします。

  3. 選択ダイアログから 1. で用意した json ファイルを選択します。

  4. json ファイルと同階層に SpineExportFiles ディレクトリが生成され、書き出し(ファイルが存在していれば上書き)されます。

では、実際に作ってみましょう

まず、Application から、Automator を開いてください。

Automator アイコン

新規ファイル作成から、アプリケーションを選んで選択します。そうすると、ドラッグ&ドロップでファイルを取得できるようになります。

アプリケーションを選んで選択

開くと、このような画面が表示されます。作業の大まかな流れですが、左側にあるアクションから、欲しいアクションを右側に追加する形になります。

左側からアクションを選んで右に持っていく

まず、「ファイルとフォルダ」から「指定されたFinder項目を取得」を右側に追加してください。これはアプリケーションを制作する際は必ず必要になります。

追加ボタンを押し、テスト用フォルダを追加

この状態で右側の「実行」ボタンを押すと、結果ウインドウに上記で選択したフォルダが返ってきてるのが確認できると思います。

実行ボタンを押して確認

続いて、「フォルダの内容を取得」を追加し、「見つかった各サブフォルダからも取得」チェックボックスをオンにしてください。

この状態で実行すると、結果ウインドウにフォルダの中身が全て返ってきているのが確認できます。

フォルダ内容をすべて取得して確認

次に、Spine 書き出し設定が書かれた json ファイルを読み込めるようにするために「Finder項目の選択を求める」を追加し、タイプを「ファイル」にします。

この状態で「実行ボタン」を押すと、ダイアログが表示され、ファイルを選択すると、上記の内容の最後に選択したファイルが追加されます。

タイプをファイルに変更

最後に選んだファイルを元に、Spine ファイルの書き出しを行ます。「ユーティリティ」から「JavaScriptを実行」を選び、下記のソースコードをコピーして貼り付けます。

function run(input, parameters) {
	
	// 変数の初期化
	var app = Application.currentApplication();
	var paths = get_path_from_input (input);
	var export_setting_json_path = paths[paths.length - 1];
	var output_path = export_setting_json_path.split("/").reverse().slice(1).reverse().join("/") + "/SpineExportFiles";
	var spine_app_path = "/Applications/Spine/Spine.app/Contents/MacOS/Spine";
	var spine_paths = [];
	
	app.includeStandardAdditions = true;
	
	// Spineデータのみを抽出
	paths.forEach( function( path ) {
 	   if(path.match(/.spine/)) {
	   		spine_paths.push(path);
	   }
	});
	
	if(spine_paths.length == 0) {
		app.displayDialog("Spineファイルが入ったフォルダ(複数可)をドラッグ&ドロップしてください。");
		return false;
	}
	
	// エクスポートファイルの書き出し
	try {
		spine_paths.forEach( function( path ) {
 	   		var dir_or_file_names = path.split("/");
	   		var self_output_path = output_path;
	   		if(self_output_path.length >= 2) {
	   		   self_output_path += "/" + dir_or_file_names[dir_or_file_names.length - 2];
	   		}
	  		var cmd = spine_app_path + " --input " + path + " --output " + self_output_path + " --export " + export_setting_json_path;
	   
	   		app.doShellScript(cmd);
		});
	}
	catch(e) {
		app.displayDialog(e);
		return false;
	}
	
	// 結果の表示
	var success_log = "";
	if(spine_paths.length >= 10) {
		success_log += "計 " + spine_paths.length + " 個のエクスポートが完了しました。";
	}
	else {
		spine_paths.forEach( function( path ) {
			success_log += path.split("/").slice(-1)[0] + "\n";
		});
		success_log += "\nのエクスポートが完了しました。";
	}
	
	app.displayDialog(success_log);
	
	return true;
}

function get_path_from_input (input_obj) {
	var path_obj = String(input_obj).split(",");
	return path_obj;
}

ここまで制作したデータを任意の名前で保存します。そして、上記の使い方の通りに使用してみて、ちゃんと動くのを確認できたら完成です。

完成したときの Automator イメージ

プログラムの説明

プログラム内でエラーハンドリングや結果表示なども行っていますので、多少長くなっていますが、やっていることは下記の3つになります。

  1. ファイル一覧からエクスポート設定ファイルを取得
  2. ファイル一覧から Spine ファイルのみを抽出
  3. ファイルを Spine のコマンドラインから書き出し

また、Mac は 10.10 (Yosemite) 以降、Javascript (JXA) で、mac を操作できるようになっています。

以下、重要な部分のみ説明をしていきます。

function run(input, parameters) {

まず、Javascript を実行が呼び出されると、上記の run という関数が実行されます。

input 引数には、それより前に取得した内容(結果ウインドウで表示されているもの)が渡されます。

ただ、そのままですと、AppleScript の記述のリストが返ってきます。こちらは、String で型変換すると、コンマ区切りのファイルパスになりますので、以下の関数を作って呼び出しています。

function get_path_from_input (input_obj) {
	var path_obj = String(input_obj).split(",");
	return path_obj;
}

呼び出す前の input 引数データサンプルがこちら。

{
	file "Macintosh HD:Users:*****:Desktop:SpineDatas:Cat:",
	file "Macintosh HD:Users:*****:Desktop:SpineDatas:Cat:images:eye_close.png"
}

呼び出したあとの input 引数データサンプルがこちらになります。

{
	"/Users/*****/Desktop/SpineDatas/Cat",
	"/Users/*****/Desktop/SpineDatas/Cat/images/eye_close.png"
}

Spine の書き出しについては、Spine エクスポートのページにコマンドラインが記載されています。

Export: Spine [-i <project.spine>] [-o <path>] -e <path>
  Pack: Spine -i <path> -o <path> -p <name>

Export:
-i, --input   Path to Spine project file, overrides export settings JSON. 
-o, --output  Path to write export file(s), overrides export settings JSON. 
-e, --export  Path to export settings JSON file. 

コマンドの呼び出しについては、以下のコードで行えます。

var app = Application.currentApplication();
app.includeStandardAdditions = true;

var cmd = ""; // 文字列にシェルスクリプトを記述
app.doShellScript(cmd);

こちらの2行目については、無いとエラーになりますので、必ず呼んで下さい。

また、完了・エラーウインドウの表示は下記になります。2行目までは、コマンド呼び出し部分と同じものです。

var app = Application.currentApplication();
app.includeStandardAdditions = true;

app.displayDialog("表示したいテキスト");

最後に

触ってみてどうでしたでしょうか?

これを使って色々なものを自動化できるんだろうな。というアイデアが出ましたでしょうか?

もしプログラムが苦手な人でも、例えば、書き出し先のフォルダ名を変えたい時はどうすれば良いのかな。みたいな所から、少しづつアイデアがカタチに出来るようになると思います。

もしリクエストや要望がありましたら、是非ツイッターをフォローして頂いて、メッセージ下さい。気が向いたら対応したいと思ってます。