update virtools export
This commit is contained in:
parent
84b3ace13d
commit
52452a96d5
@ -57,6 +57,11 @@ class BBP_OT_export_virtools(bpy.types.Operator, UTIL_file_browser.ExportVirtool
|
|||||||
self.draw_virtools_params(layout)
|
self.draw_virtools_params(layout)
|
||||||
layout.prop(self, 'compress_level')
|
layout.prop(self, 'compress_level')
|
||||||
|
|
||||||
|
_TObj3dPair = tuple[bpy.types.Object, bmap.BM3dObject]
|
||||||
|
_TMeshPair = tuple[bpy.types.Object, bpy.types.Mesh, bmap.BMMesh]
|
||||||
|
_TMaterialPair = tuple[bpy.types.Material, bmap.BMMaterial]
|
||||||
|
_TTexturePair = tuple[bpy.types.Image, bmap.BMTexture]
|
||||||
|
|
||||||
def _export_virtools(file_name_: str, encodings_: tuple[str], compress_level_: int, export_objects: tuple[bpy.types.Object, ...]) -> None:
|
def _export_virtools(file_name_: str, encodings_: tuple[str], compress_level_: int, export_objects: tuple[bpy.types.Object, ...]) -> None:
|
||||||
# create temp folder
|
# create temp folder
|
||||||
with tempfile.TemporaryDirectory() as vt_temp_folder:
|
with tempfile.TemporaryDirectory() as vt_temp_folder:
|
||||||
@ -71,12 +76,18 @@ def _export_virtools(file_name_: str, encodings_: tuple[str], compress_level_: i
|
|||||||
# prepare progress reporter
|
# prepare progress reporter
|
||||||
with ProgressReport(wm = bpy.context.window_manager) as progress:
|
with ProgressReport(wm = bpy.context.window_manager) as progress:
|
||||||
# prepare 3dobject
|
# prepare 3dobject
|
||||||
obj3d_crets: tuple[tuple[bpy.types.Object, bmap.BM3dObject], ...] = _prepare_virtools_3dobjects(
|
obj3d_crets: tuple[_TObj3dPair, ...] = _prepare_virtools_3dobjects(
|
||||||
writer, progress, export_objects)
|
writer, progress, export_objects)
|
||||||
# export group and 3dobject by prepared 3dobject
|
# export group and 3dobject by prepared 3dobject
|
||||||
_export_virtools_groups(writer, progress, obj3d_crets)
|
_export_virtools_groups(writer, progress, obj3d_crets)
|
||||||
mesh_crets: tuple[tuple[bpy.types.Object, bpy.types.Mesh, bmap.BMMesh], ...] = _export_virtools_3dobjects(
|
mesh_crets: tuple[_TMeshPair, ...] = _export_virtools_3dobjects(
|
||||||
writer, progress, obj3d_crets)
|
writer, progress, obj3d_crets)
|
||||||
|
# export mesh
|
||||||
|
material_crets: tuple[_TMaterialPair, ...] = _export_virtools_meshes(
|
||||||
|
writer, progress, mesh_crets)
|
||||||
|
# export material
|
||||||
|
texture_crets: tuple[_TTexturePair, ...] = _export_virtools_materials(
|
||||||
|
writer, progress, material_crets)
|
||||||
|
|
||||||
|
|
||||||
# save document
|
# save document
|
||||||
@ -87,12 +98,12 @@ def _prepare_virtools_3dobjects(
|
|||||||
writer: bmap.BMFileWriter,
|
writer: bmap.BMFileWriter,
|
||||||
progress: ProgressReport,
|
progress: ProgressReport,
|
||||||
export_objects: tuple[bpy.types.Object]
|
export_objects: tuple[bpy.types.Object]
|
||||||
) -> tuple[tuple[bpy.types.Object, bmap.BM3dObject], ...]:
|
) -> tuple[_TObj3dPair, ...]:
|
||||||
# this function only create equvalent entries in virtools engine and do not export anything
|
# this function only create equvalent entries in virtools engine and do not export anything
|
||||||
# because _export_virtools_3dobjects() and _export_virtools_groups() are need use the return value of this function
|
# because _export_virtools_3dobjects() and _export_virtools_groups() are need use the return value of this function
|
||||||
|
|
||||||
# create 3dobject hashset and result
|
# create 3dobject hashset and result
|
||||||
obj3d_crets: list[tuple[bpy.types.Object, bmap.BM3dObject]] = []
|
obj3d_crets: list[_TObj3dPair] = []
|
||||||
obj3d_cret_set: set[bpy.types.Object] = set()
|
obj3d_cret_set: set[bpy.types.Object] = set()
|
||||||
# start saving
|
# start saving
|
||||||
progress.enter_substeps(len(export_objects), "Creating 3dObjects")
|
progress.enter_substeps(len(export_objects), "Creating 3dObjects")
|
||||||
@ -116,7 +127,7 @@ def _prepare_virtools_3dobjects(
|
|||||||
def _export_virtools_groups(
|
def _export_virtools_groups(
|
||||||
writer: bmap.BMFileWriter,
|
writer: bmap.BMFileWriter,
|
||||||
progress: ProgressReport,
|
progress: ProgressReport,
|
||||||
obj3d_crets: tuple[tuple[bpy.types.Object, bmap.BM3dObject], ...]
|
obj3d_crets: tuple[_TObj3dPair, ...]
|
||||||
) -> None:
|
) -> None:
|
||||||
# create virtools group
|
# create virtools group
|
||||||
group_cret_map: dict[str, bmap.BMGroup] = {}
|
group_cret_map: dict[str, bmap.BMGroup] = {}
|
||||||
@ -146,10 +157,10 @@ def _export_virtools_groups(
|
|||||||
def _export_virtools_3dobjects(
|
def _export_virtools_3dobjects(
|
||||||
writer: bmap.BMFileWriter,
|
writer: bmap.BMFileWriter,
|
||||||
progress: ProgressReport,
|
progress: ProgressReport,
|
||||||
obj3d_crets: tuple[tuple[bpy.types.Object, bmap.BM3dObject], ...]
|
obj3d_crets: tuple[_TObj3dPair, ...]
|
||||||
) -> tuple[tuple[bpy.types.Object, bpy.types.Mesh, bmap.BMMesh], ...]:
|
) -> tuple[_TMeshPair, ...]:
|
||||||
# create virtools mesh
|
# create virtools mesh
|
||||||
mesh_crets: list[tuple[bpy.types.Object, bpy.types.Mesh, bmap.BMMesh]] = []
|
mesh_crets: list[_TMeshPair] = []
|
||||||
mesh_cret_map: dict[bpy.types.Mesh, bmap.BMMesh] = {}
|
mesh_cret_map: dict[bpy.types.Mesh, bmap.BMMesh] = {}
|
||||||
# start saving
|
# start saving
|
||||||
progress.enter_substeps(len(obj3d_crets), "Saving 3dObjects")
|
progress.enter_substeps(len(obj3d_crets), "Saving 3dObjects")
|
||||||
@ -187,7 +198,143 @@ def _export_virtools_3dobjects(
|
|||||||
|
|
||||||
# leave progress and return
|
# leave progress and return
|
||||||
progress.leave_substeps()
|
progress.leave_substeps()
|
||||||
|
return tuple(mesh_crets)
|
||||||
|
|
||||||
|
def _export_virtools_meshes(
|
||||||
|
writer: bmap.BMFileWriter,
|
||||||
|
progress: ProgressReport,
|
||||||
|
mesh_crets: tuple[_TMeshPair, ...]
|
||||||
|
) -> tuple[_TMaterialPair, ...]:
|
||||||
|
# create virtools mesh
|
||||||
|
material_crets: list[_TMaterialPair] = []
|
||||||
|
material_cret_map: dict[bpy.types.Material, bmap.BMMaterial] = {}
|
||||||
|
# start saving
|
||||||
|
progress.enter_substeps(len(mesh_crets), "Saving Meshes")
|
||||||
|
|
||||||
|
# iterate meshes
|
||||||
|
for obj3d, mesh, vtmesh in mesh_crets:
|
||||||
|
# we need use temporary mesh function to visit triangulated meshes
|
||||||
|
# so we ignore mesh factor and use obj3d to create temp mesh to get data
|
||||||
|
# open temp mesh helper
|
||||||
|
with UTIL_blender_mesh.TemporaryMesh(obj3d) as tempmesh:
|
||||||
|
# sync mesh name, lit mode
|
||||||
|
vtmesh.set_name(mesh.name)
|
||||||
|
mesh_settings: PROP_virtools_mesh.RawVirtoolsMesh = PROP_virtools_mesh.get_raw_virtools_mesh(mesh)
|
||||||
|
vtmesh.set_lit_mode(mesh_settings.mLitMode)
|
||||||
|
|
||||||
|
# sync mesh main data
|
||||||
|
# open mesh visitor
|
||||||
|
with UTIL_blender_mesh.MeshReader(tempmesh.get_temp_mesh()) as mesh_visitor:
|
||||||
|
# construct data provider
|
||||||
|
def pos_iterator() -> typing.Iterator[UTIL_virtools_types.VxVector3]:
|
||||||
|
for v in mesh_visitor.get_vertex_position():
|
||||||
|
UTIL_virtools_types.vxvector3_conv_co(v)
|
||||||
|
yield v
|
||||||
|
def nml_iterator() -> typing.Iterator[UTIL_virtools_types.VxVector3]:
|
||||||
|
for v in mesh_visitor.get_vertex_normal():
|
||||||
|
UTIL_virtools_types.vxvector3_conv_co(v)
|
||||||
|
yield v
|
||||||
|
def uv_iterator() -> typing.Iterator[UTIL_virtools_types.VxVector2]:
|
||||||
|
for v in mesh_visitor.get_vertex_uv():
|
||||||
|
UTIL_virtools_types.vxvector2_conv_co(v)
|
||||||
|
yield v
|
||||||
|
|
||||||
|
# construct mtl slot
|
||||||
|
def mtl_iterator() -> typing.Iterator[bmap.BMMaterial | None]:
|
||||||
|
for mtl in mesh_visitor.get_material_slot():
|
||||||
|
if mtl is None: yield None
|
||||||
|
else:
|
||||||
|
# get existing one or create new one
|
||||||
|
vtmaterial: bmap.BMMaterial | None = material_cret_map.get(mtl, None)
|
||||||
|
if vtmaterial is None:
|
||||||
|
vtmaterial = writer.create_material()
|
||||||
|
material_crets.append((mtl, vtmaterial))
|
||||||
|
material_cret_map[mtl] = vtmaterial
|
||||||
|
# yield data
|
||||||
|
yield vtmaterial
|
||||||
|
|
||||||
|
def face_idx_iterator(idx_type: int) -> typing.Iterator[UTIL_virtools_types.CKFaceIndices]:
|
||||||
|
data: UTIL_virtools_types.CKFaceIndices = UTIL_virtools_types.CKFaceIndices()
|
||||||
|
for fidx in mesh_visitor.get_face():
|
||||||
|
# swap indices
|
||||||
|
fidx.conv_co()
|
||||||
|
# set data by specific index
|
||||||
|
match(idx_type):
|
||||||
|
case 0: data.i1, data.i2, data.i3 = fidx.mIndices[0].mPosIdx, fidx.mIndices[1].mPosIdx, fidx.mIndices[2].mPosIdx
|
||||||
|
case 1: data.i1, data.i2, data.i3 = fidx.mIndices[0].mNmlIdx, fidx.mIndices[1].mNmlIdx, fidx.mIndices[2].mNmlIdx
|
||||||
|
case 2: data.i1, data.i2, data.i3 = fidx.mIndices[0].mUvIdx, fidx.mIndices[1].mUvIdx, fidx.mIndices[2].mUvIdx
|
||||||
|
case _: raise UTIL_functions.BBPException('invalid index type.')
|
||||||
|
# yield data
|
||||||
|
yield data
|
||||||
|
def face_mtl_iterator() -> typing.Iterator[int]:
|
||||||
|
for fidx in mesh_visitor.get_face():
|
||||||
|
yield fidx.mMtlIdx
|
||||||
|
|
||||||
|
# create virtools mesh transition
|
||||||
|
# and write into mesh
|
||||||
|
with bmap.BMMeshTrans() as mesh_trans:
|
||||||
|
# prepare vertices
|
||||||
|
mesh_trans.prepare_vertex(
|
||||||
|
mesh_visitor.get_vertex_position_count(),
|
||||||
|
pos_iterator()
|
||||||
|
)
|
||||||
|
mesh_trans.prepare_normal(
|
||||||
|
mesh_visitor.get_vertex_normal_count(),
|
||||||
|
nml_iterator()
|
||||||
|
)
|
||||||
|
mesh_trans.prepare_uv(
|
||||||
|
mesh_visitor.get_vertex_uv_count(),
|
||||||
|
uv_iterator()
|
||||||
|
)
|
||||||
|
# prepare mtl slots
|
||||||
|
mesh_trans.prepare_mtl_slot(
|
||||||
|
mesh_visitor.get_material_slot_count(),
|
||||||
|
mtl_iterator()
|
||||||
|
)
|
||||||
|
# prepare face
|
||||||
|
mesh_trans.prepare_face(
|
||||||
|
mesh_visitor.get_face_count(),
|
||||||
|
face_idx_iterator(0),
|
||||||
|
face_idx_iterator(1),
|
||||||
|
face_idx_iterator(2),
|
||||||
|
face_mtl_iterator()
|
||||||
|
)
|
||||||
|
|
||||||
|
# parse to vtmesh
|
||||||
|
mesh_trans.parse(writer, vtmesh)
|
||||||
|
|
||||||
|
# end of mesh trans
|
||||||
|
# end of mesh visitor
|
||||||
|
# end of temp mesh
|
||||||
|
|
||||||
|
# step
|
||||||
|
progress.step()
|
||||||
|
|
||||||
|
# leave progress and return
|
||||||
|
progress.leave_substeps()
|
||||||
|
return tuple(material_crets)
|
||||||
|
|
||||||
|
def _export_virtools_materials(
|
||||||
|
writer: bmap.BMFileWriter,
|
||||||
|
progress: ProgressReport,
|
||||||
|
material_crets: tuple[_TMaterialPair, ...]
|
||||||
|
) -> tuple[_TTexturePair, ...]:
|
||||||
|
# create virtools mesh
|
||||||
|
texture_crets: list[_TTexturePair] = []
|
||||||
|
texture_cret_map: dict[bpy.types.Image, bmap.BMTexture] = {}
|
||||||
|
# start saving
|
||||||
|
progress.enter_substeps(len(material_crets), "Saving Materials")
|
||||||
|
|
||||||
|
for material, vtmaterial in material_crets:
|
||||||
|
# set name
|
||||||
|
vtmaterial.set_name(material.name)
|
||||||
|
|
||||||
|
# step
|
||||||
|
progress.step()
|
||||||
|
|
||||||
|
# leave progress and return
|
||||||
|
progress.leave_substeps()
|
||||||
|
return tuple(texture_crets)
|
||||||
|
|
||||||
def _save_virtools_document(
|
def _save_virtools_document(
|
||||||
writer: bmap.BMFileWriter,
|
writer: bmap.BMFileWriter,
|
||||||
|
@ -115,7 +115,11 @@ def _vxvector2_iterator(pvector: bmap.bm_VxVector2_p, count: int) -> typing.Iter
|
|||||||
idx += 2
|
idx += 2
|
||||||
yield ret
|
yield ret
|
||||||
|
|
||||||
def _ckfaceindices_assigner(pindices: bmap.bm_CKDWORD_p, count: int, itor: typing.Iterator[virtools_types.CKFaceIndices]) -> None:
|
# bmap.bm_CKWORD_p | bmap.bm_CKDWORD_p is just a type hint
|
||||||
|
# wo do not need distinguish them in code.
|
||||||
|
# because the type of pindices is decided by runtime.
|
||||||
|
|
||||||
|
def _ckfaceindices_assigner(pindices: bmap.bm_CKWORD_p | bmap.bm_CKDWORD_p, count: int, itor: typing.Iterator[virtools_types.CKFaceIndices]) -> None:
|
||||||
idx: int = 0
|
idx: int = 0
|
||||||
for _ in range(count):
|
for _ in range(count):
|
||||||
userindices: virtools_types.CKFaceIndices = next(itor)
|
userindices: virtools_types.CKFaceIndices = next(itor)
|
||||||
@ -124,7 +128,7 @@ def _ckfaceindices_assigner(pindices: bmap.bm_CKDWORD_p, count: int, itor: typin
|
|||||||
pindices[idx + 2] = userindices.i3
|
pindices[idx + 2] = userindices.i3
|
||||||
idx += 3
|
idx += 3
|
||||||
|
|
||||||
def _ckfaceindices_iterator(pindices: bmap.bm_CKDWORD_p, count: int) -> typing.Iterator[virtools_types.CKFaceIndices]:
|
def _ckfaceindices_iterator(pindices: bmap.bm_CKWORD_p | bmap.bm_CKDWORD_p, count: int) -> typing.Iterator[virtools_types.CKFaceIndices]:
|
||||||
ret: virtools_types.CKFaceIndices = virtools_types.CKFaceIndices()
|
ret: virtools_types.CKFaceIndices = virtools_types.CKFaceIndices()
|
||||||
idx: int = 0
|
idx: int = 0
|
||||||
for _ in range(count):
|
for _ in range(count):
|
||||||
@ -175,12 +179,12 @@ class BMObject(_AbstractCKObject):
|
|||||||
else:
|
else:
|
||||||
return name.value.decode(g_BMapEncoding)
|
return name.value.decode(g_BMapEncoding)
|
||||||
|
|
||||||
def set_name(self, name: str | None) -> None:
|
def set_name(self, name_: str | None) -> None:
|
||||||
name: bmap.bm_CKSTRING
|
name: bmap.bm_CKSTRING
|
||||||
if name is None:
|
if name_ is None:
|
||||||
name = bmap.bm_CKSTRING(0)
|
name = bmap.bm_CKSTRING(0)
|
||||||
else:
|
else:
|
||||||
name = bmap.bm_CKSTRING(name.encode(g_BMapEncoding))
|
name = bmap.bm_CKSTRING(name_.encode(g_BMapEncoding))
|
||||||
bmap.BMObject_SetName(self._get_pointer(), self._get_ckid(), name)
|
bmap.BMObject_SetName(self._get_pointer(), self._get_ckid(), name)
|
||||||
|
|
||||||
class BMTexture(BMObject):
|
class BMTexture(BMObject):
|
||||||
@ -415,8 +419,8 @@ class BMMesh(BMObject):
|
|||||||
bmap.BMMesh_GetLitMode(self._get_pointer(), self._get_ckid(), ctypes.byref(mode))
|
bmap.BMMesh_GetLitMode(self._get_pointer(), self._get_ckid(), ctypes.byref(mode))
|
||||||
return virtools_types.VXMESH_LITMODE(mode.value)
|
return virtools_types.VXMESH_LITMODE(mode.value)
|
||||||
|
|
||||||
def set_lit_mode(self, mode: virtools_types.VXMESH_LITMODE) -> None:
|
def set_lit_mode(self, mode_: virtools_types.VXMESH_LITMODE) -> None:
|
||||||
mode: bmap.bm_enum = bmap.bm_enum(mode.value)
|
mode: bmap.bm_enum = bmap.bm_enum(mode_.value)
|
||||||
bmap.BMMesh_SetLitMode(self._get_pointer(), self._get_ckid(), mode)
|
bmap.BMMesh_SetLitMode(self._get_pointer(), self._get_ckid(), mode)
|
||||||
|
|
||||||
def get_vertex_count(self) -> int:
|
def get_vertex_count(self) -> int:
|
||||||
@ -535,9 +539,9 @@ class BM3dObject(BMObject):
|
|||||||
ret.from_const(tuple(flat[i] for i in range(16)))
|
ret.from_const(tuple(flat[i] for i in range(16)))
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def set_world_matrix(self, mat: virtools_types.VxMatrix) -> None:
|
def set_world_matrix(self, mat_: virtools_types.VxMatrix) -> None:
|
||||||
# star syntax expand the tuple as the argument.
|
# star syntax expand the tuple as the argument.
|
||||||
mat: bmap.bm_VxMatrix = bmap.bm_VxMatrix(*(mat.to_const()))
|
mat: bmap.bm_VxMatrix = bmap.bm_VxMatrix(*(mat_.to_const()))
|
||||||
bmap.BM3dObject_SetWorldMatrix(self._get_pointer(), self._get_ckid(), mat)
|
bmap.BM3dObject_SetWorldMatrix(self._get_pointer(), self._get_ckid(), mat)
|
||||||
|
|
||||||
def get_current_mesh(self) -> BMMesh | None:
|
def get_current_mesh(self) -> BMMesh | None:
|
||||||
@ -819,7 +823,7 @@ class BMMeshTrans(_AbstractPointer):
|
|||||||
|
|
||||||
idx: int = 0
|
idx: int = 0
|
||||||
for _ in range(count):
|
for _ in range(count):
|
||||||
usermtl: BMMaterial = next(itor)
|
usermtl: BMMaterial | None = next(itor)
|
||||||
if usermtl is None:
|
if usermtl is None:
|
||||||
raw_ckid[idx] = g_InvalidCKID
|
raw_ckid[idx] = g_InvalidCKID
|
||||||
else:
|
else:
|
||||||
|
@ -24,12 +24,12 @@ class FaceVertexData():
|
|||||||
|
|
||||||
class FaceData():
|
class FaceData():
|
||||||
## @remark List or tuple. List is convenient for adding and removing
|
## @remark List or tuple. List is convenient for adding and removing
|
||||||
mIndices: tuple[FaceVertexData] | list[FaceVertexData]
|
mIndices: tuple[FaceVertexData, ...] | list[FaceVertexData]
|
||||||
## Face used material slot index
|
## Face used material slot index
|
||||||
# @remark If material slot is empty, or this face do not use material, set this value to 0.
|
# @remark If material slot is empty, or this face do not use material, set this value to 0.
|
||||||
mMtlIdx: int
|
mMtlIdx: int
|
||||||
|
|
||||||
def __init__(self, indices: tuple[FaceVertexData] | list[FaceVertexData] = tuple(), mtlidx: int = 0):
|
def __init__(self, indices: tuple[FaceVertexData, ...] | list[FaceVertexData] = tuple(), mtlidx: int = 0):
|
||||||
self.mIndices = indices
|
self.mIndices = indices
|
||||||
self.mMtlIdx = mtlidx
|
self.mMtlIdx = mtlidx
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user