From 2c006b4528efd8b155a902eca58c743353d80a39 Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Thu, 4 Jan 2024 10:35:52 +0800 Subject: [PATCH] add conflict resolver --- bbp_ng/OP_IMPORT_virtools.py | 299 +++++++++++++++++++---------------- bbp_ng/UTIL_ioport_shared.py | 166 ++++++++++++------- 2 files changed, 269 insertions(+), 196 deletions(-) diff --git a/bbp_ng/OP_IMPORT_virtools.py b/bbp_ng/OP_IMPORT_virtools.py index e502701..d1fbb6f 100644 --- a/bbp_ng/OP_IMPORT_virtools.py +++ b/bbp_ng/OP_IMPORT_virtools.py @@ -21,7 +21,8 @@ class BBP_OT_import_virtools(bpy.types.Operator, UTIL_file_browser.ImportVirtool def execute(self, context): _import_virtools( self.general_get_filename(), - self.general_get_vt_encodings() + self.general_get_vt_encodings(), + self.general_get_conflict_resolver() ) self.report({'INFO'}, "Virtools File Importing Finished.") return {'FINISHED'} @@ -34,7 +35,7 @@ class BBP_OT_import_virtools(bpy.types.Operator, UTIL_file_browser.ImportVirtool layout.label(text = 'Virtools Params') self.draw_virtools_params(layout.box()) -def _import_virtools(file_name_: str, encodings_: tuple[str]) -> None: +def _import_virtools(file_name_: str, encodings_: tuple[str], resolver: UTIL_ioport_shared.ConflictResolver) -> None: # create temp folder with tempfile.TemporaryDirectory() as vt_temp_folder: print(f'Virtools Engine Temp: {vt_temp_folder}') @@ -50,22 +51,23 @@ def _import_virtools(file_name_: str, encodings_: tuple[str]) -> None: with ProgressReport(wm = bpy.context.window_manager) as progress: # import textures texture_cret_map: dict[bmap.BMTexture, bpy.types.Image] = _import_virtools_textures( - reader, progress) + reader, progress, resolver) # import materials material_cret_map: dict[bmap.BMMaterial, bpy.types.Material] = _import_virtools_materials( - reader, progress, texture_cret_map) + reader, progress, resolver, texture_cret_map) # import meshes mesh_cret_map: dict[bmap.BMMesh, bpy.types.Mesh] = _import_virtools_meshes( - reader, progress, material_cret_map) + reader, progress, resolver, material_cret_map) # import 3dobjects obj3d_cret_map: dict[bmap.BM3dObject, bpy.types.Object] = _import_virtools_3dobjects( - reader, progress, mesh_cret_map) + reader, progress, resolver, mesh_cret_map) # import groups _import_virtools_groups(reader, progress, obj3d_cret_map) def _import_virtools_textures( reader: bmap.BMFileReader, - progress:ProgressReport + progress: ProgressReport, + resolver: UTIL_ioport_shared.ConflictResolver ) -> dict[bmap.BMTexture, bpy.types.Image]: # create map texture_cret_map: dict[bmap.BMTexture, bpy.types.Image] = {} @@ -76,13 +78,13 @@ def _import_virtools_textures( print(f'Texture Raw Data Temp: {rawdata_temp}') for vttexture in reader.get_textures(): - tex: bpy.types.Image + tex_cret: typing.Callable[[], bpy.types.Image] 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: - tex = bpy.data.images.new("", 1, 1) + tex_cret = lambda: bpy.data.images.new("", 1, 1) else: # 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 @@ -96,21 +98,28 @@ def _import_virtools_textures( # detect whether it is ballance texture and load try_blc_tex: str | None = UTIL_ballance_texture.get_ballance_texture_filename(texpath_to_load) - if try_blc_tex: + if try_blc_tex is not None: # load as ballance texture - tex = UTIL_ballance_texture.load_ballance_texture(try_blc_tex) + tex_cret = lambda: UTIL_ballance_texture.load_ballance_texture(typing.cast(str, try_blc_tex)) else: # load as other textures - tex = UTIL_ballance_texture.load_other_texture(texpath_to_load) + tex_cret = lambda: UTIL_ballance_texture.load_other_texture(typing.cast(str, texpath_to_load)) - # 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) + # 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) - # rename and insert it to map - tex.name = UTIL_virtools_types.virtools_name_regulator(vttexture.get_name()) + # insert it to map texture_cret_map[vttexture] = tex # inc steps @@ -122,7 +131,8 @@ def _import_virtools_textures( def _import_virtools_materials( reader: bmap.BMFileReader, - progress: ProgressReport, + progress: ProgressReport, + resolver: UTIL_ioport_shared.ConflictResolver, texture_cret_map: dict[bmap.BMTexture, bpy.types.Image] ) -> dict[bmap.BMMaterial, bpy.types.Material]: # create map and prepare progress @@ -130,48 +140,51 @@ def _import_virtools_materials( progress.enter_substeps(reader.get_material_count(), "Loading Materials") for vtmaterial in reader.get_materials(): - # 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() - - # create mtl and apply it - mtl: bpy.types.Material = bpy.data.materials.new( + # create mtl + (mtl, init_mtl) = resolver.create_material( UTIL_virtools_types.virtools_name_regulator(vtmaterial.get_name()) ) - PROP_virtools_material.set_raw_virtools_material(mtl, rawmtl) - PROP_virtools_material.apply_to_blender_material(mtl) + + # 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) # add into map and step material_cret_map[vtmaterial] = mtl @@ -183,7 +196,8 @@ def _import_virtools_materials( def _import_virtools_meshes( reader: bmap.BMFileReader, - progress: ProgressReport, + progress: ProgressReport, + resolver: UTIL_ioport_shared.ConflictResolver, material_cret_map: dict[bmap.BMMaterial, bpy.types.Material] ) -> dict[bmap.BMMesh, bpy.types.Mesh]: # create map and prepare progress @@ -192,79 +206,81 @@ def _import_virtools_meshes( for vtmesh in reader.get_meshs(): # create mesh - mesh: bpy.types.Mesh = bpy.data.meshes.new( + (mesh, init_mesh) = resolver.create_mesh( UTIL_virtools_types.virtools_name_regulator(vtmesh.get_name()) ) - # open mesh writer - with UTIL_blender_mesh.MeshWriter(mesh) as meshoper: - # construct data provider - data_prov: UTIL_blender_mesh.MeshWriterIngredient = UTIL_blender_mesh.MeshWriterIngredient() + # 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)] - ) + # 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() + 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 + # 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 + # 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() + # 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) + # add part + meshoper.add_ingredient(data_prov) - # end of mesh writer + # 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) + # 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) # add into map and step mesh_cret_map[vtmesh] = mesh @@ -276,7 +292,8 @@ def _import_virtools_meshes( def _import_virtools_3dobjects( reader: bmap.BMFileReader, - progress: ProgressReport, + progress: ProgressReport, + resolver: UTIL_ioport_shared.ConflictResolver, mesh_cret_map: dict[bmap.BMMesh, bpy.types.Mesh] ) -> dict[bmap.BM3dObject, bpy.types.Object]: # create map and prepare progress @@ -288,25 +305,35 @@ def _import_virtools_3dobjects( blender_collection = blender_view_layer.active_layer_collection.collection for vt3dobj in reader.get_3dobjects(): + # get virtools binding mesh data first + vt3dobj_data: bmap.BMMesh | None = vt3dobj.get_current_mesh() + # create 3d object with mesh - obj3d: bpy.types.Object = bpy.data.objects.new( + (obj3d, init_obj3d) = resolver.create_object( UTIL_virtools_types.virtools_name_regulator(vt3dobj.get_name()), - mesh_cret_map.get(vt3dobj.get_current_mesh(), None) + None if vt3dobj_data is None else mesh_cret_map.get(vt3dobj_data, None) ) - # link to collection - blender_collection.objects.link(obj3d) + # setup if necessary + if init_obj3d: + # link to collection + blender_collection.objects.link(obj3d) - # 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) + # 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) - # set visibility - obj3d.hide_set(not vt3dobj.get_visibility()) + # set visibility + obj3d.hide_set(not vt3dobj.get_visibility()) - # add into map and step - obj3d_cret_map[vt3dobj] = obj3d + # 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 progress.step() # leave progress and return diff --git a/bbp_ng/UTIL_ioport_shared.py b/bbp_ng/UTIL_ioport_shared.py index 7f8a81c..ceffa5a 100644 --- a/bbp_ng/UTIL_ioport_shared.py +++ b/bbp_ng/UTIL_ioport_shared.py @@ -1,5 +1,5 @@ import bpy -import enum +import enum, typing from . import UTIL_virtools_types, UTIL_functions from . import PROP_ptrprop_resolver @@ -12,11 +12,9 @@ from . import PROP_ptrprop_resolver class ConflictStrategy(enum.IntEnum): Rename = enum.auto() Current = enum.auto() - Replace = enum.auto() _g_ConflictStrategyDesc: dict[ConflictStrategy, tuple[str, str]] = { ConflictStrategy.Rename: ('Rename', 'Rename the new one'), ConflictStrategy.Current: ('Use Current', 'Use current one'), - ConflictStrategy.Replace: ('Replace', 'Replace the old one with new one'), } _g_EnumHelper_ConflictStrategy: UTIL_functions.EnumPropHelper = UTIL_functions.EnumPropHelper( ConflictStrategy, @@ -27,6 +25,103 @@ _g_EnumHelper_ConflictStrategy: UTIL_functions.EnumPropHelper = UTIL_functions.E lambda _: '' ) +#region Assist Classes + +class ExportEditModeBackup(): + """ + The class which save Edit Mode when exporting and restore it after exporting. + Because edit mode is not allowed when exporting. + Support `with` statement. + + ``` + with ExportEditModeBackup(): + # do some exporting work + blabla() + # restore automatically when exiting "with" + ``` + """ + mInEditMode: bool + + def __init__(self): + if bpy.context.object and bpy.context.object.mode == "EDIT": + # set and toggle it. otherwise exporting will failed. + self.mInEditMode = True + bpy.ops.object.editmode_toggle() + else: + self.mInEditMode = False + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, traceback): + if self.mInEditMode: + bpy.ops.object.editmode_toggle() + self.mInEditMode = False + +class ConflictResolver(): + """ + This class frequently used when importing objects. + This class accept 4 conflict strategies for object, mesh, material and texture, + and provide 4 general creation functions to handle these strategies. + Each general creation functions will return an instance and a bool indicating whether this instance need be initialized. + """ + + __mObjectStrategy: ConflictStrategy + __mMeshStrategy: ConflictStrategy + __mMaterialStrategy: ConflictStrategy + __mTextureStrategy: ConflictStrategy + + def __init__(self, obj_strategy: ConflictStrategy, mesh_strategy: ConflictStrategy, mtl_strategy: ConflictStrategy, tex_strategy: ConflictStrategy): + self.__mObjectStrategy = obj_strategy + self.__mMeshStrategy = mesh_strategy + self.__mMaterialStrategy = mtl_strategy + self.__mTextureStrategy = tex_strategy + + def create_object(self, name: str, data: bpy.types.Mesh) -> tuple[bpy.types.Object, bool]: + """ + Create object according to conflict strategy. + `data` will only be applied when creating new object (no existing instance or strategy order rename) + """ + if self.__mObjectStrategy == ConflictStrategy.Current: + old: bpy.types.Object | None = bpy.data.objects.get(name, None) + if old is not None: + return (old, False) + return (bpy.data.objects.new(name, data), True) + + def create_mesh(self, name: str) -> tuple[bpy.types.Mesh, bool]: + if self.__mMeshStrategy == ConflictStrategy.Current: + old: bpy.types.Mesh | None = bpy.data.meshes.get(name, None) + if old is not None: + return (old, False) + return (bpy.data.meshes.new(name), True) + + def create_material(self, name: str) -> tuple[bpy.types.Material, bool]: + if self.__mMaterialStrategy == ConflictStrategy.Current: + old: bpy.types.Material | None = bpy.data.materials.get(name, None) + if old is not None: + return (old, False) + return (bpy.data.materials.new(name), True) + + def create_texture(self, name: str, fct_cret: typing.Callable[[], bpy.types.Image]) -> tuple[bpy.types.Image, bool]: + """ + Create texture according to conflict strategy. + If the strategy order current, it will return current existing instance. + If no existing instance or strategy order rename, it will call `fct_cret` to create new texture. + + Because texture do not have a general creation function, we frequently create it by other modules provided texture functions. + So `fct_cret` is the real creation function. And it will not be executed if no creation happended. + """ + if self.__mTextureStrategy == ConflictStrategy.Current: + old: bpy.types.Image | None = bpy.data.images.get(name, None) + if old is not None: + return (old, False) + # create texture, set name, and return + tex: bpy.types.Image = fct_cret() + tex.name = name + return (tex, True) + +#endregion + class ImportParams(): texture_conflict_strategy: bpy.props.EnumProperty( name = "Texture Name Conflict", @@ -78,6 +173,14 @@ class ImportParams(): def general_get_object_conflict_strategy(self) -> ConflictStrategy: return _g_EnumHelper_ConflictStrategy.get_selection(self.object_conflict_strategy) + def general_get_conflict_resolver(self) -> ConflictResolver: + return ConflictResolver( + self.general_get_object_conflict_strategy(), + self.general_get_mesh_conflict_strategy(), + self.general_get_material_conflict_strategy(), + self.general_get_texture_conflict_strategy() + ) + class ExportParams(): export_mode: bpy.props.EnumProperty( name = "Export Mode", @@ -128,60 +231,3 @@ class VirtoolsParams(): # get encoding, split it by `;` and strip blank chars. encodings: str = self.vt_encodings return tuple(map(lambda x: x.strip(), encodings.split(';'))) - -class ExportEditModeBackup(): - """ - The class which save Edit Mode when exporting and restore it after exporting. - Because edit mode is not allowed when exporting. - Support `with` statement. - - ``` - with ExportEditModeBackup(): - # do some exporting work - blabla() - # restore automatically when exiting "with" - ``` - """ - mInEditMode: bool - - def __init__(self): - if bpy.context.object and bpy.context.object.mode == "EDIT": - # set and toggle it. otherwise exporting will failed. - self.mInEditMode = True - bpy.ops.object.editmode_toggle() - else: - self.mInEditMode = False - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, traceback): - if self.mInEditMode: - bpy.ops.object.editmode_toggle() - self.mInEditMode = False - -class ConflictResolver(): - """ - This class frequently used when importing objects. - This class accept 4 conflict strategies for object, mesh, material and texture, - and provide 4 general creation functions to handle these strategies. - Each general creation functions will return an instance and a bool indicating whether this instance need be initialized. - - This class also provide 3 static common creation functions without considering conflict. - They just a redirect calling to `bpy.data.xxx.new()`. - No static texture (Image) creation function because texture is not created from `bpy.data.images`. - """ - - @staticmethod - def create_object(name: str, data: bpy.types.Mesh) -> bpy.types.Object: - return bpy.data.objects.new(name, data) - - @staticmethod - def create_mesh(name: str) -> bpy.types.Mesh: - return bpy.data.meshes.new(name) - - @staticmethod - def create_material(name: str) -> bpy.types.Material: - return bpy.data.materials.new(name) - -