From 654ce39a02646482659b9f8adbda5a0146ed2cf1 Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Sun, 19 Jul 2020 15:05:43 +0800 Subject: [PATCH] add pref and align tools --- ballance_blender_plugin/__init__.py | 67 +++++++++++++++++++++-- ballance_blender_plugin/preferences.py | 17 ++++++ ballance_blender_plugin/super_align.py | 73 ++++++++++++++++++++++++++ 3 files changed, 153 insertions(+), 4 deletions(-) create mode 100644 ballance_blender_plugin/preferences.py create mode 100644 ballance_blender_plugin/super_align.py diff --git a/ballance_blender_plugin/__init__.py b/ballance_blender_plugin/__init__.py index 90ae879..4df4959 100644 --- a/ballance_blender_plugin/__init__.py +++ b/ballance_blender_plugin/__init__.py @@ -21,14 +21,18 @@ if "bpy" in locals(): importlib.reload(utils) if "config" in locals(): importlib.reload(config) -from . import config, utils, bm_import_export, floor_rail_uv + if "preferences" in locals(): + importlib.reload(preferences) + if "super_align" 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""" + """Load a Ballance Map File (BM file spec 1.0)""" bl_idname = "import_scene.bm" - bl_label = "Import BM" + bl_label = "Import BM " bl_options = {'PRESET', 'UNDO'} filename_ext = ".bm" @@ -37,7 +41,7 @@ class ImportBM(bpy.types.Operator, bpy_extras.io_utils.ImportHelper): return {'FINISHED'} class ExportBM(bpy.types.Operator, bpy_extras.io_utils.ExportHelper): - """Save a Ballance Map File""" + """Save a Ballance Map File (BM file spec 1.0)""" bl_idname = "export_scene.bm" bl_label = 'Export BM' bl_options = {'PRESET'} @@ -84,6 +88,58 @@ class FloorUVOperator(bpy.types.Operator): floor_rail_uv.virtoolize_floor_uv() return {'FINISHED'} +class SuperAlignOperator(bpy.types.Operator): + bl_idname = "ballance.super_align" + bl_label = "Super Align" + bl_options = {'UNDO'} + + align_x: bpy.props.BoolProperty(name="X postion") + align_y: bpy.props.BoolProperty(name="Y postion") + align_z: bpy.props.BoolProperty(name="Z postion") + + 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): bl_label = "Ballance 3D" bl_idname = "OBJECT_MT_ballance3d_menu" @@ -91,16 +147,19 @@ class ThreeDViewerMenu(bpy.types.Menu): def draw(self, context): layout = self.layout + 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, ThreeDViewerMenu ) diff --git a/ballance_blender_plugin/preferences.py b/ballance_blender_plugin/preferences.py new file mode 100644 index 0000000..9bcb04a --- /dev/null +++ b/ballance_blender_plugin/preferences.py @@ -0,0 +1,17 @@ +import bpy + +class BallanceBlenderPluginPreferences(bpy.types.AddonPreferences): + bl_idname = __package__ + + external_folder: bpy.props.StringProperty( + name="External texture folder", + description="The Ballance texture folder which will be used buy this plugin to get external texture.", + ) + + def draw(self, context): + layout = self.layout + + row = layout.row() + col = row.column() + + col.prop(self, "external_folder") \ No newline at end of file diff --git a/ballance_blender_plugin/super_align.py b/ballance_blender_plugin/super_align.py new file mode 100644 index 0000000..27e5c2a --- /dev/null +++ b/ballance_blender_plugin/super_align.py @@ -0,0 +1,73 @@ +import bpy,mathutils +from . import utils + +def check_align_target(): + if bpy.context.active_object is None: + return False + + selected = bpy.context.selected_objects[:] + length = len(selected) + if bpy.context.active_object in selected: + length -= 1 + if length == 0: + return False + + return True + +def align_object(use_x, use_y, use_z, currentMode, targetMode): + if not (use_x or use_y or use_z): + return + + # calc active object data + currentObj = bpy.context.active_object + currentObjBbox = [currentObj.matrix_world @ mathutils.Vector(corner) for corner in currentObj.bound_box] + currentObjRef = provideObjRefPoint(currentObj, currentObjBbox, currentMode) + + # calc target + targetObjList = bpy.context.selected_objects[:] + if currentObj in targetObjList: + targetObjList.remove(currentObj) + + # process each obj + for targetObj in targetObjList: + targetObjBbox = [targetObj.matrix_world @ mathutils.Vector(corner) for corner in targetObj.bound_box] + targetObjRef = provideObjRefPoint(targetObj, targetObjBbox, targetMode) + + if use_x: + targetObj.location.x += currentObjRef.x - targetObjRef.x + if use_y: + targetObj.location.y += currentObjRef.y - targetObjRef.y + if use_z: + targetObj.location.z += currentObjRef.z - targetObjRef.z + +def provideObjRefPoint(obj, vecList, mode): + refPoint = mathutils.Vector((0, 0, 0)) + + if (mode == 'MIN'): + refPoint.x = min([vec.x for vec in vecList]) + refPoint.y = min([vec.y for vec in vecList]) + refPoint.z = min([vec.z for vec in vecList]) + elif (mode == 'MAX'): + refPoint.x = max([vec.x for vec in vecList]) + refPoint.y = max([vec.y for vec in vecList]) + refPoint.z = max([vec.z for vec in vecList]) + elif (mode == 'CENTER'): + maxVecCache = mathutils.Vector((0, 0, 0)) + minVecCache = mathutils.Vector((0, 0, 0)) + + minVecCache.x = min([vec.x for vec in vecList]) + minVecCache.y = min([vec.y for vec in vecList]) + minVecCache.z = min([vec.z for vec in vecList]) + maxVecCache.x = max([vec.x for vec in vecList]) + maxVecCache.y = max([vec.y for vec in vecList]) + maxVecCache.z = max([vec.z for vec in vecList]) + + refPoint.x = (maxVecCache.x + minVecCache.x) / 2 + refPoint.y = (maxVecCache.y + minVecCache.y) / 2 + refPoint.z = (maxVecCache.z + minVecCache.z) / 2 + else: + refPoint.x = obj.location.x + refPoint.y = obj.location.y + refPoint.z = obj.location.z + + return refPoint \ No newline at end of file