2025-01-03 23:42:44 +08:00
|
|
|
import bpy, mathutils
|
2023-11-09 21:41:26 +08:00
|
|
|
from bpy_extras.wm_utils.progress_report import ProgressReport
|
2023-11-10 12:26:04 +08:00
|
|
|
import tempfile, os, typing
|
2023-11-16 22:41:03 +08:00
|
|
|
from . import PROP_preferences, UTIL_ioport_shared
|
2024-04-01 14:39:11 +08:00
|
|
|
from . import UTIL_virtools_types, UTIL_functions, UTIL_file_browser, UTIL_blender_mesh, UTIL_ballance_texture, UTIL_naming_convension
|
2025-01-03 09:36:32 +08:00
|
|
|
from . import PROP_virtools_group, PROP_virtools_material, PROP_virtools_mesh, PROP_virtools_texture, PROP_virtools_light, PROP_ballance_map_info
|
2023-11-09 17:20:57 +08:00
|
|
|
from .PyBMap import bmap_wrapper as bmap
|
2023-10-18 21:23:04 +08:00
|
|
|
|
2024-12-30 17:53:42 +08:00
|
|
|
class BBP_OT_import_virtools(bpy.types.Operator, UTIL_file_browser.ImportVirtoolsFile, UTIL_ioport_shared.ImportParams, UTIL_ioport_shared.VirtoolsParams, UTIL_ioport_shared.BallanceParams):
|
2023-10-18 21:23:04 +08:00
|
|
|
"""Import Virtools File"""
|
|
|
|
bl_idname = "bbp.import_virtools"
|
|
|
|
bl_label = "Import Virtools File"
|
|
|
|
bl_options = {'PRESET', 'UNDO'}
|
2025-01-11 21:36:11 +08:00
|
|
|
bl_translation_context = 'BBP_OT_import_virtools'
|
2023-10-18 21:23:04 +08:00
|
|
|
|
|
|
|
@classmethod
|
2025-01-03 09:36:32 +08:00
|
|
|
def poll(cls, context):
|
2023-11-09 17:20:57 +08:00
|
|
|
return (
|
|
|
|
PROP_preferences.get_raw_preferences().has_valid_blc_tex_folder()
|
|
|
|
and bmap.is_bmap_available())
|
2023-10-18 21:23:04 +08:00
|
|
|
|
|
|
|
def execute(self, context):
|
2025-01-08 20:20:10 +08:00
|
|
|
# check whether encoding list is empty to avoid real stupid user.
|
|
|
|
encodings = self.general_get_vt_encodings(context)
|
|
|
|
if len(encodings) == 0:
|
|
|
|
self.report({'ERROR'}, 'You must specify at least one encoding for file loading (e.g. cp1252, gb2312)!')
|
|
|
|
return {'CANCELLED'}
|
|
|
|
|
2023-11-09 17:20:57 +08:00
|
|
|
_import_virtools(
|
|
|
|
self.general_get_filename(),
|
2025-01-08 20:20:10 +08:00
|
|
|
encodings,
|
2024-01-04 10:35:52 +08:00
|
|
|
self.general_get_conflict_resolver()
|
2023-11-09 17:20:57 +08:00
|
|
|
)
|
2023-10-18 21:23:04 +08:00
|
|
|
self.report({'INFO'}, "Virtools File Importing Finished.")
|
|
|
|
return {'FINISHED'}
|
|
|
|
|
2023-11-16 22:41:03 +08:00
|
|
|
def draw(self, context):
|
|
|
|
layout = self.layout
|
2024-12-30 17:53:42 +08:00
|
|
|
self.draw_import_params(layout)
|
2025-01-08 20:20:10 +08:00
|
|
|
self.draw_virtools_params(context, layout, True)
|
2024-12-30 17:53:42 +08:00
|
|
|
self.draw_ballance_params(layout, True)
|
2023-11-16 22:41:03 +08:00
|
|
|
|
2024-01-04 10:35:52 +08:00
|
|
|
def _import_virtools(file_name_: str, encodings_: tuple[str], resolver: UTIL_ioport_shared.ConflictResolver) -> None:
|
2023-11-09 17:20:57 +08:00
|
|
|
# create temp folder
|
|
|
|
with tempfile.TemporaryDirectory() as vt_temp_folder:
|
2025-01-12 15:15:29 +08:00
|
|
|
tr_text: str = bpy.app.translations.pgettext_rpt(
|
|
|
|
'Virtools Engine Temporary Directory: {0}', 'BBP_OT_import_virtools/execute')
|
|
|
|
print(tr_text.format(vt_temp_folder))
|
2023-11-10 12:26:04 +08:00
|
|
|
|
2023-11-09 17:20:57 +08:00
|
|
|
# create virtools reader context
|
|
|
|
with bmap.BMFileReader(
|
2023-11-09 21:41:26 +08:00
|
|
|
file_name_,
|
|
|
|
vt_temp_folder,
|
|
|
|
PROP_preferences.get_raw_preferences().mBallanceTextureFolder,
|
|
|
|
encodings_) as reader:
|
|
|
|
|
|
|
|
# prepare progress reporter
|
|
|
|
with ProgressReport(wm = bpy.context.window_manager) as progress:
|
|
|
|
# import textures
|
|
|
|
texture_cret_map: dict[bmap.BMTexture, bpy.types.Image] = _import_virtools_textures(
|
2024-01-04 10:35:52 +08:00
|
|
|
reader, progress, resolver)
|
2023-11-09 21:41:26 +08:00
|
|
|
# import materials
|
|
|
|
material_cret_map: dict[bmap.BMMaterial, bpy.types.Material] = _import_virtools_materials(
|
2024-01-04 10:35:52 +08:00
|
|
|
reader, progress, resolver, texture_cret_map)
|
2023-11-09 21:41:26 +08:00
|
|
|
# import meshes
|
|
|
|
mesh_cret_map: dict[bmap.BMMesh, bpy.types.Mesh] = _import_virtools_meshes(
|
2024-01-04 10:35:52 +08:00
|
|
|
reader, progress, resolver, material_cret_map)
|
2023-11-09 21:41:26 +08:00
|
|
|
# import 3dobjects
|
|
|
|
obj3d_cret_map: dict[bmap.BM3dObject, bpy.types.Object] = _import_virtools_3dobjects(
|
2024-01-04 10:35:52 +08:00
|
|
|
reader, progress, resolver, mesh_cret_map)
|
2025-01-03 09:36:32 +08:00
|
|
|
# import light
|
|
|
|
_import_virtools_lights(reader, progress, resolver)
|
2023-11-09 21:41:26 +08:00
|
|
|
# import groups
|
|
|
|
_import_virtools_groups(reader, progress, obj3d_cret_map)
|
|
|
|
|
|
|
|
def _import_virtools_textures(
|
|
|
|
reader: bmap.BMFileReader,
|
2024-01-04 10:35:52 +08:00
|
|
|
progress: ProgressReport,
|
|
|
|
resolver: UTIL_ioport_shared.ConflictResolver
|
2023-11-09 21:41:26 +08:00
|
|
|
) -> dict[bmap.BMTexture, bpy.types.Image]:
|
|
|
|
# create map
|
|
|
|
texture_cret_map: dict[bmap.BMTexture, bpy.types.Image] = {}
|
|
|
|
progress.enter_substeps(reader.get_texture_count(), "Loading Textures")
|
|
|
|
|
|
|
|
# create another temp folder for raw data virtools texture importing
|
|
|
|
with tempfile.TemporaryDirectory() as rawdata_temp:
|
2025-01-12 15:15:29 +08:00
|
|
|
tr_text: str = bpy.app.translations.pgettext_rpt(
|
|
|
|
'Texture Raw Data Temporary Directory: {0}', 'BBP_OT_import_virtools/execute')
|
|
|
|
print(tr_text.format(rawdata_temp))
|
2023-11-09 21:41:26 +08:00
|
|
|
|
|
|
|
for vttexture in reader.get_textures():
|
2024-01-04 10:35:52 +08:00
|
|
|
tex_cret: typing.Callable[[], bpy.types.Image]
|
2023-11-15 23:05:00 +08:00
|
|
|
texpath_to_load: str | None = vttexture.get_file_name()
|
|
|
|
|
|
|
|
# if no assoc file path (what? but it is real happended)
|
|
|
|
# this is invalid image, create a blank image instead
|
|
|
|
if texpath_to_load is None:
|
2024-01-04 10:35:52 +08:00
|
|
|
tex_cret = lambda: bpy.data.images.new("", 1, 1)
|
2023-11-09 21:41:26 +08:00
|
|
|
else:
|
2023-11-15 23:05:00 +08:00
|
|
|
# if this image is raw data, save it in external folder before loading
|
|
|
|
# the attribute of raw data saving is the file path is not absolute path
|
|
|
|
if not os.path.isabs(texpath_to_load):
|
|
|
|
texpath_to_load = os.path.join(
|
|
|
|
rawdata_temp,
|
|
|
|
os.path.basename(texpath_to_load)
|
|
|
|
)
|
|
|
|
vttexture.save_image(texpath_to_load)
|
|
|
|
|
|
|
|
# detect whether it is ballance texture and load
|
2023-11-23 22:34:06 +08:00
|
|
|
try_blc_tex: str | None = UTIL_ballance_texture.get_ballance_texture_filename(texpath_to_load)
|
2023-11-15 23:05:00 +08:00
|
|
|
|
2024-01-04 10:35:52 +08:00
|
|
|
if try_blc_tex is not None:
|
2023-11-15 23:05:00 +08:00
|
|
|
# load as ballance texture
|
2024-01-04 10:35:52 +08:00
|
|
|
tex_cret = lambda: UTIL_ballance_texture.load_ballance_texture(typing.cast(str, try_blc_tex))
|
2023-11-15 23:05:00 +08:00
|
|
|
else:
|
|
|
|
# load as other textures
|
2024-01-04 10:35:52 +08:00
|
|
|
tex_cret = lambda: UTIL_ballance_texture.load_other_texture(typing.cast(str, texpath_to_load))
|
|
|
|
|
|
|
|
# create real texture by tex cret fct
|
|
|
|
(tex, init_tex) = resolver.create_texture(
|
|
|
|
UTIL_virtools_types.virtools_name_regulator(vttexture.get_name()),
|
|
|
|
tex_cret
|
|
|
|
)
|
|
|
|
|
|
|
|
# init tex if needed
|
|
|
|
if init_tex:
|
|
|
|
# set texture cfg
|
|
|
|
rawtex: PROP_virtools_texture.RawVirtoolsTexture = PROP_virtools_texture.RawVirtoolsTexture()
|
|
|
|
rawtex.mSaveOptions = vttexture.get_save_options()
|
|
|
|
rawtex.mVideoFormat = vttexture.get_video_format()
|
|
|
|
PROP_virtools_texture.set_raw_virtools_texture(tex, rawtex)
|
|
|
|
|
|
|
|
# insert it to map
|
2023-11-09 21:41:26 +08:00
|
|
|
texture_cret_map[vttexture] = tex
|
|
|
|
|
|
|
|
# inc steps
|
|
|
|
progress.step()
|
|
|
|
|
|
|
|
# leave progress and return map
|
|
|
|
progress.leave_substeps()
|
|
|
|
return texture_cret_map
|
|
|
|
|
|
|
|
def _import_virtools_materials(
|
|
|
|
reader: bmap.BMFileReader,
|
2024-01-04 10:35:52 +08:00
|
|
|
progress: ProgressReport,
|
|
|
|
resolver: UTIL_ioport_shared.ConflictResolver,
|
2023-11-09 21:41:26 +08:00
|
|
|
texture_cret_map: dict[bmap.BMTexture, bpy.types.Image]
|
|
|
|
) -> dict[bmap.BMMaterial, bpy.types.Material]:
|
|
|
|
# create map and prepare progress
|
|
|
|
material_cret_map: dict[bmap.BMMaterial, bpy.types.Material] = {}
|
|
|
|
progress.enter_substeps(reader.get_material_count(), "Loading Materials")
|
|
|
|
|
|
|
|
for vtmaterial in reader.get_materials():
|
2024-01-04 10:35:52 +08:00
|
|
|
# create mtl
|
|
|
|
(mtl, init_mtl) = resolver.create_material(
|
2023-11-26 20:37:19 +08:00
|
|
|
UTIL_virtools_types.virtools_name_regulator(vtmaterial.get_name())
|
2023-11-09 21:41:26 +08:00
|
|
|
)
|
2024-01-04 10:35:52 +08:00
|
|
|
|
|
|
|
# apply it if necessary
|
|
|
|
if init_mtl:
|
|
|
|
# create new raw material
|
|
|
|
rawmtl: PROP_virtools_material.RawVirtoolsMaterial = PROP_virtools_material.RawVirtoolsMaterial()
|
|
|
|
|
|
|
|
rawmtl.mDiffuse = vtmaterial.get_diffuse()
|
|
|
|
rawmtl.mAmbient = vtmaterial.get_ambient()
|
|
|
|
rawmtl.mSpecular = vtmaterial.get_specular()
|
|
|
|
rawmtl.mEmissive = vtmaterial.get_emissive()
|
|
|
|
rawmtl.mSpecularPower = vtmaterial.get_specular_power()
|
|
|
|
|
|
|
|
mtltex: bmap.BMTexture | None = vtmaterial.get_texture()
|
|
|
|
if mtltex:
|
|
|
|
rawmtl.mTexture = texture_cret_map.get(mtltex, None)
|
|
|
|
else:
|
|
|
|
rawmtl.mTexture = None
|
|
|
|
rawmtl.mTextureBorderColor = vtmaterial.get_texture_border_color()
|
|
|
|
|
|
|
|
rawmtl.mTextureBlendMode = vtmaterial.get_texture_blend_mode()
|
|
|
|
rawmtl.mTextureMinMode = vtmaterial.get_texture_min_mode()
|
|
|
|
rawmtl.mTextureMagMode = vtmaterial.get_texture_mag_mode()
|
|
|
|
rawmtl.mTextureAddressMode = vtmaterial.get_texture_address_mode()
|
|
|
|
|
|
|
|
rawmtl.mSourceBlend = vtmaterial.get_source_blend()
|
|
|
|
rawmtl.mDestBlend = vtmaterial.get_dest_blend()
|
|
|
|
rawmtl.mFillMode = vtmaterial.get_fill_mode()
|
|
|
|
rawmtl.mShadeMode = vtmaterial.get_shade_mode()
|
|
|
|
|
|
|
|
rawmtl.mEnableAlphaTest = vtmaterial.get_alpha_test_enabled()
|
|
|
|
rawmtl.mEnableAlphaBlend = vtmaterial.get_alpha_blend_enabled()
|
|
|
|
rawmtl.mEnablePerspectiveCorrection = vtmaterial.get_perspective_correction_enabled()
|
|
|
|
rawmtl.mEnableZWrite = vtmaterial.get_z_write_enabled()
|
|
|
|
rawmtl.mEnableTwoSided = vtmaterial.get_two_sided_enabled()
|
|
|
|
|
|
|
|
rawmtl.mAlphaRef = vtmaterial.get_alpha_ref()
|
|
|
|
rawmtl.mAlphaFunc = vtmaterial.get_alpha_func()
|
|
|
|
rawmtl.mZFunc = vtmaterial.get_z_func()
|
|
|
|
|
|
|
|
PROP_virtools_material.set_raw_virtools_material(mtl, rawmtl)
|
|
|
|
PROP_virtools_material.apply_to_blender_material(mtl)
|
2023-11-09 21:41:26 +08:00
|
|
|
|
|
|
|
# add into map and step
|
|
|
|
material_cret_map[vtmaterial] = mtl
|
|
|
|
progress.step()
|
|
|
|
|
|
|
|
# leave progress and return
|
|
|
|
progress.leave_substeps()
|
|
|
|
return material_cret_map
|
|
|
|
|
|
|
|
def _import_virtools_meshes(
|
|
|
|
reader: bmap.BMFileReader,
|
2024-01-04 10:35:52 +08:00
|
|
|
progress: ProgressReport,
|
|
|
|
resolver: UTIL_ioport_shared.ConflictResolver,
|
2023-11-09 21:41:26 +08:00
|
|
|
material_cret_map: dict[bmap.BMMaterial, bpy.types.Material]
|
|
|
|
) -> dict[bmap.BMMesh, bpy.types.Mesh]:
|
|
|
|
# create map and prepare progress
|
|
|
|
mesh_cret_map: dict[bmap.BMMesh, bpy.types.Mesh] = {}
|
2025-01-03 09:36:32 +08:00
|
|
|
progress.enter_substeps(reader.get_mesh_count(), "Loading Meshes")
|
2023-11-09 21:41:26 +08:00
|
|
|
|
|
|
|
for vtmesh in reader.get_meshs():
|
2023-11-10 12:26:04 +08:00
|
|
|
# create mesh
|
2024-01-04 10:35:52 +08:00
|
|
|
(mesh, init_mesh) = resolver.create_mesh(
|
2023-11-26 20:37:19 +08:00
|
|
|
UTIL_virtools_types.virtools_name_regulator(vtmesh.get_name())
|
2023-11-10 12:26:04 +08:00
|
|
|
)
|
|
|
|
|
2024-01-04 10:35:52 +08:00
|
|
|
# set mesh data if necessary
|
|
|
|
if init_mesh:
|
|
|
|
# open mesh writer
|
|
|
|
with UTIL_blender_mesh.MeshWriter(mesh) as meshoper:
|
|
|
|
# construct data provider
|
|
|
|
data_prov: UTIL_blender_mesh.MeshWriterIngredient = UTIL_blender_mesh.MeshWriterIngredient()
|
|
|
|
|
|
|
|
# constructor data itor
|
|
|
|
def pos_iterator() -> typing.Iterator[UTIL_virtools_types.VxVector3]:
|
|
|
|
for v in vtmesh.get_vertex_positions():
|
|
|
|
UTIL_virtools_types.vxvector3_conv_co(v)
|
|
|
|
yield v
|
|
|
|
def nml_iterator() -> typing.Iterator[UTIL_virtools_types.VxVector3]:
|
|
|
|
for v in vtmesh.get_vertex_normals():
|
|
|
|
UTIL_virtools_types.vxvector3_conv_co(v)
|
|
|
|
yield v
|
|
|
|
def uv_iterator() -> typing.Iterator[UTIL_virtools_types.VxVector2]:
|
|
|
|
for v in vtmesh.get_vertex_uvs():
|
|
|
|
UTIL_virtools_types.vxvector2_conv_co(v)
|
|
|
|
yield v
|
|
|
|
def face_iterator() -> typing.Iterator[UTIL_blender_mesh.FaceData]:
|
|
|
|
face: UTIL_blender_mesh.FaceData = UTIL_blender_mesh.FaceData(
|
|
|
|
[UTIL_blender_mesh.FaceVertexData() for i in range(3)]
|
|
|
|
)
|
|
|
|
|
|
|
|
findices_itor = vtmesh.get_face_indices()
|
|
|
|
fmtl_itor = vtmesh.get_face_material_slot_indexs()
|
|
|
|
for _ in range(vtmesh.get_face_count()):
|
|
|
|
# set indices data
|
|
|
|
vtindices = next(findices_itor)
|
|
|
|
face.mIndices[0].mPosIdx = vtindices.i1
|
|
|
|
face.mIndices[0].mNmlIdx = vtindices.i1
|
|
|
|
face.mIndices[0].mUvIdx = vtindices.i1
|
|
|
|
face.mIndices[1].mPosIdx = vtindices.i2
|
|
|
|
face.mIndices[1].mNmlIdx = vtindices.i2
|
|
|
|
face.mIndices[1].mUvIdx = vtindices.i2
|
|
|
|
face.mIndices[2].mPosIdx = vtindices.i3
|
|
|
|
face.mIndices[2].mNmlIdx = vtindices.i3
|
|
|
|
face.mIndices[2].mUvIdx = vtindices.i3
|
|
|
|
# swap indices
|
|
|
|
face.conv_co()
|
|
|
|
|
|
|
|
# set mtl data
|
|
|
|
vtmtl = next(fmtl_itor)
|
|
|
|
face.mMtlIdx = vtmtl
|
|
|
|
|
|
|
|
# return
|
|
|
|
yield face
|
|
|
|
def mtl_iterator() -> typing.Iterator[bpy.types.Material | None]:
|
|
|
|
for vtmtl in vtmesh.get_material_slots():
|
|
|
|
if vtmtl:
|
|
|
|
yield material_cret_map.get(vtmtl, None)
|
|
|
|
else:
|
|
|
|
yield None
|
|
|
|
|
|
|
|
# assign to data provider
|
|
|
|
data_prov.mVertexPosition = pos_iterator()
|
|
|
|
data_prov.mVertexNormal = nml_iterator()
|
|
|
|
data_prov.mVertexUV = uv_iterator()
|
|
|
|
data_prov.mFace = face_iterator()
|
|
|
|
data_prov.mMaterial = mtl_iterator()
|
|
|
|
|
|
|
|
# add part
|
|
|
|
meshoper.add_ingredient(data_prov)
|
|
|
|
|
|
|
|
# end of mesh writer
|
|
|
|
|
|
|
|
# set other mesh settings
|
|
|
|
mesh_settings: PROP_virtools_mesh.RawVirtoolsMesh = PROP_virtools_mesh.RawVirtoolsMesh()
|
|
|
|
mesh_settings.mLitMode = vtmesh.get_lit_mode()
|
|
|
|
PROP_virtools_mesh.set_raw_virtools_mesh(mesh, mesh_settings)
|
2023-11-15 23:05:00 +08:00
|
|
|
|
2023-11-09 21:41:26 +08:00
|
|
|
# add into map and step
|
2023-11-10 12:26:04 +08:00
|
|
|
mesh_cret_map[vtmesh] = mesh
|
2023-11-09 21:41:26 +08:00
|
|
|
progress.step()
|
|
|
|
|
|
|
|
# leave progress and return
|
|
|
|
progress.leave_substeps()
|
|
|
|
return mesh_cret_map
|
|
|
|
|
|
|
|
def _import_virtools_3dobjects(
|
|
|
|
reader: bmap.BMFileReader,
|
2024-01-04 10:35:52 +08:00
|
|
|
progress: ProgressReport,
|
|
|
|
resolver: UTIL_ioport_shared.ConflictResolver,
|
2023-11-09 21:41:26 +08:00
|
|
|
mesh_cret_map: dict[bmap.BMMesh, bpy.types.Mesh]
|
|
|
|
) -> dict[bmap.BM3dObject, bpy.types.Object]:
|
|
|
|
# create map and prepare progress
|
|
|
|
obj3d_cret_map: dict[bmap.BM3dObject, bpy.types.Object] = {}
|
2025-01-03 09:36:32 +08:00
|
|
|
progress.enter_substeps(reader.get_3dobject_count(), "Loading 3dObjects")
|
2023-11-10 12:26:04 +08:00
|
|
|
|
2023-11-09 21:41:26 +08:00
|
|
|
for vt3dobj in reader.get_3dobjects():
|
2024-01-04 10:35:52 +08:00
|
|
|
# get virtools binding mesh data first
|
|
|
|
vt3dobj_data: bmap.BMMesh | None = vt3dobj.get_current_mesh()
|
|
|
|
|
2023-11-10 12:26:04 +08:00
|
|
|
# create 3d object with mesh
|
2024-01-04 10:35:52 +08:00
|
|
|
(obj3d, init_obj3d) = resolver.create_object(
|
2023-11-26 20:37:19 +08:00
|
|
|
UTIL_virtools_types.virtools_name_regulator(vt3dobj.get_name()),
|
2024-01-04 10:35:52 +08:00
|
|
|
None if vt3dobj_data is None else mesh_cret_map.get(vt3dobj_data, None)
|
2023-11-10 12:26:04 +08:00
|
|
|
)
|
|
|
|
|
2024-01-04 10:35:52 +08:00
|
|
|
# setup if necessary
|
|
|
|
if init_obj3d:
|
2025-01-03 09:36:32 +08:00
|
|
|
# add into scene
|
|
|
|
UTIL_functions.add_into_scene(obj3d)
|
2023-11-10 12:26:04 +08:00
|
|
|
|
2024-01-04 10:35:52 +08:00
|
|
|
# set world matrix
|
|
|
|
vtmat: UTIL_virtools_types.VxMatrix = vt3dobj.get_world_matrix()
|
|
|
|
UTIL_virtools_types.vxmatrix_conv_co(vtmat)
|
|
|
|
obj3d.matrix_world = UTIL_virtools_types.vxmatrix_to_blender(vtmat)
|
2023-11-10 12:26:04 +08:00
|
|
|
|
2024-01-04 10:35:52 +08:00
|
|
|
# set visibility
|
|
|
|
obj3d.hide_set(not vt3dobj.get_visibility())
|
2023-11-10 12:26:04 +08:00
|
|
|
|
2024-01-04 10:35:52 +08:00
|
|
|
# add into map
|
|
|
|
# NOTE: the return value only provided to group setter
|
|
|
|
# and group setter should only set group data to new created 3d objects
|
|
|
|
# thus we only insert pair when this 3d obj is new created.
|
|
|
|
obj3d_cret_map[vt3dobj] = obj3d
|
|
|
|
|
|
|
|
# step forward
|
2023-11-09 21:41:26 +08:00
|
|
|
progress.step()
|
|
|
|
|
|
|
|
# leave progress and return
|
|
|
|
progress.leave_substeps()
|
|
|
|
return obj3d_cret_map
|
|
|
|
|
2025-01-03 09:36:32 +08:00
|
|
|
def _import_virtools_lights(
|
|
|
|
reader: bmap.BMFileReader,
|
|
|
|
progress: ProgressReport,
|
|
|
|
resolver: UTIL_ioport_shared.ConflictResolver
|
|
|
|
) -> None:
|
|
|
|
# prepare progress
|
|
|
|
progress.enter_substeps(reader.get_target_light_count(), "Loading Lights")
|
|
|
|
|
|
|
|
# please note light is slightly different between virtools and blender.
|
|
|
|
# in virtools, light is the sub class of 3d entity.
|
|
|
|
# it means that virtools use class inheritance to implement light.
|
|
|
|
# however, in blender, light is the data property of object.
|
|
|
|
# comparing with normal mesh object, it just replace the data property of object to a light.
|
|
|
|
# so in blender, light is implemented as a data struct attached to object.
|
|
|
|
# thus we can reuse light data for multiple objects but virtools can not.
|
|
|
|
# in virtools, every light are individual objects.
|
|
|
|
for vtlight in reader.get_target_lights():
|
|
|
|
# create light data block and 3d object together
|
|
|
|
(light_3dobj, light, init_light) = resolver.create_light(
|
|
|
|
UTIL_virtools_types.virtools_name_regulator(vtlight.get_name())
|
|
|
|
)
|
|
|
|
|
|
|
|
if init_light:
|
|
|
|
# setup light data block
|
|
|
|
rawlight: PROP_virtools_light.RawVirtoolsLight = PROP_virtools_light.RawVirtoolsLight()
|
|
|
|
rawlight.mType = vtlight.get_type()
|
|
|
|
rawlight.mColor = vtlight.get_color()
|
|
|
|
|
|
|
|
rawlight.mConstantAttenuation = vtlight.get_constant_attenuation()
|
|
|
|
rawlight.mLinearAttenuation = vtlight.get_linear_attenuation()
|
|
|
|
rawlight.mQuadraticAttenuation = vtlight.get_quadratic_attenuation()
|
|
|
|
|
|
|
|
rawlight.mRange = vtlight.get_range()
|
|
|
|
|
|
|
|
rawlight.mHotSpot = vtlight.get_hot_spot()
|
|
|
|
rawlight.mFalloff = vtlight.get_falloff()
|
|
|
|
rawlight.mFalloffShape = vtlight.get_falloff_shape()
|
|
|
|
|
|
|
|
PROP_virtools_light.set_raw_virtools_light(light, rawlight)
|
|
|
|
PROP_virtools_light.apply_to_blender_light(light)
|
|
|
|
|
|
|
|
# setup light associated 3d object
|
|
|
|
# add into scene
|
|
|
|
UTIL_functions.add_into_scene(light_3dobj)
|
|
|
|
# set world matrix
|
|
|
|
vtmat: UTIL_virtools_types.VxMatrix = vtlight.get_world_matrix()
|
|
|
|
UTIL_virtools_types.vxmatrix_conv_co(vtmat)
|
2025-01-03 23:42:44 +08:00
|
|
|
bldmat: mathutils.Matrix = UTIL_virtools_types.vxmatrix_to_blender(vtmat)
|
|
|
|
light_3dobj.matrix_world = UTIL_virtools_types.bldmatrix_patch_light_obj(bldmat)
|
2025-01-03 09:36:32 +08:00
|
|
|
# set visibility
|
|
|
|
light_3dobj.hide_set(not vtlight.get_visibility())
|
|
|
|
|
|
|
|
# leave progress
|
|
|
|
progress.leave_substeps()
|
|
|
|
|
2023-11-09 21:41:26 +08:00
|
|
|
def _import_virtools_groups(
|
|
|
|
reader: bmap.BMFileReader,
|
|
|
|
progress: ProgressReport,
|
|
|
|
obj3d_cret_map: dict[bmap.BM3dObject, bpy.types.Object]
|
2024-04-01 14:39:11 +08:00
|
|
|
) -> None:
|
2023-11-10 12:26:04 +08:00
|
|
|
# we need iterate all groups to construct a reversed map
|
|
|
|
# to indicate which groups should this 3dobject be grouped into.
|
|
|
|
reverse_map: dict[bmap.BM3dObject, set[str]] = {}
|
2024-04-01 14:39:11 +08:00
|
|
|
# sector counter to record the maximum sector we have processed.
|
|
|
|
sector_count: int = 1
|
2023-11-10 12:26:04 +08:00
|
|
|
|
2023-11-09 21:41:26 +08:00
|
|
|
# prepare progress
|
2025-01-03 09:36:32 +08:00
|
|
|
progress.enter_substeps(reader.get_group_count(), "Loading Groups")
|
2023-11-09 21:41:26 +08:00
|
|
|
|
|
|
|
for vtgroup in reader.get_groups():
|
2023-11-10 12:26:04 +08:00
|
|
|
# if this group do not have name, skip it
|
|
|
|
group_name: str | None = vtgroup.get_name()
|
|
|
|
if group_name is None: continue
|
|
|
|
|
2024-04-01 14:39:11 +08:00
|
|
|
# try extracting sector info
|
|
|
|
potential_sector_count: int | None = UTIL_naming_convension.extract_sector_from_name(group_name)
|
|
|
|
if potential_sector_count is not None:
|
|
|
|
sector_count = max(sector_count, potential_sector_count)
|
|
|
|
|
|
|
|
# creating map
|
2023-11-10 12:26:04 +08:00
|
|
|
for item in vtgroup.get_objects():
|
|
|
|
# get or create set
|
2025-01-03 09:36:32 +08:00
|
|
|
objgroups: set[str] | None = reverse_map.get(item, None)
|
2023-11-10 12:26:04 +08:00
|
|
|
if objgroups is None:
|
|
|
|
objgroups = set()
|
|
|
|
reverse_map[item] = objgroups
|
|
|
|
|
|
|
|
# add into list
|
|
|
|
objgroups.add(group_name)
|
|
|
|
|
|
|
|
# step
|
2023-11-09 21:41:26 +08:00
|
|
|
progress.step()
|
|
|
|
|
2024-04-01 14:39:11 +08:00
|
|
|
# assign to ballance map info according to gotten sector count
|
|
|
|
map_info: PROP_ballance_map_info.RawBallanceMapInfo = PROP_ballance_map_info.get_raw_ballance_map_info(bpy.context.scene)
|
|
|
|
map_info.mSectorCount = max(map_info.mSectorCount, sector_count)
|
|
|
|
PROP_ballance_map_info.set_raw_ballance_map_info(bpy.context.scene, map_info)
|
|
|
|
|
2023-11-09 21:41:26 +08:00
|
|
|
# leave progress
|
|
|
|
progress.leave_substeps()
|
2023-10-18 21:23:04 +08:00
|
|
|
|
2023-11-10 12:26:04 +08:00
|
|
|
# now we can assign 3dobject group data by reverse map
|
2025-01-03 09:36:32 +08:00
|
|
|
progress.enter_substeps(len(reverse_map), "Applying Groups")
|
2023-11-10 12:26:04 +08:00
|
|
|
for mapk, mapv in reverse_map.items():
|
|
|
|
# check object
|
|
|
|
assoc_obj = obj3d_cret_map.get(mapk, None)
|
|
|
|
if assoc_obj is None: continue
|
|
|
|
|
|
|
|
# assign group
|
|
|
|
with PROP_virtools_group.VirtoolsGroupsHelper(assoc_obj) as gpoper:
|
2023-11-30 22:38:53 +08:00
|
|
|
gpoper.clear_groups()
|
2023-11-10 12:26:04 +08:00
|
|
|
gpoper.add_groups(mapv)
|
|
|
|
|
2025-01-03 09:36:32 +08:00
|
|
|
# step
|
|
|
|
progress.step()
|
|
|
|
|
|
|
|
# leave progress
|
2023-11-10 12:26:04 +08:00
|
|
|
progress.leave_substeps()
|
|
|
|
|
|
|
|
|
2023-10-18 21:23:04 +08:00
|
|
|
def register() -> None:
|
|
|
|
bpy.utils.register_class(BBP_OT_import_virtools)
|
|
|
|
|
|
|
|
def unregister() -> None:
|
|
|
|
bpy.utils.unregister_class(BBP_OT_import_virtools)
|