feat: update virtools file importer and exporter

- use panel to organise property group in virtools file importer and exporter.
- move all ballance params and virtools params into ioport_shared module and enable different showcase according to the argument passed to show function presenting whether current window is importer or exporter.
- add multiple type ignore to ignore the error of bpy operator member field type hints.
This commit is contained in:
yyc12345 2024-12-30 17:53:42 +08:00
parent fe47861bd0
commit 729e12ed7b
12 changed files with 172 additions and 110 deletions

View File

@ -3,44 +3,15 @@ from bpy_extras.wm_utils.progress_report import ProgressReport
import tempfile, os, typing import tempfile, os, typing
from . import PROP_preferences, UTIL_ioport_shared from . import PROP_preferences, UTIL_ioport_shared
from . import UTIL_virtools_types, UTIL_functions, UTIL_file_browser, UTIL_blender_mesh, UTIL_ballance_texture, UTIL_icons_manager, UTIL_naming_convension from . import UTIL_virtools_types, UTIL_functions, UTIL_file_browser, UTIL_blender_mesh, UTIL_ballance_texture, UTIL_icons_manager, UTIL_naming_convension
from . import PROP_virtools_group, PROP_virtools_material, PROP_virtools_mesh, PROP_virtools_texture, PROP_ballance_map_info from . import PROP_virtools_group, PROP_virtools_material, PROP_virtools_mesh, PROP_virtools_texture
from .PyBMap import bmap_wrapper as bmap from .PyBMap import bmap_wrapper as bmap
# define global tex save opt blender enum prop helper class BBP_OT_export_virtools(bpy.types.Operator, UTIL_file_browser.ExportVirtoolsFile, UTIL_ioport_shared.ExportParams, UTIL_ioport_shared.VirtoolsParams, UTIL_ioport_shared.BallanceParams):
_g_EnumHelper_CK_TEXTURE_SAVEOPTIONS: UTIL_virtools_types.EnumPropHelper = UTIL_virtools_types.EnumPropHelper(UTIL_virtools_types.CK_TEXTURE_SAVEOPTIONS)
class BBP_OT_export_virtools(bpy.types.Operator, UTIL_file_browser.ExportVirtoolsFile, UTIL_ioport_shared.ExportParams, UTIL_ioport_shared.VirtoolsParams):
"""Export Virtools File""" """Export Virtools File"""
bl_idname = "bbp.export_virtools" bl_idname = "bbp.export_virtools"
bl_label = "Export Virtools File" bl_label = "Export Virtools File"
bl_options = {'PRESET'} bl_options = {'PRESET'}
texture_save_opt: bpy.props.EnumProperty(
name = "Global Texture Save Options",
description = "Decide how texture saved if texture is specified as Use Global as its Save Options.",
items = _g_EnumHelper_CK_TEXTURE_SAVEOPTIONS.generate_items(),
default = _g_EnumHelper_CK_TEXTURE_SAVEOPTIONS.to_selection(UTIL_virtools_types.CK_TEXTURE_SAVEOPTIONS.CKTEXTURE_EXTERNAL)
) # type: ignore
use_compress: bpy.props.BoolProperty(
name="Use Compress",
description = "Whether use ZLib to compress result when saving composition.",
default = True,
) # type: ignore
compress_level: bpy.props.IntProperty(
name = "Compress Level",
description = "The ZLib compress level used by Virtools Engine when saving composition.",
min = 1, max = 9,
default = 5,
) # type: ignore
successive_sector: bpy.props.BoolProperty(
name="Successive Sector",
description = "Whether order exporter to use document specified sector count to make sure sector is successive.",
default = True,
) # type: ignore
@classmethod @classmethod
def poll(self, context): def poll(self, context):
return ( return (
@ -58,15 +29,26 @@ class BBP_OT_export_virtools(bpy.types.Operator, UTIL_file_browser.ExportVirtool
) )
return {'CANCELLED'} return {'CANCELLED'}
# check texture save option to prevent real stupid user.
texture_save_opt = self.general_get_texture_save_opt()
if texture_save_opt == UTIL_virtools_types.CK_TEXTURE_SAVEOPTIONS.CKTEXTURE_USEGLOBAL:
UTIL_functions.message_box(
('You can not specify "Use Global" as global texture save option!', ),
'Wrong Parameters',
UTIL_icons_manager.BlenderPresetIcons.Error.value
)
return {'CANCELLED'}
# start exporting # start exporting
with UTIL_ioport_shared.ExportEditModeBackup() as editmode_guard: with UTIL_ioport_shared.ExportEditModeBackup() as editmode_guard:
_export_virtools( _export_virtools(
self.general_get_filename(), self.general_get_filename(),
self.general_get_vt_encodings(), self.general_get_vt_encodings(),
_g_EnumHelper_CK_TEXTURE_SAVEOPTIONS.get_selection(self.texture_save_opt), texture_save_opt,
self.use_compress, self.general_get_use_compress(),
self.compress_level, self.general_get_compress_level(),
self.successive_sector, self.general_get_successive_sector(),
self.general_get_successive_sector_count(),
objls objls
) )
@ -75,30 +57,9 @@ class BBP_OT_export_virtools(bpy.types.Operator, UTIL_file_browser.ExportVirtool
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
layout.label(text = 'Export Target') self.draw_export_params(layout)
self.draw_export_params(layout.box()) self.draw_virtools_params(layout, False)
self.draw_ballance_params(layout, False)
layout.separator()
layout.label(text = 'Virtools Params')
box = layout.box()
self.draw_virtools_params(box)
box.separator()
box.label(text = 'Global Texture Save Option')
box.prop(self, 'texture_save_opt', text = '')
box.separator()
box.prop(self, 'use_compress')
if self.use_compress:
box.prop(self, 'compress_level')
# show sector info to notice user
layout.separator()
layout.label(text = 'Ballance Params')
box = layout.box()
map_info: PROP_ballance_map_info.RawBallanceMapInfo = PROP_ballance_map_info.get_raw_ballance_map_info(bpy.context.scene)
box.prop(self, 'successive_sector')
box.label(text = f'Map Sectors: {map_info.mSectorCount}')
_TObj3dPair = tuple[bpy.types.Object, bmap.BM3dObject] _TObj3dPair = tuple[bpy.types.Object, bmap.BM3dObject]
_TMeshPair = tuple[bpy.types.Object, bpy.types.Mesh, bmap.BMMesh] _TMeshPair = tuple[bpy.types.Object, bpy.types.Mesh, bmap.BMMesh]
@ -112,6 +73,7 @@ def _export_virtools(
use_compress_: bool, use_compress_: bool,
compress_level_: int, compress_level_: int,
successive_sector_: bool, successive_sector_: bool,
successive_sector_count_: int,
export_objects: tuple[bpy.types.Object, ...] export_objects: tuple[bpy.types.Object, ...]
) -> None: ) -> None:
@ -131,7 +93,7 @@ def _export_virtools(
obj3d_crets: tuple[_TObj3dPair, ...] = _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, successive_sector_, obj3d_crets) _export_virtools_groups(writer, progress, successive_sector_, successive_sector_count_, obj3d_crets)
mesh_crets: tuple[_TMeshPair, ...] = _export_virtools_3dobjects( mesh_crets: tuple[_TMeshPair, ...] = _export_virtools_3dobjects(
writer, progress, obj3d_crets) writer, progress, obj3d_crets)
# export mesh # export mesh
@ -181,6 +143,7 @@ def _export_virtools_groups(
writer: bmap.BMFileWriter, writer: bmap.BMFileWriter,
progress: ProgressReport, progress: ProgressReport,
successive_sector: bool, successive_sector: bool,
successive_sector_count: int,
obj3d_crets: tuple[_TObj3dPair, ...] obj3d_crets: tuple[_TObj3dPair, ...]
) -> None: ) -> None:
# create virtools group # create virtools group
@ -197,9 +160,7 @@ def _export_virtools_groups(
# #
# So we create all needed sector group in here to make sure exported virtools file can be read by Ballancde correctly. # So we create all needed sector group in here to make sure exported virtools file can be read by Ballancde correctly.
if successive_sector: if successive_sector:
map_info: PROP_ballance_map_info.RawBallanceMapInfo for i in range(successive_sector_count):
map_info = PROP_ballance_map_info.get_raw_ballance_map_info(bpy.context.scene)
for i in range(map_info.mSectorCount):
gp_name: str = UTIL_naming_convension.build_name_from_sector_index(i + 1) gp_name: str = UTIL_naming_convension.build_name_from_sector_index(i + 1)
vtgroup: bmap.BMGroup | None = group_cret_map.get(gp_name, None) vtgroup: bmap.BMGroup | None = group_cret_map.get(gp_name, None)
if vtgroup is None: if vtgroup is None:

View File

@ -6,7 +6,7 @@ from . import UTIL_virtools_types, UTIL_functions, UTIL_file_browser, UTIL_blend
from . import PROP_virtools_group, PROP_virtools_material, PROP_virtools_mesh, PROP_virtools_texture, PROP_ballance_map_info from . import PROP_virtools_group, PROP_virtools_material, PROP_virtools_mesh, PROP_virtools_texture, PROP_ballance_map_info
from .PyBMap import bmap_wrapper as bmap from .PyBMap import bmap_wrapper as bmap
class BBP_OT_import_virtools(bpy.types.Operator, UTIL_file_browser.ImportVirtoolsFile, UTIL_ioport_shared.ImportParams, UTIL_ioport_shared.VirtoolsParams): class BBP_OT_import_virtools(bpy.types.Operator, UTIL_file_browser.ImportVirtoolsFile, UTIL_ioport_shared.ImportParams, UTIL_ioport_shared.VirtoolsParams, UTIL_ioport_shared.BallanceParams):
"""Import Virtools File""" """Import Virtools File"""
bl_idname = "bbp.import_virtools" bl_idname = "bbp.import_virtools"
bl_label = "Import Virtools File" bl_label = "Import Virtools File"
@ -29,11 +29,9 @@ class BBP_OT_import_virtools(bpy.types.Operator, UTIL_file_browser.ImportVirtool
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
layout.label(text = 'Conflict Options') self.draw_import_params(layout)
self.draw_import_params(layout.box()) self.draw_virtools_params(layout, True)
layout.separator() self.draw_ballance_params(layout, True)
layout.label(text = 'Virtools Params')
self.draw_virtools_params(layout.box())
def _import_virtools(file_name_: str, encodings_: tuple[str], resolver: UTIL_ioport_shared.ConflictResolver) -> None: def _import_virtools(file_name_: str, encodings_: tuple[str], resolver: UTIL_ioport_shared.ConflictResolver) -> None:
# create temp folder # create temp folder

View File

@ -97,12 +97,12 @@ class BBP_PG_ballance_element(bpy.types.PropertyGroup):
element_id: bpy.props.IntProperty( element_id: bpy.props.IntProperty(
name = "Element Id", name = "Element Id",
default = 0 default = 0
) ) # type: ignore
mesh_ptr: bpy.props.PointerProperty( mesh_ptr: bpy.props.PointerProperty(
name = "Mesh", name = "Mesh",
type = bpy.types.Mesh type = bpy.types.Mesh
) ) # type: ignore
def get_ballance_elements(scene: bpy.types.Scene) -> bpy.types.CollectionProperty: def get_ballance_elements(scene: bpy.types.Scene) -> bpy.types.CollectionProperty:
return scene.ballance_elements return scene.ballance_elements

View File

@ -73,12 +73,12 @@ class BBP_PG_bme_material(bpy.types.PropertyGroup):
bme_material_name: bpy.props.StringProperty( bme_material_name: bpy.props.StringProperty(
name = "Name", name = "Name",
default = "" default = ""
) ) # type: ignore
material_ptr: bpy.props.PointerProperty( material_ptr: bpy.props.PointerProperty(
name = "Material", name = "Material",
type = bpy.types.Material type = bpy.types.Material
) ) # type: ignore
def get_bme_materials(scene: bpy.types.Scene) -> bpy.types.CollectionProperty: def get_bme_materials(scene: bpy.types.Scene) -> bpy.types.CollectionProperty:
return scene.bme_materials return scene.bme_materials

View File

@ -24,13 +24,13 @@ class BBPPreferences(bpy.types.AddonPreferences):
description = "The path to folder which will be used by this plugin to get external Ballance texture.", description = "The path to folder which will be used by this plugin to get external Ballance texture.",
subtype='DIR_PATH', subtype='DIR_PATH',
default = RawPreferences.cBallanceTextureFolder, default = RawPreferences.cBallanceTextureFolder,
) ) # type: ignore
no_component_collection: bpy.props.StringProperty( no_component_collection: bpy.props.StringProperty(
name = "No Component Collection", name = "No Component Collection",
description = "(Import) The object which stored in this collectiion will not be saved as component. (Export) All forced no component objects will be stored in this collection", description = "(Import) The object which stored in this collectiion will not be saved as component. (Export) All forced no component objects will be stored in this collection",
default = RawPreferences.cNoComponentCollection, default = RawPreferences.cNoComponentCollection,
) ) # type: ignore
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout

