diff --git a/ballance_blender_plugin/__init__.py b/ballance_blender_plugin/__init__.py index dd2e6d1..f42df21 100644 --- a/ballance_blender_plugin/__init__.py +++ b/ballance_blender_plugin/__init__.py @@ -30,19 +30,21 @@ if "bpy" in locals(): importlib.reload(threedsmax_align) if "no_uv_checker" in locals(): importlib.reload(no_uv_checker) -from . import config, utils, bm_import_export, rail_uv, preferences, threedsmax_align, no_uv_checker + if "add_elements" in locals(): + importlib.reload(add_elements) +from . import config, utils, bm_import_export, rail_uv, preferences, threedsmax_align, no_uv_checker, add_elements # ============================================= menu system -class ThreeDViewerMenu(bpy.types.Menu): +class BALLANCE_MT_ThreeDViewerMenu(bpy.types.Menu): """Ballance related 3D operator""" + bl_idname = "BALLANCE_MT_ThreeDViewerMenu" bl_label = "Ballance 3D" - bl_idname = "OBJECT_MT_ballance3d_menu" def draw(self, context): layout = self.layout - layout.operator("ballance.threedsmax_align") + layout.operator("ballance.super_align") layout.operator("ballance.rail_uv") layout.operator("ballance.no_uv_checker") @@ -50,23 +52,36 @@ class ThreeDViewerMenu(bpy.types.Menu): classes = ( preferences.BallanceBlenderPluginPreferences, - bm_import_export.ImportBM, - bm_import_export.ExportBM, - rail_uv.RailUVOperator, - threedsmax_align.SuperAlignOperator, - no_uv_checker.NoUVCheckerOperator, - ThreeDViewerMenu + + bm_import_export.BALLANCE_OT_import_bm, + bm_import_export.BALLANCE_OT_export_bm, + rail_uv.BALLANCE_OT_rail_uv, + threedsmax_align.BALLANCE_OT_super_align, + no_uv_checker.BALLANCE_OT_no_uv_checker, + BALLANCE_MT_ThreeDViewerMenu, + + add_elements.BALLANCE_OT_add_sector_related_elements, + add_elements.BALLANCE_OT_add_unique_elements, + add_elements.BALLANCE_OT_add_rail ) def menu_func_bm_import(self, context): - self.layout.operator(bm_import_export.ImportBM.bl_idname, text="Ballance Map (.bm)") + self.layout.operator(bm_import_export.BALLANCE_OT_import_bm.bl_idname, text="Ballance Map (.bm)") def menu_func_bm_export(self, context): - self.layout.operator(bm_import_export.ExportBM.bl_idname, text="Ballance Map (.bm)") + self.layout.operator(bm_import_export.BALLANCE_OT_export_bm.bl_idname, text="Ballance Map (.bm)") def menu_func_ballance_3d(self, context): layout = self.layout - layout.menu(ThreeDViewerMenu.bl_idname) + layout.menu(BALLANCE_MT_ThreeDViewerMenu.bl_idname) +def menu_func_ballance_add(self, context): + layout = self.layout + layout.separator() + layout.label(text="Ballance") + layout.operator_menu_enum("ballance.add_sector_related_elements", "elements_type", icon='MESH_ICOSPHERE', text="Normal elements") + layout.operator_menu_enum("ballance.add_unique_elements", "elements_type", icon='MESH_ICOSPHERE', text="Unique elements") + layout.operator("ballance.add_rail", icon='MESH_CUBE', text="Rail section") def register(): + print(__package__) for cls in classes: bpy.utils.register_class(cls) @@ -74,12 +89,14 @@ def register(): bpy.types.TOPBAR_MT_file_export.append(menu_func_bm_export) bpy.types.VIEW3D_HT_header.append(menu_func_ballance_3d) + bpy.types.VIEW3D_MT_add.append(menu_func_ballance_add) def unregister(): bpy.types.TOPBAR_MT_file_import.remove(menu_func_bm_import) bpy.types.TOPBAR_MT_file_export.remove(menu_func_bm_export) bpy.types.VIEW3D_HT_header.remove(menu_func_ballance_3d) + bpy.types.VIEW3D_MT_add.remove(menu_func_ballance_add) for cls in classes: bpy.utils.unregister_class(cls) diff --git a/ballance_blender_plugin/add_elements.py b/ballance_blender_plugin/add_elements.py new file mode 100644 index 0000000..61bb3d0 --- /dev/null +++ b/ballance_blender_plugin/add_elements.py @@ -0,0 +1,131 @@ +import bpy,mathutils +from . import utils + +sectorRelatedElements = [ + "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", + "PR_Resetpoint", + "PC_TwoFlames" +] + +uniqueElements = [ + "PE_Balloon", + "PS_FourFlames" +] + +# ================================================= actual add + +class BALLANCE_OT_add_sector_related_elements(bpy.types.Operator): + """Add sector related elements""" + bl_idname = "ballance.add_sector_related_elements" + bl_label = "Add normal elements" + bl_options = {'UNDO'} + + elements_type: bpy.props.EnumProperty( + name="Type", + description="This element type", + items=tuple(map(lambda x: (x, x, ""), sectorRelatedElements)), + ) + + elements_sector: bpy.props.IntProperty( + name="Sector", + description="Define which sector the object will be grouped in", + min=1, + max=8, + default=1, + ) + + def execute(self, context): + return {'FINISHED'} + + def invoke(self, context, event): + wm = context.window_manager + return wm.invoke_props_dialog(self) + + def draw(self, context): + layout = self.layout + layout.prop(self, "elements_type") + layout.prop(self, "elements_sector") + +class BALLANCE_OT_add_unique_elements(bpy.types.Operator): + """Add unique elements""" + bl_idname = "ballance.add_unique_elements" + bl_label = "Add unique elements" + bl_options = {'UNDO'} + + elements_type: bpy.props.EnumProperty( + name="Type", + description="This element type", + items=tuple(map(lambda x: (x, x, ""), uniqueElements)), + ) + + def execute(self, context): + return {'FINISHED'} + + def invoke(self, context, event): + wm = context.window_manager + return wm.invoke_props_dialog(self) + + def draw(self, context): + layout = self.layout + layout.prop(self, "elements_type") + +class BALLANCE_OT_add_rail(bpy.types.Operator): + """Add rail""" + bl_idname = "ballance.add_rail" + bl_label = "Add unique elements" + bl_options = {'UNDO'} + + rail_type: bpy.props.EnumProperty( + name="Type", + description="Rail type", + items=(('MONO', "Monorail", ""), + ('DOUBLE', "Rail", ""), + ), + ) + + rail_radius: bpy.props.FloatProperty( + name="Rail radius", + description="Define rail section radius", + default=0.375, + ) + + rail_span: bpy.props.FloatProperty( + name="Rail span", + description="Define rail span", + default=3.75, + ) + + def execute(self, context): + return {'FINISHED'} + + def invoke(self, context, event): + wm = context.window_manager + return wm.invoke_props_dialog(self) + + def draw(self, context): + layout = self.layout + layout.prop(self, "rail_type") + layout.prop(self, "rail_radius") + layout.prop(self, "rail_span") \ No newline at end of file diff --git a/ballance_blender_plugin/bm_import_export.py b/ballance_blender_plugin/bm_import_export.py index 83ed38e..e3ee7f5 100644 --- a/ballance_blender_plugin/bm_import_export.py +++ b/ballance_blender_plugin/bm_import_export.py @@ -6,13 +6,44 @@ from bpy_extras.io_utils import unpack_list from bpy_extras.image_utils import load_image from . import utils, config -class ImportBM(bpy.types.Operator, bpy_extras.io_utils.ImportHelper): - """Load a Ballance Map File (BM file spec 1.0)""" - bl_idname = "import_scene.bm" +class BALLANCE_OT_import_bm(bpy.types.Operator, bpy_extras.io_utils.ImportHelper): + """Load a Ballance Map File (BM file spec 1.1)""" + bl_idname = "ballance.import_bm" bl_label = "Import BM " bl_options = {'PRESET', 'UNDO'} filename_ext = ".bm" + texture_conflict_strategy: bpy.props.EnumProperty( + name="Texture name conflict", + items=(('NEW', "New instance", "Create a new instance"), + ('CURRENT', "Use current", "Use current"),), + description="Define how to process texture name conflict", + ) + + material_conflict_strategy: bpy.props.EnumProperty( + name="Material name conflict", + items=(('RENAME', "Rename", "Rename the new one"), + ('REPLACE', "Replace", "Replace the old one"), + ('CURRENT', "Use current", "Use current"),), + description="Define how to process material name conflict", + ) + + mesh_conflict_strategy: bpy.props.EnumProperty( + name="Mesh name conflict", + items=(('RENAME', "Rename", "Rename the new one"), + ('REPLACE', "Replace", "Replace the old one"), + ('CURRENT', "Use current", "Use current"),), + description="Define how to process mesh name conflict", + ) + + object_conflict_strategy: bpy.props.EnumProperty( + name="Object name conflict", + items=(('RENAME', "Rename", "Rename the new one"), + ('REPLACE', "Replace", "Replace the old one"), + ('CURRENT', "Use current", "Use current"),), + description="Define how to process object name conflict", + ) + @classmethod def poll(self, context): prefs = bpy.context.preferences.addons[__package__].preferences @@ -23,9 +54,9 @@ class ImportBM(bpy.types.Operator, bpy_extras.io_utils.ImportHelper): import_bm(context, self.filepath, prefs.external_folder, prefs.temp_texture_folder) return {'FINISHED'} -class ExportBM(bpy.types.Operator, bpy_extras.io_utils.ExportHelper): - """Save a Ballance Map File (BM file spec 1.0)""" - bl_idname = "export_scene.bm" +class BALLANCE_OT_export_bm(bpy.types.Operator, bpy_extras.io_utils.ExportHelper): + """Save a Ballance Map File (BM file spec 1.1)""" + bl_idname = "ballance.export_bm" bl_label = 'Export BM' bl_options = {'PRESET'} filename_ext = ".bm" diff --git a/ballance_blender_plugin/no_uv_checker.py b/ballance_blender_plugin/no_uv_checker.py index b1c6b12..d0e63fa 100644 --- a/ballance_blender_plugin/no_uv_checker.py +++ b/ballance_blender_plugin/no_uv_checker.py @@ -1,7 +1,7 @@ import bpy,bmesh from . import utils -class NoUVCheckerOperator(bpy.types.Operator): +class BALLANCE_OT_no_uv_checker(bpy.types.Operator): """Check whether the currently selected object has UV""" bl_idname = "ballance.no_uv_checker" bl_label = "Check UV" diff --git a/ballance_blender_plugin/rail_uv.py b/ballance_blender_plugin/rail_uv.py index bf09fd0..29a7e49 100644 --- a/ballance_blender_plugin/rail_uv.py +++ b/ballance_blender_plugin/rail_uv.py @@ -1,7 +1,7 @@ import bpy,bmesh from . import utils -class RailUVOperator(bpy.types.Operator): +class BALLANCE_OT_rail_uv(bpy.types.Operator): """Create a UV for rail""" bl_idname = "ballance.rail_uv" bl_label = "Create Rail UV" @@ -23,8 +23,6 @@ def check_rail_target(): continue if obj.mode != 'OBJECT': continue - if obj.data.uv_layers.active is None: - continue return True return False @@ -39,8 +37,8 @@ def create_rail_uv(): ignoredObj.append(obj.name) continue if obj.data.uv_layers.active is None: - ignoredObj.append(obj.name) - continue + # create a empty uv for it. + obj.data.uv_layers.new(do_init=False) meshList.append(obj.data) @@ -54,4 +52,4 @@ def create_rail_uv(): uv_layer[loop_index].uv[1] = 1 # vecList[index].co[1] if len(ignoredObj) != 0: - utils.ShowMessageBox("Following objects are not processed due to they are not suit for this function now: " + ', '.join(ignoredObj), "Check result", 'INFO') + utils.ShowMessageBox("Following objects are not processed due to they are not suit for this function now: " + ', '.join(ignoredObj), "Execution result", 'INFO') diff --git a/ballance_blender_plugin/threedsmax_align.py b/ballance_blender_plugin/threedsmax_align.py index 9b4ebfa..f8a776e 100644 --- a/ballance_blender_plugin/threedsmax_align.py +++ b/ballance_blender_plugin/threedsmax_align.py @@ -1,9 +1,9 @@ import bpy,mathutils from . import utils -class SuperAlignOperator(bpy.types.Operator): +class BALLANCE_OT_super_align(bpy.types.Operator): """Align object with 3ds Max way""" - bl_idname = "ballance.threedsmax_align" + bl_idname = "ballance.super_align" bl_label = "3ds Max Align" bl_options = {'UNDO'}