diff --git a/ballance_blender_plugin/__init__.py b/ballance_blender_plugin/__init__.py index c862145..e6c16be 100644 --- a/ballance_blender_plugin/__init__.py +++ b/ballance_blender_plugin/__init__.py @@ -27,120 +27,8 @@ if "bpy" in locals(): importlib.reload(super_align) from . import config, utils, bm_import_export, floor_rail_uv, preferences, super_align -# ============================================= func block - -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" - bl_label = "Import BM " - bl_options = {'PRESET', 'UNDO'} - filename_ext = ".bm" - - def execute(self, context): - bm_import_export.import_bm(context, self.filepath) - 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" - bl_label = 'Export BM' - bl_options = {'PRESET'} - filename_ext = ".bm" - - export_mode: bpy.props.EnumProperty( - name="Export mode", - items=(('COLLECTION', "Selected collection", "Export the selected collection"), - ('OBJECT', "Selected objects", "Export the selected objects"), - ), - ) - export_target: bpy.props.StringProperty( - name="Export target", - description="Which one will be exported", - ) - no_component_suffix: bpy.props.StringProperty( - name="No component suffix", - description="The object which have this suffix will not be saved as component.", - ) - - def execute(self, context): - bm_import_export.export_bm(context, self.filepath, self.export_mode, self.export_target, self.no_component_suffix) - return {'FINISHED'} - # ============================================= menu system -class RailUVOperator(bpy.types.Operator): - """Create a UV for rail""" - bl_idname = "ballance.rail_uv" - bl_label = "Create Rail UV" - bl_options = {'UNDO'} - - def execute(self, context): - floor_rail_uv.create_rail_uv() - return {'FINISHED'} - -class FloorUVOperator(bpy.types.Operator): - """Virtoolize the UV of floor""" - bl_idname = "ballance.floor_uv" - bl_label = "Virtoolize floor UV" - bl_options = {'UNDO'} - - def execute(self, context): - floor_rail_uv.virtoolize_floor_uv() - return {'FINISHED'} - -class SuperAlignOperator(bpy.types.Operator): - """Align object with 3ds Max way""" - bl_idname = "ballance.super_align" - bl_label = "Super Align" - bl_options = {'UNDO'} - - align_x: bpy.props.BoolProperty(name="X position") - align_y: bpy.props.BoolProperty(name="Y position") - align_z: bpy.props.BoolProperty(name="Z position") - - current_references: bpy.props.EnumProperty( - name="Current", - items=(('MIN', "Min", ""), - ('CENTER', "Center (bound box)", ""), - ('POINT', "Center (axis)", ""), - ('MAX', "Max", "") - ), - ) - - target_references: bpy.props.EnumProperty( - name="Target", - items=(('MIN', "Min", ""), - ('CENTER', "Center (bound box)", ""), - ('POINT', "Center (axis)", ""), - ('MAX', "Max", "") - ), - ) - - @classmethod - def poll(self, context): - return super_align.check_align_target() - - def execute(self, context): - super_align.align_object(self.align_x, self.align_y, self.align_z, self.current_references, self.target_references) - return {'FINISHED'} - - def invoke(self, context, event): - wm = context.window_manager - return wm.invoke_props_dialog(self) - - def draw(self, context): - layout = self.layout - col = layout.column() - col.label(text="Align axis") - - row = col.row() - row.prop(self, "align_x") - row.prop(self, "align_y") - row.prop(self, "align_z") - - col.prop(self, "current_references") - col.prop(self, "target_references") - class ThreeDViewerMenu(bpy.types.Menu): """Ballance related 3D operator""" bl_label = "Ballance 3D" @@ -151,24 +39,22 @@ class ThreeDViewerMenu(bpy.types.Menu): layout.operator("ballance.super_align") layout.operator("ballance.rail_uv") - layout.operator("ballance.floor_uv") # ============================================= blender call system classes = ( preferences.BallanceBlenderPluginPreferences, - ImportBM, - ExportBM, - RailUVOperator, - FloorUVOperator, - SuperAlignOperator, + bm_import_export.ImportBM, + bm_import_export.ExportBM, + floor_rail_uv.RailUVOperator, + super_align.SuperAlignOperator, ThreeDViewerMenu ) def menu_func_bm_import(self, context): - self.layout.operator(ImportBM.bl_idname, text="Ballance Map (.bm)") + self.layout.operator(bm_import_export.ImportBM.bl_idname, text="Ballance Map (.bm)") def menu_func_bm_export(self, context): - self.layout.operator(ExportBM.bl_idname, text="Ballance Map (.bm)") + self.layout.operator(bm_import_export.ExportBM.bl_idname, text="Ballance Map (.bm)") def menu_func_ballance_3d(self, context): layout = self.layout layout.menu(ThreeDViewerMenu.bl_idname) diff --git a/ballance_blender_plugin/bm_import_export.py b/ballance_blender_plugin/bm_import_export.py index f36a9c5..28d0014 100644 --- a/ballance_blender_plugin/bm_import_export.py +++ b/ballance_blender_plugin/bm_import_export.py @@ -4,6 +4,46 @@ import struct,shutil from bpy_extras import io_utils,node_shader_utils 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" + bl_label = "Import BM " + bl_options = {'PRESET', 'UNDO'} + filename_ext = ".bm" + + def execute(self, context): + import_bm(context, self.filepath) + 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" + bl_label = 'Export BM' + bl_options = {'PRESET'} + filename_ext = ".bm" + + export_mode: bpy.props.EnumProperty( + name="Export mode", + items=(('COLLECTION', "Selected collection", "Export the selected collection"), + ('OBJECT', "Selected objects", "Export the selected objects"), + ), + ) + export_target: bpy.props.StringProperty( + name="Export target", + description="Which one will be exported", + ) + no_component_suffix: bpy.props.StringProperty( + name="No component suffix", + description="The object which have this suffix will not be saved as component.", + ) + + def execute(self, context): + export_bm(context, self.filepath, self.export_mode, self.export_target, self.no_component_suffix) + return {'FINISHED'} + + +# ========================================== method + bm_current_version = 10 def import_bm(context,filepath): diff --git a/ballance_blender_plugin/floor_rail_uv.py b/ballance_blender_plugin/floor_rail_uv.py index 7d1fa43..9694317 100644 --- a/ballance_blender_plugin/floor_rail_uv.py +++ b/ballance_blender_plugin/floor_rail_uv.py @@ -1,15 +1,46 @@ import bpy,bmesh from . import utils -def create_rail_uv(): - meshList = [] +class RailUVOperator(bpy.types.Operator): + """Create a UV for rail""" + bl_idname = "ballance.rail_uv" + bl_label = "Create Rail UV" + bl_options = {'UNDO'} + + @classmethod + def poll(self, context): + return check_rail_target() + + def execute(self, context): + create_rail_uv() + return {'FINISHED'} + +# ====================== method + +def check_rail_target(): for obj in bpy.context.selected_objects: if obj.type != 'MESH': continue - + if obj.mode != 'OBJECT': + continue if obj.data.uv_layers.active.data == None: - utils.ShowMessageBox("You should create a UV layer for this object firstly. Then execute this operator.", "No UV layer", 'ERROR') - return + continue + return True + return False + +def create_rail_uv(): + meshList = [] + ignoredObj = [] + for obj in bpy.context.selected_objects: + if obj.type != 'MESH': + ignoredObj.append(obj.name) + continue + if obj.mode != 'OBJECT': + ignoredObj.append(obj.name) + continue + if obj.data.uv_layers.active.data == None: + ignoredObj.append(obj.name) + continue meshList.append(obj.data) @@ -22,6 +53,9 @@ def create_rail_uv(): uv_layer[loop_index].uv[0] = 0 # vecList[index].co[0] 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), "No processed object", 'WARNING') + def virtoolize_floor_uv(): pass diff --git a/ballance_blender_plugin/super_align.py b/ballance_blender_plugin/super_align.py index 27e5c2a..f05a7b5 100644 --- a/ballance_blender_plugin/super_align.py +++ b/ballance_blender_plugin/super_align.py @@ -1,6 +1,61 @@ import bpy,mathutils from . import utils +class SuperAlignOperator(bpy.types.Operator): + """Align object with 3ds Max way""" + bl_idname = "ballance.super_align" + bl_label = "Super Align" + bl_options = {'UNDO'} + + align_x: bpy.props.BoolProperty(name="X position") + align_y: bpy.props.BoolProperty(name="Y position") + align_z: bpy.props.BoolProperty(name="Z position") + + current_references: bpy.props.EnumProperty( + name="Current", + items=(('MIN', "Min", ""), + ('CENTER', "Center (bound box)", ""), + ('POINT', "Center (axis)", ""), + ('MAX', "Max", "") + ), + ) + + target_references: bpy.props.EnumProperty( + name="Target", + items=(('MIN', "Min", ""), + ('CENTER', "Center (bound box)", ""), + ('POINT', "Center (axis)", ""), + ('MAX', "Max", "") + ), + ) + + @classmethod + def poll(self, context): + return check_align_target() + + def execute(self, context): + align_object(self.align_x, self.align_y, self.align_z, self.current_references, self.target_references) + return {'FINISHED'} + + def invoke(self, context, event): + wm = context.window_manager + return wm.invoke_props_dialog(self) + + def draw(self, context): + layout = self.layout + col = layout.column() + col.label(text="Align axis") + + row = col.row() + row.prop(self, "align_x") + row.prop(self, "align_y") + row.prop(self, "align_z") + + col.prop(self, "current_references") + col.prop(self, "target_references") + +# ============================== method + def check_align_target(): if bpy.context.active_object is None: return False