View File

@ -10,19 +10,19 @@ class BBP_PG_ptrprop_resolver(bpy.types.PropertyGroup):
name = "Material", name = "Material",
description = "The material used for rail", description = "The material used for rail",
type = bpy.types.Material, type = bpy.types.Material,
) ) # type: ignore
export_collection: bpy.props.PointerProperty( export_collection: bpy.props.PointerProperty(
type = bpy.types.Collection, type = bpy.types.Collection,
name = "Collection", name = "Collection",
description = "The collection exported. Nested collections allowed." description = "The collection exported. Nested collections allowed."
) ) # type: ignore
export_object: bpy.props.PointerProperty( export_object: bpy.props.PointerProperty(
type = bpy.types.Object, type = bpy.types.Object,
name = "Object", name = "Object",
description = "The object exported" description = "The object exported"
) ) # type: ignore
def get_ptrprop_resolver() -> BBP_PG_ptrprop_resolver: def get_ptrprop_resolver() -> BBP_PG_ptrprop_resolver:
return bpy.context.scene.bbp_ptrprop_resolver return bpy.context.scene.bbp_ptrprop_resolver

View File

@ -255,19 +255,19 @@ class SharedGroupNameInputProperties():
('DEFINED', "Predefined", "Pre-defined group name."), ('DEFINED', "Predefined", "Pre-defined group name."),
('CUSTOM', "Custom", "User specified group name."), ('CUSTOM', "Custom", "User specified group name."),
), ),
) ) # type: ignore
preset_group_name: bpy.props.EnumProperty( preset_group_name: bpy.props.EnumProperty(
name = "Group Name", name = "Group Name",
description = "Pick vanilla Ballance group name.", description = "Pick vanilla Ballance group name.",
items = _g_EnumHelper_Group.generate_items(), items = _g_EnumHelper_Group.generate_items(),
) ) # type: ignore
custom_group_name: bpy.props.StringProperty( custom_group_name: bpy.props.StringProperty(
name = "Custom Group Name", name = "Custom Group Name",
description = "Input your custom group name.", description = "Input your custom group name.",
default = "", default = "",
) ) # type: ignore
def draw_group_name_input(self, layout: bpy.types.UILayout) -> None: def draw_group_name_input(self, layout: bpy.types.UILayout) -> None:
layout.prop(self, 'group_name_source', expand = True) layout.prop(self, 'group_name_source', expand = True)

