Skip to content

Instantly share code, notes, and snippets.

@ZuishoMyelin
Last active October 22, 2022 13:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ZuishoMyelin/b929700837d1a7798147cdbd4ed8e1d4 to your computer and use it in GitHub Desktop.
Save ZuishoMyelin/b929700837d1a7798147cdbd4ed8e1d4 to your computer and use it in GitHub Desktop.
※現状テクスチャの埋め込みは出来ますがdefファイルは反映されません プリファレンス->アドオンからpythonファイルを登録、blendファイル保存後、ファイル->エクスポートから実行
import bpy
import os
import shutil
import glob
# A_N_DISCARDシェーダーのハッシュ値
A_N_DISCARD_SHADER_ID = ''
bl_info = {
"name": "Blend2Bakin",
"author": "ZUISHO Myelin",
"version": (1, 0),
"blender": (3, 2, 2),
"location": "File > Export",
"description": "export to bakin",
"warning": "",
"support": "TESTING",
"wiki_url": "",
"tracker_url": "",
"category": ""
}
class SAMPLE_OT_Blend2Bakin(bpy.types.Operator):
bl_idname = "file.blend2bakin"
bl_label = "BlendToBakin"
bl_description = "bakin向けのモデルをエクスポートします"
bl_options = {'REGISTER', 'UNDO'}
# @brief GUIでメッセージを表示する
# @param [in] message メッセージ本文
# @param [in] tilte メッセージボックスのタイトル
# @param [in] icon 使用するアイコン
def ShowMessageBox(self, message = "", title = "Message Box", icon = 'INFO'):
def draw(self, context):
self.layout.label(text=message)
bpy.context.window_manager.popup_menu(draw, title = title, icon = icon)
# @brief RPGBakinのマテリアル設定ファイルを生成する
# @param [in] filepath 保存先のパス
def MakeBakinDefFile(self, filepath, filename):
with open(filepath + filename, mode='w') as f:
# 全てのメッシュオブジェクトを取得
for mesh_ob in [ob for ob in bpy.data.objects if ob.type == "MESH"]:
# 全てのマテリアルを取得
for mat_slot in set(mesh_ob.material_slots):
if not mat_slot.material:
continue
if not mat_slot.material.node_tree:
continue
# 全てのテクスチャを取得
tex_nodes = [n for n in mat_slot.material.node_tree.nodes if n.type == "TEX_IMAGE"]
# 共通
f.write("mtl " + str(mat_slot.material.name) + "\n")
# map_notex
if len(tex_nodes) == 0:
f.write("shader map_notex\n")
# a_n_discard
else:
f.write("shader a_n_discard " + A_N_DISCARD_SHADER_ID + "\n")
# マテリアルをPrincipled BSDFに差し替え(※fbxにテクスチャを埋め込むため)
mat = bpy.data.materials.new(str(mat_slot.material.name))
mat.use_nodes = True
bsdf = mat.node_tree.nodes["Principled BSDF"]
# メインテクスチャ
texImage1 = mat.node_tree.nodes.new('ShaderNodeTexImage')
texImage1.image = tex_nodes[0].image
texImage1.image.filepath = filepath + "texture/" + str(tex_nodes[0].image.name) + ".png"
texImage1.image.file_format = 'PNG'
texImage1.image.save()
mat.node_tree.links.new(bsdf.inputs['Base Color'], texImage1.outputs['Color'])
# ノーマルマップ
if len(tex_nodes) >= 3:
texImage2 = mat.node_tree.nodes.new('ShaderNodeTexImage')
texImage2.image = tex_nodes[2].image
texImage2.image.filepath = filepath + "texture/" + str(tex_nodes[2].image.name) + ".png"
texImage2.image.file_format = 'PNG'
texImage2.image.save()
mat.node_tree.links.new(bsdf.inputs['Normal'], texImage2.outputs['Color'])
mat_slot.material = mat
# 共通
f.write("emissiveBlink false\n")
f.write("emissiveBlinkSpeed 0.000000\n")
f.write("emissiveLinkBuildingLight false\n")
f.write("uscrollanim false\n")
f.write("vscrollanim false\n")
f.write("scrollanimspeed 0.000000 0.000000\n")
f.write("uvstepanim false\n")
f.write("uvstepanimparam 1 1 0 1.000000\n")
f.write("sortindex 0\n")
f.write("castshadow true\n")
f.write("cull back\n")
f.write("uvofs 0.000000 0.000000\n")
f.write("uvscl 1.000000 1.000000\n")
# map_notex
if len(tex_nodes) == 0:
f.write("color 1.000000 1.000000 1.000000\n")
f.write("roughness 0.900000\n")
f.write("metallic 0.000000\n")
f.write("specular 0.000000\n")
continue
# a_n_discard
else:
f.write("AMap " + str(tex_nodes[0].image.name) + ".png\n")
if len(tex_nodes) >= 3:
f.write("NMap " + str(tex_nodes[2].image.name) + ".png\n")
f.write("color 1.000000 1.000000 1.000000\n")
f.write("normalscl 1.000000\n")
# 共通
f.write("roughness 0.900000\n")
f.write("metallic 0.000000\n")
f.write("specular 0.000000\n")
f.write("discard_threshold 0.900000\n")
f.write("\n")
# テキストファイルから文字列を読み込む
with open(filepath + filename, 'r', encoding='utf-8') as a_file:
txt = a_file.read()
# 読み込んだ文字列のCR(\r)を削除する。
txt = txt.replace('\r', '')
# ファイルをバイナリモードで開く
with open(filepath + filename, 'wb') as a_file:
# 文字列をバイト列にして保存する
a_file.write(txt.encode('utf-8'))
def execute(self, context):
# 全てのオブジェクトを選択する
bpy.ops.object.select_all(action='SELECT')
# blendファイルのパス
blend_dirpath = os.path.dirname(bpy.data.filepath).replace("\\", "/")
# blendファイルのファイル名
blend_filename = os.path.basename(bpy.data.filepath)[:-6]
# 保存先ディレクトリのパス
export_dirpath = blend_dirpath + "/" + blend_filename
# 未保存の場合は処理を終了する
if not blend_dirpath:
self.ShowMessageBox("please save project file")
return
# 保存先ディレクトリの作成
try:
os.mkdir(export_dirpath)
except FileNotFoundError as e:
print(e)
self.ShowMessageBox(e)
return
# テクスチャの保存先ディレクトリの作成
try:
os.mkdir(export_dirpath + "/texture")
except FileNotFoundError as e:
print(e)
self.ShowMessageBox(e)
return
# RPGBakinの設定ファイルを出力
try:
self.MakeBakinDefFile(export_dirpath + "/", blend_filename + ".def")
except FileNotFoundError as e:
print(e)
self.ShowMessageBox(e)
return
# テクスチャをアンパック
# bpy.ops.file.unpack_all(method='WRITE_LOCAL')
# shutil.move(blend_dirpath + "/textures", export_dirpath + "/texture") # bakinとの紐づけ用
# for i in glob.glob(export_dirpath + "/texture/*"):
# shutil.copy(str(i), export_dirpath) # fbxとの紐づけ用
# fbxエクスポート
bpy.ops.export_scene.fbx(
filepath= export_dirpath + "/" + blend_filename + ".fbx",
check_existing=True,
filter_glob="*.fbx",
use_selection=True,
use_active_collection=False,
global_scale=1.00,
apply_unit_scale=True,
apply_scale_options='FBX_SCALE_NONE',
bake_space_transform=False,
object_types={'EMPTY', 'ARMATURE', 'MESH'},
use_mesh_modifiers=False,
use_mesh_modifiers_render=True,
mesh_smooth_type='OFF',
use_subsurf=False,
use_mesh_edges=False,
use_tspace=True,
use_custom_props=False,
add_leaf_bones=True,
primary_bone_axis='Y',
secondary_bone_axis='X',
use_armature_deform_only=False,
armature_nodetype='NULL',
bake_anim=True,
bake_anim_use_all_bones=True,
bake_anim_use_nla_strips=True,
bake_anim_use_all_actions=True,
bake_anim_force_startend_keying=True,
bake_anim_step=1.0,
bake_anim_simplify_factor=1.0,
path_mode='RELATIVE',
embed_textures=False,
batch_mode='OFF',
use_batch_own_dir=True,
use_metadata=True,
axis_forward='-Z',
axis_up='Y'
)
return {'FINISHED'}
def menu_fn(self, context):
self.layout.separator()
self.layout.operator(SAMPLE_OT_Blend2Bakin.bl_idname)
classes = [
SAMPLE_OT_Blend2Bakin,
]
def register():
for c in classes:
bpy.utils.register_class(c)
bpy.types.TOPBAR_MT_file_export.append(menu_fn)
def unregister():
bpy.types.TOPBAR_MT_file_export.remove(menu_fn)
for c in classes:
bpy.utils.unregister_class(c)
if __name__ == "__main__":
register()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment