ScreenPocket - 画面の隙間

Unityエンジニアの日々の雑記。たまにpython3、DirectX、PhotoshopScript(JavaScript)も触ります

大宮ゲーム開発部 もくもく会 第5回のお知らせ

9/1から毎週もくもく会を開いていましたが、とうとう継続して1ヶ月が経ちました。次回は土曜日。
atnd.org

大宮近郊在住のUnity使い方、もしいらっしゃれば一緒にモクモク作業いたしましょう!

大宮ゲーム開発部を作りたい…というか作ります。

今回の記事は、Unity関係ないです。
久々にCEDECに参加したのですが、一つ思ったこととして

・こういう勉強会や、もくもく会を埼玉でも開いて欲しい。
・いや、埼玉というよりもウチの近所(大宮、それも西側)で開いて欲しい

というのがあります。

ただ、現状特にそういった会を開く組織は無い(一番近いのは さいたまげーむす様 かも?)ようなので 大宮ゲーム開発部 という組織を作りたい…というか作ります。

・現状、部長は私で、部員も私のみです。
大宮ソフト様とは全く関係ございません。
・さいたまげーむす様とも全く関係ございません。
・その内、大宮(西側)でLT会とかもくもく会とかをしたい。

興味がある方はご連絡ください。
とりあえず今回は「大宮ゲーム開発部を作ったぞ」という言い出しっぺの表明として、記事にしておきます。

macにJenkinsをパッケージインストーラーからインストールし、初回起動時に「Offlineに見えます」と言われたときの解決方法

具体的なタイトル。Jenkinsのインストール後の流れの一部で躓いたのでブログに残しておきます。
Jenkinsのインストール

パスワードの入力を求められたときは、ターミナルで

sudo cat /Users/Shared/Jenkins/Home/secrets/initialAdminPassword


で、その後

This Jenkins instance appears to be offline

と言われてしまった時の対応。

stackoverflow.com
この記事にある通り、

/Users/Shared/Jenkins/Home/hudson.model.UpdateCenter.xml

のファイル内の https を http に書き換えて、Jenkinsを停止→起動とすることで解決できます。

停止、起動については下記の記事
qiita.com
に倣って

停止

sudo launchctl unload /Library/LaunchDaemons/org.jenkins-ci.plist

起動

sudo launchctl load /Library/LaunchDaemons/org.jenkins-ci.plist

とすることで停止→起動が可能になります。

ようやく家の環境に自動でPluginをインストールできました;

SmartObjectレイヤーの名前と、配置されたSmartObjectの4頂点の座標を一括出力するスクリプト

一晩寝て、ちょっと調べたら解決策があったので、もう一つ記事投稿しておきます

