update export module into bm 1.1

This commit is contained in:
yyc12345 2020-08-07 10:41:50 +08:00
parent da4f07f37a
commit 034f1e55aa

View File

@ -42,7 +42,7 @@ class ExportBM(bpy.types.Operator, bpy_extras.io_utils.ExportHelper):
) )
def execute(self, context): def execute(self, context):
export_bm(context, self.filepath, self.export_mode, self.export_target, "") #todo: fix no_component_suffix export_bm(context, self.filepath, self.export_mode, self.export_target)
return {'FINISHED'} return {'FINISHED'}
@ -254,8 +254,20 @@ def import_bm(context,filepath,externalTexture,blenderTempFolder):
# object # object
fobject = open(os.path.join(tempFolder, "object.bm"), "rb") fobject = open(os.path.join(tempFolder, "object.bm"), "rb")
# we need get needed collection first
view_layer = context.view_layer view_layer = context.view_layer
collection = view_layer.active_layer_collection.collection collection = view_layer.active_layer_collection.collection
if prefs.no_component_collection == "":
forcedCollection = None
else:
try:
forcedCollection = bpy.data.collections[prefs.no_component_collection]
except:
forcedCollection = bpy.data.collections.new(prefs.no_component_collection)
view_layer.active_layer_collection.collection.children.link(forcedCollection)
# start process it
for item in objectList: for item in objectList:
fobject.seek(item.offset, os.SEEK_SET) fobject.seek(item.offset, os.SEEK_SET)
@ -276,9 +288,12 @@ def import_bm(context,filepath,externalTexture,blenderTempFolder):
obj = bpy.data.objects.new(item.name, neededMesh) obj = bpy.data.objects.new(item.name, neededMesh)
obj.matrix_world = object_worldMatrix obj.matrix_world = object_worldMatrix
obj.hide_viewport = object_isHidden obj.hide_viewport = object_isHidden
# todo: finish forced collection grouping
collection.objects.link(obj)
if (not object_isComponent) and object_isForcedNoComponent and (forcedCollection != None):
forcedCollection.objects.link(obj)
else:
collection.objects.link(obj)
fobject.close() fobject.close()
view_layer.update() view_layer.update()
@ -293,27 +308,23 @@ def export_bm(context,filepath,export_mode, export_target, no_component_suffix):
# tempFolder = "G:\\ziptest" # tempFolder = "G:\\ziptest"
tempTextureFolder = os.path.join(tempFolder, "Texture") tempTextureFolder = os.path.join(tempFolder, "Texture")
os.makedirs(tempTextureFolder) os.makedirs(tempTextureFolder)
prefs = bpy.context.preferences.addons[__package__].preferences
# ============================================ find export target # ============================================ find export target. don't need judge them in there. just collect them
if export_mode== "COLLECTION": if export_mode== "COLLECTION":
objectList = bpy.data.collections[export_target].objects objectList = bpy.data.collections[export_target].objects
else: else:
objectList = [bpy.data.objects[export_target]] objectList = [bpy.data.objects[export_target]]
needSuffixChecker = no_component_suffix != "" # try get forcedCollection
componentObj = set() try:
for obj in objectList: forcedCollection = bpy.data.collections[prefs.no_component_collection]
if needSuffixChecker and obj.name.endwith(no_component_suffix): except:
pass # meshObjList.add(obj) forcedCollection = None
else:
if is_component(obj.name):
componentObj.add(obj)
else:
pass # meshObjList.add(obj)
# ============================================ export # ============================================ export
finfo = open(os.path.join(tempFolder, "index.bm"), "wb") finfo = open(os.path.join(tempFolder, "index.bm"), "wb")
finfo.write(struct.pack("I", bm_current_version)) write_uint32(finfo, bm_current_version)
# ====================== export object # ====================== export object
fobject = open(os.path.join(tempFolder, "object.bm"), "wb") fobject = open(os.path.join(tempFolder, "object.bm"), "wb")
@ -325,14 +336,21 @@ def export_bm(context,filepath,export_mode, export_target, no_component_suffix):
if obj.type != 'MESH': if obj.type != 'MESH':
continue continue
varis_component = obj in componentObj
# clean no mesh object # clean no mesh object
currentMesh = obj.data currentMesh = obj.data
if currentMesh == None: if currentMesh == None:
continue continue
# judge component
object_isComponent = is_component(obj.name)
object_isForcedNoComponent = False
if (forcedCollection != None) and (obj.name in forcedCollection.objects):
# change it to forced no component
object_isComponent = False
object_isForcedNoComponent = True
# triangle first and then group # triangle first and then group
if not varis_component: if not object_isComponent:
if currentMesh not in meshSet: if currentMesh not in meshSet:
mesh_triangulate(currentMesh) mesh_triangulate(currentMesh)
meshSet.add(currentMesh) meshSet.add(currentMesh)
@ -341,19 +359,23 @@ def export_bm(context,filepath,export_mode, export_target, no_component_suffix):
meshCount += 1 meshCount += 1
else: else:
meshId = meshList.index(currentMesh) meshId = meshList.index(currentMesh)
else:
meshId = get_component_id(obj.name)
# get visibility
object_isHidden = obj.hide_viewport
# write finfo first # write finfo first
write_string(finfo, obj.name) write_string(finfo, obj.name)
write_int(finfo, info_bm_type.OBJECT) write_uint32(finfo, info_bm_type.OBJECT)
write_long(finfo, fobject.tell()) write_uint64(finfo, fobject.tell())
# write fobject # write fobject
write_int(fobject, 1 if varis_component else 0) write_bool(fobject, object_isComponent)
write_bool(fobject, object_isForcedNoComponent)
write_bool(fobject, object_isHidden)
write_worldMatrix(fobject, obj.matrix_world) write_worldMatrix(fobject, obj.matrix_world)
if varis_component: write_uint32(fobject, meshId)
write_int(fobject, get_component_id(obj.name))
else:
write_int(fobject, meshId)
fobject.close() fobject.close()
@ -366,13 +388,13 @@ def export_bm(context,filepath,export_mode, export_target, no_component_suffix):
# write finfo first # write finfo first
write_string(finfo, mesh.name) write_string(finfo, mesh.name)
write_int(finfo, info_bm_type.MESH) write_uint32(finfo, info_bm_type.MESH)
write_long(finfo, fmesh.tell()) write_uint64(finfo, fmesh.tell())
# write fmesh # write fmesh
# vertices # vertices
vecList = mesh.vertices[:] vecList = mesh.vertices[:]
write_int(fmesh, len(vecList)) write_uint32(fmesh, len(vecList))
for vec in vecList: for vec in vecList:
#swap yz #swap yz
write_3vector(fmesh,vec.co[0],vec.co[2],vec.co[1]) write_3vector(fmesh,vec.co[0],vec.co[2],vec.co[1])
@ -380,7 +402,7 @@ def export_bm(context,filepath,export_mode, export_target, no_component_suffix):
# uv # uv
face_index_pairs = [(face, index) for index, face in enumerate(mesh.polygons)] face_index_pairs = [(face, index) for index, face in enumerate(mesh.polygons)]
uv_layer = mesh.uv_layers.active.data[:] uv_layer = mesh.uv_layers.active.data[:]
write_int(fmesh, len(face_index_pairs) * 3) write_uint32(fmesh, len(face_index_pairs) * 3)
for f, f_index in face_index_pairs: for f, f_index in face_index_pairs:
# it should be triangle face, otherwise throw a error # it should be triangle face, otherwise throw a error
if (f.loop_total != 3): if (f.loop_total != 3):
@ -392,7 +414,7 @@ def export_bm(context,filepath,export_mode, export_target, no_component_suffix):
write_2vector(fmesh, uv[0], -uv[1]) write_2vector(fmesh, uv[0], -uv[1])
# normals # normals
write_int(fmesh, len(face_index_pairs) * 3) write_uint32(fmesh, len(face_index_pairs) * 3)
for f, f_index in face_index_pairs: for f, f_index in face_index_pairs:
# no need to check triangle again # no need to check triangle again
for loop_index in range(f.loop_start, f.loop_start + f.loop_total): for loop_index in range(f.loop_start, f.loop_start + f.loop_total):
@ -409,7 +431,7 @@ def export_bm(context,filepath,export_mode, export_target, no_component_suffix):
materialSet.add(mat) materialSet.add(mat)
materialList.append(mat) materialList.append(mat)
write_int(fmesh, len(face_index_pairs)) write_uint32(fmesh, len(face_index_pairs))
vtIndex = [] vtIndex = []
vnIndex = [] vnIndex = []
vIndex = [] vIndex = []
@ -438,8 +460,8 @@ def export_bm(context,filepath,export_mode, export_target, no_component_suffix):
vIndex[0], vtIndex[0], vnIndex[0]) vIndex[0], vtIndex[0], vnIndex[0])
# set used material # set used material
write_int(fmesh, 0 if noMaterial else 1) write_bool(fmesh, not noMaterial)
write_int(fmesh, usedMat) write_uint32(fmesh, usedMat)
mesh.free_normals_split() mesh.free_normals_split()
@ -454,19 +476,28 @@ def export_bm(context,filepath,export_mode, export_target, no_component_suffix):
for material in materialList: for material in materialList:
# write finfo first # write finfo first
write_string(finfo, material.name) write_string(finfo, material.name)
write_int(finfo, info_bm_type.MATERIAL) write_uint32(finfo, info_bm_type.MATERIAL)
write_long(finfo, fmaterial.tell()) write_uint64(finfo, fmaterial.tell())
# write basic color # try get original written data
material_colAmbient = try_get_custom_property(material, 'virtools-ambient')
material_colDiffuse = try_get_custom_property(material, 'virtools-diffuse')
material_colSpecular = try_get_custom_property(material, 'virtools-specular')
material_colEmissive = try_get_custom_property(material, 'virtools-emissive')
material_specularPower = try_get_custom_property(material, 'virtools-power')
# get basic color
mat_wrap = node_shader_utils.PrincipledBSDFWrapper(material) mat_wrap = node_shader_utils.PrincipledBSDFWrapper(material)
if mat_wrap: if mat_wrap:
use_mirror = mat_wrap.metallic != 0.0 use_mirror = mat_wrap.metallic != 0.0
if use_mirror: if use_mirror:
write_3vector(fmaterial, mat_wrap.metallic, mat_wrap.metallic, mat_wrap.metallic) set_value_when_none(material_colAmbient, (mat_wrap.metallic, mat_wrap.metallic, mat_wrap.metallic))
else: else:
write_3vector(fmaterial, 1, 1, 1) set_value_when_none(material_colAmbient, (1.0, 1.0, 1.0))
write_3vector(fmaterial, mat_wrap.base_color[0], mat_wrap.base_color[1], mat_wrap.base_color[2]) set_value_when_none(material_colDiffuse, (mat_wrap.base_color[0], mat_wrap.base_color[1], mat_wrap.base_color[2]))
write_3vector(fmaterial, mat_wrap.specular, mat_wrap.specular, mat_wrap.specular) set_value_when_none(material_colSpecular, (mat_wrap.specular, mat_wrap.specular, mat_wrap.specular))
set_value_when_none(material_colEmissive, mat_wrap.emission_color[:3])
set_value_when_none(material_specularPower, 0.0)
# confirm texture # confirm texture
tex_wrap = getattr(mat_wrap, "base_color_texture", None) tex_wrap = getattr(mat_wrap, "base_color_texture", None)
@ -482,24 +513,35 @@ def export_bm(context,filepath,export_mode, export_target, no_component_suffix):
else: else:
currentTexture = textureList.index(image) currentTexture = textureList.index(image)
write_int(fmaterial, 1) material_useTexture = True
write_int(fmaterial, currentTexture) material_texture = currentTexture
else: else:
# no texture # no texture
write_int(fmaterial, 0) material_useTexture = False
write_int(fmaterial, 0) material_texture = 0
else: else:
# no texture # no texture
write_int(fmaterial, 0) material_useTexture = False
write_int(fmaterial, 0) material_texture = 0
else: else:
# no Principled BSDF. write garbage # no Principled BSDF. write garbage
write_3vector(fmaterial, 0.8, 0.8, 0.8) set_value_when_none(material_colAmbient, (0.8, 0.8, 0.8))
write_3vector(fmaterial, 0.8, 0.8, 0.8) set_value_when_none(material_colDiffuse, (0.8, 0.8, 0.8))
write_3vector(fmaterial, 0.8, 0.8, 0.8) set_value_when_none(material_colSpecular, (0.8, 0.8, 0.8))
write_int(fmaterial, 0) set_value_when_none(material_colEmissive, (0.8, 0.8, 0.8))
write_int(fmaterial, 0) set_value_when_none(material_specularPower, 0.0)
material_useTexture = False
material_texture = 0
write_color(fmaterial, material_colAmbient)
write_color(fmaterial, material_colDiffuse)
write_color(fmaterial, material_colSpecular)
write_color(fmaterial, material_colEmissive)
write_float(fmaterial, material_specularPower)
write_bool(fmaterial, material_useTexture)
write_uint32(fmaterial, material_texture)
fmaterial.close() fmaterial.close()
@ -511,8 +553,8 @@ def export_bm(context,filepath,export_mode, export_target, no_component_suffix):
for texture in textureList: for texture in textureList:
# write finfo first # write finfo first
write_string(finfo, texture.name) write_string(finfo, texture.name)
write_int(finfo, info_bm_type.TEXTURE) write_uint32(finfo, info_bm_type.TEXTURE)
write_long(finfo, ftexture.tell()) write_uint64(finfo, ftexture.tell())
# confirm internal # confirm internal
texture_filepath = io_utils.path_reference(texture.filepath, source_dir, tempTextureFolder, texture_filepath = io_utils.path_reference(texture.filepath, source_dir, tempTextureFolder,
@ -520,10 +562,10 @@ def export_bm(context,filepath,export_mode, export_target, no_component_suffix):
filename = os.path.basename(texture_filepath) filename = os.path.basename(texture_filepath)
write_string(ftexture, filename) write_string(ftexture, filename)
if (is_external_texture(filename)): if (is_external_texture(filename)):
write_int(ftexture, 1) write_bool(ftexture, True)
else: else:
# copy internal texture, if this file is copied, do not copy it again # copy internal texture, if this file is copied, do not copy it again
write_int(ftexture, 0) write_bool(ftexture, False)
if filename not in existed_texture: if filename not in existed_texture:
shutil.copy(texture_filepath, os.path.join(tempTextureFolder, filename)) shutil.copy(texture_filepath, os.path.join(tempTextureFolder, filename))
existed_texture.add(filename) existed_texture.add(filename)
@ -604,6 +646,16 @@ def mesh_triangulate(me):
bm.to_mesh(me) bm.to_mesh(me)
bm.free() bm.free()
def try_get_custom_property(obj, field):
try:
cache = obj[field]
except:
return None
def set_value_when_none(obj, newValue):
if obj == None:
obj = newValue
# ======================================================================================= file io assistant # ======================================================================================= file io assistant
# import # import
@ -654,15 +706,27 @@ def read_face(fs):
def write_string(fs,str): def write_string(fs,str):
count=len(str) count=len(str)
write_int(fs,count) write_uint32(fs,count)
fs.write(str.encode("utf_32_le")) fs.write(str.encode("utf_32_le"))
def write_int(fs,num): def write_uint8(fs,num):
fs.write(struct.pack("B", num))
def write_uint32(fs,num):
fs.write(struct.pack("I", num)) fs.write(struct.pack("I", num))
def write_long(fs,num): def write_uint64(fs,num):
fs.write(struct.pack("Q", num)) fs.write(struct.pack("Q", num))
def write_bool(fs,boolean):
if boolean:
write_uint8(fs, 1)
else:
write_uint8(fs, 0)
def write_float(fs,fl):
fs.write(struct.pack("f", fl))
def write_worldMatrix(fs, matt): def write_worldMatrix(fs, matt):
mat = matt.transposed() mat = matt.transposed()
fs.write(struct.pack("ffffffffffffffff", fs.write(struct.pack("ffffffffffffffff",
@ -674,6 +738,9 @@ def write_worldMatrix(fs, matt):
def write_3vector(fs, x, y ,z): def write_3vector(fs, x, y ,z):
fs.write(struct.pack("fff", x, y ,z)) fs.write(struct.pack("fff", x, y ,z))
def write_color(fs, colors):
write_3vector(fs, colors[0], colors[1], colors[2])
def write_2vector(fs, u, v): def write_2vector(fs, u, v):
fs.write(struct.pack("ff", u, v)) fs.write(struct.pack("ff", u, v))