HumanIK Effector Ctrl AnimationExporter/importer

HumanIKのコントローラーのRIGアニメーション作成は楽しいので昔のKeyFrameを新しいファイルに入れたいときに使う。

animでもatomでも持っていけなかったのでに作るしかないかーと思った。

どうしてもRigなので引っ張られている分ポーズがまんま持っていけるわけではないので確認と調整が必要、ポーズによってはそのまま使える

OKなポーズ

NGだったポーズ

ほとんどNGやないかい。まあ大体の大枠のポーズはインポートできてる。
膝のまがりとかがダメだった。

腰の位置にキーが入らないというかそこらへんが問題ある
HumanIKのHipはへんな記事があった。
HumanIKヒップエフェクターが壊れています
https://forums.cgsociety.org/t/humanik-hip-effector-broken/1583635/3
によると設定をデフォルトにすると直るとか直らないとか神のみぞ知るとか。。

まあとりあえずソース公開

HumanIK Effecter Ctrl Animation Exporter

import maya.cmds as cmds

class HumanIK_Effecter_Ctrl_AnimationExporter:
	def MainWay(self):

		selects=cmds.ls(sl=True)
		selectRef=selects[0]
		print("selectRef= "+selectRef)

		_CtrlIndex=selectRef.find("_Ctrl")
		print("_CtrlIndex= "+str(_CtrlIndex))

		SkeletonName=selectRef[0:_CtrlIndex]
		print("SkeletonName= "+SkeletonName)

		HipsCtrlName=SkeletonName+"_Ctrl_Hips"
		print("HipsCtrlName= "+HipsCtrlName)
		
		startFrame=185
		endFrame=206


		self.keyAllLineStr=""
		
		self.NodeAllLoop(selectRef,HipsCtrlName,startFrame,endFrame)
	
	def key_to_add_line(self,CtrlNode,Way,key_arr):
		if(str(key_arr)=="None"):
			pass
		else:
			 key_arr.insert(0, Way)
			 key_arr.insert(0, CtrlNode)
			 key_str_arr=[]
			 #1度数値を文字列に変換する
			 for v in key_arr:
				str_v=str(v)
				key_str_arr.append(str_v)
			 key_arr_str=",".join(key_str_arr)
			 
			 print("key_arr_str= "+key_arr_str)
			 self.keyAllLineStr=self.keyAllLineStr+key_arr_str+"\n"

	def NodeAllLoop(self,selectRef,HipsCtrlName,startFrame,endFrame):
		
		# 指定したノード以下全てを検索
		CtrlNodeAll=cmds.ls(HipsCtrlName,dag=1)
		#CtrlNodeAll=cmds.ls(selectRef,dag=1)
		print("CtrlNodeAll= "+str(CtrlNodeAll))
		
		CtrlNodeAll.insert(0,selectRef)
		
		for CtrlNode in CtrlNodeAll:
			keyFrameData=""
			#0〜20の時間範囲内のオブジェクト「surface1」のすべてのキーフレームをクエリします。
			#
			keyFrames_rx = cmds.keyframe( CtrlNode,at='rx', time=(startFrame,endFrame), query=True, valueChange=True, timeChange=True);
			keyFrames_ry = cmds.keyframe( CtrlNode,at='ry', time=(startFrame,endFrame), query=True, valueChange=True, timeChange=True);
			keyFrames_rz = cmds.keyframe( CtrlNode,at='rz', time=(startFrame,endFrame), query=True, valueChange=True, timeChange=True);
			
			self.key_to_add_line(CtrlNode,"rx",keyFrames_rx)
			self.key_to_add_line(CtrlNode,"ry",keyFrames_ry)
			self.key_to_add_line(CtrlNode,"rz",keyFrames_rz)
			#print("keyFrames_rx= "+str(keyFrames_rx))
			#print("keyFrames_ry= "+str(keyFrames_ry))
			#print("keyFrames_rz= "+str(keyFrames_rz))

			keyFrames_tx = cmds.keyframe( CtrlNode,at='tx', time=(startFrame,endFrame), query=True, valueChange=True, timeChange=True);
			keyFrames_ty = cmds.keyframe( CtrlNode,at='ty', time=(startFrame,endFrame), query=True, valueChange=True, timeChange=True);
			keyFrames_tz = cmds.keyframe( CtrlNode,at='tz', time=(startFrame,endFrame), query=True, valueChange=True, timeChange=True);
			#keyFrames=cmds.keyframe( sel、time =(185,206)、query = True、valueChange = True、timeChange = True);

			self.key_to_add_line(CtrlNode,"tx",keyFrames_tx)
			self.key_to_add_line(CtrlNode,"ty",keyFrames_ty)
			self.key_to_add_line(CtrlNode,"tz",keyFrames_tz)

			#print("keyFrames_tx= "+str(keyFrames_tx))
			#print("keyFrames_ty= "+str(keyFrames_ty))
			#print("keyFrames_tz= "+str(keyFrames_tz))
			
			keyFrames_sx = cmds.keyframe( CtrlNode,at='sx', time=(startFrame,endFrame), query=True, valueChange=True, timeChange=True);
			keyFrames_sy = cmds.keyframe( CtrlNode,at='sy', time=(startFrame,endFrame), query=True, valueChange=True, timeChange=True);
			keyFrames_sz = cmds.keyframe( CtrlNode,at='sz', time=(startFrame,endFrame), query=True, valueChange=True, timeChange=True);
			
			self.key_to_add_line(CtrlNode,"sx",keyFrames_sx)
			self.key_to_add_line(CtrlNode,"sy",keyFrames_sy)
			self.key_to_add_line(CtrlNode,"sz",keyFrames_sz)
			
		print("self.keyAllLineStr ="+ self.keyAllLineStr)
		self.fileWrite()
		
	def fileWrite(self):
		
		import codecs

		fout = codecs.open('C:/Users/whaison/Documents/maya/2016/ja_JP/scripts/python/MotionMerge/p030motionbuilder_chimera_0_Start/HumanIK_Effecter_Ctrl_AnimationExporter_keyFrameData.csv', 'w', 'utf_8')
		fout.write(self.keyAllLineStr)