//SmartObjectの4頂点の座標を返す
function GetSmartObjectCorner()
{  
	try
	{  
		var r = new ActionReference();  
		r.putEnumerated( charIDToTypeID( "Lyr " ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );  
		var d;  
		try
		{
			d = executeActionGet(r);
		}
		catch (e)
		{
			alert(e);
			return;
		}  
	
		try
		{
			d = d.getObjectValue(stringIDToTypeID("smartObjectMore"));
		}
		catch (e)
		{
			alert(e);
			return;
		}
	
		try
		{
			d = d.getList(stringIDToTypeID("nonAffineTransform"));
		}
		catch (e)
		{
			alert(e);
			return;
		}
	
		var ret = [[d.getDouble(0),d.getDouble(1)],  
			[d.getDouble(2),d.getDouble(3)],  
			[d.getDouble(4),d.getDouble(5)],  
			[d.getDouble(6),d.getDouble(7)]];  
		return ret;
	}  
	catch (e)
	{
		alert(e);
	}  
}


//レイヤーを探す
//LayerSetだったら再帰で探す
function FindLayer( rootLayer, condition )
{
	var artLayers = [];
	var layers = rootLayer.layers;
	var length = layers.length;
	for ( var i = 0 ; i < length ; ++i )
	{
		var layer = layers[i];
		if ( layer.typename == "ArtLayer" )
		{
			if ( condition( layer ) )
			{
				artLayers.push(layer);
			}
		}
		else if ( layer.typename == "LayerSet" )
		{
			artLayers = artLayers.concat( FindLayer(layer, condition) );
		}
	}
	return artLayers;
}

//全てのArtLayerを取得したいときのCondition
function FindAlways( artLayer )
{
	return true;
}

//全てのArtLayerを取得したいときのCondition
function FindSmartObject( artLayer )
{
	return artLayer.kind == LayerKind.SMARTOBJECT;
}

//文字列(** px)となっているboundsをparseしてIntで返す
function GetIntBounds( artLayer )
{
	var intBounds = [];
	intBounds.push( parseInt(artLayer.bounds[0]) );
	intBounds.push( parseInt(artLayer.bounds[1]) );
	intBounds.push( parseInt(artLayer.bounds[2]) );
	intBounds.push( parseInt(artLayer.bounds[3]) );
	return intBounds;
}

function WriteLineSmartObjectCorner( f, artLayer )
{
	app.activeDocument.activeLayer = artLayer;
	f.write(artLayer.name+",");
	
	var corner = GetSmartObjectCorner();
	f.write(corner[0]+","+corner[1]+","+corner[2]+","+corner[3]);
	f.write("\n");
}

//処理メイン
function Main()
{	
	var activeDocument = app.activeDocument;
	if ( activeDocument == null )
	{
		return;
	}

	//初期設定
	var keepActiveLayer = activeDocument.activeLayer;
	var keepUnit = preferences.rulerUnits;
	preferences.rulerUnits = Units.PIXELS;//pixelユニットとする

	//ドキュメント名
	var documentName = activeDocument.name;

	var findLayers = FindLayer(activeDocument, FindSmartObject);
	var length = findLayers.length;
	if ( length == 0 )
	{
		preferences.rulerUnits = keepUnit;
		activeDocument.activeLayer = keepActiveLayer;
		alert("目的のレイヤーを発見できませんでした。");
		return;
	}

	var txtFile = File.openDialog("矩形情報Textファイルを出力します", "*.txt");
	if ( txtFile == null )
	{
		preferences.rulerUnits = keepUnit;
		activeDocument.activeLayer = keepActiveLayer;
		return;
	}

	var f = new File(txtFile);
	f.open('w');
	for ( var i = 0 ; i < length ; ++i )
	{
		WriteLineSmartObjectCorner(f, findLayers[i]);
	}
	f.close();
	
	//戻す
	preferences.rulerUnits = keepUnit;
	activeDocument.activeLayer = keepActiveLayer;
	
	//完了ダイアログ表示
	alert("出力が完了しました");
}

Main();

SmartObjectのScaleにも対応されているようなので、とりあえずこれで目的は達成されました。
これでアーティストに座標を聞きに行く手間が解消されるかな。

↓参考サイト
forums.adobe.com

SmartObjectレイヤーの名前を出力するPhotoshopスクリプト

ちょっと必要に迫られたので、スマートオブジェクトレイヤーの一覧をtxtファイルに一括出力するスクリプトを用意しました。

//レイヤーを探す
//LayerSetだったら再帰で探す
function FindLayer( rootLayer, condition )
{
	var artLayers = [];
	var layers = rootLayer.layers;
	var length = layers.length;
	for ( var i = 0 ; i < length ; ++i )
	{
		var layer = layers[i];
		if ( layer.typename == "ArtLayer" )
		{
			if ( condition( layer ) )
			{
				artLayers.push(layer);
			}
		}
		else if ( layer.typename == "LayerSet" )
		{
			artLayers = artLayers.concat( FindLayer(layer, condition) );
		}
	}
	return artLayers;
}

//SmartObjectのArtLayerを取得したいときのCondition
function FindSmartObject( artLayer )
{
	return artLayer.kind == LayerKind.SMARTOBJECT;
}

function WriteLine( f, artLayer )
{
	f.write(artLayer.name);
//情報を足したいときはここに
	f.write("\n");
}

//処理メイン
function Main()
{	
	var activeDocument = app.activeDocument;
	if ( activeDocument == null )
	{
		return;
	}

	//初期設定
	keepUnit = preferences.rulerUnits;
	preferences.rulerUnits = Units.PIXELS;//pixelユニットとする

	//ドキュメント名
	var documentName = activeDocument.name;

	var findLayers = FindLayer(activeDocument, FindSmartObject);
	var length = findLayers.length;
	if ( length == 0 )
	{
		preferences.rulerUnits = keepUnit;
		alert("目的のレイヤーを発見できませんでした。");
		return;
	}

	var txtFile = File.openDialog("矩形情報Textファイルを出力します", "*.txt");
	var f = new File(txtFile);
	f.open('w');
	for ( var i = 0 ; i < length ; ++i )
	{
		WriteLine(f, findLayers[i]);
	}
	f.close();
	
	//戻す
	preferences.rulerUnits = keepUnit;
	
	//完了ダイアログ表示
	alert("出力が完了しました");
}

Main();

本当はスマートオブジェクトのTransformも出力したかったけれどもAMCodeを呼ばなければいけないようなので、後ほどの宿題ということで。

SceneViewのカメラ位置を、特定のカメラ位置と合わせるコンポーネント

SceneViewのOverDrawやMipMapを確認する時に、結局現在のGameViewカメラで見た時の具合を確認したい時があります。
なので、特定のカメラの位置情報をSceneViewカメラに渡すためのコンポーネントを書いてみました。

#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;

namespace ScreenPocket
{
	/// <summary>
	/// カメラの位置をSceneViewのカメラに流し込む
	/// </summary>
	[DisallowMultipleComponent]
	[RequireComponent(typeof(Camera))]
	public class SyncSceneViewCamera : MonoBehaviour
	{
#if UNITY_EDITOR
		public bool isSync = false;

		void OnGUI()
		{
			if (!isSync)
			{
				return;
			}

			var view = SceneView.lastActiveSceneView;
			if ( view == null )
			{
				return;
			}

			var myTransform = transform;
			var forward = myTransform.forward;
			var myCamera = GetComponent<Camera>();

			view.pivot = myTransform.position + forward * myCamera.farClipPlane;
			view.rotation = Quaternion.LookRotation(forward);
			view.size = myCamera.farClipPlane;
			view.orthographic = myCamera.orthographic;
		}
#endif
	}
}

これで大体の見た目は合わせられます。
GameViewの位置サイズを取ってきてSceneViewの位置サイズも合わせようかと思いましたが、
エディタのレイアウトが崩れてしまったので、コレくらいの処理で止めておきます。