View File

@ -25,7 +25,7 @@ class BBP_PG_virtools_mesh(bpy.types.PropertyGroup):
description = "Lighting mode of the mesh.", description = "Lighting mode of the mesh.",
items = _g_Helper_VXMESH_LITMODE.generate_items(), items = _g_Helper_VXMESH_LITMODE.generate_items(),
default = _g_Helper_VXMESH_LITMODE.to_selection(RawVirtoolsMesh.cDefaultLitMode) default = _g_Helper_VXMESH_LITMODE.to_selection(RawVirtoolsMesh.cDefaultLitMode)
) ) # type: ignore
# Getter Setter # Getter Setter

View File

@ -30,14 +30,14 @@ class BBP_PG_virtools_texture(bpy.types.PropertyGroup):
description = "When saving a composition textures or sprites can be kept as reference to external files or converted to a given format and saved inside the composition file.", description = "When saving a composition textures or sprites can be kept as reference to external files or converted to a given format and saved inside the composition file.",
items = _g_Helper_CK_TEXTURE_SAVEOPTIONS.generate_items(), items = _g_Helper_CK_TEXTURE_SAVEOPTIONS.generate_items(),
default = _g_Helper_CK_TEXTURE_SAVEOPTIONS.to_selection(RawVirtoolsTexture.cDefaultSaveOptions) default = _g_Helper_CK_TEXTURE_SAVEOPTIONS.to_selection(RawVirtoolsTexture.cDefaultSaveOptions)
) ) # type: ignore
video_format: bpy.props.EnumProperty( video_format: bpy.props.EnumProperty(
name = "Video Format", name = "Video Format",
description = "The desired surface pixel format in video memory.", description = "The desired surface pixel format in video memory.",
items = _g_Helper_VX_PIXELFORMAT.generate_items(), items = _g_Helper_VX_PIXELFORMAT.generate_items(),
default = _g_Helper_VX_PIXELFORMAT.to_selection(RawVirtoolsTexture.cDefaultVideoFormat) default = _g_Helper_VX_PIXELFORMAT.to_selection(RawVirtoolsTexture.cDefaultVideoFormat)
) ) # type: ignore
#region Virtools Texture Getter Setter #region Virtools Texture Getter Setter

