From 4ffe29654be289254b788bebc0fd078a26ebed03 Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Sat, 11 Jan 2025 21:36:11 +0800 Subject: [PATCH] feat: add translation context for operators and their properties. - add translation context for operator, menu, panel and etc. and their associated properties. - improve some name and description but not finished. - move reset BME material function inside BMEMaterialsHelper. - rename variable of collection visitor in BME adder operator for clear meaning. - replace some message box to report in ballance elements reset operator, BME materials reset operator and rail UV operator --- bbp_ng/OP_ADDS_bme.py | 94 +++++++++++--------- bbp_ng/OP_ADDS_component.py | 31 +++++-- bbp_ng/OP_ADDS_rail.py | 44 ++++++--- bbp_ng/OP_EXPORT_bmfile.py | 4 +- bbp_ng/OP_EXPORT_virtools.py | 1 + bbp_ng/OP_IMPORT_bmfile.py | 4 +- bbp_ng/OP_IMPORT_virtools.py | 1 + bbp_ng/OP_MTL_fix_material.py | 3 +- bbp_ng/OP_OBJECT_legacy_align.py | 21 +++-- bbp_ng/OP_OBJECT_naming_convention.py | 3 + bbp_ng/OP_OBJECT_snoop_group_then_to_mesh.py | 1 + bbp_ng/OP_OBJECT_virtools_group.py | 7 +- bbp_ng/OP_UV_flatten_uv.py | 11 ++- bbp_ng/OP_UV_rail_uv.py | 36 ++++---- bbp_ng/PROP_ballance_element.py | 14 +-- bbp_ng/PROP_ballance_map_info.py | 4 +- bbp_ng/PROP_bme_material.py | 47 ++++------ bbp_ng/PROP_preferences.py | 8 +- bbp_ng/PROP_ptrprop_resolver.py | 24 +++-- bbp_ng/PROP_virtools_group.py | 10 ++- bbp_ng/PROP_virtools_light.py | 29 ++++-- bbp_ng/PROP_virtools_material.py | 76 +++++++++++----- bbp_ng/PROP_virtools_mesh.py | 4 +- bbp_ng/PROP_virtools_texture.py | 6 +- bbp_ng/UTIL_ioport_shared.py | 12 ++- bbp_ng/UTIL_translation.py | 87 ++++++++++++++++++ bbp_ng/__init__.py | 68 ++++++++------ 27 files changed, 444 insertions(+), 206 deletions(-) create mode 100644 bbp_ng/UTIL_translation.py diff --git a/bbp_ng/OP_ADDS_bme.py b/bbp_ng/OP_ADDS_bme.py index d7c0239..7c78f23 100644 --- a/bbp_ng/OP_ADDS_bme.py +++ b/bbp_ng/OP_ADDS_bme.py @@ -1,7 +1,7 @@ import bpy, mathutils import typing from . import PROP_preferences -from . import UTIL_functions, UTIL_bme +from . import UTIL_functions, UTIL_translation, UTIL_bme #region BME Adder @@ -9,29 +9,33 @@ _g_EnumHelper_BmeStructType: UTIL_bme.EnumPropHelper = UTIL_bme.EnumPropHelper() class BBP_PG_bme_adder_cfgs(bpy.types.PropertyGroup): prop_int: bpy.props.IntProperty( - name = 'Single Int', description = 'Single Int', + name = 'Integral Value', description = 'The field representing a single integral value.', min = 0, max = 64, soft_min = 0, soft_max = 32, step = 1, default = 1, + translation_context = 'BBP_PG_bme_adder_cfgs/property' ) # type: ignore prop_float: bpy.props.FloatProperty( - name = 'Single Float', description = 'Single Float', + name = 'Float Point Value', description = 'The field representing a single float point value.', min = 0.0, max = 1024.0, soft_min = 0.0, soft_max = 512.0, step = 50, # Step is in UI, in [1, 100] (WARNING: actual value is /100). So we choose 50, mean 0.5 default = 5.0, + translation_context = 'BBP_PG_bme_adder_cfgs/property' ) # type: ignore prop_bool: bpy.props.BoolProperty( - name = 'Single Bool', description = 'Single Bool', - default = True + name = 'Boolean Value', description = 'The field representing a single boolean value.', + default = True, + translation_context = 'BBP_PG_bme_adder_cfgs/property' ) # type: ignore class BBP_OT_add_bme_struct(bpy.types.Operator): - """Add BME Struct""" + """Add BME structure""" bl_idname = "bbp.add_bme_struct" - bl_label = "Add BME Struct" + bl_label = "Add BME Structure" bl_options = {'REGISTER', 'UNDO'} + bl_translation_context = 'BBP_OT_add_bme_struct' ## There is a compromise due to the shitty Blender design. # @@ -51,8 +55,9 @@ class BBP_OT_add_bme_struct(bpy.types.Operator): ## Compromise used "outdated" flag. outdated_flag: bpy.props.BoolProperty( - name = "Outdated Type", - description = "Internal flag.", + # TR: Internal property should not have name and desc otherwise they will be written in translation. + # name = "Outdated Type", + # description = "Internal flag.", options = {'HIDDEN', 'SKIP_SAVE'}, default = False ) # type: ignore @@ -96,29 +101,29 @@ class BBP_OT_add_bme_struct(bpy.types.Operator): # init data collection - adder_cfgs_visitor: UTIL_functions.CollectionVisitor[BBP_PG_bme_adder_cfgs] - adder_cfgs_visitor = UTIL_functions.CollectionVisitor(self.bme_struct_cfgs) + op_cfgs_visitor: UTIL_functions.CollectionVisitor[BBP_PG_bme_adder_cfgs] + op_cfgs_visitor = UTIL_functions.CollectionVisitor(self.bme_struct_cfgs) # clear first - adder_cfgs_visitor.clear() + op_cfgs_visitor.clear() # create enough entries specified by gotten cfgs for _ in range(max(counter_int, counter_float, counter_bool)): - adder_cfgs_visitor.add() + op_cfgs_visitor.add() # assign default value for (cfg, cfg_index) in self.bme_struct_cfg_index_cache: # show prop differently by cfg type match(cfg.get_type()): case UTIL_bme.PrototypeShowcaseCfgsTypes.Integer: - adder_cfgs_visitor[cfg_index].prop_int = cfg.get_default() + op_cfgs_visitor[cfg_index].prop_int = cfg.get_default() case UTIL_bme.PrototypeShowcaseCfgsTypes.Float: - adder_cfgs_visitor[cfg_index].prop_float = cfg.get_default() + op_cfgs_visitor[cfg_index].prop_float = cfg.get_default() case UTIL_bme.PrototypeShowcaseCfgsTypes.Boolean: - adder_cfgs_visitor[cfg_index].prop_bool = cfg.get_default() + op_cfgs_visitor[cfg_index].prop_bool = cfg.get_default() case UTIL_bme.PrototypeShowcaseCfgsTypes.Face: # face is just 6 bool default_values: tuple[bool, ...] = cfg.get_default() for i in range(6): - adder_cfgs_visitor[cfg_index + i].prop_bool = default_values[i] + op_cfgs_visitor[cfg_index + i].prop_bool = default_values[i] # reset outdated flag self.outdated_flag = False @@ -132,15 +137,17 @@ class BBP_OT_add_bme_struct(bpy.types.Operator): bme_struct_type: bpy.props.EnumProperty( name = "Type", - description = "BME struct type", + description = "The type of BME structure.", items = _g_EnumHelper_BmeStructType.generate_items(), - update = bme_struct_type_updated + update = bme_struct_type_updated, + translation_context = 'BBP_OT_add_bme_struct/property' ) # type: ignore bme_struct_cfgs : bpy.props.CollectionProperty( - name = "Cfgs", - description = "Cfg collection.", + name = "Configurations", + description = "The collection holding BME structure configurations.", type = BBP_PG_bme_adder_cfgs, + translation_context = 'BBP_OT_add_bme_struct/property' ) # type: ignore ## Extra transform for good "what you see is what you gotten". @@ -151,7 +158,8 @@ class BBP_OT_add_bme_struct(bpy.types.Operator): size = 3, subtype = 'TRANSLATION', step = 50, # same step as the float entry of BBP_PG_bme_adder_cfgs - default = (0.0, 0.0, 0.0) + default = (0.0, 0.0, 0.0), + translation_context = 'BBP_OT_add_bme_struct/property' ) # type: ignore extra_rotation: bpy.props.FloatVectorProperty( name = "Extra Rotation", @@ -159,7 +167,8 @@ class BBP_OT_add_bme_struct(bpy.types.Operator): size = 3, subtype = 'EULER', step = 100, # We choosen 100, mean 1. Sync with property window. - default = (0.0, 0.0, 0.0) + default = (0.0, 0.0, 0.0), + translation_context = 'BBP_OT_add_bme_struct/property' ) # type: ignore @classmethod @@ -185,22 +194,22 @@ class BBP_OT_add_bme_struct(bpy.types.Operator): self.__internal_update_bme_struct_type() # create cfg visitor - adder_cfgs_visitor: UTIL_functions.CollectionVisitor[BBP_PG_bme_adder_cfgs] - adder_cfgs_visitor = UTIL_functions.CollectionVisitor(self.bme_struct_cfgs) + op_cfgs_visitor: UTIL_functions.CollectionVisitor[BBP_PG_bme_adder_cfgs] + op_cfgs_visitor = UTIL_functions.CollectionVisitor(self.bme_struct_cfgs) # collect cfgs data cfgs: dict[str, typing.Any] = {} for (cfg, cfg_index) in self.bme_struct_cfg_index_cache: match(cfg.get_type()): case UTIL_bme.PrototypeShowcaseCfgsTypes.Integer: - cfgs[cfg.get_field()] = adder_cfgs_visitor[cfg_index].prop_int + cfgs[cfg.get_field()] = op_cfgs_visitor[cfg_index].prop_int case UTIL_bme.PrototypeShowcaseCfgsTypes.Float: - cfgs[cfg.get_field()] = adder_cfgs_visitor[cfg_index].prop_float + cfgs[cfg.get_field()] = op_cfgs_visitor[cfg_index].prop_float case UTIL_bme.PrototypeShowcaseCfgsTypes.Boolean: - cfgs[cfg.get_field()] = adder_cfgs_visitor[cfg_index].prop_bool + cfgs[cfg.get_field()] = op_cfgs_visitor[cfg_index].prop_bool case UTIL_bme.PrototypeShowcaseCfgsTypes.Face: # face is just 6 bool tuple cfgs[cfg.get_field()] = tuple( - adder_cfgs_visitor[cfg_index + i].prop_bool for i in range(6) + op_cfgs_visitor[cfg_index + i].prop_bool for i in range(6) ) # call general creator @@ -231,8 +240,8 @@ class BBP_OT_add_bme_struct(bpy.types.Operator): layout.prop(self, 'bme_struct_type') # create cfg visitor - adder_cfgs_visitor: UTIL_functions.CollectionVisitor[BBP_PG_bme_adder_cfgs] - adder_cfgs_visitor = UTIL_functions.CollectionVisitor(self.bme_struct_cfgs) + op_cfgs_visitor: UTIL_functions.CollectionVisitor[BBP_PG_bme_adder_cfgs] + op_cfgs_visitor = UTIL_functions.CollectionVisitor(self.bme_struct_cfgs) # visit cfgs cache list to show cfg layout.label(text = "Prototype Configurations:") for (cfg, cfg_index) in self.bme_struct_cfg_index_cache: @@ -246,29 +255,29 @@ class BBP_OT_add_bme_struct(bpy.types.Operator): # show prop differently by cfg type match(cfg.get_type()): case UTIL_bme.PrototypeShowcaseCfgsTypes.Integer: - box_layout.prop(adder_cfgs_visitor[cfg_index], 'prop_int', text = '') + box_layout.prop(op_cfgs_visitor[cfg_index], 'prop_int', text = '') case UTIL_bme.PrototypeShowcaseCfgsTypes.Float: - box_layout.prop(adder_cfgs_visitor[cfg_index], 'prop_float', text = '') + box_layout.prop(op_cfgs_visitor[cfg_index], 'prop_float', text = '') case UTIL_bme.PrototypeShowcaseCfgsTypes.Boolean: - box_layout.prop(adder_cfgs_visitor[cfg_index], 'prop_bool', text = '') + box_layout.prop(op_cfgs_visitor[cfg_index], 'prop_bool', text = '') case UTIL_bme.PrototypeShowcaseCfgsTypes.Face: # face will show a special layout (grid view) grids = box_layout.grid_flow( row_major=True, columns=3, even_columns=True, even_rows=True, align=True) grids.alignment = 'CENTER' grids.separator() - grids.prop(adder_cfgs_visitor[cfg_index + 0], 'prop_bool', text = 'Top') # top - grids.prop(adder_cfgs_visitor[cfg_index + 2], 'prop_bool', text = 'Front') # front - grids.prop(adder_cfgs_visitor[cfg_index + 4], 'prop_bool', text = 'Left') # left + grids.prop(op_cfgs_visitor[cfg_index + 0], 'prop_bool', text = 'Top') # top + grids.prop(op_cfgs_visitor[cfg_index + 2], 'prop_bool', text = 'Front') # front + grids.prop(op_cfgs_visitor[cfg_index + 4], 'prop_bool', text = 'Left') # left grids.label(text = '', icon = 'CUBE') # show a 3d cube as icon - grids.prop(adder_cfgs_visitor[cfg_index + 5], 'prop_bool', text = 'Right') # right - grids.prop(adder_cfgs_visitor[cfg_index + 3], 'prop_bool', text = 'Back') # back - grids.prop(adder_cfgs_visitor[cfg_index + 1], 'prop_bool', text = 'Bottom') # bottom + grids.prop(op_cfgs_visitor[cfg_index + 5], 'prop_bool', text = 'Right') # right + grids.prop(op_cfgs_visitor[cfg_index + 3], 'prop_bool', text = 'Back') # back + grids.prop(op_cfgs_visitor[cfg_index + 1], 'prop_bool', text = 'Bottom') # bottom grids.separator() # show extra transform props # forcely order that each one are placed horizontally - layout.label(text = "Extra Transform:") + layout.label(text = "Extra Transform") # translation layout.label(text = 'Translation') hbox_layout: bpy.types.UILayout = layout.row() @@ -285,7 +294,8 @@ class BBP_OT_add_bme_struct(bpy.types.Operator): cop = layout.operator( cls.bl_idname, text = _g_EnumHelper_BmeStructType.get_bme_showcase_title(ident), - icon_value = _g_EnumHelper_BmeStructType.get_bme_showcase_icon(ident) + icon_value = _g_EnumHelper_BmeStructType.get_bme_showcase_icon(ident), + text_ctxt = UTIL_translation.build_prototype_showcase_context(ident) ) # and assign its init type value cop.bme_struct_type = _g_EnumHelper_BmeStructType.to_selection(ident) diff --git a/bbp_ng/OP_ADDS_component.py b/bbp_ng/OP_ADDS_component.py index bc710e4..f0b5c72 100644 --- a/bbp_ng/OP_ADDS_component.py +++ b/bbp_ng/OP_ADDS_component.py @@ -8,10 +8,11 @@ from . import PROP_ballance_element, PROP_virtools_group, PROP_ballance_map_info class ComponentSectorParam(): component_sector: bpy.props.IntProperty( name = "Sector", - description = "Define which sector the object will be grouped in", + description = "The sector which this component will be grouped in.", min = 1, max = 999, soft_min = 1, soft_max = 8, default = 1, + translation_context = 'BBP/OP_ADDS_component.ComponentSectorParam/property' ) # type: ignore def general_get_component_sector(self) -> int: @@ -23,10 +24,11 @@ class ComponentSectorParam(): class ComponentCountParam(): component_count: bpy.props.IntProperty( name = "Count", - description = "The count of components you want to generate", + description = "The count of components which you want to generate", min = 1, max = 64, soft_min = 1, soft_max = 32, default = 1, + translation_context = 'BBP/OP_ADDS_component.ComponentCountParam/property' ) # type: ignore def general_get_component_count(self) -> int: @@ -192,15 +194,17 @@ _g_EnumHelper_Component: UTIL_functions.EnumPropHelper = UTIL_functions.EnumProp ) class BBP_OT_add_component(bpy.types.Operator, ComponentSectorParam): - """Add Component""" + """Add ordinary Component""" bl_idname = "bbp.add_component" bl_label = "Add Component" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_add_component' component_type: bpy.props.EnumProperty( name = "Type", - description = "This component type", + description = "The type of this component.", items = _g_EnumHelper_Component.generate_items(), + translation_context = 'BBP_OT_add_component/property' ) # type: ignore def invoke(self, context, event): @@ -241,7 +245,8 @@ class BBP_OT_add_component(bpy.types.Operator, ComponentSectorParam): cop = layout.operator( BBP_OT_add_component.bl_idname, text = item_name, - icon_value = UTIL_icons_manager.get_component_icon(item_name) + icon_value = UTIL_icons_manager.get_component_icon(item_name), + translate = False ) cop.component_type = _g_EnumHelper_Component.to_selection(item) @@ -254,6 +259,7 @@ class BBP_OT_add_nong_extra_point(bpy.types.Operator, ComponentSectorParam, Comp bl_idname = "bbp.add_nong_extra_point" bl_label = "Nong Extra Point" bl_options = {'REGISTER', 'UNDO'} + bl_translation_context = 'BBP_OT_add_nong_extra_point' def draw(self, context): layout = self.layout @@ -289,13 +295,15 @@ class BBP_OT_add_nong_ventilator(bpy.types.Operator, ComponentSectorParam, Compo bl_idname = "bbp.add_nong_ventilator" bl_label = "Nong Ventilator" bl_options = {'REGISTER', 'UNDO'} + bl_translation_context = 'BBP_OT_add_nong_ventilator' ventilator_count_source: bpy.props.EnumProperty( name = "Ventilator Count Source", items = [ ('DEFINED', "Predefined", "Pre-defined ventilator count."), ('CUSTOM', "Custom", "User specified ventilator count."), - ], + ], + translation_context = 'BBP_OT_add_nong_ventilator/property' ) # type: ignore preset_vetilator_count: bpy.props.EnumProperty( @@ -307,6 +315,7 @@ class BBP_OT_add_nong_ventilator(bpy.types.Operator, ComponentSectorParam, Compo ('WOOD', 'Wood', 'The ventilator count (6) can push wood ball up.'), ('STONE', 'Stone', 'The ventilator count (32) can push stone ball up.'), ], + translation_context = 'BBP_OT_add_nong_ventilator/property' ) # type: ignore def draw(self, context): @@ -363,6 +372,7 @@ class BBP_OT_add_tilting_block_series(bpy.types.Operator, ComponentSectorParam, bl_idname = "bbp.add_tilting_block_series" bl_label = "Tilting Block Series" bl_options = {'REGISTER', 'UNDO'} + bl_translation_context = 'BBP_OT_add_tilting_block_series' component_span: bpy.props.FloatProperty( name = "Span", @@ -370,6 +380,7 @@ class BBP_OT_add_tilting_block_series(bpy.types.Operator, ComponentSectorParam, min = 0.0, max = 100.0, soft_min = 0.0, soft_max = 12.0, default = 6.0022, + translation_context = 'BBP_OT_add_tilting_block_series/property' ) # type: ignore def draw(self, context): @@ -407,6 +418,7 @@ class BBP_OT_add_swing_series(bpy.types.Operator, ComponentSectorParam, Componen bl_idname = "bbp.add_swing_series" bl_label = "Swing Series" bl_options = {'REGISTER', 'UNDO'} + bl_translation_context = 'BBP_OT_add_swing_series' component_span: bpy.props.FloatProperty( name = "Span", @@ -414,12 +426,14 @@ class BBP_OT_add_swing_series(bpy.types.Operator, ComponentSectorParam, Componen min = 0.0, max = 100.0, soft_min = 0.0, soft_max = 30.0, default = 15.0, + translation_context = 'BBP_OT_add_swing_series/property' ) # type: ignore staggered_swing: bpy.props.BoolProperty( name = 'Staggered', description = 'Whether place Swing staggered. Staggered Swing accept any ball however Non-Staggered Swing only accept Wood and Paper ball.', - default = True + default = True, + translation_context = 'BBP_OT_add_swing_series/property' ) # type: ignore def draw(self, context): @@ -465,6 +479,7 @@ class BBP_OT_add_ventilator_series(bpy.types.Operator, ComponentSectorParam, Com bl_idname = "bbp.add_ventilator_series" bl_label = "Ventilator Series" bl_options = {'REGISTER', 'UNDO'} + bl_translation_context = 'BBP_OT_add_ventilator_series' component_translation: bpy.props.FloatVectorProperty( name = "Delta Vector", @@ -473,6 +488,7 @@ class BBP_OT_add_ventilator_series(bpy.types.Operator, ComponentSectorParam, Com min = 0.0, max = 100.0, soft_min = 0.0, soft_max = 50.0, default = (0.0, 0.0, 15.0), + translation_context = 'BBP_OT_add_ventilator_series/property' ) # type: ignore def draw(self, context): @@ -514,6 +530,7 @@ class BBP_OT_add_sector_component_pair(bpy.types.Operator, ComponentSectorParam) bl_idname = "bbp.add_sector_component_pair" bl_label = "Sector Pair" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_add_sector_component_pair' def __get_checkpoint(self) -> tuple[PROP_ballance_element.BallanceElementType, int]: if self.general_get_component_sector() == 1: diff --git a/bbp_ng/OP_ADDS_rail.py b/bbp_ng/OP_ADDS_rail.py index 22b6fff..ccbc4c2 100644 --- a/bbp_ng/OP_ADDS_rail.py +++ b/bbp_ng/OP_ADDS_rail.py @@ -46,7 +46,8 @@ class SharedExtraTransform(): size = 3, subtype = 'TRANSLATION', step = 50, # same step as the float entry of BBP_PG_bme_adder_cfgs - default = (0.0, 0.0, 0.0) + default = (0.0, 0.0, 0.0), + translation_context = 'BBP/OP_ADDS_rail.SharedExtraTransform/property' ) # type: ignore extra_rotation: bpy.props.FloatVectorProperty( name = "Extra Rotation", @@ -54,7 +55,8 @@ class SharedExtraTransform(): size = 3, subtype = 'EULER', step = 100, # We choosen 100, mean 1. Sync with property window. - default = (0.0, 0.0, 0.0) + default = (0.0, 0.0, 0.0), + translation_context = 'BBP/OP_ADDS_rail.SharedExtraTransform/property' ) # type: ignore def draw_extra_transform_input(self, layout: bpy.types.UILayout) -> None: @@ -91,6 +93,7 @@ class SharedRailSectionInputProperty(): ('RAIL', "Rail", ""), ], default = 'RAIL', + translation_context = 'BBP/OP_ADDS_rail.SharedRailSectionInputProperty/property' ) # type: ignore def draw_rail_section_input(self, layout: bpy.types.UILayout) -> None: @@ -109,13 +112,15 @@ class SharedRailCapInputProperty(): rail_start_cap: bpy.props.BoolProperty( name = 'Start Cap', description = 'Whether this rail should have cap at start terminal.', - default = False + default = False, + translation_context = 'BBP/OP_ADDS_rail.SharedRailCapInputProperty/property' ) # type: ignore rail_end_cap: bpy.props.BoolProperty( name = 'End Cap', description = 'Whether this rail should have cap at end terminal.', - default = False + default = False, + translation_context = 'BBP/OP_ADDS_rail.SharedRailCapInputProperty/property' ) # type: ignore def draw_rail_cap_input(self, layout: bpy.types.UILayout) -> None: @@ -140,7 +145,8 @@ class SharedStraightRailInputProperty(): default = 5.0, min = 0, step = 50, # same unit as BME Struct - unit = 'LENGTH' + unit = 'LENGTH', + translation_context = 'BBP/OP_ADDS_rail.SharedStraightRailInputProperty/property' ) # type: ignore def draw_straight_rail_input(self, layout: bpy.types.UILayout) -> None: @@ -159,6 +165,7 @@ class SharedScrewRailInputProperty(): description = "The segment count per iteration. More segment, more smooth but lower performance.", default = 28, min = 1, + translation_context = 'BBP/OP_ADDS_rail.SharedScrewRailInputProperty/property' ) # type: ignore rail_screw_radius: bpy.props.FloatProperty( @@ -166,25 +173,29 @@ class SharedScrewRailInputProperty(): description = "The screw radius.", default = 5, min = 0, - unit = 'LENGTH' + unit = 'LENGTH', + translation_context = 'BBP/OP_ADDS_rail.SharedScrewRailInputProperty/property' ) # type: ignore rail_screw_flip_x: bpy.props.BoolProperty( name = 'Flip X', description = 'Whether flip this rail with X axis', - default = False + default = False, + translation_context = 'BBP/OP_ADDS_rail.SharedScrewRailInputProperty/property' ) # type: ignore rail_screw_flip_y: bpy.props.BoolProperty( name = 'Flip Y', description = 'Whether flip this rail with Y axis', - default = False + default = False, + translation_context = 'BBP/OP_ADDS_rail.SharedScrewRailInputProperty/property' ) # type: ignore rail_screw_flip_z: bpy.props.BoolProperty( name = 'Flip Z', description = 'Whether flip this rail with Z axis', - default = False + default = False, + translation_context = 'BBP/OP_ADDS_rail.SharedScrewRailInputProperty/property' ) # type: ignore def draw_screw_rail_input(self, layout: bpy.types.UILayout) -> None: @@ -220,6 +231,7 @@ class BBP_OT_add_rail_section(SharedRailSectionInputProperty, bpy.types.Operator bl_idname = "bbp.add_rail_section" bl_label = "Rail Section" bl_options = {'REGISTER', 'UNDO'} + bl_translation_context = 'BBP_OT_add_rail_section' def execute(self, context): UTIL_rail_creator.rail_creator_wrapper( @@ -240,6 +252,7 @@ class BBP_OT_add_transition_section(bpy.types.Operator): bl_idname = "bbp.add_transition_section" bl_label = "Transition Section" bl_options = {'REGISTER', 'UNDO'} + bl_translation_context = 'BBP_OT_add_transition_section' def execute(self, context): UTIL_rail_creator.rail_creator_wrapper( @@ -257,6 +270,7 @@ class BBP_OT_add_straight_rail(SharedExtraTransform, SharedRailSectionInputPrope bl_idname = "bbp.add_straight_rail" bl_label = "Straight Rail" bl_options = {'REGISTER', 'UNDO'} + bl_translation_context = 'BBP_OT_add_straight_rail' def execute(self, context): UTIL_rail_creator.rail_creator_wrapper( @@ -285,6 +299,7 @@ class BBP_OT_add_transition_rail(SharedExtraTransform, SharedRailCapInputPropert bl_idname = "bbp.add_transition_rail" bl_label = "Transition Rail" bl_options = {'REGISTER', 'UNDO'} + bl_translation_context = 'BBP_OT_add_transition_rail' def execute(self, context): UTIL_rail_creator.rail_creator_wrapper( @@ -312,6 +327,7 @@ class BBP_OT_add_side_rail(SharedExtraTransform, SharedRailCapInputProperty, Sha bl_idname = "bbp.add_side_rail" bl_label = "Side Rail" bl_options = {'REGISTER', 'UNDO'} + bl_translation_context = 'BBP_OT_add_side_rail' side_rail_type: bpy.props.EnumProperty( name = "Side Type", @@ -321,6 +337,7 @@ class BBP_OT_add_side_rail(SharedExtraTransform, SharedRailCapInputProperty, Sha ('STONE', "Stone Specific", "The side rail which also allow stone ball passed."), ], default = 'NORMAL', + translation_context = 'BBP_OT_add_side_rail/property' ) # type: ignore def execute(self, context): @@ -351,6 +368,7 @@ class BBP_OT_add_arc_rail(SharedExtraTransform, SharedRailSectionInputProperty, bl_idname = "bbp.add_arc_rail" bl_label = "Arc Rail" bl_options = {'REGISTER', 'UNDO'} + bl_translation_context = 'BBP_OT_add_arc_rail' rail_screw_angle: bpy.props.FloatProperty( name = "Angle", @@ -358,6 +376,7 @@ class BBP_OT_add_arc_rail(SharedExtraTransform, SharedRailSectionInputProperty, default = math.radians(90), min = 0, max = math.radians(360), subtype = 'ANGLE', + translation_context = 'BBP_OT_add_arc_rail/property' ) # type: ignore def execute(self, context): @@ -392,12 +411,14 @@ class BBP_OT_add_spiral_rail(SharedExtraTransform, SharedRailCapInputProperty, S bl_idname = "bbp.add_spiral_rail" bl_label = "Spiral Rail" bl_options = {'REGISTER', 'UNDO'} + bl_translation_context = 'BBP_OT_add_spiral_rail' rail_screw_screw: bpy.props.FloatProperty( name = "Screw", description = "The increased height in each iteration. Minus height also is accepted.", default = c_SpiralRailScrew, - unit = 'LENGTH' + unit = 'LENGTH', + translation_context = 'BBP_OT_add_spiral_rail/property' ) # type: ignore rail_screw_iterations: bpy.props.IntProperty( @@ -405,6 +426,7 @@ class BBP_OT_add_spiral_rail(SharedExtraTransform, SharedRailCapInputProperty, S description = "Indicate how many layers of this spiral rail should be generated.", default = 1, min = 1, + translation_context = 'BBP_OT_add_spiral_rail/property' ) # type: ignore def execute(self, context): @@ -439,6 +461,7 @@ class BBP_OT_add_side_spiral_rail(SharedExtraTransform, SharedRailSectionInputPr bl_idname = "bbp.add_side_spiral_rail" bl_label = "Side Spiral Rail" bl_options = {'REGISTER', 'UNDO'} + bl_translation_context = 'BBP_OT_add_side_spiral_rail' rail_screw_iterations: bpy.props.IntProperty( name = "Iterations", @@ -447,6 +470,7 @@ class BBP_OT_add_side_spiral_rail(SharedExtraTransform, SharedRailSectionInputPr # at least 2 ietrations can create 1 useful side spiral rail. # becuase side spiral rail is edge shared. min = 2, + translation_context = 'BBP_OT_add_side_spiral_rail/property' ) # type: ignore def execute(self, context): diff --git a/bbp_ng/OP_EXPORT_bmfile.py b/bbp_ng/OP_EXPORT_bmfile.py index 450d8c3..3383743 100644 --- a/bbp_ng/OP_EXPORT_bmfile.py +++ b/bbp_ng/OP_EXPORT_bmfile.py @@ -6,19 +6,19 @@ class BBP_OT_export_bmfile(bpy.types.Operator, UTIL_file_browser.ExportBmxFile, bl_idname = "bbp.export_bmfile" bl_label = "Export BM (Ballance Map) File" bl_options = {'PRESET'} + bl_translation_context = 'BBP_OT_export_bmfile' @classmethod def poll(cls, context): return PROP_preferences.get_raw_preferences().has_valid_blc_tex_folder() def execute(self, context): - self.report({'ERROR'}, 'This function not supported yet.') + self.report({'ERROR'}, 'This feature is not supported yet.') # self.report({'INFO'}, "BM File Exporting Finished.") return {'FINISHED'} def draw(self, context): layout = self.layout - layout.label(text = 'Export Target') self.draw_export_params(context, layout.box()) def register() -> None: diff --git a/bbp_ng/OP_EXPORT_virtools.py b/bbp_ng/OP_EXPORT_virtools.py index eb34031..cb43744 100644 --- a/bbp_ng/OP_EXPORT_virtools.py +++ b/bbp_ng/OP_EXPORT_virtools.py @@ -11,6 +11,7 @@ class BBP_OT_export_virtools(bpy.types.Operator, UTIL_file_browser.ExportVirtool bl_idname = "bbp.export_virtools" bl_label = "Export Virtools File" bl_options = {'PRESET'} + bl_translation_context = 'BBP_OT_export_virtools' @classmethod def poll(cls, context): diff --git a/bbp_ng/OP_IMPORT_bmfile.py b/bbp_ng/OP_IMPORT_bmfile.py index 7d867f8..5652510 100644 --- a/bbp_ng/OP_IMPORT_bmfile.py +++ b/bbp_ng/OP_IMPORT_bmfile.py @@ -6,19 +6,19 @@ class BBP_OT_import_bmfile(bpy.types.Operator, UTIL_file_browser.ImportBmxFile, bl_idname = "bbp.import_bmfile" bl_label = "Import BM (Ballance Map) File" bl_options = {'PRESET', 'UNDO'} + bl_translation_context = 'BBP_OT_import_bmfile' @classmethod def poll(cls, context): return PROP_preferences.get_raw_preferences().has_valid_blc_tex_folder() def execute(self, context): - self.report({'ERROR'}, 'This function not supported yet.') + self.report({'ERROR'}, 'This feature is not supported yet.') # self.report({'INFO'}, "BM File Importing Finished.") return {'FINISHED'} def draw(self, context): layout = self.layout - layout.label(text = 'Conflict Options') self.draw_import_params(layout.box()) def register() -> None: diff --git a/bbp_ng/OP_IMPORT_virtools.py b/bbp_ng/OP_IMPORT_virtools.py index ac411d4..ca9d2ad 100644 --- a/bbp_ng/OP_IMPORT_virtools.py +++ b/bbp_ng/OP_IMPORT_virtools.py @@ -11,6 +11,7 @@ class BBP_OT_import_virtools(bpy.types.Operator, UTIL_file_browser.ImportVirtool bl_idname = "bbp.import_virtools" bl_label = "Import Virtools File" bl_options = {'PRESET', 'UNDO'} + bl_translation_context = 'BBP_OT_import_virtools' @classmethod def poll(cls, context): diff --git a/bbp_ng/OP_MTL_fix_material.py b/bbp_ng/OP_MTL_fix_material.py index db14cc7..c8edaac 100644 --- a/bbp_ng/OP_MTL_fix_material.py +++ b/bbp_ng/OP_MTL_fix_material.py @@ -5,8 +5,9 @@ from . import PROP_virtools_material, PROP_preferences class BBP_OT_fix_all_material(bpy.types.Operator): """Fix All Materials by Its Referred Ballance Texture Name.""" bl_idname = "bbp.fix_all_material" - bl_label = "Fix Material" + bl_label = "Fix All Materials" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_fix_all_material' @classmethod def poll(cls, context): diff --git a/bbp_ng/OP_OBJECT_legacy_align.py b/bbp_ng/OP_OBJECT_legacy_align.py index 368a285..e60ab44 100644 --- a/bbp_ng/OP_OBJECT_legacy_align.py +++ b/bbp_ng/OP_OBJECT_legacy_align.py @@ -43,24 +43,29 @@ class BBP_PG_legacy_align_history(bpy.types.PropertyGroup): align_x: bpy.props.BoolProperty( name = "X Position", default = False, + translation_context = 'BBP_PG_legacy_align_history/property' ) # type: ignore align_y: bpy.props.BoolProperty( name = "Y Position", default = False, + translation_context = 'BBP_PG_legacy_align_history/property' ) # type: ignore align_z: bpy.props.BoolProperty( name = "Z Position", default = False, + translation_context = 'BBP_PG_legacy_align_history/property' ) # type: ignore current_align_mode: bpy.props.EnumProperty( name = "Current Object (Active Object)", items = _g_EnumHelper_AlignMode.generate_items(), default = _g_EnumHelper_AlignMode.to_selection(AlignMode.AxisCenter), + translation_context = 'BBP_PG_legacy_align_history/property' ) # type: ignore target_align_mode: bpy.props.EnumProperty( name = "Target Objects (Other Objects)", items = _g_EnumHelper_AlignMode.generate_items(), default = _g_EnumHelper_AlignMode.to_selection(AlignMode.AxisCenter), + translation_context = 'BBP_PG_legacy_align_history/property' ) # type: ignore #endregion @@ -70,6 +75,7 @@ class BBP_OT_legacy_align(bpy.types.Operator): bl_idname = "bbp.legacy_align" bl_label = "3ds Max Align" bl_options = {'REGISTER', 'UNDO'} + bl_translation_context = 'BBP_OT_legacy_align' # the updator for apply flag value def apply_flag_updated(self, context): @@ -111,17 +117,20 @@ class BBP_OT_legacy_align(bpy.types.Operator): options = {'HIDDEN', 'SKIP_SAVE'}, default = True, # default True value to make it as a "light" button, not a grey one. update = apply_flag_updated, + translation_context = 'BBP_OT_legacy_align/property' ) # type: ignore recursive_hinder: bpy.props.BoolProperty( - name = "Recursive Hinder", - description = "An internal flag to prevent the loop calling to apply_flags's updator.", + # TR: internal used property should not have name and description, otherwise it will be translated. + # name = "Recursive Hinder", + # description = "An internal flag to prevent the loop calling to apply_flags's updator.", options = {'HIDDEN', 'SKIP_SAVE'}, - default = False, + default = False ) # type: ignore align_history : bpy.props.CollectionProperty( - name = "Historys", - description = "Align history.", - type = BBP_PG_legacy_align_history, + # TR: same reason for no name and description. + # name = "Historys", + # description = "Align history.", + type = BBP_PG_legacy_align_history ) # type: ignore @classmethod diff --git a/bbp_ng/OP_OBJECT_naming_convention.py b/bbp_ng/OP_OBJECT_naming_convention.py index eea3d21..d49f6a2 100644 --- a/bbp_ng/OP_OBJECT_naming_convention.py +++ b/bbp_ng/OP_OBJECT_naming_convention.py @@ -7,6 +7,7 @@ class BBP_OT_regulate_objects_name(bpy.types.Operator): bl_idname = "bbp.regulate_objects_name" bl_label = "Regulate Objects Name" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_regulate_objects_name' def invoke(self, context, event): wm = context.window_manager @@ -24,6 +25,7 @@ class BBP_OT_auto_grouping(bpy.types.Operator): bl_idname = "bbp.auto_grouping" bl_label = "Auto Grouping" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_auto_grouping' def invoke(self, context, event): wm = context.window_manager @@ -41,6 +43,7 @@ class BBP_OT_convert_to_imengyu(bpy.types.Operator): bl_idname = "bbp.convert_to_imengyu" bl_label = "Convert to Imengyu" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_convert_to_imengyu' def invoke(self, context, event): wm = context.window_manager diff --git a/bbp_ng/OP_OBJECT_snoop_group_then_to_mesh.py b/bbp_ng/OP_OBJECT_snoop_group_then_to_mesh.py index 0cc5c4e..d8a547a 100644 --- a/bbp_ng/OP_OBJECT_snoop_group_then_to_mesh.py +++ b/bbp_ng/OP_OBJECT_snoop_group_then_to_mesh.py @@ -7,6 +7,7 @@ class BBP_OT_snoop_group_then_to_mesh(bpy.types.Operator): bl_idname = "bbp.snoop_group_then_to_mesh" bl_label = "Snoop Group then to Mesh" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_snoop_group_then_to_mesh' @classmethod def poll(cls, context): diff --git a/bbp_ng/OP_OBJECT_virtools_group.py b/bbp_ng/OP_OBJECT_virtools_group.py index 24d02b9..268c28d 100644 --- a/bbp_ng/OP_OBJECT_virtools_group.py +++ b/bbp_ng/OP_OBJECT_virtools_group.py @@ -32,12 +32,14 @@ class BBP_OT_select_object_by_virtools_group(bpy.types.Operator, PROP_virtools_g bl_idname = "bbp.select_object_by_virtools_group" bl_label = "Select by Virtools Group" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_select_object_by_virtools_group' selection_mode: bpy.props.EnumProperty( name = "Mode", description = "Selection mode", items = _g_EnumHelper_SelectMode.generate_items(), - default = _g_EnumHelper_SelectMode.to_selection(SelectMode.Intersect) + default = _g_EnumHelper_SelectMode.to_selection(SelectMode.Intersect), + translation_context = 'BBP_OT_select_object_by_virtools_group/property' ) # type: ignore @classmethod @@ -122,6 +124,7 @@ class BBP_OT_add_objects_virtools_group(bpy.types.Operator, PROP_virtools_group. bl_idname = "bbp.add_objects_virtools_group" bl_label = "Grouping Objects" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_add_objects_virtools_group' @classmethod def poll(cls, context): @@ -147,6 +150,7 @@ class BBP_OT_rm_objects_virtools_group(bpy.types.Operator, PROP_virtools_group.S bl_idname = "bbp.rm_objects_virtools_group" bl_label = "Ungrouping Objects" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_rm_objects_virtools_group' @classmethod def poll(cls, context): @@ -172,6 +176,7 @@ class BBP_OT_clear_objects_virtools_group(bpy.types.Operator): bl_idname = "bbp.clear_objects_virtools_group" bl_label = "Clear All Groups" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_clear_objects_virtools_group' @classmethod def poll(cls, context): diff --git a/bbp_ng/OP_UV_flatten_uv.py b/bbp_ng/OP_UV_flatten_uv.py index abc7819..1d354fe 100644 --- a/bbp_ng/OP_UV_flatten_uv.py +++ b/bbp_ng/OP_UV_flatten_uv.py @@ -78,6 +78,7 @@ class BBP_OT_flatten_uv(bpy.types.Operator): bl_idname = "bbp.flatten_uv" bl_label = "Flatten UV" bl_options = {'REGISTER', 'UNDO'} + bl_translation_context = 'BBP_OT_flatten_uv' reference_edge: bpy.props.IntProperty( name = "Reference Edge", @@ -85,6 +86,7 @@ class BBP_OT_flatten_uv(bpy.types.Operator): min = 0, soft_min = 0, soft_max = 3, default = 0, + translation_context = 'BBP_OT_flatten_uv/property' ) # type: ignore flatten_method: bpy.props.EnumProperty( @@ -94,7 +96,8 @@ class BBP_OT_flatten_uv(bpy.types.Operator): ('FLOOR', "Floor", "Floor specific flatten UV."), ('WOOD', "Wood", "Wood specific flatten UV."), ], - default = 'RAW' + default = 'RAW', + translation_context = 'BBP_OT_flatten_uv/property' ) # type: ignore scale_mode: bpy.props.EnumProperty( @@ -103,7 +106,8 @@ class BBP_OT_flatten_uv(bpy.types.Operator): ('NUM', "Scale Size", "Scale UV with specific number."), ('REF', "Ref. Point", "Scale UV with Reference Point feature."), ], - default = 'NUM' + default = 'NUM', + translation_context = 'BBP_OT_flatten_uv/property' ) # type: ignore scale_number: bpy.props.FloatProperty( @@ -114,6 +118,7 @@ class BBP_OT_flatten_uv(bpy.types.Operator): default = 5.0, step = 10, precision = 1, + translation_context = 'BBP_OT_flatten_uv/property' ) # type: ignore reference_point: bpy.props.IntProperty( @@ -122,6 +127,7 @@ class BBP_OT_flatten_uv(bpy.types.Operator): min = 2, # 0 and 1 is invalid. we can not order the reference edge to be set on the outside of uv axis soft_min = 2, soft_max = 3, default = 2, + translation_context = 'BBP_OT_flatten_uv/property' ) # type: ignore reference_uv: bpy.props.FloatProperty( @@ -131,6 +137,7 @@ class BBP_OT_flatten_uv(bpy.types.Operator): default = 0.5, step = 10, precision = 2, + translation_context = 'BBP_OT_flatten_uv/property' ) # type: ignore @classmethod diff --git a/bbp_ng/OP_UV_rail_uv.py b/bbp_ng/OP_UV_rail_uv.py index d7aa475..3f51f77 100644 --- a/bbp_ng/OP_UV_rail_uv.py +++ b/bbp_ng/OP_UV_rail_uv.py @@ -8,10 +8,11 @@ class BBP_OT_rail_uv(bpy.types.Operator): bl_idname = "bbp.rail_uv" bl_label = "Rail UV" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_rail_uv' @classmethod def poll(cls, context): - return _check_rail_target() + return _check_rail_target(context) def invoke(self, context, event): wm: bpy.types.WindowManager = context.window_manager @@ -26,7 +27,13 @@ class BBP_OT_rail_uv(bpy.types.Operator): return {'CANCELLED'} # apply rail uv - _create_rail_uv(_get_rail_target(), mtl) + (has_invalid_objs, meshes) = _get_rail_target(context) + _create_rail_uv(meshes, mtl) + + # show warning if there is invalid objects + if has_invalid_objs: + self.report({'WARNING'}, 'Some objects are invalid for this operation. See Console for more details.') + return {'FINISHED'} def draw(self, context): @@ -36,8 +43,8 @@ class BBP_OT_rail_uv(bpy.types.Operator): #region Real Worker Functions -def _check_rail_target() -> bool: - for obj in bpy.context.selected_objects: +def _check_rail_target(context: bpy.types.Context) -> bool: + for obj in context.selected_objects: if obj.type != 'MESH': continue if obj.mode != 'OBJECT': @@ -47,11 +54,11 @@ def _check_rail_target() -> bool: return True return False -def _get_rail_target() -> typing.Iterable[bpy.types.Mesh]: +def _get_rail_target(context: bpy.types.Context) -> tuple[bool, typing.Iterable[bpy.types.Mesh]]: # collect objects meshes: list[bpy.types.Mesh] = [] error_objname: list[str] = [] - for obj in bpy.context.selected_objects: + for obj in context.selected_objects: if obj.type != 'MESH': error_objname.append(obj.name) continue @@ -62,28 +69,21 @@ def _get_rail_target() -> typing.Iterable[bpy.types.Mesh]: error_objname.append(obj.name) continue - meshes.append(obj.data) + meshes.append(typing.cast(bpy.types.Mesh, obj.data)) # display warning window if necessary - if len(error_objname) != 0: - # show dialog - UTIL_functions.message_box( - ("Some objects is not processed, see Console for more infos.", ), - "Object Type Warning", - UTIL_icons_manager.BlenderPresetIcons.Warning.value - ) - + has_invalid_objs = len(error_objname) != 0 + if has_invalid_objs: # output to console print('') - print('=====') + print('========== Rail UV Report ==========') print('Following objects are not processed by Rail UV because they do not meet the requirements of Rail UV.') for objname in error_objname: print(objname) - print('=====') print('') # return valid - return meshes + return (has_invalid_objs, meshes) def _tt_reflection_mapping_compute( point_: UTIL_virtools_types.ConstVxVector3, diff --git a/bbp_ng/PROP_ballance_element.py b/bbp_ng/PROP_ballance_element.py index 3efc140..40b9226 100644 --- a/bbp_ng/PROP_ballance_element.py +++ b/bbp_ng/PROP_ballance_element.py @@ -96,12 +96,14 @@ def is_ballance_element(name: str) -> bool: class BBP_PG_ballance_element(bpy.types.PropertyGroup): element_id: bpy.props.IntProperty( name = "Element Id", - default = 0 + default = 0, + translation_context = 'BBP_PG_ballance_element/property' ) # type: ignore mesh_ptr: bpy.props.PointerProperty( name = "Mesh", - type = bpy.types.Mesh + type = bpy.types.Mesh, + translation_context = 'BBP_PG_ballance_element/property' ) # type: ignore def get_ballance_elements(scene: bpy.types.Scene) -> UTIL_functions.CollectionVisitor[BBP_PG_ballance_element]: @@ -322,6 +324,7 @@ class BBP_OT_reset_ballance_elements(bpy.types.Operator): bl_idname = "bbp.reset_ballance_elements" bl_label = "Reset Ballance Elements" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_reset_ballance_elements' @classmethod def poll(cls, context): @@ -331,11 +334,7 @@ class BBP_OT_reset_ballance_elements(bpy.types.Operator): with BallanceElementsHelper(context.scene) as helper: helper.reset_elements() # show a window to let user know, not silence - UTIL_functions.message_box( - ('Reset OK.', ), - "Reset Result", - UTIL_icons_manager.BlenderPresetIcons.Info.value - ) + self.report({'INFO'}, 'Reset Ballance elements successfully.') return {'FINISHED'} class BBP_PT_ballance_elements(bpy.types.Panel): @@ -345,6 +344,7 @@ class BBP_PT_ballance_elements(bpy.types.Panel): bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = "scene" + bl_translation_context = 'BBP_PT_ballance_elements' @classmethod def poll(cls, context): diff --git a/bbp_ng/PROP_ballance_map_info.py b/bbp_ng/PROP_ballance_map_info.py index 9deec6a..d2b47e9 100644 --- a/bbp_ng/PROP_ballance_map_info.py +++ b/bbp_ng/PROP_ballance_map_info.py @@ -22,7 +22,8 @@ class BBP_PG_ballance_map_info(bpy.types.PropertyGroup): default = 1, max = 999, min = 1, soft_max = 8, soft_min = 1, - step = 1 + step = 1, + translation_context = 'BBP_PG_ballance_map_info/property' ) # type: ignore def get_ballance_map_info(scene: bpy.types.Scene) -> BBP_PG_ballance_map_info: @@ -51,6 +52,7 @@ class BBP_PT_ballance_map_info(bpy.types.Panel): bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = "scene" + bl_translation_context = 'BBP_PT_ballance_map_info' @classmethod def poll(cls, context): diff --git a/bbp_ng/PROP_bme_material.py b/bbp_ng/PROP_bme_material.py index d0a51e4..98f08dc 100644 --- a/bbp_ng/PROP_bme_material.py +++ b/bbp_ng/PROP_bme_material.py @@ -77,12 +77,14 @@ _g_BMEMaterialPresets: dict[str, _BMEMaterialPreset] = { class BBP_PG_bme_material(bpy.types.PropertyGroup): bme_material_name: bpy.props.StringProperty( name = "Name", - default = "" + default = "", + translation_context = 'BBP_PG_bme_material/property' ) # type: ignore material_ptr: bpy.props.PointerProperty( name = "Material", - type = bpy.types.Material + type = bpy.types.Material, + translation_context = 'BBP_PG_bme_material/property' ) # type: ignore def get_bme_materials(scene: bpy.types.Scene) -> UTIL_functions.CollectionVisitor[BBP_PG_bme_material]: @@ -175,6 +177,14 @@ class BMEMaterialsHelper(): self.__mMaterialMap[preset_name] = new_mtl return new_mtl + def reset_materials(self) -> None: + if not self.is_valid(): + raise UTIL_functions.BBPException('calling invalid BMEMaterialsHelper') + + # load all items + for preset_name, mtl in self.__mMaterialMap.items(): + _load_bme_material_preset(mtl, preset_name) + def __write_to_bme_materials(self) -> None: mtls = get_bme_materials(self.__mAssocScene) mtls.clear() @@ -194,28 +204,6 @@ class BMEMaterialsHelper(): # add into map self.__mMaterialMap[item.bme_material_name] = item.material_ptr -def reset_bme_materials(scene: bpy.types.Scene) -> None: - invalid_idx: list[int] = [] - mtls = get_bme_materials(scene) - - # re-load all elements - index: int = 0 - item: BBP_PG_bme_material - for item in mtls: - # load or record invalid entry - if item.material_ptr is None: - invalid_idx.append(index) - else: - _load_bme_material_preset(item.material_ptr, item.bme_material_name) - - # inc counter - index += 1 - - # remove invalid one with reversed order - invalid_idx.reverse() - for idx in invalid_idx: - mtls.remove(idx) - #endregion #region BME Materials Representation @@ -233,19 +221,17 @@ class BBP_OT_reset_bme_materials(bpy.types.Operator): bl_idname = "bbp.reset_bme_materials" bl_label = "Reset BME Materials" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_reset_bme_materials' @classmethod def poll(cls, context): return context.scene is not None def execute(self, context): - reset_bme_materials(context.scene) + with BMEMaterialsHelper(context.scene) as helper: + helper.reset_materials() # show a window to let user know, not silence - UTIL_functions.message_box( - ('Reset OK.', ), - "Reset Result", - UTIL_icons_manager.BlenderPresetIcons.Info.value - ) + self.report({'INFO'}, 'Reset BME materials successfully.') return {'FINISHED'} class BBP_PT_bme_materials(bpy.types.Panel): @@ -255,6 +241,7 @@ class BBP_PT_bme_materials(bpy.types.Panel): bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = "scene" + bl_translation_context = 'BBP_PT_bme_materials' @classmethod def poll(cls, context): diff --git a/bbp_ng/PROP_preferences.py b/bbp_ng/PROP_preferences.py index 5982f59..ad7eb53 100644 --- a/bbp_ng/PROP_preferences.py +++ b/bbp_ng/PROP_preferences.py @@ -22,18 +22,20 @@ class BBPPreferences(bpy.types.AddonPreferences): ballance_texture_folder: bpy.props.StringProperty( name = "Ballance Texture Folder", 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, + translation_context = 'BBPPreferences/property' ) # type: ignore no_component_collection: bpy.props.StringProperty( 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 = "When importing, it is the name of collection where objects store will not be saved as component. When exporting, all forced no component objects will be stored in this name represented collection", default = RawPreferences.cNoComponentCollection, + translation_context = 'BBPPreferences/property' ) # type: ignore def draw(self, context): - layout = self.layout + layout: bpy.types.UILayout = self.layout row = layout.row() col = row.column() diff --git a/bbp_ng/PROP_ptrprop_resolver.py b/bbp_ng/PROP_ptrprop_resolver.py index d160322..305d820 100644 --- a/bbp_ng/PROP_ptrprop_resolver.py +++ b/bbp_ng/PROP_ptrprop_resolver.py @@ -12,7 +12,8 @@ from . import UTIL_functions, UTIL_virtools_types class BBP_PG_bmap_encoding(bpy.types.PropertyGroup): encoding: bpy.props.StringProperty( name = "Encoding", - default = "" + default = "", + translation_context = 'BBP_PG_bmap_encoding/property' ) # type: ignore class BBP_UL_bmap_encoding(bpy.types.UIList): @@ -24,23 +25,25 @@ class BBP_PG_ptrprop_resolver(bpy.types.PropertyGroup): name = "Material", description = "The material used for rail", type = bpy.types.Material, + translation_context = 'BBP_PG_ptrprop_resolver/property' ) # type: ignore export_collection: bpy.props.PointerProperty( - type = bpy.types.Collection, name = "Collection", - description = "The collection exported. Nested collections allowed." + description = "The collection exported. Nested collections allowed.", + type = bpy.types.Collection, + translation_context = 'BBP_PG_ptrprop_resolver/property' ) # type: ignore export_object: bpy.props.PointerProperty( - type = bpy.types.Object, name = "Object", - description = "The object exported" + description = "The object exported", + type = bpy.types.Object, + translation_context = 'BBP_PG_ptrprop_resolver/property' ) # type: ignore - ioport_encodings: bpy.props.CollectionProperty( - type = BBP_PG_bmap_encoding - ) # type: ignore + # TR: These encoding related items should not have explicit name and description + ioport_encodings: bpy.props.CollectionProperty(type = BBP_PG_bmap_encoding) # type: ignore active_ioport_encodings: bpy.props.IntProperty() # type: ignore #endregion @@ -62,6 +65,7 @@ class BBP_OT_add_ioport_encodings(bpy.types.Operator): bl_idname = "bbp.add_ioport_encodings" bl_label = "Add in Encodings List" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_add_ioport_encodings' @classmethod def poll(cls, context: bpy.types.Context) -> bool: @@ -77,6 +81,7 @@ class BBP_OT_rm_ioport_encodings(bpy.types.Operator): bl_idname = "bbp.rm_ioport_encodings" bl_label = "Remove from Encodings List" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_rm_ioport_encodings' @classmethod def poll(cls, context: bpy.types.Context) -> bool: @@ -100,6 +105,7 @@ class BBP_OT_up_ioport_encodings(bpy.types.Operator): bl_idname = "bbp.up_ioport_encodings" bl_label = "Move Up in Encodings List" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_up_ioport_encodings' @classmethod def poll(cls, context: bpy.types.Context) -> bool: @@ -119,6 +125,7 @@ class BBP_OT_down_ioport_encodings(bpy.types.Operator): bl_idname = "bbp.down_ioport_encodings" bl_label = "Move Down in Encodings List" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_down_ioport_encodings' @classmethod def poll(cls, context: bpy.types.Context) -> bool: @@ -138,6 +145,7 @@ class BBP_OT_clear_ioport_encodings(bpy.types.Operator): bl_idname = "bbp.clear_ioport_encodings" bl_label = "Clear Encodings List" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_clear_ioport_encodings' @classmethod def poll(cls, context: bpy.types.Context) -> bool: diff --git a/bbp_ng/PROP_virtools_group.py b/bbp_ng/PROP_virtools_group.py index 287231b..6f04d7d 100644 --- a/bbp_ng/PROP_virtools_group.py +++ b/bbp_ng/PROP_virtools_group.py @@ -7,7 +7,8 @@ from . import UTIL_functions, UTIL_icons_manager class BBP_PG_virtools_group(bpy.types.PropertyGroup): group_name: bpy.props.StringProperty( name = "Group Name", - default = "" + default = "", + translation_context = 'BBP_PG_virtools_group/property' ) # type: ignore def get_virtools_groups(obj: bpy.types.Object) -> UTIL_functions.CollectionVisitor[BBP_PG_virtools_group]: @@ -251,18 +252,21 @@ class SharedGroupNameInputProperties(): ('DEFINED', "Predefined", "Pre-defined group name."), ('CUSTOM', "Custom", "User specified group name."), ), + translation_context = 'BME/PROP_virtools_grourp.SharedGroupNameInputProperties/property' ) # type: ignore preset_group_name: bpy.props.EnumProperty( name = "Group Name", description = "Pick vanilla Ballance group name.", items = _g_EnumHelper_Group.generate_items(), + translation_context = 'BME/PROP_virtools_grourp.SharedGroupNameInputProperties/property' ) # type: ignore custom_group_name: bpy.props.StringProperty( name = "Custom Group Name", description = "Input your custom group name.", default = "", + translation_context = 'BME/PROP_virtools_grourp.SharedGroupNameInputProperties/property' ) # type: ignore def draw_group_name_input(self, layout: bpy.types.UILayout) -> None: @@ -291,6 +295,7 @@ class BBP_OT_add_virtools_group(bpy.types.Operator, SharedGroupNameInputProperti bl_idname = "bbp.add_virtools_groups" bl_label = "Add to Virtools Groups" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_add_virtools_group' @classmethod def poll(cls, context: bpy.types.Context): @@ -315,6 +320,7 @@ class BBP_OT_rm_virtools_group(bpy.types.Operator): bl_idname = "bbp.rm_virtools_groups" bl_label = "Remove from Virtools Groups" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_rm_virtools_group' ## This class is slightly unique. # Because we need get user selected group name first. @@ -347,6 +353,7 @@ class BBP_OT_clear_virtools_groups(bpy.types.Operator): bl_idname = "bbp.clear_virtools_groups" bl_label = "Clear Virtools Groups" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_clear_virtools_groups' @classmethod def poll(cls, context: bpy.types.Context): @@ -369,6 +376,7 @@ class BBP_PT_virtools_groups(bpy.types.Panel): bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = "object" + bl_translation_context = 'BBP_PT_virtools_groups' @classmethod def poll(cls, context): diff --git a/bbp_ng/PROP_virtools_light.py b/bbp_ng/PROP_virtools_light.py index 1683a3f..4b9de4a 100644 --- a/bbp_ng/PROP_virtools_light.py +++ b/bbp_ng/PROP_virtools_light.py @@ -80,7 +80,8 @@ class BBP_PG_virtools_light(bpy.types.PropertyGroup): name = "Type", description = "The type of this light", items = _g_Helper_VXLIGHT_TYPE.generate_items(), - default = _g_Helper_VXLIGHT_TYPE.to_selection(RawVirtoolsLight.cDefaultType) + default = _g_Helper_VXLIGHT_TYPE.to_selection(RawVirtoolsLight.cDefaultType), + translation_context = 'BBP_PG_virtools_light/property' ) # type: ignore light_color: bpy.props.FloatVectorProperty( @@ -90,7 +91,8 @@ class BBP_PG_virtools_light(bpy.types.PropertyGroup): min = 0.0, max = 1.0, size = 3, - default = RawVirtoolsLight.cDefaultColor.to_const_rgb() + default = RawVirtoolsLight.cDefaultColor.to_const_rgb(), + translation_context = 'BBP_PG_virtools_light/property' ) # type: ignore constant_attenuation: bpy.props.FloatProperty( @@ -99,7 +101,8 @@ class BBP_PG_virtools_light(bpy.types.PropertyGroup): min = 0.0, max = 10.0, step = 10, - default = RawVirtoolsLight.cDefaultConstantAttenuation + default = RawVirtoolsLight.cDefaultConstantAttenuation, + translation_context = 'BBP_PG_virtools_light/property' ) # type: ignore linear_attenuation: bpy.props.FloatProperty( @@ -108,7 +111,8 @@ class BBP_PG_virtools_light(bpy.types.PropertyGroup): min = 0.0, max = 10.0, step = 10, - default = RawVirtoolsLight.cDefaultLinearAttenuation + default = RawVirtoolsLight.cDefaultLinearAttenuation, + translation_context = 'BBP_PG_virtools_light/property' ) # type: ignore quadratic_attenuation: bpy.props.FloatProperty( @@ -117,7 +121,8 @@ class BBP_PG_virtools_light(bpy.types.PropertyGroup): min = 0.0, max = 10.0, step = 10, - default = RawVirtoolsLight.cDefaultQuadraticAttenuation + default = RawVirtoolsLight.cDefaultQuadraticAttenuation, + translation_context = 'BBP_PG_virtools_light/property' ) # type: ignore light_range: bpy.props.FloatProperty( @@ -126,7 +131,8 @@ class BBP_PG_virtools_light(bpy.types.PropertyGroup): min = 0.0, max = 200.0, step = 100, - default = RawVirtoolsLight.cDefaultRange + default = RawVirtoolsLight.cDefaultRange, + translation_context = 'BBP_PG_virtools_light/property' ) # type: ignore hot_spot: bpy.props.FloatProperty( @@ -135,7 +141,8 @@ class BBP_PG_virtools_light(bpy.types.PropertyGroup): min = 0.0, max = math.radians(180), subtype = 'ANGLE', - default = RawVirtoolsLight.cDefaultHotSpot + default = RawVirtoolsLight.cDefaultHotSpot, + translation_context = 'BBP_PG_virtools_light/property' ) # type: ignore falloff: bpy.props.FloatProperty( @@ -144,7 +151,8 @@ class BBP_PG_virtools_light(bpy.types.PropertyGroup): min = 0.0, max = math.radians(180), subtype = 'ANGLE', - default = RawVirtoolsLight.cDefaultFalloff + default = RawVirtoolsLight.cDefaultFalloff, + translation_context = 'BBP_PG_virtools_light/property' ) # type: ignore falloff_shape: bpy.props.FloatProperty( @@ -153,7 +161,8 @@ class BBP_PG_virtools_light(bpy.types.PropertyGroup): min = 0.0, max = 10.0, step = 10, - default = RawVirtoolsLight.cDefaultFalloffShape + default = RawVirtoolsLight.cDefaultFalloffShape, + translation_context = 'BBP_PG_virtools_light/property' ) # type: ignore # Getter Setter and Applyer @@ -239,6 +248,7 @@ class BBP_OT_apply_virtools_light(bpy.types.Operator): bl_idname = "bbp.apply_virtools_light" bl_label = "Apply to Blender Light" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_apply_virtools_light' @classmethod def poll(cls, context): @@ -258,6 +268,7 @@ class BBP_PT_virtools_light(bpy.types.Panel): bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = "data" # idk why blender use `data` as the light tab same as mesh. + bl_translation_context = 'BBP_PT_virtools_light' @classmethod def poll(cls, context): diff --git a/bbp_ng/PROP_virtools_material.py b/bbp_ng/PROP_virtools_material.py index 884aa50..61029ef 100644 --- a/bbp_ng/PROP_virtools_material.py +++ b/bbp_ng/PROP_virtools_material.py @@ -132,7 +132,8 @@ class BBP_PG_virtools_material(bpy.types.PropertyGroup): min = 0.0, max = 1.0, size = 3, - default = RawVirtoolsMaterial.cDefaultAmbient.to_const_rgb() + default = RawVirtoolsMaterial.cDefaultAmbient.to_const_rgb(), + translation_context = 'BBP_PG_virtools_material/property' ) # type: ignore diffuse: bpy.props.FloatVectorProperty( @@ -142,7 +143,8 @@ class BBP_PG_virtools_material(bpy.types.PropertyGroup): min = 0.0, max = 1.0, size = 4, - default = RawVirtoolsMaterial.cDefaultDiffuse.to_const_rgba() + default = RawVirtoolsMaterial.cDefaultDiffuse.to_const_rgba(), + translation_context = 'BBP_PG_virtools_material/property' ) # type: ignore specular: bpy.props.FloatVectorProperty( @@ -152,7 +154,8 @@ class BBP_PG_virtools_material(bpy.types.PropertyGroup): min = 0.0, max = 1.0, size = 3, - default = RawVirtoolsMaterial.cDefaultSpecular.to_const_rgb() + default = RawVirtoolsMaterial.cDefaultSpecular.to_const_rgb(), + translation_context = 'BBP_PG_virtools_material/property' ) # type: ignore emissive: bpy.props.FloatVectorProperty( @@ -162,7 +165,8 @@ class BBP_PG_virtools_material(bpy.types.PropertyGroup): min = 0.0, max = 1.0, size = 3, - default = RawVirtoolsMaterial.cDefaultEmissive.to_const_rgb() + default = RawVirtoolsMaterial.cDefaultEmissive.to_const_rgb(), + translation_context = 'BBP_PG_virtools_material/property' ) # type: ignore specular_power: bpy.props.FloatProperty( @@ -170,13 +174,15 @@ class BBP_PG_virtools_material(bpy.types.PropertyGroup): description = "Specular highlight power", min = 0.0, max = 100.0, - default = RawVirtoolsMaterial.cDefaultSpecularPower + default = RawVirtoolsMaterial.cDefaultSpecularPower, + translation_context = 'BBP_PG_virtools_material/property' ) # type: ignore texture: bpy.props.PointerProperty( type = bpy.types.Image, name = "Texture", - description = "Texture of the material" + description = "Texture of the material", + translation_context = 'BBP_PG_virtools_material/property' ) # type: ignore texture_border_color: bpy.props.FloatVectorProperty( @@ -186,89 +192,103 @@ class BBP_PG_virtools_material(bpy.types.PropertyGroup): min = 0.0, max = 1.0, size = 4, - default = RawVirtoolsMaterial.cDefaultTextureBorderColor.to_const_rgba() + default = RawVirtoolsMaterial.cDefaultTextureBorderColor.to_const_rgba(), + translation_context = 'BBP_PG_virtools_material/property' ) # type: ignore texture_blend_mode: bpy.props.EnumProperty( name = "Texture Blend", description = "Texture blend mode", items = _g_Helper_VXTEXTURE_BLENDMODE.generate_items(), - default = _g_Helper_VXTEXTURE_BLENDMODE.to_selection(RawVirtoolsMaterial.cDefaultTextureBlendMode) + default = _g_Helper_VXTEXTURE_BLENDMODE.to_selection(RawVirtoolsMaterial.cDefaultTextureBlendMode), + translation_context = 'BBP_PG_virtools_material/property' ) # type: ignore texture_min_mode: bpy.props.EnumProperty( name = "Filter Min", description = "Texture filter mode when the texture is minified", items = _g_Helper_VXTEXTURE_FILTERMODE.generate_items(), - default = _g_Helper_VXTEXTURE_FILTERMODE.to_selection(RawVirtoolsMaterial.cDefaultTextureMinMode) + default = _g_Helper_VXTEXTURE_FILTERMODE.to_selection(RawVirtoolsMaterial.cDefaultTextureMinMode), + translation_context = 'BBP_PG_virtools_material/property' ) # type: ignore texture_mag_mode: bpy.props.EnumProperty( name = "Filter Mag", description = "Texture filter mode when the texture is magnified", items = _g_Helper_VXTEXTURE_FILTERMODE.generate_items(), - default = _g_Helper_VXTEXTURE_FILTERMODE.to_selection(RawVirtoolsMaterial.cDefaultTextureMagMode) + default = _g_Helper_VXTEXTURE_FILTERMODE.to_selection(RawVirtoolsMaterial.cDefaultTextureMagMode), + translation_context = 'BBP_PG_virtools_material/property' ) # type: ignore texture_address_mode: bpy.props.EnumProperty( name = "Address Mode", description = "The address mode controls how the texture coordinates outside the range 0..1", items = _g_Helper_VXTEXTURE_ADDRESSMODE.generate_items(), - default = _g_Helper_VXTEXTURE_ADDRESSMODE.to_selection(RawVirtoolsMaterial.cDefaultTextureAddressMode) + default = _g_Helper_VXTEXTURE_ADDRESSMODE.to_selection(RawVirtoolsMaterial.cDefaultTextureAddressMode), + translation_context = 'BBP_PG_virtools_material/property' ) # type: ignore source_blend: bpy.props.EnumProperty( name = "Source Blend", description = "Source blend factor", items = _g_Helper_VXBLEND_MODE.generate_items(), - default = _g_Helper_VXBLEND_MODE.to_selection(RawVirtoolsMaterial.cDefaultSourceBlend) + default = _g_Helper_VXBLEND_MODE.to_selection(RawVirtoolsMaterial.cDefaultSourceBlend), + translation_context = 'BBP_PG_virtools_material/property' ) # type: ignore dest_blend: bpy.props.EnumProperty( name = "Destination Blend", description = "Destination blend factor", items = _g_Helper_VXBLEND_MODE.generate_items(), - default = _g_Helper_VXBLEND_MODE.to_selection(RawVirtoolsMaterial.cDefaultDestBlend) + default = _g_Helper_VXBLEND_MODE.to_selection(RawVirtoolsMaterial.cDefaultDestBlend), + translation_context = 'BBP_PG_virtools_material/property' ) # type: ignore fill_mode: bpy.props.EnumProperty( name = "Fill Mode", description = "Fill mode", items = _g_Helper_VXFILL_MODE.generate_items(), - default = _g_Helper_VXFILL_MODE.to_selection(RawVirtoolsMaterial.cDefaultFillMode) + default = _g_Helper_VXFILL_MODE.to_selection(RawVirtoolsMaterial.cDefaultFillMode), + translation_context = 'BBP_PG_virtools_material/property' ) # type: ignore shade_mode: bpy.props.EnumProperty( name = "Shade Mode", description = "Shade mode", items = _g_Helper_VXSHADE_MODE.generate_items(), - default = _g_Helper_VXSHADE_MODE.to_selection(RawVirtoolsMaterial.cDefaultShadeMode) + default = _g_Helper_VXSHADE_MODE.to_selection(RawVirtoolsMaterial.cDefaultShadeMode), + translation_context = 'BBP_PG_virtools_material/property' ) # type: ignore enable_alpha_test: bpy.props.BoolProperty( name = "Alpha Test", description = "Whether the alpha test is enabled", - default = RawVirtoolsMaterial.cDefaultEnableAlphaTest + default = RawVirtoolsMaterial.cDefaultEnableAlphaTest, + translation_context = 'BBP_PG_virtools_material/property' ) # type: ignore enable_alpha_blend: bpy.props.BoolProperty( name = "Blend", description = "Whether alpha blending is enabled or not.", - default = RawVirtoolsMaterial.cDefaultEnableAlphaBlend + default = RawVirtoolsMaterial.cDefaultEnableAlphaBlend, + translation_context = 'BBP_PG_virtools_material/property' ) # type: ignore enable_perspective_correction: bpy.props.BoolProperty( name = "Perspective Correction", description = "Whether texture perspective correction is enabled", - default = RawVirtoolsMaterial.cDefaultEnablePerspectiveCorrection + default = RawVirtoolsMaterial.cDefaultEnablePerspectiveCorrection, + translation_context = 'BBP_PG_virtools_material/property' ) # type: ignore enable_z_write: bpy.props.BoolProperty( name = "Z-Buffer Write", description = "Whether writing in ZBuffer is enabled.", - default = RawVirtoolsMaterial.cDefaultEnableZWrite + default = RawVirtoolsMaterial.cDefaultEnableZWrite, + translation_context = 'BBP_PG_virtools_material/property' ) # type: ignore enable_two_sided: bpy.props.BoolProperty( name = "Both Sided", description = "Whether the material is both sided or not", - default = RawVirtoolsMaterial.cDefaultEnableTwoSided + default = RawVirtoolsMaterial.cDefaultEnableTwoSided, + translation_context = 'BBP_PG_virtools_material/property' ) # type: ignore alpha_ref: bpy.props.IntProperty( @@ -276,21 +296,24 @@ class BBP_PG_virtools_material(bpy.types.PropertyGroup): description = "Alpha referential value", min = 0, max = 255, - default = RawVirtoolsMaterial.cDefaultAlphaRef + default = RawVirtoolsMaterial.cDefaultAlphaRef, + translation_context = 'BBP_PG_virtools_material/property' ) # type: ignore alpha_func: bpy.props.EnumProperty( name = "Alpha Test Function", description = "Alpha comparision function", items = _g_Helper_VXCMPFUNC.generate_items(), - default = _g_Helper_VXCMPFUNC.to_selection(RawVirtoolsMaterial.cDefaultAlphaFunc) + default = _g_Helper_VXCMPFUNC.to_selection(RawVirtoolsMaterial.cDefaultAlphaFunc), + translation_context = 'BBP_PG_virtools_material/property' ) # type: ignore z_func: bpy.props.EnumProperty( name = "Z Compare Function", description = "Z Comparison function", items = _g_Helper_VXCMPFUNC.generate_items(), - default = _g_Helper_VXCMPFUNC.to_selection(RawVirtoolsMaterial.cDefaultZFunc) + default = _g_Helper_VXCMPFUNC.to_selection(RawVirtoolsMaterial.cDefaultZFunc), + translation_context = 'BBP_PG_virtools_material/property' ) # type: ignore #region Getter Setter @@ -877,6 +900,7 @@ class BBP_OT_apply_virtools_material(bpy.types.Operator): bl_idname = "bbp.apply_virtools_material" bl_label = "Apply to Blender Material" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_apply_virtools_material' @classmethod def poll(cls, context): @@ -892,6 +916,7 @@ class BBP_OT_fix_single_material(bpy.types.Operator): bl_idname = "bbp.fix_single_material" bl_label = "Fix Material" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_fix_single_material' @classmethod def poll(cls, context): @@ -911,7 +936,7 @@ class BBP_OT_fix_single_material(bpy.types.Operator): # if suc, apply to blender mtl and show info if ret: apply_to_blender_material(mtl) - self.report({'INFO'}, 'Fix done.') + self.report({'INFO'}, 'Fix material successfully.') else: # otherwise report warning self.report({'WARNING'}, 'This material is not suit for fixer.') @@ -923,6 +948,7 @@ class BBP_OT_preset_virtools_material(bpy.types.Operator): bl_idname = "bbp.preset_virtools_material" bl_label = "Preset Virtools Material" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_preset_virtools_material' preset_type: bpy.props.EnumProperty( name = "Preset", @@ -957,6 +983,7 @@ class BBP_OT_direct_set_virtools_texture(bpy.types.Operator, UTIL_file_browser.I bl_idname = "bbp.direct_set_virtools_texture" bl_label = "Import and Assign Texture" bl_options = {'UNDO'} + bl_translation_context = 'BBP_OT_direct_set_virtools_texture' @classmethod def poll(cls, context): @@ -1009,6 +1036,7 @@ class BBP_PT_virtools_material(bpy.types.Panel): bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = "material" + bl_translation_context = 'BBP_PT_virtools_material' @classmethod def poll(cls, context): diff --git a/bbp_ng/PROP_virtools_mesh.py b/bbp_ng/PROP_virtools_mesh.py index b3ff5b2..cc97e6e 100644 --- a/bbp_ng/PROP_virtools_mesh.py +++ b/bbp_ng/PROP_virtools_mesh.py @@ -24,7 +24,8 @@ class BBP_PG_virtools_mesh(bpy.types.PropertyGroup): name = "Lit Mode", description = "Lighting mode of the mesh.", 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), + translation_context = 'BBP_PG_virtools_mesh/property' ) # type: ignore # Getter Setter @@ -54,6 +55,7 @@ class BBP_PT_virtools_mesh(bpy.types.Panel): bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = "data" # idk why blender use `data` as the mesh tab. + bl_translation_context = 'BBP_PT_virtools_mesh' @classmethod def poll(cls, context): diff --git a/bbp_ng/PROP_virtools_texture.py b/bbp_ng/PROP_virtools_texture.py index 07de7dd..c66b49d 100644 --- a/bbp_ng/PROP_virtools_texture.py +++ b/bbp_ng/PROP_virtools_texture.py @@ -29,14 +29,16 @@ class BBP_PG_virtools_texture(bpy.types.PropertyGroup): name = "Save Options", 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(), - default = _g_Helper_CK_TEXTURE_SAVEOPTIONS.to_selection(RawVirtoolsTexture.cDefaultSaveOptions) + default = _g_Helper_CK_TEXTURE_SAVEOPTIONS.to_selection(RawVirtoolsTexture.cDefaultSaveOptions), + translation_context = 'BBP_PG_virtools_texture/property' ) # type: ignore video_format: bpy.props.EnumProperty( name = "Video Format", description = "The desired surface pixel format in video memory.", 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), + translation_context = 'BBP_PG_virtools_texture/property' ) # type: ignore #region Virtools Texture Getter Setter diff --git a/bbp_ng/UTIL_ioport_shared.py b/bbp_ng/UTIL_ioport_shared.py index 979ce47..cb73a60 100644 --- a/bbp_ng/UTIL_ioport_shared.py +++ b/bbp_ng/UTIL_ioport_shared.py @@ -159,6 +159,7 @@ class ImportParams(): items = _g_EnumHelper_ConflictStrategy.generate_items(), description = "Define how to process texture name conflict", default = _g_EnumHelper_ConflictStrategy.to_selection(ConflictStrategy.Current), + translation_context = 'BME/UTIL_ioport_shared.ImportParams/property' ) # type: ignore material_conflict_strategy: bpy.props.EnumProperty( @@ -166,6 +167,7 @@ class ImportParams(): items = _g_EnumHelper_ConflictStrategy.generate_items(), description = "Define how to process material name conflict", default = _g_EnumHelper_ConflictStrategy.to_selection(ConflictStrategy.Rename), + translation_context = 'BME/UTIL_ioport_shared.ImportParams/property' ) # type: ignore mesh_conflict_strategy: bpy.props.EnumProperty( @@ -173,6 +175,7 @@ class ImportParams(): items = _g_EnumHelper_ConflictStrategy.generate_items(), description = "Define how to process mesh name conflict", default = _g_EnumHelper_ConflictStrategy.to_selection(ConflictStrategy.Rename), + translation_context = 'BME/UTIL_ioport_shared.ImportParams/property' ) # type: ignore light_conflict_strategy: bpy.props.EnumProperty( @@ -180,6 +183,7 @@ class ImportParams(): items = _g_EnumHelper_ConflictStrategy.generate_items(), description = "Define how to process light name conflict", default = _g_EnumHelper_ConflictStrategy.to_selection(ConflictStrategy.Rename), + translation_context = 'BME/UTIL_ioport_shared.ImportParams/property' ) # type: ignore object_conflict_strategy: bpy.props.EnumProperty( @@ -187,6 +191,7 @@ class ImportParams(): items = _g_EnumHelper_ConflictStrategy.generate_items(), description = "Define how to process object name conflict", default = _g_EnumHelper_ConflictStrategy.to_selection(ConflictStrategy.Rename), + translation_context = 'BME/UTIL_ioport_shared.ImportParams/property' ) # type: ignore def draw_import_params(self, layout: bpy.types.UILayout) -> None: @@ -240,6 +245,7 @@ class ExportParams(): ('COLLECTION', "Collection", "Export a collection", 'OUTLINER_COLLECTION', 0), ('OBJECT', "Object", "Export an object", 'OBJECT_DATA', 1), ), + translation_context = 'BME/UTIL_ioport_shared.ExportParams/property' ) # type: ignore def draw_export_params(self, context: bpy.types.Context, layout: bpy.types.UILayout) -> None: @@ -284,13 +290,15 @@ class VirtoolsParams(): 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) + default = _g_EnumHelper_CK_TEXTURE_SAVEOPTIONS.to_selection(UTIL_virtools_types.CK_TEXTURE_SAVEOPTIONS.CKTEXTURE_EXTERNAL), + translation_context = 'BME/UTIL_ioport_shared.VirtoolsParams/property' ) # type: ignore use_compress: bpy.props.BoolProperty( name="Use Compress", description = "Whether use ZLib to compress result when saving composition.", default = True, + translation_context = 'BME/UTIL_ioport_shared.VirtoolsParams/property' ) # type: ignore compress_level: bpy.props.IntProperty( @@ -298,6 +306,7 @@ class VirtoolsParams(): description = "The ZLib compress level used by Virtools Engine when saving composition.", min = 1, max = 9, default = 5, + translation_context = 'BME/UTIL_ioport_shared.VirtoolsParams/property' ) # type: ignore def draw_virtools_params(self, context: bpy.types.Context, layout: bpy.types.UILayout, is_importer: bool) -> None: @@ -344,6 +353,7 @@ class BallanceParams(): name="Successive Sector", description = "Whether order exporter to use document specified sector count to make sure sector is successive.", default = True, + translation_context = 'BME/UTIL_ioport_shared.BallanceParams/property' ) # type: ignore def draw_ballance_params(self, layout: bpy.types.UILayout, is_importer: bool) -> None: diff --git a/bbp_ng/UTIL_translation.py b/bbp_ng/UTIL_translation.py new file mode 100644 index 0000000..f1af622 --- /dev/null +++ b/bbp_ng/UTIL_translation.py @@ -0,0 +1,87 @@ +import bpy + +#region Translation Contexts + +## NOTE: Translation Priniciple +# Due to the shitty design of Blender I18N tools (I can't specify context for every translation entries and its static analyse is so bad), +# I will specify all context but I can't do anything if Blender throw my translation context away. +# +# BME module has its own context naming convention which make sure all configuration fields of prototypes are properly translated. +# This module also provide a corresponding function to compute these context string from given BME prototype name and the index of configuration fields. +# +# For BBP plugin self, there is a priniciple list which you should follow when providing translation context. +# - For operator, menu, panel and etc, set their `bl_translation_context` to their names, such as `BBP_OT_some_operator` +# - For property located in operator, menu, panel and etc, set their `translation_context` to corresponding class name, +# plus `/property` suffix, such as `BBP_OT_some_operator/property`. +# - For draw function located in operator, menu, panel and etc, set their `translation_context` to corresponding class name, +# plus `/draw` suffix, such as `BBP_OT_some_operator/draw`. +# - For property loacted in shared class (usually shared by multiple operators), set their `translation_context` to `BME/./property`. +# `` is the module name (file name) where this class located. `` is the name of this class. +# For example, `BBP/some_module.some_class/property` +# +# Due to the shitty design, I can't find a way to add translation context for descrption field. +# So these description may collide with Blender official translation and thus not put in result file. +# I have no idea about this. +# +# Due to the shitty static analyse ability of Blender I18N plugin, all context should be written in literal, +# not the reference to other fields or the return value of some function. +# However for those strings, which originally should not be extracted by Blender I18N plugin, the way to get their context string is free. +# +# +# For the string given to Python `print()` which will be output in console, +# please use `bpy.app.translations.pgettext_rpt()` to get translation message because they are report. +# For the string given to `UTIL_functions.message_box()`, please use `bpy.app.translations.pgettext_iface` because they are UI elements. +# +# It seema that `bpy.app.translations.pgettext` function family has fatal error when extracting message with context +# (it will produce a correct one and a wrong one which just simply concat the message and its context. I don't know why). +# +# +# All translation annotation are started with `TR:` +# + +# The universal translation context prefix for BBP_NG plugin. +CTX_BBP: str = 'BBP' + +# The universal translation context prefix for BME module in BBP_NG plugin. +CTX_BBP_BME: str = CTX_BBP + '/BME' +def build_prototype_showcase_context(identifier: str) -> str: + """ + Build the context for getting the translation for BME prototype showcase title. + @param[in] identifier The identifier of this prototype. + @return The context for getting translation. + """ + return CTX_BBP_BME + '/' + identifier +def build_prototype_showcase_cfg_context(identifier: str, cfg_index: int) -> str: + """ + Build the context for getting the translation for BME prototype showcase configuration title or description. + @param[in] identifier The identifier of this prototype. + @param[in] cfg_index The index of this configuration in this prototype showcase. + @return The context for getting translation. + """ + return CTX_BBP_BME + f'/{identifier}/[{cfg_index}]' + +#endregion + +# ##### BEGIN AUTOGENERATED I18N SECTION ##### +# NOTE: You can safely move around this auto-generated block (with the begin/end markers!), +# and edit the translations by hand. +# Just carefully respect the format of the tuple! + +# Tuple of tuples: +# ((msgctxt, msgid), (sources, gen_comments), (lang, translation, (is_fuzzy, comments)), ...) +translations_tuple = () + +translations_dict = {} +for msg in translations_tuple: + key = msg[0] + for lang, trans, (is_fuzzy, comments) in msg[2:]: + if trans and not is_fuzzy: + translations_dict.setdefault(lang, {})[key] = trans + +# ##### END AUTOGENERATED I18N SECTION ##### + +def register() -> None: + bpy.app.translations.register(__package__, translations_dict) + +def unregister() -> None: + bpy.app.translations.unregister(__package__) diff --git a/bbp_ng/__init__.py b/bbp_ng/__init__.py index 6393fcd..1d93c9d 100644 --- a/bbp_ng/__init__.py +++ b/bbp_ng/__init__.py @@ -5,6 +5,8 @@ import bpy import typing, collections # reload if needed +# TODO: finish reload feature if needed. +# (reload script raise too much exceptions so I usually restart blender to test my plugin.) if "bpy" in locals(): import importlib @@ -16,6 +18,7 @@ from . import UTIL_icons_manager UTIL_icons_manager.register() # then load other modules +from . import UTIL_translation from . import PROP_preferences, PROP_ptrprop_resolver, PROP_virtools_material, PROP_virtools_texture, PROP_virtools_mesh, PROP_virtools_light, PROP_virtools_group from . import PROP_ballance_element, PROP_bme_material, PROP_ballance_map_info from . import OP_IMPORT_bmfile, OP_EXPORT_bmfile, OP_IMPORT_virtools, OP_EXPORT_virtools @@ -29,29 +32,31 @@ from . import OP_OBJECT_legacy_align, OP_OBJECT_virtools_group, OP_OBJECT_snoop_ # ===== Menu Defines ===== class BBP_MT_View3DMenu(bpy.types.Menu): - """Ballance 3D Operators""" + """Ballance 3D related operators""" bl_idname = "BBP_MT_View3DMenu" bl_label = "Ballance" + bl_translation_context = 'BBP_MT_View3DMenu' def draw(self, context): layout = self.layout - layout.label(text = 'UV', icon = 'UV') + layout.label(text='UV', icon='UV') 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.separator() - layout.label(text = 'Align', icon = 'SNAP_ON') + layout.label(text='Align', icon='SNAP_ON') layout.operator(OP_OBJECT_legacy_align.BBP_OT_legacy_align.bl_idname) layout.separator() - layout.label(text = 'Select', icon = 'SELECT_SET') + layout.label(text='Select', icon='SELECT_SET') layout.operator(OP_OBJECT_virtools_group.BBP_OT_select_object_by_virtools_group.bl_idname) layout.separator() - layout.label(text = 'Material', icon = 'MATERIAL') + layout.label(text='Material', icon='MATERIAL') layout.operator(OP_MTL_fix_material.BBP_OT_fix_all_material.bl_idname) class BBP_MT_AddBmeMenu(bpy.types.Menu): """Add Ballance Floor""" bl_idname = "BBP_MT_AddBmeMenu" bl_label = "Floors" + bl_translation_context = 'BBP_MT_AddBmeMenu' def draw(self, context): layout = self.layout @@ -61,49 +66,52 @@ class BBP_MT_AddRailMenu(bpy.types.Menu): """Add Ballance Rail""" bl_idname = "BBP_MT_AddRailMenu" bl_label = "Rails" + bl_translation_context = 'BBP_MT_AddRailMenu' def draw(self, context): layout = self.layout - layout.label(text = "Sections", icon = 'MESH_CIRCLE') + layout.label(text="Sections", icon='MESH_CIRCLE') layout.operator(OP_ADDS_rail.BBP_OT_add_rail_section.bl_idname) layout.operator(OP_ADDS_rail.BBP_OT_add_transition_section.bl_idname) layout.separator() - layout.label(text = "Straight Rails", icon = 'IPO_CONSTANT') + layout.label(text="Straight Rails", icon='IPO_CONSTANT') layout.operator(OP_ADDS_rail.BBP_OT_add_straight_rail.bl_idname) layout.operator(OP_ADDS_rail.BBP_OT_add_transition_rail.bl_idname) layout.operator(OP_ADDS_rail.BBP_OT_add_side_rail.bl_idname) layout.separator() - layout.label(text = "Curve Rails", icon = 'MOD_SCREW') + layout.label(text="Curve Rails", icon='MOD_SCREW') layout.operator(OP_ADDS_rail.BBP_OT_add_arc_rail.bl_idname) layout.operator(OP_ADDS_rail.BBP_OT_add_spiral_rail.bl_idname) layout.operator(OP_ADDS_rail.BBP_OT_add_side_spiral_rail.bl_idname) class BBP_MT_AddComponentsMenu(bpy.types.Menu): - """Add Ballance Components""" + """Add Ballance Component""" bl_idname = "BBP_MT_AddComponentsMenu" bl_label = "Components" + bl_translation_context = 'BBP_MT_AddComponentsMenu' + def draw(self, context): layout = self.layout - layout.label(text = "Basic Components") + layout.label(text="Basic Components") OP_ADDS_component.BBP_OT_add_component.draw_blc_menu(layout) layout.separator() - layout.label(text = "Nong Components") + layout.label(text="Nong Components") OP_ADDS_component.BBP_OT_add_nong_extra_point.draw_blc_menu(layout) OP_ADDS_component.BBP_OT_add_nong_ventilator.draw_blc_menu(layout) layout.separator() - layout.label(text = "Series Components") + layout.label(text="Series Components") OP_ADDS_component.BBP_OT_add_tilting_block_series.draw_blc_menu(layout) OP_ADDS_component.BBP_OT_add_swing_series.draw_blc_menu(layout) OP_ADDS_component.BBP_OT_add_ventilator_series.draw_blc_menu(layout) layout.separator() - layout.label(text = "Components Pair") + layout.label(text="Components Pair") OP_ADDS_component.BBP_OT_add_sector_component_pair.draw_blc_menu(layout) # ===== Menu Drawer ===== @@ -112,13 +120,13 @@ MenuDrawer_t = typing.Callable[[typing.Any, typing.Any], None] def menu_drawer_import(self, context) -> None: layout: bpy.types.UILayout = self.layout - #layout.operator(OP_IMPORT_bmfile.BBP_OT_import_bmfile.bl_idname, text = "Ballance Map (.bmx)") - layout.operator(OP_IMPORT_virtools.BBP_OT_import_virtools.bl_idname, text = "Virtools File (.nmo/.cmo/.vmo) (experimental)") + #layout.operator(OP_IMPORT_bmfile.BBP_OT_import_bmfile.bl_idname, text="Ballance Map (.bmx)") + layout.operator(OP_IMPORT_virtools.BBP_OT_import_virtools.bl_idname, text="Virtools File (.nmo/.cmo/.vmo) (experimental)") def menu_drawer_export(self, context) -> None: layout: bpy.types.UILayout = self.layout - #layout.operator(OP_EXPORT_bmfile.BBP_OT_export_bmfile.bl_idname, text = "Ballance Map (.bmx)") - layout.operator(OP_EXPORT_virtools.BBP_OT_export_virtools.bl_idname, text = "Virtools File (.nmo/.cmo/.vmo) (experimental)") + #layout.operator(OP_EXPORT_bmfile.BBP_OT_export_bmfile.bl_idname, text="Ballance Map (.bmx)") + layout.operator(OP_EXPORT_virtools.BBP_OT_export_virtools.bl_idname, text="Virtools File (.nmo/.cmo/.vmo) (experimental)") def menu_drawer_view3d(self, context) -> None: layout: bpy.types.UILayout = self.layout @@ -127,7 +135,7 @@ def menu_drawer_view3d(self, context) -> None: def menu_drawer_add(self, context) -> None: layout: bpy.types.UILayout = self.layout layout.separator() - layout.label(text = "Ballance") + layout.label(text="Ballance") layout.menu(BBP_MT_AddBmeMenu.bl_idname, icon='MESH_CUBE') layout.menu(BBP_MT_AddRailMenu.bl_idname, icon='MESH_CIRCLE') layout.menu(BBP_MT_AddComponentsMenu.bl_idname, icon='MESH_ICOSPHERE') @@ -143,16 +151,16 @@ def menu_drawer_grouping(self, context) -> None: col = layout.column() col.operator_context = 'INVOKE_DEFAULT' - col.label(text = "Virtools Group") - col.operator(OP_OBJECT_virtools_group.BBP_OT_add_objects_virtools_group.bl_idname, icon = 'ADD', text = "Group into...") - col.operator(OP_OBJECT_virtools_group.BBP_OT_rm_objects_virtools_group.bl_idname, icon = 'REMOVE', text = "Ungroup from...") - col.operator(OP_OBJECT_virtools_group.BBP_OT_clear_objects_virtools_group.bl_idname, icon = 'TRASH', text = "Clear All Groups") + col.label(text="Virtools Group") + col.operator(OP_OBJECT_virtools_group.BBP_OT_add_objects_virtools_group.bl_idname, icon='ADD', text="Group into...") + col.operator(OP_OBJECT_virtools_group.BBP_OT_rm_objects_virtools_group.bl_idname, icon='REMOVE', text="Ungroup from...") + col.operator(OP_OBJECT_virtools_group.BBP_OT_clear_objects_virtools_group.bl_idname, icon='TRASH', text="Clear All Groups") def menu_drawer_snoop_then_conv(self, context) -> None: layout: bpy.types.UILayout = self.layout layout.separator() - layout.label(text = "Ballance") - layout.operator(OP_OBJECT_snoop_group_then_to_mesh.BBP_OT_snoop_group_then_to_mesh.bl_idname, icon = 'OUTLINER_OB_MESH') + layout.label(text="Ballance") + layout.operator(OP_OBJECT_snoop_group_then_to_mesh.BBP_OT_snoop_group_then_to_mesh.bl_idname, icon='OUTLINER_OB_MESH') def menu_drawer_naming_convention(self, context) -> None: layout: bpy.types.UILayout = self.layout @@ -162,10 +170,10 @@ def menu_drawer_naming_convention(self, context) -> None: col = layout.column() col.operator_context = 'INVOKE_DEFAULT' - col.label(text = "Ballance") - col.operator(OP_OBJECT_naming_convention.BBP_OT_regulate_objects_name.bl_idname, icon = 'GREASEPENCIL') - col.operator(OP_OBJECT_naming_convention.BBP_OT_auto_grouping.bl_idname, icon = 'GROUP') - col.operator(OP_OBJECT_naming_convention.BBP_OT_convert_to_imengyu.bl_idname, icon = 'ARROW_LEFTRIGHT') + col.label(text="Ballance") + col.operator(OP_OBJECT_naming_convention.BBP_OT_regulate_objects_name.bl_idname, icon='GREASEPENCIL') + col.operator(OP_OBJECT_naming_convention.BBP_OT_auto_grouping.bl_idname, icon='GROUP') + col.operator(OP_OBJECT_naming_convention.BBP_OT_convert_to_imengyu.bl_idname, icon='ARROW_LEFTRIGHT') #endregion @@ -204,7 +212,9 @@ g_BldMenus: tuple[MenuEntry, ...] = ( def register() -> None: # register module + UTIL_translation.register() PROP_preferences.register() + PROP_ptrprop_resolver.register() PROP_virtools_material.register() @@ -285,7 +295,9 @@ def unregister() -> None: PROP_virtools_material.unregister() PROP_ptrprop_resolver.unregister() + PROP_preferences.unregister() + UTIL_translation.unregister() if __name__ == "__main__": register()