201 lines
8.1 KiB
Python
201 lines
8.1 KiB
Python
import bpy
|
|
import os
|
|
import sys
|
|
import traceback
|
|
import json
|
|
from mathutils import Vector
|
|
import numpy as np
|
|
|
|
|
|
TEST_SCENE_DIR = os.path.join(os.getcwd(), "assets/blender-2.80")
|
|
EXPORTED_DIR = os.path.join(os.getcwd(), ".")
|
|
|
|
def export_escn(out_file, config):
|
|
"""Fake the export operator call"""
|
|
import io_scene_godot
|
|
io_scene_godot.export(out_file, config)
|
|
|
|
def split_export(out_dir, config):
|
|
SOURCE_SCENE = os.path.join(os.getcwd(), "assets", "blender-2.80", "common-all.blend")
|
|
EXPORT_DIR = os.path.join(os.getcwd(), "assets", "blender-2.80", "exports")
|
|
SCENE_DIR = os.path.join(os.getcwd(), "assets", "blender-2.80")
|
|
CHARACTER_DIR = out_dir
|
|
SHAPES_PER_PART = 12
|
|
def make_part_list(shapes):
|
|
part_no = 0
|
|
ret = {}
|
|
part_shapes = []
|
|
for k in shapes:
|
|
if len(part_shapes) < SHAPES_PER_PART:
|
|
part_shapes.append(k)
|
|
else:
|
|
fn = "common_part%d.blend" % (part_no)
|
|
ret[fn] = part_shapes
|
|
part_shapes = [k]
|
|
part_no += 1
|
|
ret["common_part%d.blend" % (part_no)] = part_shapes
|
|
return ret
|
|
|
|
base_config = config
|
|
shape_list = []
|
|
result_data = {}
|
|
if os.path.exists(os.path.join(CHARACTER_DIR, "data.json")):
|
|
result_data = json.load(open(os.path.join(CHARACTER_DIR, "data.json")))
|
|
result_data["files"] = []
|
|
# bpy.ops.wm.open_mainfile(filepath=config["source"])
|
|
if not os.path.exists(EXPORT_DIR):
|
|
os.makedirs(EXPORT_DIR)
|
|
|
|
for shape_key_iter in bpy.data.objects["base"].data.shape_keys.key_blocks:
|
|
if shape_key_iter.name != "Basis":
|
|
shape_list.append(shape_key_iter.name)
|
|
split_list = make_part_list(shape_list)
|
|
for fn in split_list.keys():
|
|
bpy.ops.wm.save_mainfile(filepath=os.path.join(EXPORT_DIR, fn), check_existing=False)
|
|
for fn in split_list.keys():
|
|
bpy.ops.wm.open_mainfile(filepath=os.path.join(EXPORT_DIR, fn))
|
|
for ob in bpy.data.objects:
|
|
if ob.name == "base" or ob.name.endswith("_helper"):
|
|
for shape_key_iter in ob.data.shape_keys.key_blocks:
|
|
if not shape_key_iter.name in split_list[fn] + ["Basis"]:
|
|
ob.shape_key_remove(shape_key_iter)
|
|
bpy.ops.wm.save_mainfile(filepath=os.path.join(EXPORT_DIR, fn), check_existing=False)
|
|
out_path = os.path.join(
|
|
CHARACTER_DIR,
|
|
fn.replace('.blend', '.escn')
|
|
)
|
|
export_escn(out_path, base_config)
|
|
result_data["files"].append(os.path.join("characters", "common", fn.replace('.blend', '.escn')))
|
|
print("Exported to {}".format(os.path.abspath(out_path)))
|
|
fd = open(os.path.join(CHARACTER_DIR, "data.json"), "w")
|
|
fd.write(json.dumps(result_data, indent=4, sort_keys=True))
|
|
fd.close()
|
|
print("Exported to {}".format(os.path.abspath(out_path)))
|
|
|
|
def main():
|
|
dir_queue = list()
|
|
dir_queue.append('.')
|
|
while dir_queue:
|
|
dir_relpath = dir_queue.pop(0)
|
|
|
|
# read config file if present, otherwise use default
|
|
src_dir_path = os.path.join(TEST_SCENE_DIR, dir_relpath)
|
|
if os.path.exists(os.path.join(src_dir_path, "config.json")):
|
|
with open(os.path.join(src_dir_path, "config.json")) as config_file:
|
|
base_config = json.load(config_file)
|
|
else:
|
|
base_config = {
|
|
"outpath": "exports",
|
|
"collections": [],
|
|
"split": False,
|
|
"use_visible_objects": True,
|
|
"use_export_selected": False,
|
|
"use_mesh_modifiers": True,
|
|
"use_exclude_ctrl_bone": False,
|
|
"use_export_animation": True,
|
|
"use_export_material": True,
|
|
"material_mode": "SPATIAL",
|
|
"use_export_shape_key": True,
|
|
"use_stashed_action": True,
|
|
"use_beta_features": True,
|
|
"generate_external_material": False,
|
|
"animation_modes": "ACTIONS",
|
|
"object_types": ["EMPTY", "LIGHT", "ARMATURE", "GEOMETRY"]
|
|
}
|
|
|
|
# create exported to directory
|
|
exported_dir_path = os.path.join(EXPORTED_DIR, dir_relpath)
|
|
if not os.path.exists(exported_dir_path):
|
|
os.makedirs(exported_dir_path)
|
|
|
|
for item in os.listdir(os.path.join(TEST_SCENE_DIR, dir_relpath)):
|
|
item_abspath = os.path.join(TEST_SCENE_DIR, dir_relpath, item)
|
|
if os.path.isdir(item_abspath):
|
|
# push dir into queue for later traversal
|
|
dir_queue.append(os.path.join(dir_relpath, item))
|
|
elif item_abspath.endswith('blend'):
|
|
config = {}
|
|
for k, v in base_config.items():
|
|
if k == "object_types":
|
|
config[k] = set(v)
|
|
else:
|
|
config[k] = v
|
|
cpath = item_abspath.replace('.blend', '.json')
|
|
if os.path.exists(cpath):
|
|
_config = json.load(open(cpath))
|
|
for k, v in _config.items():
|
|
if k == "object_types":
|
|
config[k] = set(v)
|
|
else:
|
|
config[k] = v
|
|
if "skip" in config and config["skip"]:
|
|
continue
|
|
# export blend file
|
|
print("---------")
|
|
print("Exporting {}".format(os.path.abspath(item_abspath)))
|
|
bpy.ops.wm.open_mainfile(filepath=item_abspath)
|
|
dirpath = os.path.join(EXPORTED_DIR,
|
|
dir_relpath,
|
|
config["outpath"]
|
|
)
|
|
if not os.path.exists(dirpath):
|
|
os.makedirs(dirpath, 0o755, True)
|
|
|
|
out_path = os.path.join(
|
|
EXPORTED_DIR,
|
|
dir_relpath,
|
|
config["outpath"],
|
|
item.replace('.blend', '.escn')
|
|
)
|
|
if config["split"]:
|
|
config["source"] = item_abspath
|
|
out_path = os.path.join(
|
|
EXPORTED_DIR,
|
|
dir_relpath,
|
|
config["outpath"]
|
|
)
|
|
split_export(out_path, config)
|
|
elif len(config["collections"]) > 0:
|
|
for cur_col in config["collections"]:
|
|
col_keep = {}
|
|
for c in bpy.data.collections:
|
|
col_keep[c.name] = c.hide_viewport
|
|
if c.name == cur_col:
|
|
c.hide_viewport = False
|
|
elif c.name in config["collections"]:
|
|
c.hide_viewport = True
|
|
out_path = os.path.join(
|
|
EXPORTED_DIR,
|
|
dir_relpath,
|
|
config["outpath"],
|
|
item.replace('.blend', '') + "_" + cur_col + ".escn"
|
|
)
|
|
export_escn(out_path, config)
|
|
for c in bpy.data.collections:
|
|
c.hide_viewport=col_keep[c.name]
|
|
print("Exported to {}".format(os.path.abspath(out_path)))
|
|
else:
|
|
out_path = os.path.join(
|
|
EXPORTED_DIR,
|
|
dir_relpath,
|
|
config["outpath"],
|
|
item.replace('.blend', '.escn')
|
|
)
|
|
export_escn(out_path, config)
|
|
print("Exported to {}".format(os.path.abspath(out_path)))
|
|
|
|
|
|
def run_with_abort(function):
|
|
"""Runs a function such that an abort causes blender to quit with an error
|
|
code. Otherwise, even a failed script will allow the Makefile to continue
|
|
running"""
|
|
try:
|
|
function()
|
|
except:
|
|
traceback.print_exc()
|
|
exit(1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
run_with_abort(main)
|