ClassIns = HumanIK_Effecter_Ctrl_AnimationExporter()
ClassIns.MainWay()

HumanIK Effecter Ctrl Animation Importer

import maya.cmds as cmds

class HumanIK_Effecter_Ctrl_AnimationImporter:
	def MainWay(self):

		selects=cmds.ls(sl=True)
		selectRef=selects[0]
		print("selectRef= "+selectRef)

		_CtrlIndex=selectRef.find("_Ctrl")
		print("_CtrlIndex= "+str(_CtrlIndex))

		SkeletonName=selectRef[0:_CtrlIndex]
		print("SkeletonName= "+SkeletonName)

		HipsCtrlName=SkeletonName+"_Ctrl_Hips"
		print("HipsCtrlName= "+HipsCtrlName)
		
		startFrame=185
		endFrame=206


		self.keyAllLineStr=""
		
		#self.NodeAllLoop(HipsCtrlName,startFrame,endFrame,)
		
		self.fileReader()
		
		
	def fileReader(self):
		
		import codecs
		fin = codecs.open('C:/Users/whaison/Documents/maya/2016/ja_JP/scripts/python/MotionMerge/p030motionbuilder_chimera_0_Start/HumanIK_Effecter_Ctrl_AnimationExporter_keyFrameData.csv', 'r', 'utf_8')
		for line in fin:
			print("line= "+line)
			if(line==""):
				pass
			else:
				self.line_to_setkeyframe(line)
			
	
	def line_to_setkeyframe(self,line):
		key_arr=line.split(",")
		CtrlName=key_arr[0]
		print("CtrlName= "+CtrlName)
		Way=key_arr[1]
		print("Way= "+Way)
		key_arr_len=len(key_arr)
		frameStr=""
		valueStr=""
		for i in range(2,key_arr_len):
			val=key_arr[i]
			
			if i % 2 == 0:
				print('frame= '+val)
				frameStr=val
				framefloat=float(frameStr)
			else:
				print('Value= '+val)
				valueStr=val
				valuefloat=float(valueStr)
				print('cmds.setKeyframe( '+CtrlName+","+Way+",t="+str(framefloat)+",v="+str(valuefloat)+")")
				try:
					cmds.setKeyframe( CtrlName, attribute=Way, t=framefloat,v=valuefloat)
				except OSError as err:
					print("OS error: {0}".format(err))
				except ValueError:
					print("Could not convert data to an integer.")
				except:
					print("Unexpected error:", sys.exc_info()[0])
					raise
				
	
	def NodeAllLoop(self,HipsCtrlNam,startFrame,endFramee):
		
		# 指定したノード以下全てを検索
		CtrlNodeAll=cmds.ls(HipsCtrlName,dag=1)
		print("CtrlNodeAll= "+str(CtrlNodeAll))
		
		for CtrlNode in CtrlNodeAll:
			pass
"""
keyFrames_rx= [185.0, 21.089741780299963, 186.0, 21.15808805587963, 187.0, 21.57269253024709, 188.0, 15.651666434240237, 189.0, -27.60824368710669, 190.0, -66.8640151602632, 191.0, -3.6033652533432057, 192.0, -12.976039746033836, 193.0, 21.089741780299963, 206.0, 21.089741780299963]
keyFrames_ry= [185.0, 64.06950181042265, 186.0, -43.06801204369242, 187.0, -42.23534535644165, 188.0, 6.3003207259776, 189.0, -18.619267402281043, 190.0, -46.39726736167605, 191.0, 7.25455667934068, 192.0, 22.112923704038533, 193.0, 64.06950181042265, 206.0, 64.06950181042265]
keyFrames_rz= [185.0, -39.35273351243995, 186.0, -71.88505367073185, 187.0, -71.23919938208138, 188.0, -12.884469861914607, 189.0, -23.728143045065494, 190.0, 1.5441603410596807, 191.0, -29.38106191819622, 192.0, 27.959038658924545, 193.0, -39.35273351243995, 206.0, -39.35273351243995]

#tx
keyFrames_tx= [185.0, -31.063541412353516, 186.0, 13.386266787875757, 187.0, 12.569612782818957, 188.0, -68.13177446430325, 189.0, -14.078931727868042, 190.0, 34.98399964606946, 191.0, -58.035783944634446, 192.0, 38.62583642912938, 193.0, -31.063541412353516, 206.0, -31.063541412353516]
keyFrames_ty= [185.0, 103.91255187988281, 186.0, 160.48102799110984, 187.0, 135.33789404307092, 188.0, 123.42318340077544, 189.0, 143.61781646990772, 190.0, 162.44752777221774, 191.0, 147.59765966522042, 192.0, 149.99067818831213, 193.0, 103.91255187988281, 206.0, 103.91255187988281]
keyFrames_tz= [185.0, -13.255008697509766, 186.0, 126.81360281638925, 187.0, 114.12469622889218, 188.0, 62.25401426920391, 189.0, 116.16546039338427, 190.0, 124.82832123482547, 191.0, 79.97223357269715, 192.0, 43.964009286900165, 193.0, -13.255008697509766, 206.0, -13.255008697509766]

cmds.setKeyframe( 'group_meshHIK_TposeSK_Ctrl_Reference', attribute='translateX', t=186.0,v=-27.940739594423125,)
cmds.setKeyframe( 'group_meshHIK_TposeSK_Ctrl_Reference', attribute='rotationX', t=186.0,v=-27.940739594423125,)
cmds.setKeyframe( 'group_meshHIK_TposeSK_Ctrl_Reference', attribute='rx', t=186.0,v=-27.940739594423125,)

cmds.setKeyframe( 'group_meshHIK_TposeSK_Ctrl_RightArm', attribute='rx', t=185.0,v=21.15808805587963)
cmds.setKeyframe( 'group_meshHIK_TposeSK_Ctrl_RightArm', attribute='ry', t=185.0,v=-43.06801204369242)
cmds.setKeyframe( 'group_meshHIK_TposeSK_Ctrl_RightArm', attribute='rz', t=185.0,v=-71.88505367073185)
#translate
cmds.setKeyframe( 'group_meshHIK_TposeSK_Ctrl_RightWristEffector', attribute='tx', t=186.0,v= 13.386266787875757)
cmds.setKeyframe( 'group_meshHIK_TposeSK_Ctrl_RightWristEffector', attribute='ty', t=186.0,v=160.48102799110984)
cmds.setKeyframe( 'group_meshHIK_TposeSK_Ctrl_RightWristEffector', attribute='tz', t=186.0,v=126.81360281638925)
"""
ClassIns=HumanIK_Effecter_Ctrl_AnimationImporter()
ClassIns.MainWay()

スキンウェイトに詳しくなりたい2 deformerWeights コマンド

https://area.autodesk.jp/column/tutorial/maya_atoz/save-load-skin-weight/にあった最新のスキンウェイトのコピー方法

//XMLexport
deformerWeights -export -deformer “group_mesh|Mesh|Genesis8FemaleSkin” -format “XML” -path “C:/Download/Game/UE4_SK_Mannequin_Motions/scenes/OneTimeLine/” “Genesis8FemaleSkin.xml”;

//XMLimport
deformerWeights -import -method “index” -deformer “group_meshHIK|Mesh|Genesis8FemaleSkin” -path “C:/Download/Game/UE4_SK_Mannequin_Motions/scenes/OneTimeLine/” “Genesis8FemaleSkin.xml”;
skinCluster -e -forceNormalizeWeights “group_meshHIK|Mesh|Genesis8FemaleSkin”; // オプション設定でNormalize weightsがオンだった場合この行も実行。

Maya2016でだと
// エラー: line 1: 無効なフラグ ‘-format’ // になる。
Maya2020で試した
// エラー: line 2: 有効なデフォーマが見つかりません。 //

なんだろ。

モデルがわるかった。スキンバインドが壊れてた。ジョイント曲げても反応なし

スキンウェイトに詳しくなりたい copySkinWeights コマンド

スキンウェイトに詳しくなりたい
スキンウェイトの世界は自動化がまだ追いついてないっぽい。
スキンウェイトのコピーの中身は

copySkinWeights -sourceSkin skinCluster1 -destinationSkin skinCluster2 -noMirror;
http://me.autodesk.jp/wam/maya/docs/Maya2010/Commands/copySkinWeights.html

cmds.copySkinWeights( sourceSkin=’skinCluster1′, destinationSkin=’skinCluster2′, noMirror=True
http://me.autodesk.jp/wam/maya/docs/Maya2010/CommandsPython/copySkinWeights.html

解決できないエラー(モデルがわるかった。スキンバインド全体が壊れてた。)
cmds.copySkinWeights( sourceSkin=’group_mesh|Mesh|Genesis8FemaleSkin’, destinationSkin=’group_meshHIK|Mesh|Genesis8FemaleSkin’, noMirror=True )

エラー: line 1: RuntimeError: file line 1: skinCluster ノードは -sourceSkin/-ss フラグとともに指定する必要があります。 #

解決できないエラー(一般的)(モデルがわるかった。スキンバインド全体が壊れてた。)
copySkinWeights -noMirror -surfaceAssociation closestPoint -influenceAssociation closestJoint;
// 警告: line 0: スキン オブジェクトではないので ‘Genesis8FemaleSkinShape’ をスキップします。 //
// エラー: line 0: 1 つのソース スキンと 1 つの目的のスキン、もしくはソースと目的のスキン上のコンポーネントを選択する必要があります。 //

ーーーーーーーーーーーーーーーーー
Maya2020でも解決できていない様子、(モデルがわるかった。スキンバインド全体が壊れてた。)

copySkinWeights -noMirror -surfaceAssociation closestPoint -influenceAssociation closestJoint;
// 警告: line 0: スキン オブジェクトではないので ‘Genesis8FemaleSkinShape’ をスキップします。 //
// エラー: line 0: 1 つのソース スキンと 1 つの目的のスキン、もしくはソースと目的のスキン上のコンポーネントを選択する必要があります。 //

cmds.copySkinWeights( sourceSkin=’group_mesh|Mesh|Genesis8FemaleSkin’, destinationSkin=’group_meshHIK|Mesh|Genesis8FemaleSkin’, noMirror=True )
エラー: RuntimeError: file line 1: skinCluster ノードは -sourceSkin/-ss フラグとともに指定する必要があります。 #

copySkinWeightsはそのコマンドの処理の中で、skinClusterコマンドを使っているみたいで
その引数部分にsourceSkinがうまくわたせてないみたいに見える。

モデルがわるかった。スキンバインド全体が壊れてた。


これも関係ありそう。
skinClusterは、一度に1つのジオメトリのみをバインドします。したがって、複数のジオメトリをバインドするには、複数のskinClusterコマンドを発行する必要があります。

https://help.autodesk.com/cloudhelp/2016/ENU/Maya-Tech-Docs/Commands/skinCluster.html

一旦1つの裸ジオメトリのスキンウェイトにしておいてそれを複数の服にコピーしていく流れをやったらいいのかもな。
ーーーーーーーーーーーーーーーーーーーーー

ダメだった。
cmds.copySkinWeights( sourceSkin=’group_mesh|Mesh|Genesis8FemaleSkin’, destinationSkin=’group_meshHIK|Mesh|Genesis8FemaleSkin’, noMirror=True )
エラー: line 1: RuntimeError: file line 1: skinCluster ノードは -sourceSkin/-ss フラグとともに指定する必要があります。 #

copySkinWeights -noMirror -surfaceAssociation closestPoint -influenceAssociation closestJoint;
// 警告: line 0: スキン オブジェクトではないので ‘Genesis8FemaleSkinShape’ をスキップします。 //
// エラー: line 0: 1 つのソース スキンと 1 つの目的のスキン、もしくはソースと目的のスキン上のコンポーネントを選択する必要があります。 //

メッシュを追加するたびにスキンウェイトをやりなおす?その必要はないスキンウェイトのコピーはメッシュ単位。

メッシュを追加するたびにスキンウェイトをやりなおす?その必要はないスキンウェイトのコピーはメッシュ単位。

スキンウェイトの情報は.mb/.maシーンデータに入っているからシーンごと読み込むことが重要だ。

1,OldシーンにNewシーンを読み込んでOldキャラとNewキャラをそれぞれグループ化して並べる
2,見にくいけど、グループの座標は同じにしてから、
3,OldキャラとNewキャラを順に選択して、Skin > Edit Smooth Skin > Copy Skin Weights を実行したらうまくいった。

ついでに追加したメッシュが体に添うようなスキニーパンツやフィットしたスーツなら
体から服にスキンをコピーしてあげればびったり添う

曲げても平気

こんなに曲げても大丈夫

明日python書く予定は未定。

jointにSkinClusterがないと起こるエラー

jointにSkinClasterがないとなるエラー

The plug-in has found the following skin definition problems :
Unable to find the bind pose for : / SK_Mannequin / root / pelvis / spine_01 / spine_02 / spine_03 / clavicle_l / upperarm_l / lowerarm_l / hand_l / ring_01_l. No bind poses in the hierarchy containing the object will be exported.
Unable to find the bind pose for : / SK_Mannequin / root / pelvis / spine_01 / spine_02 / spine_03 / clavicle_r / upperarm_r / lowerarm_r / hand_r / middle_01_r / middle_02_r. No bind poses in the hierarchy containing the object will be exported.

これを解決するためにテストした

jointにSkinClusterがないとなるようで

たとえば下のように手のジョイントがSphereの外に突き出ている場合に

手のjointのSkinClusterがない状態になる。この状態でスキンバインドし保存し開きなおしてFBX出力するとエラーが出る。

このようにメッシュが外をカバーできていればエラーが出ない。

メッシュをスケールしjointを覆うだけでなおせる。。 下は読む必要がない。

もっと深堀してみると、、、、

このエラーがでるのは
BindPoseにはSkinClusterが必要だということになる。
SkinClusterなかったら、スキンバインド時にBindPoseは作られるがFBX出力時に怒られる
たぶんこのFBX exporter pluginが
SkinCluster経由で探したBindPoseがみつからないか?
・BindPoseのSkinClusterがないとこの「プラグインは、次のスキン定義の問題を発見しました。」と言っているのでBindPoseのSkin情報がないというのは問題になるみたいだ。


ノードエディタだと正常な場合こうJointノードにバインドポーズがあってBindPose1に接続されてる。

スキンクラスターがないノード
バインドポーズからピンがでていない


・jointのバインドポーズを直接BindPose1へノードエディタでつなげてみる
 →やってみたが、どのワールド行列につないだらよいかわからない。

もう少しシンプルなものでテストしてみたほうがいい。


下の例では
・gotoBindPose;をしても問題が出ない
・チャネルボックスエディタでもノードエディタでもBindPoseを持たないjointが存在。
・SkinClusterがなくても保存して開きなおしてFBX出力してもエラーが出ない。

一辺倒な言葉ではなにも語れないことがわかった。
jointがメッシュからはみ出ているなら 、だって骨が皮からはみ出ているなら問題あるでしょ。
・メッシュをかぶせる
・ジョイントをめり込ませるか
このめんどうな作業をやり直したほうがよさそうだ。

Maya Selected Node All Childs node disconnectAttr Loop

選択したノード以下のすべての接続を解除するループ

import maya.cmds as cmds
selectionNode=cmds.ls(sl=True)
# 指定したノード以下全てを検索
selectionNodes=cmds.ls(selectionNode,dag=1)
for node in selectionNodes:
	try:
		attribute1 =node+"_translateX.output"
		attribute2 =node+".translateX"
		cmds.disconnectAttr(attribute1, attribute2)
	except RuntimeError as err:
		pass
	

	try:
		attribute1 =node+"_translateY.output"
		attribute2 =node+".translateY"
		cmds.disconnectAttr(attribute1, attribute2)
	except RuntimeError as err:
		pass

	try:
		attribute1 =node+"_translateZ.output"
		attribute2 =node+".translateZ"
		cmds.disconnectAttr(attribute1, attribute2)
	except RuntimeError as err:
		pass

	try:
		attribute1 =node+"_rotateX.output"
		attribute2 =node+".rotateX"
		cmds.disconnectAttr(attribute1, attribute2)
	except RuntimeError as err:
		pass

	try:
		attribute1 =node+"_rotateY.output"
		attribute2 =node+".rotateY"
		cmds.disconnectAttr(attribute1, attribute2)
	except RuntimeError as err:
		pass

	try:
		attribute1 =node+"_rotateZ.output"
		attribute2 =node+".rotateZ"
		cmds.disconnectAttr(attribute1, attribute2)
	except RuntimeError as err:
		pass

	try:
		attribute1 =node+"_scaleX.output"
		attribute2 =node+".scaleX"
		cmds.disconnectAttr(attribute1, attribute2)
	except RuntimeError as err:
		pass

	try:
		attribute1 =node+"_scaleY.output"
		attribute2 =node+".scaleY"
		cmds.disconnectAttr(attribute1, attribute2)
	except RuntimeError as err:
		pass

	try:
		attribute1 =node+"_scaleZ.output"
		attribute2 =node+".scaleZ"
		cmds.disconnectAttr(attribute1, attribute2)
	except RuntimeError as err:
		pass

illustrator jsx でレイヤー表示3x5x6=90パターンpng24で書き出し

カラーの展開を納品確認するために90パターンをjsxで再現してpng24で書き出すスクリプトを書いた。

 メインのオブジェクトの色3色(ホワイト、ブラック、グリーン)
 文字5色(ホワイト、ブラック、グレー、グリーン、パープル) 
 背景6色(透明、ホワイト、ブラック、グレー、グリーン、パープル)

がほしいみたいなすごいこと言われて、マジかと思って。作りました。

//var folder = Folder.selectDialog();


//alert(  "filepath= "+filepath);

//var folder =filepath;
var document = app.activeDocument;


//if(document && folder)
if(document)
{  
  var options = new ExportOptionsPNG24();
  options.antiAliasing = true;
  options.transparency = true;
  options.artBoardClipping = true;
  options.verticalScale = 1413.4276;
  options.horizontalScale = 1413.4276;
  
  
  //alert(  "document.layers= "+document.layers);
  //配列グループの中にレイヤー番号を集める

  var kupuTopArr=[];

  for(var i=0; i<document.layers.length; ++i)
  {
	  layerName=document.layers[i].name;
	  if(layerName.indexOf( 'kupu_' )>-1)
		  kupuTopArr.push(i);
  }
  //alert(  "kupuTopArr= "+kupuTopArr);
  
  var kupuUnderArr=[];
  for(var i=0; i<document.layers.length; ++i)
  {
	  layerName=document.layers[i].name;
	  if(layerName.indexOf( 'kupuunder_' )>-1)
		  kupuUnderArr.push(i);
  }
  //alert(  "kupuUnderArr= "+kupuUnderArr);
  
  var fontArr=[];
  for(var i=0; i<document.layers.length; ++i)
  {
	  layerName=document.layers[i].name;
	  if(layerName.indexOf( 'font_' )>-1)
		  fontArr.push(i);
  }
  //alert(  "fontArr= "+fontArr);
  var bgArr=[];
  for(var i=0; i<document.layers.length; ++i)
  {
	  layerName=document.layers[i].name;
	  if(layerName.indexOf( 'bg_' )>-1)
		  bgArr.push(i);
  }
  //alert(  "bgArr= "+bgArr);
  
  //全パターンを出力
  //alert(  "kupuTopArr.length= "+kupuTopArr.length);
  for(var kupuTop_i=0; kupuTop_i<kupuTopArr.length; ++kupuTop_i)
  {
	  //alert(  "kupuTop_i= "+kupuTop_i);
	  
	  //他のkupu_レイヤーを非表示
	  hideArrAllLayers(kupuTopArr)

	  //今回のkupu_レイヤーを表示
	  var kupuTop_Laynum=kupuTopArr[kupuTop_i];
	  //alert(  "kupuTop_Laynum= "+kupuTop_Laynum);
	  document.layers[kupuTop_Laynum].visible = true;
	  
	  //他のkupuunderレイヤーを非表示
	  hideArrAllLayers(kupuUnderArr)

	  //今回のkupuunderレイヤーを表示
	  var kupuUnder_Laynum=kupuUnderArr[kupuTop_i];
	  //alert(  "kupuUnder_Laynum= "+kupuUnder_Laynum);
	  document.layers[kupuUnder_Laynum].visible = true;
	  
	  var kupuTop_Layer_Name=document.layers[kupuTop_Laynum].name+"";
	  //alert(  "kupuTop_Layer_Name= "+kupuTop_Layer_Name);
	  
	  
	  for(var font_i=0; font_i<fontArr.length; ++font_i)
	  {
			//他のfontレイヤーを非表示
			hideArrAllLayers(fontArr)
	  
		    //今回のfontイヤーを表示
			var font_Laynum=fontArr[font_i];
			//alert(  "kupuUnder_Laynum= "+kupuUnder_Laynum);
			document.layers[font_Laynum].visible = true;
			
			var font_Layer_Name=document.layers[font_Laynum].name+"";
			
			
			
			for(var bg_i=0; bg_i<bgArr.length; ++bg_i)
			{
				
				//他のbgレイヤーを非表示
				hideArrAllLayers(bgArr)
		  
				//今回のbgイヤーを表示
				var bg_Laynum=bgArr[bg_i];
				//alert(  "kupuUnder_Laynum= "+kupuUnder_Laynum);
				document.layers[bg_Laynum].visible = true;
				
				var bg_Layer_Name=document.layers[bg_Laynum].name+"";
					
				
			
				//Export -------------------------------------------------------------
				
				filepath=app.activeDocument.path.fsName.toString()+"";
				filepathArr = filepath.split('\\'); // ["apple", "banana", "orange"]
				filepath=filepathArr.join('/');
				
				var makedDirPath = mkdirp(filepath + '/nouhin/'+kupuTop_Layer_Name+'/'+font_Layer_Name+"");
				//alert("makedDirPath= "+makedDirPath);
		  
				var ExportfilePath = makedDirPath+kupuTop_Layer_Name+"_"+font_Layer_Name+"_"+bg_Layer_Name+".png"
				//alert(  "ExportfilePath= "+ExportfilePath);
		  
				var file = new File(ExportfilePath);
				document.exportFile(file,ExportType.PNG24,options);
			}
	  }
	  

	  
	  
	  
  }
  /*
  var n = document.layers.length;
  for(var i=0; i<n; ++i)
  {
    hideAllLayers();
    var layer = document.layers[i];
	alert(  "document.layers["+i+"].name= "+document.layers[i].name);
    layer.visible = true;

    //var file = new File(folder.fsName+"/"+layer.name+".png");
    var file = new File(filepath+"/"+layer.name+".png");

    document.exportFile(file,ExportType.PNG24,options);
  }
  */
  
  showAllLayers();
  
  
  alert(  " 処理が完了しました ");
}

function kupu_white_view(){
  forEach(document.layers, function(layer) {
	if(layer.name=="kupu_white"){
	   layer.visible = true;
	}
    layer.visible = false;
  });
}

function hideArrAllLayers(Arr)
{
	for(var i=0; i<Arr.length; ++i)
    {
		  var Laynum=Arr[i];
		  //alert(  "kupuTop_Laynum= "+kupuTop_Laynum);
		  document.layers[Laynum].visible = false;
	}
}

function hideAllLayers()
{
  forEach(document.layers, function(layer) {
    layer.visible = false;
  });
}

function showAllLayers()
{
  forEach(document.layers, function(layer) {
    layer.visible = true;
  });    
}

function forEach(collection, fn)
{
  var n = collection.length;
  for(var i=0; i<n; ++i)
  {
    fn(collection[i]);
  }
}

function mkdirp(path) {
    var fullPath = "";
    path = path.toString();
    var arr = path.split("/");
    for (var i = 0; i < arr.length; i++) {
        var folderName = arr[i];
        fullPath += folderName + "/";
        var folder = new Folder(fullPath);
        if (!folder.exists) folder.create();
    }
    return fullPath;
}