View File

@ -29,7 +29,7 @@ class ImportBallanceImage(bpy_extras.io_utils.ImportHelper):
filter_glob: bpy.props.StringProperty( filter_glob: bpy.props.StringProperty(
default = "*.bmp;*.tga", default = "*.bmp;*.tga",
options = {'HIDDEN'} options = {'HIDDEN'}
) ) # type: ignore
def general_set_filename(self, filename: str) -> None: def general_set_filename(self, filename: str) -> None:
self.filepath = filename self.filepath = filename
@ -44,7 +44,7 @@ class ImportBmxFile(bpy_extras.io_utils.ImportHelper):
filter_glob: bpy.props.StringProperty( filter_glob: bpy.props.StringProperty(
default = "*.bmx", default = "*.bmx",
options = {'HIDDEN'} options = {'HIDDEN'}
) ) # type: ignore
def general_get_filename(self) -> str: def general_get_filename(self) -> str:
return self.filepath return self.filepath
@ -56,7 +56,7 @@ class ExportBmxFile(bpy_extras.io_utils.ExportHelper):
filter_glob: bpy.props.StringProperty( filter_glob: bpy.props.StringProperty(
default = "*.bmx", default = "*.bmx",
options = {'HIDDEN'} options = {'HIDDEN'}
) ) # type: ignore
def general_get_filename(self) -> str: def general_get_filename(self) -> str:
return self.filepath return self.filepath
@ -68,7 +68,7 @@ class ImportVirtoolsFile(bpy_extras.io_utils.ImportHelper):
filter_glob: bpy.props.StringProperty( filter_glob: bpy.props.StringProperty(
default = "*.nmo;*.cmo;*.vmo", default = "*.nmo;*.cmo;*.vmo",
options = {'HIDDEN'} options = {'HIDDEN'}
) ) # type: ignore
def general_get_filename(self) -> str: def general_get_filename(self) -> str:
return self.filepath return self.filepath
@ -80,7 +80,7 @@ class ExportVirtoolsFile(bpy_extras.io_utils.ExportHelper):
filter_glob: bpy.props.StringProperty( filter_glob: bpy.props.StringProperty(
default = "*.nmo", default = "*.nmo",
options = {'HIDDEN'} options = {'HIDDEN'}
) ) # type: ignore
def general_get_filename(self) -> str: def general_get_filename(self) -> str:
return self.filepath return self.filepath
@ -94,7 +94,7 @@ class ImportDirectory(bpy_extras.io_utils.ImportHelper):
filter_glob: bpy.props.StringProperty( filter_glob: bpy.props.StringProperty(
default = "", default = "",
options = {'HIDDEN'} options = {'HIDDEN'}
) ) # type: ignore
def general_get_directory(self) -> str: def general_get_directory(self) -> str:
return self.directory return self.directory

