write shit
This commit is contained in:
parent
ca7e047c09
commit
ae9a848864
77
bbp_ng/OP_ADDS_component.py
Normal file
77
bbp_ng/OP_ADDS_component.py
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import bpy
|
||||||
|
from . import UTIL_functions, UTIL_icons_manager
|
||||||
|
from . import PROP_preferences, PROP_ballance_element, PROP_virtools_group
|
||||||
|
|
||||||
|
_g_UniqueElements = {
|
||||||
|
"PS_FourFlames": 'PS_FourFlames_01',
|
||||||
|
"PE_Balloon": 'PE_Balloon_01'
|
||||||
|
}
|
||||||
|
|
||||||
|
def _get_component_name(comp_name: str, comp_sector: int) -> str:
|
||||||
|
return '{}_{:0>2d}_'.format(comp_name, comp_sector)
|
||||||
|
|
||||||
|
class BBP_OT_add_component(bpy.types.Operator):
|
||||||
|
"""Add Element"""
|
||||||
|
bl_idname = "bbp.add_component"
|
||||||
|
bl_label = "Add Element"
|
||||||
|
bl_options = {'UNDO'}
|
||||||
|
|
||||||
|
element_sector: bpy.props.IntProperty(
|
||||||
|
name = "Sector",
|
||||||
|
description = "Define which sector the object will be grouped in",
|
||||||
|
min = 1, max = 999,
|
||||||
|
soft_min = 1, soft_max = 8,
|
||||||
|
default = 1,
|
||||||
|
)
|
||||||
|
|
||||||
|
element_type: bpy.props.EnumProperty(
|
||||||
|
name = "Type",
|
||||||
|
description = "This element type",
|
||||||
|
#items=tuple(map(lambda x: (x, x, ""), UTILS_constants.bmfile_componentList)),
|
||||||
|
items = tuple(
|
||||||
|
# token, display name, descriptions, icon, index
|
||||||
|
(str(item.value), item.name, "", UTIL_icons_manager.get_element_icon(item.name), item.value)
|
||||||
|
for item in PROP_ballance_element.BallanceElementType
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
wm = context.window_manager
|
||||||
|
return wm.invoke_props_dialog(self)
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
layout.prop(self, "element_type")
|
||||||
|
layout.prop(self, "element_sector")
|
||||||
|
|
||||||
|
# check for unique name and show warning
|
||||||
|
elename: str | None = _g_UniqueElements.get(PROP_ballance_element.BallanceElementType(int(self.element_type)).name, None)
|
||||||
|
if elename is not None and elename in bpy.data.objects:
|
||||||
|
layout.label(f'Warning: {elename} already exist.')
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
# create by ballance elements
|
||||||
|
eletype: PROP_ballance_element.BallanceElementType = PROP_ballance_element.BallanceElementType(int(self.element_type))
|
||||||
|
with PROP_ballance_element.BallanceElementsHelper(bpy.context.scene) as creator:
|
||||||
|
obj = bpy.data.objects.new(
|
||||||
|
_get_component_name(eletype.name, self.element_sector),
|
||||||
|
creator.get_element(eletype.value)
|
||||||
|
)
|
||||||
|
UTIL_functions.add_into_scene_and_move_to_cursor(obj)
|
||||||
|
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def draw_blc_menu(self, layout: bpy.types.UILayout):
|
||||||
|
for item in PROP_ballance_element.BallanceElementType:
|
||||||
|
cop = layout.operator(
|
||||||
|
self.bl_idname, text = item.name,
|
||||||
|
icon_value = UTIL_icons_manager.get_element_icon(item.name))
|
||||||
|
cop.element_type = str(item.value)
|
||||||
|
|
||||||
|
def register():
|
||||||
|
# register all classes
|
||||||
|
bpy.utils.register_class(BBP_OT_add_component)
|
||||||
|
|
||||||
|
def unregister():
|
||||||
|
bpy.utils.unregister_class(BBP_OT_add_component)
|
@ -318,7 +318,7 @@ class BBP_UL_ballance_elements(bpy.types.UIList):
|
|||||||
def draw_item(self, context, layout: bpy.types.UILayout, data, item: BBP_PG_ballance_element, icon, active_data, active_propname):
|
def draw_item(self, context, layout: bpy.types.UILayout, data, item: BBP_PG_ballance_element, icon, active_data, active_propname):
|
||||||
if item.element_name != "" and item.mesh_ptr is not None:
|
if item.element_name != "" and item.mesh_ptr is not None:
|
||||||
layout.label(text = item.element_name, translate = False)
|
layout.label(text = item.element_name, translate = False)
|
||||||
layout.label(text = item.mesh_ptr, translate = False, icon = 'MESH_DATA')
|
layout.label(text = item.mesh_ptr.name, translate = False, icon = 'MESH_DATA')
|
||||||
|
|
||||||
class BBP_OT_reset_ballance_elements(bpy.types.Operator):
|
class BBP_OT_reset_ballance_elements(bpy.types.Operator):
|
||||||
"""Reset all Meshes of Loaded Ballance Elements to Original Geometry."""
|
"""Reset all Meshes of Loaded Ballance Elements to Original Geometry."""
|
||||||
|
@ -5,11 +5,11 @@ from . import UTIL_naming_convension
|
|||||||
class RawPreferences():
|
class RawPreferences():
|
||||||
cBallanceTextureFolder: typing.ClassVar[str] = ""
|
cBallanceTextureFolder: typing.ClassVar[str] = ""
|
||||||
cNoComponentCollection: typing.ClassVar[str] = ""
|
cNoComponentCollection: typing.ClassVar[str] = ""
|
||||||
cDefaultNamingConvention: typing.ClassVar[int] = UTIL_naming_convension._EnumPropHelper.get_default_naming_identifier()
|
cDefaultNamingConvention: typing.ClassVar[UTIL_naming_convension.NamingConvention] = UTIL_naming_convension._EnumPropHelper.get_default_naming_identifier()
|
||||||
|
|
||||||
mBallanceTextureFolder: str
|
mBallanceTextureFolder: str
|
||||||
mNoComponentCollection: str
|
mNoComponentCollection: str
|
||||||
mDefaultNamingConvention: int
|
mDefaultNamingConvention: UTIL_naming_convension.NamingConvention
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
self.mBallanceTextureFolder = kwargs.get("mBallanceTextureFolder", "")
|
self.mBallanceTextureFolder = kwargs.get("mBallanceTextureFolder", "")
|
||||||
|
@ -109,14 +109,22 @@ class VirtoolsGroupsHelper():
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def intersect_groups(self, gnames: set[str]) -> set[str]:
|
||||||
|
self.__check_valid()
|
||||||
|
return self.__mGroupsSet.intersection(gnames)
|
||||||
|
|
||||||
def iterate_groups(self) -> typing.Iterator[str]:
|
def iterate_groups(self) -> typing.Iterator[str]:
|
||||||
self.__check_valid()
|
self.__check_valid()
|
||||||
return iter(self.__mGroupsSet)
|
return iter(self.__mGroupsSet)
|
||||||
|
|
||||||
def clear_groups(self):
|
def clear_groups(self) -> None:
|
||||||
self.__check_valid()
|
self.__check_valid()
|
||||||
self.__mNoChange = False
|
self.__mNoChange = False
|
||||||
self.__mGroupsSet.clear()
|
self.__mGroupsSet.clear()
|
||||||
|
|
||||||
|
def get_count(self) -> int:
|
||||||
|
self.__check_valid()
|
||||||
|
return len(self.__mGroupsSet)
|
||||||
|
|
||||||
def __write_to_virtools_groups(self) -> None:
|
def __write_to_virtools_groups(self) -> None:
|
||||||
groups: bpy.types.CollectionProperty = get_virtools_groups(self.__mAssocObj)
|
groups: bpy.types.CollectionProperty = get_virtools_groups(self.__mAssocObj)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import bpy
|
import bpy
|
||||||
import typing, enum
|
import typing, enum
|
||||||
from . import UTIL_virtools_types, UTIL_functions
|
from . import UTIL_virtools_types, UTIL_functions, UTIL_ballance_texture, UTIL_file_browser
|
||||||
from . import PROP_virtools_texture
|
from . import PROP_virtools_texture, PROP_preferences
|
||||||
|
|
||||||
class RawVirtoolsMaterial():
|
class RawVirtoolsMaterial():
|
||||||
|
|
||||||
@ -616,6 +616,50 @@ class BBP_OT_preset_virtools_material(bpy.types.Operator):
|
|||||||
preset_virtools_material(mtl, expected_preset)
|
preset_virtools_material(mtl, expected_preset)
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
class BBP_OT_direct_set_virtools_texture(bpy.types.Operator, UTIL_file_browser.ImportBallanceImage):
|
||||||
|
"""Import and Assign Texture Directly"""
|
||||||
|
bl_idname = "bbp.direct_set_virtools_texture"
|
||||||
|
bl_label = "Import and Assign Texture"
|
||||||
|
bl_options = {'UNDO'}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
# ballance texture order this
|
||||||
|
if not PROP_preferences.get_raw_preferences().has_valid_blc_tex_folder(): return False
|
||||||
|
# we only accept panel executing
|
||||||
|
if context.material is None: return False
|
||||||
|
# ok
|
||||||
|
return True
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
# preset tex folder
|
||||||
|
self.general_set_filename(PROP_preferences.get_raw_preferences().mBallanceTextureFolder)
|
||||||
|
return UTIL_file_browser.ImportBallanceImage.invoke(self, context, event)
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
# get assoc mtl
|
||||||
|
mtl: bpy.types.Material = context.material
|
||||||
|
rawmtl: RawVirtoolsMaterial = get_raw_virtools_material(mtl)
|
||||||
|
|
||||||
|
# import texture according to whether it is ballance texture
|
||||||
|
texture_filepath: str = self.general_get_filename()
|
||||||
|
try_filepath: str | None = UTIL_ballance_texture.get_ballance_texture_filename(texture_filepath)
|
||||||
|
tex: bpy.types.Image
|
||||||
|
if try_filepath is None:
|
||||||
|
# load as other texture
|
||||||
|
tex = UTIL_ballance_texture.load_other_texture(texture_filepath)
|
||||||
|
else:
|
||||||
|
# load as ballance texture
|
||||||
|
tex = UTIL_ballance_texture.load_ballance_texture(try_filepath)
|
||||||
|
|
||||||
|
# assign texture
|
||||||
|
rawmtl.mTexture = tex
|
||||||
|
set_raw_virtools_material(mtl, rawmtl)
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
class BBP_PT_virtools_material(bpy.types.Panel):
|
class BBP_PT_virtools_material(bpy.types.Panel):
|
||||||
@ -655,7 +699,11 @@ class BBP_PT_virtools_material(bpy.types.Panel):
|
|||||||
|
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.label(text="Texture Parameters")
|
layout.label(text="Texture Parameters")
|
||||||
layout.prop(props, 'texture', emboss = True)
|
# texture prop with direct importing
|
||||||
|
sublay = layout.row()
|
||||||
|
sublay.prop(props, 'texture', emboss = True)
|
||||||
|
sublay.operator(BBP_OT_direct_set_virtools_texture.bl_idname, text = '', icon = 'FILEBROWSER')
|
||||||
|
# texture detail
|
||||||
if props.texture is not None:
|
if props.texture is not None:
|
||||||
# have texture, show texture settings and enclosed by a border.
|
# have texture, show texture settings and enclosed by a border.
|
||||||
boxlayout = layout.box()
|
boxlayout = layout.box()
|
||||||
@ -694,6 +742,7 @@ def register():
|
|||||||
bpy.utils.register_class(BBP_PG_virtools_material)
|
bpy.utils.register_class(BBP_PG_virtools_material)
|
||||||
bpy.utils.register_class(BBP_OT_apply_virtools_material)
|
bpy.utils.register_class(BBP_OT_apply_virtools_material)
|
||||||
bpy.utils.register_class(BBP_OT_preset_virtools_material)
|
bpy.utils.register_class(BBP_OT_preset_virtools_material)
|
||||||
|
bpy.utils.register_class(BBP_OT_direct_set_virtools_texture)
|
||||||
bpy.utils.register_class(BBP_PT_virtools_material)
|
bpy.utils.register_class(BBP_PT_virtools_material)
|
||||||
|
|
||||||
# add into material metadata
|
# add into material metadata
|
||||||
@ -704,6 +753,7 @@ def unregister():
|
|||||||
del bpy.types.Material.virtools_material
|
del bpy.types.Material.virtools_material
|
||||||
|
|
||||||
bpy.utils.unregister_class(BBP_PT_virtools_material)
|
bpy.utils.unregister_class(BBP_PT_virtools_material)
|
||||||
|
bpy.utils.unregister_class(BBP_OT_direct_set_virtools_texture)
|
||||||
bpy.utils.unregister_class(BBP_OT_preset_virtools_material)
|
bpy.utils.unregister_class(BBP_OT_preset_virtools_material)
|
||||||
bpy.utils.unregister_class(BBP_OT_apply_virtools_material)
|
bpy.utils.unregister_class(BBP_OT_apply_virtools_material)
|
||||||
bpy.utils.unregister_class(BBP_PG_virtools_material)
|
bpy.utils.unregister_class(BBP_PG_virtools_material)
|
||||||
|
@ -31,6 +31,9 @@ class ImportBallanceImage(bpy_extras.io_utils.ImportHelper):
|
|||||||
options = {'HIDDEN'}
|
options = {'HIDDEN'}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def general_set_filename(self, filename: str) -> None:
|
||||||
|
self.filepath = filename
|
||||||
|
|
||||||
def general_get_filename(self) -> str:
|
def general_get_filename(self) -> str:
|
||||||
return self.filepath
|
return self.filepath
|
||||||
|
|
||||||
|
@ -51,3 +51,13 @@ def message_box(message: tuple[str, ...], title: str, icon: str):
|
|||||||
layout.label(text=item, translate=False)
|
layout.label(text=item, translate=False)
|
||||||
|
|
||||||
bpy.context.window_manager.popup_menu(draw, title = title, icon = icon)
|
bpy.context.window_manager.popup_menu(draw, title = title, icon = icon)
|
||||||
|
|
||||||
|
def move_to_cursor(obj: bpy.types.Object):
|
||||||
|
obj.location = bpy.context.scene.cursor.location
|
||||||
|
|
||||||
|
def add_into_scene_and_move_to_cursor(obj: bpy.types.Object):
|
||||||
|
move_to_cursor(obj)
|
||||||
|
|
||||||
|
view_layer = bpy.context.view_layer
|
||||||
|
collection = view_layer.active_layer_collection.collection
|
||||||
|
collection.objects.link(obj)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import bpy
|
import bpy
|
||||||
import typing, enum
|
import typing, enum, re
|
||||||
from . import UTIL_functions, UTIL_icons_manager
|
from . import UTIL_functions, UTIL_icons_manager
|
||||||
from . import PROP_virtools_group
|
from . import PROP_virtools_group
|
||||||
|
|
||||||
@ -125,19 +125,17 @@ class BallanceObjectInfo():
|
|||||||
return cls(basic_type)
|
return cls(basic_type)
|
||||||
|
|
||||||
class _NamingConventionProfile():
|
class _NamingConventionProfile():
|
||||||
_TNameFct = typing.Callable[[], str]
|
|
||||||
_TDescFct = typing.Callable[[], str]
|
|
||||||
_TParseFct = typing.Callable[[bpy.types.Object, _RenameErrorReporter | None], BallanceObjectInfo | None]
|
_TParseFct = typing.Callable[[bpy.types.Object, _RenameErrorReporter | None], BallanceObjectInfo | None]
|
||||||
_TSetFct = typing.Callable[[bpy.types.Object,BallanceObjectInfo, _RenameErrorReporter | None], bool]
|
_TSetFct = typing.Callable[[bpy.types.Object,BallanceObjectInfo, _RenameErrorReporter | None], bool]
|
||||||
|
|
||||||
mNameFct: _TNameFct
|
mName: str
|
||||||
mDescFct: _TDescFct
|
mDesc: str
|
||||||
mParseFct: _TParseFct
|
mParseFct: _TParseFct
|
||||||
mSetFct: _TSetFct
|
mSetFct: _TSetFct
|
||||||
|
|
||||||
def __init__(self, name_fct: _TNameFct, desc_fct: _TDescFct, parse_fct: _TParseFct, set_fct: _TSetFct):
|
def __init__(self, name: str, desc: str, parse_fct: _TParseFct, set_fct: _TSetFct):
|
||||||
self.mNameFct = name_fct
|
self.mName = name
|
||||||
self.mDescFct = desc_fct
|
self.mDesc = desc
|
||||||
self.mParseFct = parse_fct
|
self.mParseFct = parse_fct
|
||||||
self.mSetFct = set_fct
|
self.mSetFct = set_fct
|
||||||
|
|
||||||
@ -145,20 +143,214 @@ class _NamingConventionProfile():
|
|||||||
|
|
||||||
#region Naming Convention Declaration
|
#region Naming Convention Declaration
|
||||||
|
|
||||||
|
_g_BlcNormalComponents: set[str] = set((
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.P_Extra_Life.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.P_Extra_Point.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.P_Trafo_Paper.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.P_Trafo_Stone.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.P_Trafo_Wood.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.P_Ball_Paper.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.P_Ball_Stone.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.P_Ball_Wood.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.P_Box.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.P_Dome.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.P_Modul_01.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.P_Modul_03.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.P_Modul_08.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.P_Modul_17.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.P_Modul_18.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.P_Modul_19.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.P_Modul_25.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.P_Modul_26.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.P_Modul_29.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.P_Modul_30.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.P_Modul_34.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.P_Modul_37.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.P_Modul_41.value,
|
||||||
|
))
|
||||||
|
_g_BlcUniqueComponents: set[str] = set((
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.PS_Levelstart.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.PE_Levelende.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.PC_Checkpoints.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.PR_Resetpoints.value,
|
||||||
|
))
|
||||||
|
_g_BlcFloor: set[str] = set((
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.Sound_HitID_01.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.Sound_RollID_01.value,
|
||||||
|
))
|
||||||
|
_g_BlcWood: set[str] = set((
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.Sound_HitID_02.value,
|
||||||
|
PROP_virtools_group.VirtoolsGroupsPreset.Sound_RollID_02.value,
|
||||||
|
))
|
||||||
|
|
||||||
class _VirtoolsGroupConvention():
|
class _VirtoolsGroupConvention():
|
||||||
|
cRegexGroupSector: typing.ClassVar[re.Pattern] = re.compile('^Sector_(0[1-8]|[1-9][0-9]{1,2}|9)$')
|
||||||
|
cRegexComponent: typing.ClassVar[re.Pattern] = re.compile('^(' + '|'.join(_g_BlcNormalComponents) + ')_(0[1-9]|[1-9][0-9])_.*$')
|
||||||
|
cRegexPC: typing.ClassVar[re.Pattern] = re.compile('^PC_TwoFlames_(0[1-7])$')
|
||||||
|
cRegexPR: typing.ClassVar[re.Pattern] = re.compile('^PR_Resetpoint_(0[1-8])$')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def __get_pcpr_from_name(name: str, reporter: _RenameErrorReporter | None) -> BallanceObjectInfo | None:
|
||||||
|
regex_result = _VirtoolsGroupConvention.cRegexPC.match(name)
|
||||||
|
if regex_result is not None:
|
||||||
|
return BallanceObjectInfo.create_from_checkpoint(
|
||||||
|
int(regex_result.group(1))
|
||||||
|
)
|
||||||
|
regex_result = _VirtoolsGroupConvention.cRegexPR.match(name)
|
||||||
|
if regex_result is not None:
|
||||||
|
return BallanceObjectInfo.create_from_resetpoint(
|
||||||
|
int(regex_result.group(1))
|
||||||
|
)
|
||||||
|
|
||||||
|
if reporter: reporter.add_error("PC_Checkpoints or PR_Resetpoints detected. But couldn't get sector from name.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def __get_sector_from_groups(gps: typing.Iterator[str]) -> int | None:
|
||||||
|
# this counter is served for stupid
|
||||||
|
# multi-sector-grouping accident.
|
||||||
|
counter: int = 0
|
||||||
|
last_matched_sector: int = 0
|
||||||
|
for i in gps:
|
||||||
|
regex_result = _VirtoolsGroupConvention.cRegexGroupSector.match(i)
|
||||||
|
if regex_result is not None:
|
||||||
|
last_matched_sector = int(regex_result.group(1))
|
||||||
|
counter += 1
|
||||||
|
|
||||||
|
if counter != 1: return None
|
||||||
|
else: return last_matched_sector
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_from_object(obj: bpy.types.Object, reporter: _RenameErrorReporter | None) -> BallanceObjectInfo | None:
|
def parse_from_object(obj: bpy.types.Object, reporter: _RenameErrorReporter | None) -> BallanceObjectInfo | None:
|
||||||
return None
|
# create visitor
|
||||||
|
with PROP_virtools_group.VirtoolsGroupsHelper(obj) as gp:
|
||||||
|
# if no group, we should consider it is decoration or skylayer
|
||||||
|
if gp.get_count() == 0:
|
||||||
|
if obj.name == 'SkyLayer': return BallanceObjectInfo.create_from_others(BallanceObjectType.SKYLAYER)
|
||||||
|
else: return BallanceObjectInfo.create_from_others(BallanceObjectType.DECORATION)
|
||||||
|
|
||||||
|
# try to filter unique elements first
|
||||||
|
inter_gps: set[str] = gp.intersect_groups(_g_BlcUniqueComponents)
|
||||||
|
if len(inter_gps) == 1:
|
||||||
|
# get it
|
||||||
|
match((tuple(inter_gps))[0]):
|
||||||
|
case PROP_virtools_group.VirtoolsGroupsPreset.PS_Levelstart.value:
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.LEVEL_START)
|
||||||
|
case PROP_virtools_group.VirtoolsGroupsPreset.PE_Levelende.value:
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.LEVEL_END)
|
||||||
|
case PROP_virtools_group.VirtoolsGroupsPreset.PC_Checkpoints.value | PROP_virtools_group.VirtoolsGroupsPreset.PR_Resetpoints.value:
|
||||||
|
# these type's data should be gotten from its name
|
||||||
|
return _VirtoolsGroupConvention.__get_pcpr_from_name(obj.name, reporter)
|
||||||
|
case _:
|
||||||
|
if reporter: reporter.add_error("The match of Unique Component lost.")
|
||||||
|
return None
|
||||||
|
elif len(inter_gps) != 0:
|
||||||
|
if reporter: reporter.add_error("A Multi-grouping Unique Component.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# distinguish normal elements
|
||||||
|
inter_gps = gp.intersect_groups(_g_BlcNormalComponents)
|
||||||
|
if len(inter_gps) == 1:
|
||||||
|
# get it
|
||||||
|
# now try get its sector
|
||||||
|
gotten_elements: str = (tuple(inter_gps))[0]
|
||||||
|
gotten_sector: int | None = _VirtoolsGroupConvention.__get_sector_from_groups(gp.iterate_groups())
|
||||||
|
if gotten_sector is None:
|
||||||
|
# fail to get sector
|
||||||
|
if reporter: reporter.add_error("Component detected. But couldn't get sector from CKGroup data.")
|
||||||
|
return None
|
||||||
|
return BallanceObjectInfo.create_from_component(
|
||||||
|
gotten_elements,
|
||||||
|
gotten_sector
|
||||||
|
)
|
||||||
|
elif len(inter_gps) != 0:
|
||||||
|
# must be a weird grouping, report it
|
||||||
|
if reporter: reporter.add_error("A Multi-grouping Component.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# distinguish road
|
||||||
|
if gp.contain_group(PROP_virtools_group.VirtoolsGroupsPreset.Phys_FloorRails.value):
|
||||||
|
# rail
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.RAIL)
|
||||||
|
elif gp.contain_group(PROP_virtools_group.VirtoolsGroupsPreset.Phys_Floors.value):
|
||||||
|
# distinguish it between Floor and Wood
|
||||||
|
floor_result = gp.intersect_groups(_g_BlcFloor)
|
||||||
|
rail_result = gp.intersect_groups(_g_BlcWood)
|
||||||
|
if len(floor_result) > 0 and len(rail_result) == 0:
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.FLOOR)
|
||||||
|
elif len(floor_result) == 0 and len(rail_result) > 0:
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.WOOD)
|
||||||
|
else:
|
||||||
|
if reporter: reporter.add_warning("Can't distinguish object between Floors and Rails. Suppose it is Floors.")
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.FLOOR)
|
||||||
|
elif gp.contain_group(PROP_virtools_group.VirtoolsGroupsPreset.Phys_FloorStopper.value):
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.STOPPER)
|
||||||
|
elif gp.contain_group(PROP_virtools_group.VirtoolsGroupsPreset.DepthTestCubes.value):
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.DEPTH_CUBE)
|
||||||
|
|
||||||
|
# no matched
|
||||||
|
if reporter: reporter.add_error("Group match lost.")
|
||||||
|
return None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def set_to_object(obj: bpy.types.Object, info: BallanceObjectInfo, reporter: _RenameErrorReporter | None) -> bool:
|
def set_to_object(obj: bpy.types.Object, info: BallanceObjectInfo, reporter: _RenameErrorReporter | None) -> bool:
|
||||||
return False
|
# create visitor
|
||||||
|
with PROP_virtools_group.VirtoolsGroupsHelper(obj) as gp:
|
||||||
|
# match by basic type
|
||||||
|
match(info.mBasicType):
|
||||||
|
case BallanceObjectType.DECORATION: pass # decoration do not need group
|
||||||
|
case BallanceObjectType.SKYLAYER: pass # sky layer do not need group
|
||||||
|
|
||||||
|
case BallanceObjectType.LEVEL_START:
|
||||||
|
gp.add_group(PROP_virtools_group.VirtoolsGroupsPreset.PS_Levelstart.value)
|
||||||
|
case BallanceObjectType.LEVEL_END:
|
||||||
|
gp.add_group(PROP_virtools_group.VirtoolsGroupsPreset.PE_Levelende.value)
|
||||||
|
case BallanceObjectType.CHECKPOINT:
|
||||||
|
gp.add_group(PROP_virtools_group.VirtoolsGroupsPreset.PC_Checkpoints.value)
|
||||||
|
case BallanceObjectType.RESETPOINT:
|
||||||
|
gp.add_group(PROP_virtools_group.VirtoolsGroupsPreset.PR_Resetpoints.value)
|
||||||
|
|
||||||
|
case BallanceObjectType.DEPTH_CUBE:
|
||||||
|
gp.add_group(PROP_virtools_group.VirtoolsGroupsPreset.PE_Levelende.value)
|
||||||
|
|
||||||
|
case BallanceObjectType.FLOOR:
|
||||||
|
gp.add_group(PROP_virtools_group.VirtoolsGroupsPreset.Phys_Floors.value)
|
||||||
|
gp.add_group(PROP_virtools_group.VirtoolsGroupsPreset.Sound_HitID_01.value)
|
||||||
|
gp.add_group(PROP_virtools_group.VirtoolsGroupsPreset.Sound_RollID_01.value)
|
||||||
|
case BallanceObjectType.RAIL:
|
||||||
|
gp.add_group(PROP_virtools_group.VirtoolsGroupsPreset.Phys_FloorRails.value)
|
||||||
|
gp.add_group(PROP_virtools_group.VirtoolsGroupsPreset.Sound_HitID_02.value)
|
||||||
|
gp.add_group(PROP_virtools_group.VirtoolsGroupsPreset.Sound_RollID_02.value)
|
||||||
|
case BallanceObjectType.WOOD:
|
||||||
|
gp.add_group(PROP_virtools_group.VirtoolsGroupsPreset.Phys_Floors.value)
|
||||||
|
gp.add_group(PROP_virtools_group.VirtoolsGroupsPreset.Sound_HitID_03.value)
|
||||||
|
gp.add_group(PROP_virtools_group.VirtoolsGroupsPreset.Sound_RollID_03.value)
|
||||||
|
case BallanceObjectType.STOPPER:
|
||||||
|
gp.add_group(PROP_virtools_group.VirtoolsGroupsPreset.Phys_FloorStopper.value)
|
||||||
|
|
||||||
|
case BallanceObjectType.COMPONENT:
|
||||||
|
# group into component type
|
||||||
|
gp.add_group(info.mComponentType)
|
||||||
|
|
||||||
|
# group to sector
|
||||||
|
if info.mSector == 9:
|
||||||
|
gp.add_group('Sector_9')
|
||||||
|
else:
|
||||||
|
gp.add_group(f'Sector_{info.mSector:0>2d}')
|
||||||
|
|
||||||
|
case _:
|
||||||
|
if reporter is not None:
|
||||||
|
reporter.add_error('No matched info.')
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def register() -> _NamingConventionProfile:
|
def register() -> _NamingConventionProfile:
|
||||||
return _NamingConventionProfile(
|
return _NamingConventionProfile(
|
||||||
lambda: 'Virtools Group',
|
'Virtools Group',
|
||||||
lambda: 'Virtools Group',
|
'Virtools Group',
|
||||||
_VirtoolsGroupConvention.parse_from_object,
|
_VirtoolsGroupConvention.parse_from_object,
|
||||||
_VirtoolsGroupConvention.set_to_object
|
_VirtoolsGroupConvention.set_to_object
|
||||||
)
|
)
|
||||||
@ -166,42 +358,210 @@ class _VirtoolsGroupConvention():
|
|||||||
class _YYCToolchainConvention():
|
class _YYCToolchainConvention():
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_from_object(obj: bpy.types.Object, reporter: _RenameErrorReporter | None) -> BallanceObjectInfo | None:
|
def parse_from_object(obj: bpy.types.Object, reporter: _RenameErrorReporter | None) -> BallanceObjectInfo | None:
|
||||||
|
# check component first
|
||||||
|
regex_result = _VirtoolsGroupConvention.cRegexComponent.match(obj.name)
|
||||||
|
if regex_result is not None:
|
||||||
|
return BallanceObjectInfo.create_from_component(
|
||||||
|
regex_result.group(1),
|
||||||
|
int(regex_result.group(2))
|
||||||
|
)
|
||||||
|
|
||||||
|
# check PC PR elements
|
||||||
|
regex_result = _VirtoolsGroupConvention.cRegexPC.match(obj.name)
|
||||||
|
if regex_result is not None:
|
||||||
|
return BallanceObjectInfo.create_from_checkpoint(
|
||||||
|
int(regex_result.group(1))
|
||||||
|
)
|
||||||
|
regex_result = _VirtoolsGroupConvention.cRegexPR.match(obj.name)
|
||||||
|
if regex_result is not None:
|
||||||
|
return BallanceObjectInfo.create_from_resetpoint(
|
||||||
|
int(regex_result.group(1))
|
||||||
|
)
|
||||||
|
|
||||||
|
# check other unique elements
|
||||||
|
if obj.name == "PS_FourFlames_01":
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.LEVEL_START)
|
||||||
|
if obj.name == "PE_Balloon_01":
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.LEVEL_END)
|
||||||
|
|
||||||
|
# process floors
|
||||||
|
if obj.name.startswith("A_Floor"):
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.FLOOR)
|
||||||
|
if obj.name.startswith("A_Rail"):
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.RAIL)
|
||||||
|
if obj.name.startswith("A_Wood"):
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.WOOD)
|
||||||
|
if obj.name.startswith("A_Stopper"):
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.STOPPER)
|
||||||
|
|
||||||
|
# process others
|
||||||
|
if obj.name.startswith("DepthCubes"):
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.DEPTH_CUBE)
|
||||||
|
if obj.name.startswith("D_"):
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.DECORATION)
|
||||||
|
if obj.name == 'SkyLayer':
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.SKYLAYER)
|
||||||
|
|
||||||
|
if reporter is not None:
|
||||||
|
reporter.add_error("Name match lost.")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def set_to_object(obj: bpy.types.Object, info: BallanceObjectInfo, reporter: _RenameErrorReporter | None) -> bool:
|
def set_to_object(obj: bpy.types.Object, info: BallanceObjectInfo, reporter: _RenameErrorReporter | None) -> bool:
|
||||||
return False
|
match(info.mBasicType):
|
||||||
|
case BallanceObjectType.DECORATION:
|
||||||
|
obj.name = 'D_'
|
||||||
|
case BallanceObjectType.SKYLAYER:
|
||||||
|
obj.name = 'SkyLayer'
|
||||||
|
|
||||||
|
case BallanceObjectType.LEVEL_START:
|
||||||
|
obj.name = 'PS_FourFlames_01'
|
||||||
|
case BallanceObjectType.LEVEL_END:
|
||||||
|
obj.name = 'PE_Balloon_01'
|
||||||
|
case BallanceObjectType.CHECKPOINT:
|
||||||
|
obj.name = f'PR_Resetpoint_{info.mSector:0>2d}'
|
||||||
|
case BallanceObjectType.RESETPOINT:
|
||||||
|
obj.name = f'PC_TwoFlames_{info.mSector:0>2d}'
|
||||||
|
|
||||||
|
case BallanceObjectType.DEPTH_CUBE:
|
||||||
|
obj.name = 'DepthCubes_'
|
||||||
|
|
||||||
|
case BallanceObjectType.FLOOR:
|
||||||
|
obj.name = 'A_Floor_'
|
||||||
|
case BallanceObjectType.RAIL:
|
||||||
|
obj.name = 'A_Wood_'
|
||||||
|
case BallanceObjectType.WOOD:
|
||||||
|
obj.name = 'A_Rail_'
|
||||||
|
case BallanceObjectType.STOPPER:
|
||||||
|
obj.name = 'A_Stopper_'
|
||||||
|
|
||||||
|
case BallanceObjectType.COMPONENT:
|
||||||
|
obj.name = '{}_{:0>2d}_'.format(
|
||||||
|
info.mComponentType, info.mSector)
|
||||||
|
|
||||||
|
case _:
|
||||||
|
if reporter is not None:
|
||||||
|
reporter.add_error('No matched info.')
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def register() -> _NamingConventionProfile:
|
def register() -> _NamingConventionProfile:
|
||||||
return _NamingConventionProfile(
|
return _NamingConventionProfile(
|
||||||
lambda: 'YYC Toolchain',
|
'YYC Toolchain',
|
||||||
lambda: 'YYC Toolchain name standard.',
|
'YYC Toolchain name standard.',
|
||||||
_YYCToolchainConvention.parse_from_object,
|
_YYCToolchainConvention.parse_from_object,
|
||||||
_YYCToolchainConvention.set_to_object
|
_YYCToolchainConvention.set_to_object
|
||||||
)
|
)
|
||||||
|
|
||||||
class _ImengyuConvention():
|
class _ImengyuConvention():
|
||||||
|
cRegexComponent: typing.ClassVar[re.Pattern] = re.compile('^(' + '|'.join(_g_BlcNormalComponents) + '):[^:]*:([1-9]|[1-9][0-9])$')
|
||||||
|
cRegexPC: typing.ClassVar[re.Pattern] = re.compile('^PC_CheckPoint:([0-9]+)$')
|
||||||
|
cRegexPR: typing.ClassVar[re.Pattern] = re.compile('^PR_ResetPoint:([0-9]+)$')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_from_object(obj: bpy.types.Object, reporter: _RenameErrorReporter | None) -> BallanceObjectInfo | None:
|
def parse_from_object(obj: bpy.types.Object, reporter: _RenameErrorReporter | None) -> BallanceObjectInfo | None:
|
||||||
|
# check component first
|
||||||
|
regex_result = _ImengyuConvention.cRegexComponent.match(obj.name)
|
||||||
|
if regex_result is not None:
|
||||||
|
return BallanceObjectInfo.create_from_component(
|
||||||
|
regex_result.group(1),
|
||||||
|
int(regex_result.group(2))
|
||||||
|
)
|
||||||
|
|
||||||
|
# check PC PR elements
|
||||||
|
regex_result = _ImengyuConvention.cRegexPC.match(obj.name)
|
||||||
|
if regex_result is not None:
|
||||||
|
return BallanceObjectInfo.create_from_checkpoint(
|
||||||
|
int(regex_result.group(1))
|
||||||
|
)
|
||||||
|
regex_result = _ImengyuConvention.cRegexPR.match(obj.name)
|
||||||
|
if regex_result is not None:
|
||||||
|
return BallanceObjectInfo.create_from_resetpoint(
|
||||||
|
int(regex_result.group(1))
|
||||||
|
)
|
||||||
|
|
||||||
|
# check other unique elements
|
||||||
|
if obj.name == "PS_LevelStart":
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.LEVEL_START)
|
||||||
|
if obj.name == "PE_LevelEnd":
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.LEVEL_END)
|
||||||
|
|
||||||
|
# process floors
|
||||||
|
if obj.name.startswith("S_Floors"):
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.FLOOR)
|
||||||
|
if obj.name.startswith("S_FloorRails"):
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.RAIL)
|
||||||
|
if obj.name.startswith("S_FloorWoods"):
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.WOOD)
|
||||||
|
if obj.name.startswith("S_FloorStopper"):
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.STOPPER)
|
||||||
|
|
||||||
|
# process others
|
||||||
|
if obj.name.startswith("DepthTestCubes"):
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.DEPTH_CUBE)
|
||||||
|
if obj.name.startswith("O_"):
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.DECORATION)
|
||||||
|
if obj.name == 'SkyLayer':
|
||||||
|
return BallanceObjectInfo.create_from_others(BallanceObjectType.SKYLAYER)
|
||||||
|
|
||||||
|
if reporter is not None:
|
||||||
|
reporter.add_error("Name match lost.")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def set_to_object(obj: bpy.types.Object, info: BallanceObjectInfo, reporter: _RenameErrorReporter | None) -> bool:
|
def set_to_object(obj: bpy.types.Object, info: BallanceObjectInfo, reporter: _RenameErrorReporter | None) -> bool:
|
||||||
return False
|
match(info.mBasicType):
|
||||||
|
case BallanceObjectType.DECORATION:
|
||||||
|
obj.name = 'O_'
|
||||||
|
case BallanceObjectType.SKYLAYER:
|
||||||
|
obj.name = 'SkyLayer'
|
||||||
|
|
||||||
|
case BallanceObjectType.LEVEL_START:
|
||||||
|
obj.name = 'PS_LevelStart'
|
||||||
|
case BallanceObjectType.LEVEL_END:
|
||||||
|
obj.name = 'PE_LevelEnd'
|
||||||
|
case BallanceObjectType.CHECKPOINT:
|
||||||
|
obj.name = f'PR_ResetPoint:{info.mSector:d}'
|
||||||
|
case BallanceObjectType.RESETPOINT:
|
||||||
|
obj.name = f'PC_CheckPoint:{info.mSector:d}'
|
||||||
|
|
||||||
|
case BallanceObjectType.DEPTH_CUBE:
|
||||||
|
obj.name = 'DepthTestCubes'
|
||||||
|
|
||||||
|
case BallanceObjectType.FLOOR:
|
||||||
|
obj.name = 'S_Floors'
|
||||||
|
case BallanceObjectType.RAIL:
|
||||||
|
obj.name = 'S_FloorWoods'
|
||||||
|
case BallanceObjectType.WOOD:
|
||||||
|
obj.name = 'S_FloorRails'
|
||||||
|
case BallanceObjectType.STOPPER:
|
||||||
|
obj.name = 'S_FloorStopper'
|
||||||
|
|
||||||
|
case BallanceObjectType.COMPONENT:
|
||||||
|
obj.name = '{}:{}:{:d}'.format(
|
||||||
|
info.mComponentType, obj.name.replace(':', '_'), info.mSector)
|
||||||
|
|
||||||
|
case _:
|
||||||
|
if reporter is not None:
|
||||||
|
reporter.add_error('No matched info.')
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def register() -> _NamingConventionProfile:
|
def register() -> _NamingConventionProfile:
|
||||||
return _NamingConventionProfile(
|
return _NamingConventionProfile(
|
||||||
lambda: 'Imengyu Ballance',
|
'Imengyu Ballance',
|
||||||
lambda: 'Auto grouping name standard for Imengyu/Ballance.',
|
'Auto grouping name standard for Imengyu/Ballance.',
|
||||||
_ImengyuConvention.parse_from_object,
|
_ImengyuConvention.parse_from_object,
|
||||||
_ImengyuConvention.set_to_object
|
_ImengyuConvention.set_to_object
|
||||||
)
|
)
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Nameing Convention Register
|
#region Naming Convention Register
|
||||||
|
|
||||||
## All available naming conventions
|
## All available naming conventions
|
||||||
# Each naming convention should have a identifier for visiting them.
|
# Each naming convention should have a identifier for visiting them.
|
||||||
@ -213,19 +573,11 @@ def _register_naming_convention_with_index(profile: _NamingConventionProfile) ->
|
|||||||
_g_NamingConventions.append(profile)
|
_g_NamingConventions.append(profile)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
# register native and default one and others
|
# register and assign to a enum
|
||||||
# but only native one and default one need keep its index
|
class NamingConvention(enum.IntEnum):
|
||||||
#
|
VirtoolsGroup = _register_naming_convention_with_index(_VirtoolsGroupConvention.register())
|
||||||
# The native naming convention is Virtools Group
|
YYCToolchain = _register_naming_convention_with_index(_YYCToolchainConvention.register())
|
||||||
# We treat it as naming convention because we want use a universal interface to process naming converting.
|
Imengyu = _register_naming_convention_with_index(_ImengyuConvention.register())
|
||||||
# So Virtools Group can no be seen as a naming convention, but we treat it like naming convention in code.
|
|
||||||
# The "native" mean this is
|
|
||||||
#
|
|
||||||
# The default fallback naming convention is YYC toolchain
|
|
||||||
#
|
|
||||||
_g_NativeNamingConventionIndex: int = _register_naming_convention_with_index(_VirtoolsGroupConvention.register())
|
|
||||||
_g_DefaultNamingConventionIndex: int = _register_naming_convention_with_index(_YYCToolchainConvention.register())
|
|
||||||
_register_naming_convention_with_index(_ImengyuConvention.register())
|
|
||||||
|
|
||||||
class _EnumPropHelper():
|
class _EnumPropHelper():
|
||||||
"""
|
"""
|
||||||
@ -238,52 +590,56 @@ class _EnumPropHelper():
|
|||||||
# create a function to filter Virtools Group profile
|
# create a function to filter Virtools Group profile
|
||||||
# and return index at the same time
|
# and return index at the same time
|
||||||
def naming_convention_iter() -> typing.Iterator[tuple[int, _NamingConventionProfile]]:
|
def naming_convention_iter() -> typing.Iterator[tuple[int, _NamingConventionProfile]]:
|
||||||
for idx, item in enumerate(_g_NamingConventions):
|
for item in NamingConvention:
|
||||||
if idx != _g_NativeNamingConventionIndex:
|
if item != NamingConvention.VirtoolsGroup:
|
||||||
yield (idx, item)
|
yield (item.value, _g_NamingConventions[item.value])
|
||||||
|
|
||||||
# token, display name, descriptions, icon, index
|
# token, display name, descriptions, icon, index
|
||||||
return tuple(
|
return tuple(
|
||||||
(
|
(
|
||||||
str(idx),
|
str(idx),
|
||||||
item.mNameFct(),
|
item.mName,
|
||||||
item.mDescFct(),
|
item.mDesc,
|
||||||
"",
|
"",
|
||||||
idx
|
idx
|
||||||
) for idx, item in naming_convention_iter()
|
) for idx, item in naming_convention_iter()
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_selection(prop: str) -> int:
|
def get_selection(prop: str) -> NamingConvention:
|
||||||
return int(prop)
|
return NamingConvention(int(prop))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def to_selection(val: int) -> str:
|
def to_selection(val: NamingConvention) -> str:
|
||||||
return str(val)
|
return str(val.value)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_virtools_group_identifier() -> int:
|
def get_virtools_group_identifier() -> NamingConvention:
|
||||||
return _g_NativeNamingConventionIndex
|
# The native naming convention is Virtools Group
|
||||||
|
# We treat it as naming convention because we want use a universal interface to process naming converting.
|
||||||
|
# So Virtools Group can no be seen as a naming convention, but we treat it like naming convention in code.
|
||||||
|
return NamingConvention.VirtoolsGroup
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_default_naming_identifier() -> int:
|
def get_default_naming_identifier() -> NamingConvention:
|
||||||
return _g_DefaultNamingConventionIndex
|
# The default fallback naming convention is YYC toolchain
|
||||||
|
return NamingConvention.YYCToolchain
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
def name_setter_core(ident: int, info: BallanceObjectInfo, obj: bpy.types.Object) -> None:
|
def name_setter_core(ident: NamingConvention, info: BallanceObjectInfo, obj: bpy.types.Object) -> None:
|
||||||
# get profile
|
# get profile
|
||||||
profile: _NamingConventionProfile = _g_NamingConventions[ident]
|
profile: _NamingConventionProfile = _g_NamingConventions[ident.value]
|
||||||
# set name. don't care whether success.
|
# set name. don't care whether success.
|
||||||
profile.mSetFct(obj, info, None)
|
profile.mSetFct(obj, info, None)
|
||||||
|
|
||||||
def name_converting_core(src_ident: int, dst_ident: int, objs: typing.Iterable[bpy.types.Object]) -> None:
|
def name_converting_core(src_ident: NamingConvention, dst_ident: NamingConvention, objs: typing.Iterable[bpy.types.Object]) -> None:
|
||||||
# no convert needed
|
# no convert needed
|
||||||
if src_ident == dst_ident: return
|
if src_ident == dst_ident: return
|
||||||
|
|
||||||
# get convert profile
|
# get convert profile
|
||||||
src: _NamingConventionProfile = _g_NamingConventions[src_ident]
|
src: _NamingConventionProfile = _g_NamingConventions[src_ident.value]
|
||||||
dst: _NamingConventionProfile = _g_NamingConventions[dst_ident]
|
dst: _NamingConventionProfile = _g_NamingConventions[dst_ident.value]
|
||||||
|
|
||||||
# create reporter and success counter
|
# create reporter and success counter
|
||||||
failed_obj_counter: int = 0
|
failed_obj_counter: int = 0
|
||||||
@ -327,4 +683,3 @@ def name_converting_core(src_ident: int, dst_ident: int, objs: typing.Iterable[b
|
|||||||
"Rename Report",
|
"Rename Report",
|
||||||
UTIL_icons_manager.BlenderPresetIcons.Info.value
|
UTIL_icons_manager.BlenderPresetIcons.Info.value
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ UTIL_icons_manager.register()
|
|||||||
from . import PROP_preferences, PROP_ptrprop_resolver, PROP_virtools_material, PROP_virtools_texture, PROP_virtools_mesh, PROP_ballance_element, PROP_virtools_group
|
from . import PROP_preferences, PROP_ptrprop_resolver, PROP_virtools_material, PROP_virtools_texture, PROP_virtools_mesh, PROP_ballance_element, PROP_virtools_group
|
||||||
from . import OP_IMPORT_bmfile, OP_EXPORT_bmfile, OP_IMPORT_virtools, OP_EXPORT_virtools
|
from . import OP_IMPORT_bmfile, OP_EXPORT_bmfile, OP_IMPORT_virtools, OP_EXPORT_virtools
|
||||||
from . import OP_UV_flatten_uv, OP_UV_rail_uv
|
from . import OP_UV_flatten_uv, OP_UV_rail_uv
|
||||||
|
from . import OP_ADDS_component
|
||||||
|
|
||||||
#region Menu
|
#region Menu
|
||||||
|
|
||||||
@ -47,6 +48,43 @@ class BBP_MT_View3DMenu(bpy.types.Menu):
|
|||||||
layout.operator(OP_UV_flatten_uv.BBP_OT_flatten_uv.bl_idname)
|
layout.operator(OP_UV_flatten_uv.BBP_OT_flatten_uv.bl_idname)
|
||||||
layout.operator(OP_UV_rail_uv.BBP_OT_rail_uv.bl_idname)
|
layout.operator(OP_UV_rail_uv.BBP_OT_rail_uv.bl_idname)
|
||||||
|
|
||||||
|
class BBP_MT_AddFloorMenu(bpy.types.Menu):
|
||||||
|
"""Add Ballance Floor"""
|
||||||
|
bl_idname = "BBP_MT_AddFloorMenu"
|
||||||
|
bl_label = "Floors"
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
|
||||||
|
layout.label(text="Basic floor")
|
||||||
|
|
||||||
|
layout.separator()
|
||||||
|
layout.label(text="Derived floor")
|
||||||
|
class BBP_MT_AddRailMenu(bpy.types.Menu):
|
||||||
|
"""Add Ballance Rail"""
|
||||||
|
bl_idname = "BBP_MT_AddRailMenu"
|
||||||
|
bl_label = "Rails"
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
class BBP_MT_AddElementsMenu(bpy.types.Menu):
|
||||||
|
"""Add Ballance Elements"""
|
||||||
|
bl_idname = "BBP_MT_AddElementsMenu"
|
||||||
|
bl_label = "Elements"
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
|
||||||
|
layout.label(text="Basic Elements")
|
||||||
|
OP_ADDS_component.BBP_OT_add_component.draw_blc_menu(layout)
|
||||||
|
|
||||||
|
layout.separator()
|
||||||
|
layout.label(text="Duplicated Elements")
|
||||||
|
#OBJS_add_components.BBP_OT_add_components_dup.draw_blc_menu(layout)
|
||||||
|
|
||||||
|
layout.separator()
|
||||||
|
layout.label(text="Elements Pair")
|
||||||
|
#OBJS_add_components.BBP_OT_add_components_series.draw_blc_menu(layout)
|
||||||
|
|
||||||
# ===== Menu Drawer =====
|
# ===== Menu Drawer =====
|
||||||
|
|
||||||
MenuDrawer_t = typing.Callable[[typing.Any, typing.Any], None]
|
MenuDrawer_t = typing.Callable[[typing.Any, typing.Any], None]
|
||||||
@ -65,12 +103,25 @@ def menu_drawer_view3d(self, context):
|
|||||||
layout: bpy.types.UILayout = self.layout
|
layout: bpy.types.UILayout = self.layout
|
||||||
layout.menu(BBP_MT_View3DMenu.bl_idname)
|
layout.menu(BBP_MT_View3DMenu.bl_idname)
|
||||||
|
|
||||||
|
def menu_drawer_add(self, context):
|
||||||
|
layout: bpy.types.UILayout = self.layout
|
||||||
|
layout.separator()
|
||||||
|
layout.label(text="Ballance")
|
||||||
|
layout.menu(BBP_MT_AddFloorMenu.bl_idname, icon='MESH_CUBE')
|
||||||
|
layout.menu(BBP_MT_AddRailMenu.bl_idname, icon='MESH_CIRCLE')
|
||||||
|
layout.menu(BBP_MT_AddElementsMenu.bl_idname, icon='MESH_ICOSPHERE')
|
||||||
|
#layout.operator_menu_enum(
|
||||||
|
# OBJS_add_components.BALLANCE_OT_add_components.bl_idname,
|
||||||
|
# "elements_type", icon='MESH_ICOSPHERE', text="Elements")
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Register and Unregister.
|
#region Register and Unregister.
|
||||||
|
|
||||||
g_BldClasses: tuple[typing.Any, ...] = (
|
g_BldClasses: tuple[typing.Any, ...] = (
|
||||||
BBP_MT_View3DMenu,
|
BBP_MT_View3DMenu,
|
||||||
|
BBP_MT_AddFloorMenu,
|
||||||
|
BBP_MT_AddRailMenu,
|
||||||
|
BBP_MT_AddElementsMenu
|
||||||
)
|
)
|
||||||
|
|
||||||
class MenuEntry():
|
class MenuEntry():
|
||||||
@ -86,6 +137,7 @@ g_BldMenus: tuple[MenuEntry, ...] = (
|
|||||||
MenuEntry(bpy.types.VIEW3D_MT_editor_menus, False, menu_drawer_view3d),
|
MenuEntry(bpy.types.VIEW3D_MT_editor_menus, False, menu_drawer_view3d),
|
||||||
MenuEntry(bpy.types.TOPBAR_MT_file_import, True, menu_drawer_import),
|
MenuEntry(bpy.types.TOPBAR_MT_file_import, True, menu_drawer_import),
|
||||||
MenuEntry(bpy.types.TOPBAR_MT_file_export, True, menu_drawer_export),
|
MenuEntry(bpy.types.TOPBAR_MT_file_export, True, menu_drawer_export),
|
||||||
|
MenuEntry(bpy.types.VIEW3D_MT_add, True, menu_drawer_add),
|
||||||
)
|
)
|
||||||
|
|
||||||
def register() -> None:
|
def register() -> None:
|
||||||
@ -106,6 +158,7 @@ def register() -> None:
|
|||||||
|
|
||||||
OP_UV_rail_uv.register()
|
OP_UV_rail_uv.register()
|
||||||
OP_UV_flatten_uv.register()
|
OP_UV_flatten_uv.register()
|
||||||
|
OP_ADDS_component.register()
|
||||||
|
|
||||||
# register other classes
|
# register other classes
|
||||||
for cls in g_BldClasses:
|
for cls in g_BldClasses:
|
||||||
@ -128,6 +181,7 @@ def unregister() -> None:
|
|||||||
bpy.utils.unregister_class(cls)
|
bpy.utils.unregister_class(cls)
|
||||||
|
|
||||||
# unregister modules
|
# unregister modules
|
||||||
|
OP_ADDS_component.unregister()
|
||||||
OP_UV_flatten_uv.unregister()
|
OP_UV_flatten_uv.unregister()
|
||||||
OP_UV_rail_uv.unregister()
|
OP_UV_rail_uv.unregister()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user