refactor: rename some operators and modules.
- rename module OP_MTL_fix_all_material to OP_MTL_fix_all_materials. - rename operator BBP_OT_fix_all_material to BBP_OT_fix_all_materials. - rename module UTIL_naming_convension to UTIL_naming_convention. - change some translation contexts to correspond with this change.
This commit is contained in:
669
bbp_ng/UTIL_naming_convention.py
Normal file
669
bbp_ng/UTIL_naming_convention.py
Normal file
@ -0,0 +1,669 @@
|
||||
import bpy
|
||||
import typing, enum, re
|
||||
from . import UTIL_functions
|
||||
from . import PROP_virtools_group
|
||||
|
||||
#region Rename Error Reporter
|
||||
|
||||
class _RenameErrorType(enum.IntEnum):
|
||||
ERROR = enum.auto()
|
||||
WARNING = enum.auto()
|
||||
INFO = enum.auto()
|
||||
|
||||
class _RenameErrorItem():
|
||||
mErrType: _RenameErrorType
|
||||
mDescription: str
|
||||
|
||||
def __init__(self, err_t: _RenameErrorType, description: str):
|
||||
self.mErrType = err_t
|
||||
self.mDescription = description
|
||||
|
||||
class RenameErrorReporter():
|
||||
"""
|
||||
A basic 'rename error report' using simple prints in console.
|
||||
|
||||
This object can be used as a context manager.
|
||||
|
||||
It supports multiple levels of 'substeps' - you shall always enter at least one substep (because level 0
|
||||
has only one single step, representing the whole 'area' of the progress stuff).
|
||||
|
||||
You should give the object renaming of substeps each time you enter a new one.
|
||||
|
||||
Leaving a substep automatically steps by one the parent level.
|
||||
|
||||
```
|
||||
with RenameErrorReporter() as reporter:
|
||||
progress.enter_object(obj)
|
||||
|
||||
# process for object with reporter
|
||||
reporter.add_error('fork!')
|
||||
|
||||
progress.leave_object()
|
||||
```
|
||||
"""
|
||||
mAllObjCounter: int
|
||||
mFailedObjCounter: int
|
||||
|
||||
mErrList: list[_RenameErrorItem]
|
||||
mOldName: str
|
||||
mHasError: bool
|
||||
|
||||
def __init__(self):
|
||||
self.mAllObjCounter = 0
|
||||
self.mFailedObjCounter = 0
|
||||
|
||||
self.mErrList = []
|
||||
self.mOldName = ""
|
||||
self.mHasError = False
|
||||
|
||||
def add_error(self, description: str):
|
||||
self.mHasError = True
|
||||
self.mErrList.append(_RenameErrorItem(_RenameErrorType.ERROR, description))
|
||||
def add_warning(self, description: str):
|
||||
self.mErrList.append(_RenameErrorItem(_RenameErrorType.WARNING, description))
|
||||
def add_info(self, description: str):
|
||||
self.mErrList.append(_RenameErrorItem(_RenameErrorType.INFO, description))
|
||||
|
||||
def get_all_objs_count(self) -> int: return self.mAllObjCounter
|
||||
def get_failed_objs_count(self) -> int: return self.mFailedObjCounter
|
||||
|
||||
def __enter__(self):
|
||||
# print console report header
|
||||
print('============')
|
||||
print(bpy.app.translations.pgettext_rpt(
|
||||
'Rename Report',
|
||||
'BBP/UTIL_naming_convention.RenameErrorReporter'
|
||||
))
|
||||
print('------------')
|
||||
# return self as context
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
# print console report tail
|
||||
print('------------')
|
||||
tr_text: str = bpy.app.translations.pgettext_rpt(
|
||||
'All / Failed - {0} / {1}', 'BBP/UTIL_naming_convention.RenameErrorReporter')
|
||||
print(tr_text.format(self.mAllObjCounter, self.mFailedObjCounter))
|
||||
print('============')
|
||||
# reset variables
|
||||
self.mAllObjCounter = 0
|
||||
self.mFailedObjCounter = 0
|
||||
|
||||
def enter_object(self, obj: bpy.types.Object) -> None:
|
||||
# inc all counter
|
||||
self.mAllObjCounter += 1
|
||||
# assign old name
|
||||
self.mOldName = obj.name
|
||||
def leave_object(self, obj:bpy.types.Object) -> None:
|
||||
# if error list is empty, no need to report
|
||||
if len(self.mErrList) == 0: return
|
||||
|
||||
# inc failed if necessary
|
||||
if self.mHasError:
|
||||
self.mFailedObjCounter += 1
|
||||
|
||||
# output header
|
||||
# if new name is different with old name, output both of them
|
||||
tr_text: str
|
||||
new_name: str = obj.name
|
||||
if self.mOldName == new_name:
|
||||
tr_text = bpy.app.translations.pgettext_rpt('For object "{0}"', 'BBP/UTIL_naming_convention.RenameErrorReporter')
|
||||
print(tr_text.format(new_name))
|
||||
else:
|
||||
tr_text = bpy.app.translations.pgettext_rpt('For object "{0}" (Old name: "{1}")', 'BBP/UTIL_naming_convention.RenameErrorReporter')
|
||||
print(tr_text.format(new_name, self.mOldName))
|
||||
|
||||
# output error list with indent
|
||||
for item in self.mErrList:
|
||||
print('\t' + RenameErrorReporter.__erritem_to_string(item))
|
||||
|
||||
# clear error list for next object
|
||||
self.mErrList.clear()
|
||||
self.mHasError = False
|
||||
|
||||
@staticmethod
|
||||
def __errtype_to_string(err_v: _RenameErrorType) -> str:
|
||||
match(err_v):
|
||||
case _RenameErrorType.ERROR:
|
||||
return bpy.app.translations.pgettext_rpt('ERROR', 'BBP/UTIL_naming_convention.RenameErrorReporter')
|
||||
case _RenameErrorType.WARNING:
|
||||
return bpy.app.translations.pgettext_rpt('WARN', 'BBP/UTIL_naming_convention.RenameErrorReporter')
|
||||
case _RenameErrorType.INFO:
|
||||
return bpy.app.translations.pgettext_rpt('INFO', 'BBP/UTIL_naming_convention.RenameErrorReporter')
|
||||
case _: raise UTIL_functions.BBPException("Unknown error type.")
|
||||
@staticmethod
|
||||
def __erritem_to_string(item: _RenameErrorItem) -> str:
|
||||
return f'[{RenameErrorReporter.__errtype_to_string(item.mErrType)}]\t{item.mDescription}'
|
||||
|
||||
#endregion
|
||||
|
||||
#region Naming Convention Used Types
|
||||
|
||||
class BallanceObjectType(enum.IntEnum):
|
||||
COMPONENT = enum.auto()
|
||||
|
||||
FLOOR = enum.auto()
|
||||
RAIL = enum.auto()
|
||||
WOOD = enum.auto()
|
||||
STOPPER = enum.auto()
|
||||
|
||||
LEVEL_START = enum.auto()
|
||||
LEVEL_END = enum.auto()
|
||||
CHECKPOINT = enum.auto()
|
||||
RESETPOINT = enum.auto()
|
||||
|
||||
DEPTH_CUBE = enum.auto()
|
||||
SKYLAYER = enum.auto()
|
||||
|
||||
DECORATION = enum.auto()
|
||||
|
||||
class BallanceObjectInfo():
|
||||
mBasicType: BallanceObjectType
|
||||
|
||||
## Only available for COMPONENT basic type
|
||||
mComponentType: str | None
|
||||
## Only available for COMPONENT, CHECKPOINT, RESETPOINT basic type
|
||||
# For COMPONENT, it indicate which sector this component belong to.
|
||||
# For CHECKPOINT, RESETPOINT, it indicate the index of this object.
|
||||
# In CHECKPOINT, RESETPOINT mode, the sector actually is the suffix number of these objects' name. So checkpoint starts with 1, not 0.
|
||||
mSector: int | None
|
||||
|
||||
def __init__(self, basic_type: BallanceObjectType):
|
||||
self.mBasicType = basic_type
|
||||
|
||||
@classmethod
|
||||
def create_from_component(cls, comp_type: str, sector: int):
|
||||
inst = cls(BallanceObjectType.COMPONENT)
|
||||
inst.mComponentType = comp_type
|
||||
inst.mSector = sector
|
||||
return inst
|
||||
|
||||
@classmethod
|
||||
def create_from_checkpoint(cls, sector: int):
|
||||
inst = cls(BallanceObjectType.CHECKPOINT)
|
||||
inst.mSector = sector
|
||||
return inst
|
||||
@classmethod
|
||||
def create_from_resetpoint(cls, sector: int):
|
||||
inst = cls(BallanceObjectType.RESETPOINT)
|
||||
inst.mSector = sector
|
||||
return inst
|
||||
|
||||
@classmethod
|
||||
def create_from_others(cls, basic_type: BallanceObjectType):
|
||||
return cls(basic_type)
|
||||
|
||||
#endregion
|
||||
|
||||
#region Sector Extractor
|
||||
|
||||
_g_RegexBlcSectorGroup: re.Pattern = re.compile('^Sector_(0[1-8]|[1-9][0-9]{1,2}|9)$')
|
||||
|
||||
def extract_sector_from_name(group_name: str) -> int | None:
|
||||
"""
|
||||
A convenient function to extract sector index from given group name.
|
||||
This function also supports 999 sector plugin.
|
||||
|
||||
Not only in this module, but also in outside modules, this function is vary used to extract sector index info.
|
||||
|
||||
Function return the index extracted, or None if given group name is not a valid sector group.
|
||||
The valid sector index is range from 1 to 999 (inclusive)
|
||||
"""
|
||||
regex_result = _g_RegexBlcSectorGroup.match(group_name)
|
||||
if regex_result is not None:
|
||||
return int(regex_result.group(1))
|
||||
else:
|
||||
return None
|
||||
|
||||
def build_name_from_sector_index(sector_index: int) -> str:
|
||||
"""
|
||||
A convenient function to build Ballance recognizable sector group name.
|
||||
This function also supports 999 sector plugin.
|
||||
|
||||
This function also is used in this module or other modules outside.
|
||||
|
||||
Function return a sector name string. It basically the reverse operation of `extract_sector_from_name`.
|
||||
"""
|
||||
if sector_index == 9:
|
||||
return 'Sector_9'
|
||||
else:
|
||||
return f'Sector_{sector_index:0>2d}'
|
||||
|
||||
#endregion
|
||||
|
||||
#region Naming Convention Declaration
|
||||
|
||||
_g_BlcNormalComponents: set[str] = set((
|
||||
"P_Extra_Life",
|
||||
"P_Extra_Point",
|
||||
"P_Trafo_Paper",
|
||||
"P_Trafo_Stone",
|
||||
"P_Trafo_Wood",
|
||||
"P_Ball_Paper",
|
||||
"P_Ball_Stone",
|
||||
"P_Ball_Wood",
|
||||
"P_Box",
|
||||
"P_Dome",
|
||||
"P_Modul_01",
|
||||
"P_Modul_03",
|
||||
"P_Modul_08",
|
||||
"P_Modul_17",
|
||||
"P_Modul_18",
|
||||
"P_Modul_19",
|
||||
"P_Modul_25",
|
||||
"P_Modul_26",
|
||||
"P_Modul_29",
|
||||
"P_Modul_30",
|
||||
"P_Modul_34",
|
||||
"P_Modul_37",
|
||||
"P_Modul_41"
|
||||
))
|
||||
_g_BlcUniqueComponents: set[str] = set((
|
||||
"PS_Levelstart",
|
||||
"PE_Levelende",
|
||||
"PC_Checkpoints",
|
||||
"PR_Resetpoints"
|
||||
))
|
||||
_g_BlcFloor: set[str] = set((
|
||||
"Sound_HitID_01",
|
||||
"Sound_RollID_01"
|
||||
))
|
||||
_g_BlcWood: set[str] = set((
|
||||
"Sound_HitID_02",
|
||||
"Sound_RollID_02"
|
||||
))
|
||||
|
||||
class VirtoolsGroupConvention():
|
||||
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))
|
||||
)
|
||||
|
||||
tr_text: str = bpy.app.translations.pgettext_rpt(
|
||||
"PC_Checkpoints or PR_Resetpoints detected. But couldn't get sector from name.", 'BBP/UTIL_naming_convention.VirtoolsGroupConvention')
|
||||
if reporter: reporter.add_error(tr_text)
|
||||
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: int | None = extract_sector_from_name(i)
|
||||
if regex_result is not None:
|
||||
last_matched_sector = regex_result
|
||||
counter += 1
|
||||
|
||||
if counter != 1: return None
|
||||
else: return last_matched_sector
|
||||
|
||||
@staticmethod
|
||||
def parse_from_object(obj: bpy.types.Object, reporter: RenameErrorReporter | None) -> BallanceObjectInfo | None:
|
||||
# declare translation string type
|
||||
tr_text: str
|
||||
|
||||
# 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 'PS_Levelstart':
|
||||
return BallanceObjectInfo.create_from_others(BallanceObjectType.LEVEL_START)
|
||||
case 'PE_Levelende':
|
||||
return BallanceObjectInfo.create_from_others(BallanceObjectType.LEVEL_END)
|
||||
case 'PC_Checkpoints' | 'PR_Resetpoints':
|
||||
# these type's data should be gotten from its name
|
||||
return VirtoolsGroupConvention.__get_pcpr_from_name(obj.name, reporter)
|
||||
case _:
|
||||
tr_text = bpy.app.translations.pgettext_rpt(
|
||||
"The match of Unique Component lost.", 'BBP/UTIL_naming_convention.VirtoolsGroupConvention')
|
||||
if reporter: reporter.add_error(tr_text)
|
||||
return None
|
||||
elif len(inter_gps) != 0:
|
||||
tr_text = bpy.app.translations.pgettext_rpt(
|
||||
"A Multi-grouping Unique Component.", 'BBP/UTIL_naming_convention.VirtoolsGroupConvention')
|
||||
if reporter: reporter.add_error(tr_text)
|
||||
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
|
||||
tr_text = bpy.app.translations.pgettext_rpt(
|
||||
"Component detected. But couldn't get sector from CKGroup data.", 'BBP/UTIL_naming_convention.VirtoolsGroupConvention')
|
||||
if reporter: reporter.add_error(tr_text)
|
||||
return None
|
||||
return BallanceObjectInfo.create_from_component(
|
||||
gotten_elements,
|
||||
gotten_sector
|
||||
)
|
||||
elif len(inter_gps) != 0:
|
||||
# must be a weird grouping, report it
|
||||
tr_text = bpy.app.translations.pgettext_rpt(
|
||||
"A Multi-grouping Component.", 'BBP/UTIL_naming_convention.VirtoolsGroupConvention')
|
||||
if reporter: reporter.add_error(tr_text)
|
||||
return None
|
||||
|
||||
# distinguish road
|
||||
if gp.contain_group('Phys_FloorRails'):
|
||||
# rail
|
||||
return BallanceObjectInfo.create_from_others(BallanceObjectType.RAIL)
|
||||
elif gp.contain_group('Phys_Floors'):
|
||||
# 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:
|
||||
tr_text = bpy.app.translations.pgettext_rpt(
|
||||
"Can't distinguish object between Floors and Rails. Suppose it is Floors.", 'BBP/UTIL_naming_convention.VirtoolsGroupConvention')
|
||||
if reporter: reporter.add_warning(tr_text)
|
||||
return BallanceObjectInfo.create_from_others(BallanceObjectType.FLOOR)
|
||||
elif gp.contain_group('Phys_FloorStopper'):
|
||||
return BallanceObjectInfo.create_from_others(BallanceObjectType.STOPPER)
|
||||
elif gp.contain_group('DepthTestCubes'):
|
||||
return BallanceObjectInfo.create_from_others(BallanceObjectType.DEPTH_CUBE)
|
||||
|
||||
# no matched
|
||||
tr_text = bpy.app.translations.pgettext_rpt(
|
||||
"Group match lost.", 'BBP/UTIL_naming_convention.VirtoolsGroupConvention')
|
||||
if reporter: reporter.add_error(tr_text)
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def set_to_object(obj: bpy.types.Object, info: BallanceObjectInfo, reporter: RenameErrorReporter | None) -> bool:
|
||||
# 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('PS_Levelstart')
|
||||
case BallanceObjectType.LEVEL_END:
|
||||
gp.add_group('PE_Levelende')
|
||||
case BallanceObjectType.CHECKPOINT:
|
||||
gp.add_group('PC_Checkpoints')
|
||||
case BallanceObjectType.RESETPOINT:
|
||||
gp.add_group('PR_Resetpoints')
|
||||
|
||||
case BallanceObjectType.DEPTH_CUBE:
|
||||
gp.add_group('PE_Levelende')
|
||||
|
||||
case BallanceObjectType.FLOOR:
|
||||
gp.add_group('Phys_Floors')
|
||||
gp.add_group('Sound_HitID_01')
|
||||
gp.add_group('Sound_RollID_01')
|
||||
# floor type also need group into shadow group.
|
||||
gp.add_group('Shadow')
|
||||
case BallanceObjectType.RAIL:
|
||||
gp.add_group('Phys_FloorRails')
|
||||
gp.add_group('Sound_HitID_03')
|
||||
gp.add_group('Sound_RollID_03')
|
||||
case BallanceObjectType.WOOD:
|
||||
gp.add_group('Phys_Floors')
|
||||
gp.add_group('Sound_HitID_02')
|
||||
gp.add_group('Sound_RollID_02')
|
||||
case BallanceObjectType.STOPPER:
|
||||
gp.add_group('Phys_FloorStopper')
|
||||
|
||||
case BallanceObjectType.COMPONENT:
|
||||
# group into component type
|
||||
# use typing.cast() to force linter accept it because None is impossible
|
||||
gp.add_group(typing.cast(str, info.mComponentType))
|
||||
# group to sector
|
||||
gp.add_group(build_name_from_sector_index(typing.cast(int, info.mSector)))
|
||||
|
||||
case _:
|
||||
tr_text: str = bpy.app.translations.pgettext_rpt(
|
||||
"No matched info.", 'BBP/UTIL_naming_convention.VirtoolsGroupConvention')
|
||||
if reporter: reporter.add_error(tr_text)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
class YYCToolchainConvention():
|
||||
@staticmethod
|
||||
def parse_from_name(name: str, reporter: RenameErrorReporter | None) -> BallanceObjectInfo | None:
|
||||
# check component first
|
||||
regex_result = VirtoolsGroupConvention.cRegexComponent.match(name) # use vt one because they are same
|
||||
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(name) # use vt one because they are same
|
||||
if regex_result is not None:
|
||||
return BallanceObjectInfo.create_from_checkpoint(
|
||||
int(regex_result.group(1))
|
||||
)
|
||||
regex_result = VirtoolsGroupConvention.cRegexPR.match(name) # use vt one because they are same
|
||||
if regex_result is not None:
|
||||
return BallanceObjectInfo.create_from_resetpoint(
|
||||
int(regex_result.group(1))
|
||||
)
|
||||
|
||||
# check other unique elements
|
||||
if name == "PS_FourFlames_01":
|
||||
return BallanceObjectInfo.create_from_others(BallanceObjectType.LEVEL_START)
|
||||
if name == "PE_Balloon_01":
|
||||
return BallanceObjectInfo.create_from_others(BallanceObjectType.LEVEL_END)
|
||||
|
||||
# process floors
|
||||
if name.startswith("A_Floor"):
|
||||
return BallanceObjectInfo.create_from_others(BallanceObjectType.FLOOR)
|
||||
if name.startswith("A_Rail"):
|
||||
return BallanceObjectInfo.create_from_others(BallanceObjectType.RAIL)
|
||||
if name.startswith("A_Wood"):
|
||||
return BallanceObjectInfo.create_from_others(BallanceObjectType.WOOD)
|
||||
if name.startswith("A_Stopper"):
|
||||
return BallanceObjectInfo.create_from_others(BallanceObjectType.STOPPER)
|
||||
|
||||
# process others
|
||||
if name.startswith("DepthCubes"):
|
||||
return BallanceObjectInfo.create_from_others(BallanceObjectType.DEPTH_CUBE)
|
||||
if name.startswith("D_"):
|
||||
return BallanceObjectInfo.create_from_others(BallanceObjectType.DECORATION)
|
||||
if name == 'SkyLayer':
|
||||
return BallanceObjectInfo.create_from_others(BallanceObjectType.SKYLAYER)
|
||||
|
||||
tr_text: str = bpy.app.translations.pgettext_rpt(
|
||||
"Name match lost.", 'BBP/UTIL_naming_convention.YYCToolchainConvention')
|
||||
if reporter: reporter.add_error(tr_text)
|
||||
return None
|
||||
|
||||
|
||||
@staticmethod
|
||||
def parse_from_object(obj: bpy.types.Object, reporter: RenameErrorReporter | None) -> BallanceObjectInfo | None:
|
||||
return YYCToolchainConvention.parse_from_name(obj.name, reporter)
|
||||
|
||||
@staticmethod
|
||||
def set_to_name(info: BallanceObjectInfo, reporter: RenameErrorReporter | None) -> str | None:
|
||||
match(info.mBasicType):
|
||||
case BallanceObjectType.DECORATION:
|
||||
return 'D_'
|
||||
case BallanceObjectType.SKYLAYER:
|
||||
return 'SkyLayer'
|
||||
|
||||
case BallanceObjectType.LEVEL_START:
|
||||
return 'PS_FourFlames_01'
|
||||
case BallanceObjectType.LEVEL_END:
|
||||
return 'PE_Balloon_01'
|
||||
case BallanceObjectType.CHECKPOINT:
|
||||
return f'PC_TwoFlames_{info.mSector:0>2d}'
|
||||
case BallanceObjectType.RESETPOINT:
|
||||
return f'PR_Resetpoint_{info.mSector:0>2d}'
|
||||
|
||||
case BallanceObjectType.DEPTH_CUBE:
|
||||
return 'DepthCubes_'
|
||||
|
||||
case BallanceObjectType.FLOOR:
|
||||
return 'A_Floor_'
|
||||
case BallanceObjectType.RAIL:
|
||||
return 'A_Rail_'
|
||||
case BallanceObjectType.WOOD:
|
||||
return 'A_Wood_'
|
||||
case BallanceObjectType.STOPPER:
|
||||
return 'A_Stopper_'
|
||||
|
||||
case BallanceObjectType.COMPONENT:
|
||||
return '{}_{:0>2d}_'.format(
|
||||
info.mComponentType, info.mSector)
|
||||
|
||||
case _:
|
||||
tr_text: str = bpy.app.translations.pgettext_rpt(
|
||||
"No matched info.", 'BBP/UTIL_naming_convention.YYCToolchainConvention')
|
||||
if reporter: reporter.add_error(tr_text)
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def set_to_object(obj: bpy.types.Object, info: BallanceObjectInfo, reporter: RenameErrorReporter | None) -> bool:
|
||||
expect_name: str | None = YYCToolchainConvention.set_to_name(info, reporter)
|
||||
if expect_name is None: return False
|
||||
|
||||
obj.name = expect_name
|
||||
return True
|
||||
|
||||
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
|
||||
def parse_from_name(name: str, reporter: RenameErrorReporter | None) -> BallanceObjectInfo | None:
|
||||
# check component first
|
||||
regex_result = ImengyuConvention.cRegexComponent.match(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(name)
|
||||
if regex_result is not None:
|
||||
return BallanceObjectInfo.create_from_checkpoint(
|
||||
int(regex_result.group(1))
|
||||
)
|
||||
regex_result = ImengyuConvention.cRegexPR.match(name)
|
||||
if regex_result is not None:
|
||||
return BallanceObjectInfo.create_from_resetpoint(
|
||||
int(regex_result.group(1))
|
||||
)
|
||||
|
||||
# check other unique elements
|
||||
if name == "PS_LevelStart":
|
||||
return BallanceObjectInfo.create_from_others(BallanceObjectType.LEVEL_START)
|
||||
if name == "PE_LevelEnd":
|
||||
return BallanceObjectInfo.create_from_others(BallanceObjectType.LEVEL_END)
|
||||
|
||||
# process floors
|
||||
if name.startswith("S_Floors"):
|
||||
return BallanceObjectInfo.create_from_others(BallanceObjectType.FLOOR)
|
||||
if name.startswith("S_FloorRails"):
|
||||
return BallanceObjectInfo.create_from_others(BallanceObjectType.RAIL)
|
||||
if name.startswith("S_FloorWoods"):
|
||||
return BallanceObjectInfo.create_from_others(BallanceObjectType.WOOD)
|
||||
if name.startswith("S_FloorStopper"):
|
||||
return BallanceObjectInfo.create_from_others(BallanceObjectType.STOPPER)
|
||||
|
||||
# process others
|
||||
if name.startswith("DepthTestCubes"):
|
||||
return BallanceObjectInfo.create_from_others(BallanceObjectType.DEPTH_CUBE)
|
||||
if name.startswith("O_"):
|
||||
return BallanceObjectInfo.create_from_others(BallanceObjectType.DECORATION)
|
||||
if name == 'SkyLayer':
|
||||
return BallanceObjectInfo.create_from_others(BallanceObjectType.SKYLAYER)
|
||||
|
||||
tr_text: str = bpy.app.translations.pgettext_rpt(
|
||||
"Name match lost.", 'BBP/UTIL_naming_convention.ImengyuConvention')
|
||||
if reporter: reporter.add_error(tr_text)
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def parse_from_object(obj: bpy.types.Object, reporter: RenameErrorReporter | None) -> BallanceObjectInfo | None:
|
||||
return ImengyuConvention.parse_from_name(obj.name, reporter)
|
||||
|
||||
@staticmethod
|
||||
def set_to_name(info: BallanceObjectInfo, oldname: str | None, reporter: RenameErrorReporter | None) -> str | None:
|
||||
match(info.mBasicType):
|
||||
case BallanceObjectType.DECORATION:
|
||||
return 'O_'
|
||||
case BallanceObjectType.SKYLAYER:
|
||||
return 'SkyLayer'
|
||||
|
||||
case BallanceObjectType.LEVEL_START:
|
||||
return 'PS_LevelStart'
|
||||
case BallanceObjectType.LEVEL_END:
|
||||
return 'PE_LevelEnd'
|
||||
case BallanceObjectType.CHECKPOINT:
|
||||
return f'PR_ResetPoint:{info.mSector:d}'
|
||||
case BallanceObjectType.RESETPOINT:
|
||||
return f'PC_CheckPoint:{info.mSector:d}'
|
||||
|
||||
case BallanceObjectType.DEPTH_CUBE:
|
||||
return 'DepthTestCubes'
|
||||
|
||||
case BallanceObjectType.FLOOR:
|
||||
return 'S_Floors'
|
||||
case BallanceObjectType.RAIL:
|
||||
return 'S_FloorWoods'
|
||||
case BallanceObjectType.WOOD:
|
||||
return 'S_FloorRails'
|
||||
case BallanceObjectType.STOPPER:
|
||||
return 'S_FloorStopper'
|
||||
|
||||
case BallanceObjectType.COMPONENT:
|
||||
return '{}:{}:{:d}'.format(
|
||||
info.mComponentType,
|
||||
oldname.replace(':', '_') if oldname is not None else '',
|
||||
info.mSector
|
||||
)
|
||||
|
||||
case _:
|
||||
tr_text: str = bpy.app.translations.pgettext_rpt(
|
||||
"No matched info.", 'BBP/UTIL_naming_convention.ImengyuConvention')
|
||||
if reporter: reporter.add_error(tr_text)
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def set_to_object(obj: bpy.types.Object, info: BallanceObjectInfo, reporter: RenameErrorReporter | None) -> bool:
|
||||
expect_name: str | None = ImengyuConvention.set_to_name(info, obj.name, reporter)
|
||||
if expect_name is None: return False
|
||||
|
||||
obj.name = expect_name
|
||||
return True
|
||||
|
||||
|
||||
#endregion
|
Reference in New Issue
Block a user