View File

@ -2,6 +2,10 @@ import bpy, mathutils
import struct, os, io, typing import struct, os, io, typing
from . import UTIL_virtools_types from . import UTIL_virtools_types
## MARK:
# This module may be deprecated because the host refering this module,
# BM file import and export is no longer existing.
_FileWriter_t = io.BufferedWriter _FileWriter_t = io.BufferedWriter
_FileReader_t = io.BufferedReader _FileReader_t = io.BufferedReader
@ -31,10 +35,10 @@ def write_float(fs: _FileWriter_t, fl: float) -> None:
fs.write(struct.pack("<f", fl)) fs.write(struct.pack("<f", fl))
def write_world_matrix(fs: _FileWriter_t, mat: UTIL_virtools_types.VxMatrix) -> None: def write_world_matrix(fs: _FileWriter_t, mat: UTIL_virtools_types.VxMatrix) -> None:
fs.write(struct.pack("<16f", *mat.to_tuple())) fs.write(struct.pack("<16f", *mat.to_const()))
def write_color(fs: _FileWriter_t, colors: UTIL_virtools_types.VxColor) -> None: def write_color(fs: _FileWriter_t, colors: UTIL_virtools_types.VxColor) -> None:
fs.write(struct.pack("<fff", *colors.to_tuple_rgb())) fs.write(struct.pack("<fff", *colors.to_const_rgb()))
def write_uint32_array(fs: _FileWriter_t, vals: typing.Iterable[int], count: int) -> None: def write_uint32_array(fs: _FileWriter_t, vals: typing.Iterable[int], count: int) -> None:
fs.write(struct.pack('<' + str(count) + 'I', *vals)) fs.write(struct.pack('<' + str(count) + 'I', *vals))
@ -67,11 +71,11 @@ def read_string(fs: _FileReader_t) -> str:
count = read_uint32(fs) count = read_uint32(fs)
return fs.read(count * 4).decode("utf_32_le") return fs.read(count * 4).decode("utf_32_le")
def read_bool(fs: _FileReader_t) -> None: def read_bool(fs: _FileReader_t) -> bool:
return read_uint8(fs) != 0 return read_uint8(fs) != 0
def read_world_materix(fs: _FileReader_t, mat: UTIL_virtools_types.VxMatrix) -> None: def read_world_materix(fs: _FileReader_t, mat: UTIL_virtools_types.VxMatrix) -> None:
mat.from_tuple(struct.unpack("<16f", fs.read(16 * 4))) mat.from_const(struct.unpack("<16f", fs.read(16 * 4)))
def read_color(fs: _FileReader_t, target: UTIL_virtools_types.VxColor) -> None: def read_color(fs: _FileReader_t, target: UTIL_virtools_types.VxColor) -> None:
target.from_const_rgb(struct.unpack("fff", fs.read(3 * 4))) target.from_const_rgb(struct.unpack("fff", fs.read(3 * 4)))

View File

@ -1,7 +1,7 @@
import bpy import bpy
import enum, typing import enum, typing
from . import UTIL_virtools_types, UTIL_functions from . import UTIL_virtools_types, UTIL_functions
from . import PROP_ptrprop_resolver from . import PROP_ptrprop_resolver, PROP_ballance_map_info
## Intent ## Intent
# Some importer or exporter may share same properties. # Some importer or exporter may share same properties.
@ -152,14 +152,20 @@ class ImportParams():
) # type: ignore ) # type: ignore
def draw_import_params(self, layout: bpy.types.UILayout) -> None: def draw_import_params(self, layout: bpy.types.UILayout) -> None:
layout.label(text = 'Object Name Conflict') header: bpy.types.UILayout
layout.prop(self, 'object_conflict_strategy', text = '') body: bpy.types.UILayout
layout.label(text = 'Mesh Name Conflict') header, body = layout.panel("BBP_PT_ioport_shared_import_params", default_closed=False)
layout.prop(self, 'mesh_conflict_strategy', text = '') header.label(text = 'Import Parameters')
layout.label(text = 'Material Name Conflict') if body is None: return
layout.prop(self, 'material_conflict_strategy', text = '')
layout.label(text = 'Texture Name Conflict') body.label(text = 'Object Name Conflict')
layout.prop(self, 'texture_conflict_strategy', text = '') body.prop(self, 'object_conflict_strategy', text = '')
body.label(text = 'Mesh Name Conflict')
body.prop(self, 'mesh_conflict_strategy', text = '')
body.label(text = 'Material Name Conflict')
body.prop(self, 'material_conflict_strategy', text = '')
body.label(text = 'Texture Name Conflict')
body.prop(self, 'texture_conflict_strategy', text = '')
def general_get_texture_conflict_strategy(self) -> ConflictStrategy: def general_get_texture_conflict_strategy(self) -> ConflictStrategy:
return _g_EnumHelper_ConflictStrategy.get_selection(self.texture_conflict_strategy) return _g_EnumHelper_ConflictStrategy.get_selection(self.texture_conflict_strategy)
@ -191,16 +197,22 @@ class ExportParams():
) # type: ignore ) # type: ignore
def draw_export_params(self, layout: bpy.types.UILayout) -> None: def draw_export_params(self, layout: bpy.types.UILayout) -> None:
header: bpy.types.UILayout
body: bpy.types.UILayout
header, body = layout.panel("BBP_PT_ioport_shared_export_params", default_closed=False)
header.label(text = 'Export Parameters')
if body is None: return
# make prop expand horizontaly, not vertical. # make prop expand horizontaly, not vertical.
sublayout = layout.row() horizon_body = body.row()
# draw switch # draw switch
sublayout.prop(self, "export_mode", expand = True) horizon_body.prop(self, "export_mode", expand = True)
# draw picker # draw picker
if self.export_mode == 'COLLECTION': if self.export_mode == 'COLLECTION':
PROP_ptrprop_resolver.draw_export_collection(layout) PROP_ptrprop_resolver.draw_export_collection(body)
elif self.export_mode == 'OBJECT': elif self.export_mode == 'OBJECT':
PROP_ptrprop_resolver.draw_export_object(layout) PROP_ptrprop_resolver.draw_export_object(body)
def general_get_export_objects(self) -> tuple[bpy.types.Object] | None: def general_get_export_objects(self) -> tuple[bpy.types.Object] | None:
""" """
@ -216,6 +228,9 @@ class ExportParams():
if obj is None: return None if obj is None: return None
else: return (obj, ) else: return (obj, )
# define global tex save opt blender enum prop helper
_g_EnumHelper_CK_TEXTURE_SAVEOPTIONS: UTIL_virtools_types.EnumPropHelper = UTIL_virtools_types.EnumPropHelper(UTIL_virtools_types.CK_TEXTURE_SAVEOPTIONS)
class VirtoolsParams(): class VirtoolsParams():
vt_encodings: bpy.props.StringProperty( vt_encodings: bpy.props.StringProperty(
name = "Encodings", name = "Encodings",
@ -223,11 +238,95 @@ class VirtoolsParams():
default = UTIL_virtools_types.g_PyBMapDefaultEncoding default = UTIL_virtools_types.g_PyBMapDefaultEncoding
) # type: ignore ) # type: ignore
def draw_virtools_params(self, layout: bpy.types.UILayout) -> None: texture_save_opt: bpy.props.EnumProperty(
layout.label(text = 'Encodings') name = "Global Texture Save Options",
layout.prop(self, 'vt_encodings', text = '') description = "Decide how texture saved if texture is specified as Use Global as its Save Options.",
items = _g_EnumHelper_CK_TEXTURE_SAVEOPTIONS.generate_items(),
default = _g_EnumHelper_CK_TEXTURE_SAVEOPTIONS.to_selection(UTIL_virtools_types.CK_TEXTURE_SAVEOPTIONS.CKTEXTURE_EXTERNAL)
) # type: ignore
use_compress: bpy.props.BoolProperty(
name="Use Compress",
description = "Whether use ZLib to compress result when saving composition.",
default = True,
) # type: ignore
compress_level: bpy.props.IntProperty(
name = "Compress Level",
description = "The ZLib compress level used by Virtools Engine when saving composition.",
min = 1, max = 9,
default = 5,
) # type: ignore
def draw_virtools_params(self, layout: bpy.types.UILayout, is_importer: bool) -> None:
header: bpy.types.UILayout
body: bpy.types.UILayout
header, body = layout.panel("BBP_PT_ioport_shared_virtools_params", default_closed=False)
header.label(text = 'Virtools Parameters')
if body is None: return
# draw encodings
body.label(text = 'Encodings')
body.prop(self, 'vt_encodings', text = '')
# following field are only valid in exporter
if not is_importer:
body.separator()
body.label(text = 'Global Texture Save Options')
body.prop(self, 'texture_save_opt', text = '')
body.separator()
body.prop(self, 'use_compress')
if self.use_compress:
body.prop(self, 'compress_level')
def general_get_vt_encodings(self) -> tuple[str]: def general_get_vt_encodings(self) -> tuple[str]:
# get encoding, split it by `;` and strip blank chars. # get encoding, split it by `;` and strip blank chars.
encodings: str = self.vt_encodings encodings: str = self.vt_encodings
return tuple(map(lambda x: x.strip(), encodings.split(';'))) return tuple(map(lambda x: x.strip(), encodings.split(';')))
def general_get_texture_save_opt(self) -> UTIL_virtools_types.CK_TEXTURE_SAVEOPTIONS:
return _g_EnumHelper_CK_TEXTURE_SAVEOPTIONS.get_selection(self.texture_save_opt)
def general_get_use_compress(self) -> bool:
return self.use_compress
def general_get_compress_level(self) -> int:
return self.compress_level
class BallanceParams():
successive_sector: bpy.props.BoolProperty(
name="Successive Sector",
description = "Whether order exporter to use document specified sector count to make sure sector is successive.",
default = True,
) # type: ignore
def draw_ballance_params(self, layout: bpy.types.UILayout, is_importer: bool) -> None:
# ballance params only presented in exporter.
# so if we are in impoerter, we skip the whole function
# because we don't want to create an empty panel.
if is_importer: return
header: bpy.types.UILayout
body: bpy.types.UILayout
header, body = layout.panel("BBP_PT_ioport_shared_ballance_params", default_closed=False)
header.label(text = 'Ballance Parameters')
if body is None: return
map_info: PROP_ballance_map_info.RawBallanceMapInfo = PROP_ballance_map_info.get_raw_ballance_map_info(bpy.context.scene)
body.prop(self, 'successive_sector')
body.label(text = f'Map Sectors: {map_info.mSectorCount}')
def general_get_successive_sector(self) -> bool:
return self.successive_sector
def general_get_successive_sector_count(self) -> int:
# if user do not pick successive sector, return a random int directly.
if not self.general_get_successive_sector():
return 0
# otherwise fetch user specified sector number
map_info: PROP_ballance_map_info.RawBallanceMapInfo
map_info = PROP_ballance_map_info.get_raw_ballance_map_info(bpy.context.scene)
return map_info.mSectorCount