# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import math
import bmesh
import bpy.utils.previews
import bpy

bl_info = {
    "name": "Isometric Room Gen",
    "author": "SkdSam & Mr Steve",
    "description": "Generate Isometric Rooms",
    "blender": (3, 6, 0),
    "version": (1, 0, 6),
    "location": "",
    "warning": "",
    "doc_url": "https://superhivemarket.com/creators/skdsam",
    "tracker_url": "",
    "category": "3D View"
}


def string_to_int(value):
    if value.isdigit():
        return int(value)
    return 0


def string_to_icon(value):
    if value in bpy.types.UILayout.bl_rna.functions["prop"].parameters["icon"].enum_items.keys():
        return bpy.types.UILayout.bl_rna.functions["prop"].parameters["icon"].enum_items[value].value
    return string_to_int(value)


addon_keymaps = {}
_icons = None


class SNA_PT_IRG_3542C(bpy.types.Panel):
    bl_label = 'IRG'
    bl_idname = 'SNA_PT_IRG_3542C'
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_context = ''
    bl_category = 'IRG'
    bl_order = 0
    bl_ui_units_x = 0

    @classmethod
    def poll(cls, context):
        return not (False)

    def draw_header(self, context):
        layout = self.layout

    def draw(self, context):
        layout = self.layout
        layout.prop(bpy.context.scene, 'sna_style',
                    text=bpy.context.scene.sna_style, icon_value=0, emboss=True, expand=True)
        if bpy.context.scene.sna_style == "Square":
            col_F2E32 = layout.column(heading='', align=False)
            col_F2E32.alert = False
            col_F2E32.enabled = True
            col_F2E32.active = True
            col_F2E32.use_property_split = False
            col_F2E32.use_property_decorate = False
            col_F2E32.scale_x = 1.0
            col_F2E32.scale_y = 1.0
            col_F2E32.alignment = 'Expand'.upper()
            col_F2E32.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
            row_8A9B7 = col_F2E32.row(heading='', align=True)
            row_8A9B7.alert = False
            row_8A9B7.enabled = True
            row_8A9B7.active = True
            row_8A9B7.use_property_split = False
            row_8A9B7.use_property_decorate = False
            row_8A9B7.scale_x = 1.0
            row_8A9B7.scale_y = 1.0
            row_8A9B7.alignment = 'Expand'.upper()
            row_8A9B7.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
            row_8A9B7.prop(bpy.context.scene, 'sna_room_settings', text='Room Settings    ', icon_value=(
                11 if bpy.context.scene.sna_room_settings else 10), emboss=False, toggle=True)
            row_8A9B7.prop(bpy.context.scene, 'sna_room_settings', text='', icon_value=string_to_icon(
                'MATCUBE'), emboss=bpy.context.scene.sna_room_settings, toggle=True)
            col_AF92C = col_F2E32.column(heading='', align=False)
            col_AF92C.alert = False
            col_AF92C.enabled = True
            col_AF92C.active = True
            col_AF92C.use_property_split = False
            col_AF92C.use_property_decorate = False
            col_AF92C.scale_x = 1.0
            col_AF92C.scale_y = 1.0
            col_AF92C.alignment = 'Expand'.upper()
            col_AF92C.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
            if bpy.context.scene.sna_room_settings:
                box_480DE = col_AF92C.box()
                box_480DE.alert = False
                box_480DE.enabled = True
                box_480DE.active = True
                box_480DE.use_property_split = False
                box_480DE.use_property_decorate = False
                box_480DE.alignment = 'Expand'.upper()
                box_480DE.scale_x = 1.0
                box_480DE.scale_y = 1.0
                if not True:
                    box_480DE.operator_context = "EXEC_DEFAULT"
                box_480DE.prop(bpy.context.scene, 'sna_room_width',
                               text='Room Width', icon_value=0, emboss=True)
                box_480DE.prop(bpy.context.scene, 'sna_room_depth',
                               text='Room Depth', icon_value=0, emboss=True)
                box_480DE.prop(bpy.context.scene, 'sna_room_height',
                               text='Room Height', icon_value=0, emboss=True)
                box_480DE.prop(bpy.context.scene, 'sna_wall_thickness',
                               text='Wall Thickness', icon_value=0, emboss=True)
            row_C816B = col_F2E32.row(heading='', align=True)
            row_C816B.alert = False
            row_C816B.enabled = True
            row_C816B.active = True
            row_C816B.use_property_split = False
            row_C816B.use_property_decorate = False
            row_C816B.scale_x = 1.0
            row_C816B.scale_y = 1.0
            row_C816B.alignment = 'Expand'.upper()
            row_C816B.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
            row_C816B.prop(bpy.context.scene, 'sna_winows_settings', text='Window Settings', icon_value=(
                11 if bpy.context.scene.sna_winows_settings else 10), emboss=False, toggle=True)
            row_C816B.prop(bpy.context.scene, 'sna_winows_settings', text='', icon_value=string_to_icon(
                'MESH_PLANE'), emboss=bpy.context.scene.sna_winows_settings, toggle=True)
            if bpy.context.scene.sna_winows_settings:
                box_7092C = col_F2E32.box()
                box_7092C.alert = False
                box_7092C.enabled = True
                box_7092C.active = True
                box_7092C.use_property_split = False
                box_7092C.use_property_decorate = False
                box_7092C.alignment = 'Expand'.upper()
                box_7092C.scale_x = 1.0
                box_7092C.scale_y = 1.0
                if not True:
                    box_7092C.operator_context = "EXEC_DEFAULT"
                box_7092C.prop(bpy.context.scene, 'sna_windows_enum',
                               text='Window Placement', icon_value=0, emboss=True)
                if (bpy.context.scene.sna_windows_enum != 'NONE'):
                    col_8CB93 = box_7092C.column(heading='', align=False)
                    col_8CB93.alert = False
                    col_8CB93.enabled = True
                    col_8CB93.active = True
                    col_8CB93.use_property_split = False
                    col_8CB93.use_property_decorate = False
                    col_8CB93.scale_x = 1.0
                    col_8CB93.scale_y = 1.0
                    col_8CB93.alignment = 'Expand'.upper()
                    col_8CB93.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
                    col_8CB93.prop(bpy.context.scene, 'sna_window_style',
                                   text='Type', icon_value=0, emboss=True)
                    col_8CB93.prop(bpy.context.scene, 'sna_windows_count',
                                   text='Window Count', icon_value=0, emboss=True)
                    col_8CB93.prop(bpy.context.scene, 'sna_windows_width',
                                   text='Window Width %', icon_value=0, emboss=True)
                    col_8CB93.prop(bpy.context.scene, 'sna_windows_height',
                                   text='Window Height %', icon_value=0, emboss=True)

            # 添加拱门设置
            row_arch = col_F2E32.row(heading='', align=True)
            row_arch.alert = False
            row_arch.enabled = True
            row_arch.active = True
            row_arch.use_property_split = False
            row_arch.use_property_decorate = False
            row_arch.scale_x = 1.0
            row_arch.scale_y = 1.0
            row_arch.alignment = 'Expand'.upper()
            row_arch.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
            row_arch.prop(bpy.context.scene, 'sna_arch_settings', text='Arch Settings    ', icon_value=(
                11 if bpy.context.scene.sna_arch_settings else 10), emboss=False, toggle=True)
            row_arch.prop(bpy.context.scene, 'sna_arch_settings', text='', icon_value=string_to_icon(
                'MESH_CUBE'), emboss=bpy.context.scene.sna_arch_settings, toggle=True)

            if bpy.context.scene.sna_arch_settings:
                box_arch = col_F2E32.box()
                box_arch.alert = False
                box_arch.enabled = True
                box_arch.active = True
                box_arch.use_property_split = False
                box_arch.use_property_decorate = False
                box_arch.alignment = 'Expand'.upper()
                box_arch.scale_x = 1.0
                box_arch.scale_y = 1.0
                if not True:
                    box_arch.operator_context = "EXEC_DEFAULT"
                box_arch.prop(bpy.context.scene, 'sna_arch_placement',
                              text='Arch Placement', icon_value=0, emboss=True)
                if bpy.context.scene.sna_arch_placement != 'NONE':
                    box_arch.prop(bpy.context.scene, 'sna_arch_width',
                                  text='Arch Width', icon_value=0, emboss=True)
                    box_arch.prop(bpy.context.scene, 'sna_arch_height',
                                  text='Arch Height', icon_value=0, emboss=True)
                    box_arch.prop(bpy.context.scene, 'sna_arch_thickness',
                                  text='Arch Thickness', icon_value=0, emboss=True)

            col_F2E32.separator(factor=1.0000016689300537)
            row_A6551 = col_F2E32.row(heading='', align=False)
            row_A6551.alert = False
            row_A6551.enabled = True
            row_A6551.active = True
            row_A6551.use_property_split = False
            row_A6551.use_property_decorate = False
            row_A6551.scale_x = 1.0
            row_A6551.scale_y = 2.440000057220459
            row_A6551.alignment = 'Expand'.upper()
            row_A6551.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
            op = row_A6551.operator('sna.gen_room_1803a', text='Generate Room', icon_value=string_to_icon(
                'SHAPEKEY_DATA'), emboss=True, depress=False)
        elif bpy.context.scene.sna_style == "Round":
            col_05349 = layout.column(heading='', align=False)
            col_05349.alert = False
            col_05349.enabled = True
            col_05349.active = True
            col_05349.use_property_split = False
            col_05349.use_property_decorate = False
            col_05349.scale_x = 1.0
            col_05349.scale_y = 1.0
            col_05349.alignment = 'Expand'.upper()
            col_05349.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
            row_31CFF = col_05349.row(heading='', align=True)
            row_31CFF.alert = False
            row_31CFF.enabled = True
            row_31CFF.active = True
            row_31CFF.use_property_split = False
            row_31CFF.use_property_decorate = False
            row_31CFF.scale_x = 1.0
            row_31CFF.scale_y = 1.0
            row_31CFF.alignment = 'Expand'.upper()
            row_31CFF.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
            row_31CFF.prop(bpy.context.scene, 'sna_round_room_settings', text='Room Settings    ', icon_value=(
                11 if bpy.context.scene.sna_round_room_settings else 10), emboss=False, toggle=True)
            row_31CFF.prop(bpy.context.scene, 'sna_round_room_settings', text='', icon_value=string_to_icon(
                'MATCUBE'), emboss=bpy.context.scene.sna_round_room_settings, toggle=True)
            col_549D5 = col_05349.column(heading='', align=False)
            col_549D5.alert = False
            col_549D5.enabled = True
            col_549D5.active = True
            col_549D5.use_property_split = False
            col_549D5.use_property_decorate = False
            col_549D5.scale_x = 1.0
            col_549D5.scale_y = 1.0
            col_549D5.alignment = 'Expand'.upper()
            col_549D5.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
            if bpy.context.scene.sna_round_room_settings:
                box_B3F1F = col_549D5.box()
                box_B3F1F.alert = False
                box_B3F1F.enabled = True
                box_B3F1F.active = True
                box_B3F1F.use_property_split = False
                box_B3F1F.use_property_decorate = False
                box_B3F1F.alignment = 'Expand'.upper()
                box_B3F1F.scale_x = 1.0
                box_B3F1F.scale_y = 1.0
                if not True:
                    box_B3F1F.operator_context = "EXEC_DEFAULT"
                box_B3F1F.prop(bpy.context.scene, 'sna_room_diameter_round',
                               text='Room Diameter', icon_value=0, emboss=True)
                box_B3F1F.prop(bpy.context.scene, 'sna_room_floor_thickness_round',
                               text='Floor Depth', icon_value=0, emboss=True)
                box_B3F1F.prop(bpy.context.scene, 'sna_room_height_round',
                               text='Room Height', icon_value=0, emboss=True)
                box_B3F1F.prop(bpy.context.scene, 'sna_wall_thickness_round',
                               text='Wall Thickness', icon_value=0, emboss=True)
            row_6F6A0 = col_05349.row(heading='', align=True)
            row_6F6A0.alert = False
            row_6F6A0.enabled = True
            row_6F6A0.active = True
            row_6F6A0.use_property_split = False
            row_6F6A0.use_property_decorate = False
            row_6F6A0.scale_x = 1.0
            row_6F6A0.scale_y = 1.0
            row_6F6A0.alignment = 'Expand'.upper()
            row_6F6A0.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
            row_6F6A0.prop(bpy.context.scene, 'sna_round_window_settings', text='Window Settings', icon_value=(
                11 if bpy.context.scene.sna_round_window_settings else 10), emboss=False, toggle=True)
            row_6F6A0.prop(bpy.context.scene, 'sna_round_window_settings', text='', icon_value=string_to_icon(
                'MESH_PLANE'), emboss=bpy.context.scene.sna_round_window_settings, toggle=True)
            if bpy.context.scene.sna_round_window_settings:
                box_E2A99 = col_05349.box()
                box_E2A99.alert = False
                box_E2A99.enabled = True
                box_E2A99.active = True
                box_E2A99.use_property_split = False
                box_E2A99.use_property_decorate = False
                box_E2A99.alignment = 'Expand'.upper()
                box_E2A99.scale_x = 1.0
                box_E2A99.scale_y = 1.0
                if not True:
                    box_E2A99.operator_context = "EXEC_DEFAULT"
                box_E2A99.prop(bpy.context.scene, 'sna_window_style_round',
                               text='Window Placement', icon_value=0, emboss=True)
                if (bpy.context.scene.sna_window_style_round != 'NONE'):
                    col_765D0 = box_E2A99.column(heading='', align=False)
                    col_765D0.alert = False
                    col_765D0.enabled = True
                    col_765D0.active = True
                    col_765D0.use_property_split = False
                    col_765D0.use_property_decorate = False
                    col_765D0.scale_x = 1.0
                    col_765D0.scale_y = 1.0
                    col_765D0.alignment = 'Expand'.upper()
                    col_765D0.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
                    col_765D0.prop(bpy.context.scene, 'sna_round_window_amount',
                                   text='Window Count', icon_value=0, emboss=True)
                    col_765D0.prop(bpy.context.scene, 'sna_round_window_width',
                                   text='Window Width %', icon_value=0, emboss=True)
                    col_765D0.prop(bpy.context.scene, 'sna_round_window_height',
                                   text='Window Height %', icon_value=0, emboss=True)
            col_05349.separator(factor=1.0000016689300537)
            row_63B4A = col_05349.row(heading='', align=False)
            row_63B4A.alert = False
            row_63B4A.enabled = True
            row_63B4A.active = True
            row_63B4A.use_property_split = False
            row_63B4A.use_property_decorate = False
            row_63B4A.scale_x = 1.0
            row_63B4A.scale_y = 2.440000057220459
            row_63B4A.alignment = 'Expand'.upper()
            row_63B4A.operator_context = "INVOKE_DEFAULT" if True else "EXEC_DEFAULT"
            op = row_63B4A.operator('sna.gen_round_room_a43ca', text='Generate Room', icon_value=string_to_icon(
                'SHAPEKEY_DATA'), emboss=True, depress=False)


class SNA_OT_Gen_Room_1803A(bpy.types.Operator):
    bl_idname = "sna.gen_room_1803a"
    bl_label = "Gen room"
    bl_description = "Create room"
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        if bpy.app.version >= (3, 0, 0) and True:
            cls.poll_message_set('')
        return not False

    def execute(self, context):
        room_width = bpy.context.scene.sna_room_width
        room_depth = bpy.context.scene.sna_room_depth
        room_height = bpy.context.scene.sna_room_height
        wall_thickness = bpy.context.scene.sna_wall_thickness
        window_placement = bpy.context.scene.sna_windows_enum
        window_count = bpy.context.scene.sna_windows_count
        window_width_pct = bpy.context.scene.sna_windows_width
        window_height_pct = bpy.context.scene.sna_windows_height
        window_type = bpy.context.scene.sna_window_style
        import math

        # 确保大的值为room_depth，小的值为room_width
        if room_width > room_depth:
            # 交换值
            room_width, room_depth = room_depth, room_width
            print(f"自动调整房间尺寸：宽度={room_width}m，深度={room_depth}m")

        # 在generate_room函数中，将拱门生成函数定义在调用之前
        def generate_room(
                room_width, room_depth, room_height, wall_thickness,
                window_placement, window_count, window_width_pct, window_height_pct,
                window_type='SQUARE', window_divisions=2,
                sash_bottom_pct=0.55):
            """
            1) Make floor & walls as separate cubes (scale applied)
            2) Carve windows from each wall (cutters & panes all apply scale)
            3) Boolean-union walls into the floor
            4) Join sash-frame bits, then weld stray verts
            5) Add ceiling (天花板)
            6) Add arch door (拱门)
            """
            extra = 0.01
            inset = (wall_thickness - extra) / 2.0
            glass_thickness = extra
            ceiling_thickness = 0.10  # 天花板厚度10cm

            # 拱门生成函数（定义在generate_room内部，但在使用之前）
            def add_arch_to_room(room_obj, room_width, room_depth, room_height, wall_thickness):
                """创建独立的拱门墙面"""
                arch_placement = bpy.context.scene.sna_arch_placement

                # 如果选择"无"，则不生成拱门
                if arch_placement == 'NONE':
                    print("未选择拱门位置，跳过拱门生成")
                    return

                # 根据规则计算拱门参数
                # 基础空间：5x3x2.8，拱门距背景墙1米，空间每加1米长，距离增加30cm
                base_distance = 1.0  # 基础距离1米
                distance_increase = 0.3  # 每增加1米距离增加30cm
                extra_length = room_depth - 5.0  # 超出基础5米的长度（不是3米）
                arch_distance = base_distance + \
                    (extra_length * distance_increase)

                # 门洞宽度：基础1.2米，空间宽度每加1米，门洞宽度+30cm
                base_width = 1.2  # 基础宽度1.2米
                width_increase = 0.3  # 每增加1米宽度增加30cm
                extra_width = room_width - 3.0  # 超出基础3米的宽度（不是5米）
                arch_width = base_width + (extra_width * width_increase)

                # 门洞高度：根据层高确定
                arch_height = 2.4  # 默认2.4米
                if room_height >= 3.2:
                    arch_height = 2.7
                elif room_height >= 3.0:
                    arch_height = 2.6
                elif room_height >= 2.8:
                    arch_height = 2.4

                # 拱门墙面厚度
                arch_wall_thickness = 0.10  # 10cm厚

                print(f"拱门墙面参数计算:")
                print(f"  房间尺寸: {room_width}x{room_depth}x{room_height}")
                print(f"  拱门墙面距离背景墙: {arch_distance}m")
                print(f"  拱门宽度: {arch_width}m")
                print(f"  拱门高度: {arch_height}m")
                print(f"  拱门墙面厚度: {arch_wall_thickness}m")

                # 创建拱门墙面（复制并移动选择的墙面）
                arch_wall = create_arch_wall_by_copy(
                    room_width, room_depth, room_height, arch_wall_thickness, arch_placement, arch_distance)

                if arch_wall:
                    # 在拱门墙面上挖洞
                    # 增加切割器厚度，确保能完全穿透拱门墙面
                    arch_cutter = create_arch_cutter(
                        arch_width, arch_height, arch_wall_thickness + 0.05)  # 增加厚度确保穿透

                    if arch_cutter:
                        # 设置拱门切割器位置（相对于拱门墙面）
                        if arch_placement == 'BACK':
                            # 在后墙前面创建拱门墙面，在墙面上挖洞
                            # 拱门墙面位置：(0, room_depth - distance - wall_thickness, 0)
                            # 切割器应该在拱门墙面中心：(room_width/2, room_depth - distance - wall_thickness, 0)
                            arch_cutter.location = (
                                room_width/2,  # X居中
                                room_depth - arch_distance - arch_wall_thickness +
                                arch_wall_thickness/2,  # Y在拱门墙面中心，多加半个墙体厚度
                                0              # Z从地面开始
                            )
                            # 参考COPY4的旋转设置：绕Y轴旋转90度，使其垂直于墙面
                            arch_cutter.rotation_euler = (0, 0, 0)

                        # 使用布尔运算在拱门墙面上挖洞
                        print(
                            f"开始布尔运算，拱门墙面: {arch_wall.name}, 切割器: {arch_cutter.name}")
                        print(
                            f"拱门墙面位置: {arch_wall.location}, 切割器位置: {arch_cutter.location}")
                        print(
                            f"拱门墙面尺寸: {arch_wall.dimensions}, 切割器尺寸: {arch_cutter.dimensions}")

                        # 确保切割器完全穿透拱门墙面
                        mod = arch_wall.modifiers.new("ArchCut", 'BOOLEAN')
                        mod.operation = 'DIFFERENCE'
                        mod.object = arch_cutter
                        bpy.context.view_layer.objects.active = arch_wall
                        bpy.ops.object.modifier_apply(modifier=mod.name)

                        print(f"布尔运算完成")

                        # 删除拱门切割器对象
                        bpy.data.objects.remove(arch_cutter, do_unlink=True)

                        print(f"拱门墙面已创建并挖洞，位置: {arch_placement}")

            def create_arch_wall_by_copy(room_width, room_depth, room_height, wall_thickness, placement, distance):
                """通过复制墙面创建拱门墙面"""
                # 创建墙面几何体
                bm = bmesh.new()

                # 房间外轮廓尺寸（包含墙体）
                room_outer_width = room_width  # 直接使用房间宽度，不加墙体厚度
                room_outer_depth = room_depth + wall_thickness
                room_inner_height = room_height

                if placement == 'BACK':
                    # 复制后墙并前移
                    # 后墙尺寸：宽度=房间宽度，高度=房间内高度，厚度=10cm
                    wall_width = room_outer_width
                    wall_height = room_inner_height
                    wall_depth = wall_thickness

                    # 拱门墙面位置：在Y=distance处（距背景墙distance米）
                    # 创建墙面顶点（从原点开始，然后移动到正确位置）
                    verts = [
                        (0, 0, 0),           # 左下后（地面顶面）
                        (wall_width, 0, 0),  # 右下后（地面顶面）
                        (wall_width, wall_depth, 0),  # 右下前（地面顶面）
                        (0, wall_depth, 0),           # 左下前（地面顶面）
                        (0, 0, room_inner_height),  # 左上后（天花板底面）
                        (wall_width, 0, room_inner_height),  # 右上后（天花板底面）
                        (wall_width, wall_depth, room_inner_height),  # 右上前（天花板底面）
                        (0, wall_depth, room_inner_height)  # 左上前（天花板底面）
                    ]

                # 添加顶点到bmesh
                bm_verts = [bm.verts.new(v) for v in verts]
                bm.verts.ensure_lookup_table()

                # 创建面
                faces = [
                    [0, 1, 2, 3],  # 底面
                    [4, 5, 6, 7],  # 顶面
                    [0, 4, 7, 3],  # 左面
                    [1, 5, 6, 2],  # 右面
                    [3, 7, 6, 2],  # 前面
                    [0, 4, 5, 1]   # 后面
                ]

                for face_verts in faces:
                    bm.faces.new([bm_verts[i] for i in face_verts])

                # 创建网格对象
                mesh = bpy.data.meshes.new("ArchWallMesh")
                bm.to_mesh(mesh)
                bm.free()

                obj = bpy.data.objects.new("ArchWall", mesh)
                bpy.context.collection.objects.link(obj)

                # 设置拱门墙面位置
                if placement == 'BACK':
                    # 背景墙位置：Y=room_depth
                    # 拱门墙面位置：Y=room_depth - distance
                    # 调整：向原点方向移动半个墙面厚度，使背面距背景墙前面distance米
                    obj.location = (0, room_depth - distance -
                                    wall_thickness, 0)

                return obj

            def create_arch_cutter(width, height, thickness, segments=32):
                """创建拱门切割器（垂直XY面）"""
                bm = bmesh.new()

                radius = width / 2
                wall_height = height - radius  # 墙体部分高度

                # 创建拱门轮廓点（在XZ平面上）
                profile_verts = []

                # 底部矩形部分 - 从左下角开始，逆时针，从地面以下开始，确保完全穿透
                profile_verts.extend([
                    (-radius, 0, -thickness/2),      # 左下（地面以下）
                    (radius, 0, -thickness/2),       # 右下（地面以下）
                    (radius, 0, wall_height),  # 右上（墙体顶部）
                    (-radius, 0, wall_height)  # 左上（墙体顶部）
                ])

                # 顶部半圆部分 - 从右到左创建半圆顶点
                # 注意：这里需要从右到左，所以角度从0到π
                for i in range(segments + 1):
                    angle = math.pi * i / segments  # 从0到π
                    x = radius * math.cos(angle)
                    z = wall_height + radius * math.sin(angle)
                    profile_verts.append((x, 0, z))

                # 拉伸创建3D几何体（沿Y轴拉伸）
                extrude_profile_to_3d_vertical(
                    bm, profile_verts, thickness, radius, wall_height)

                # 创建网格对象
                mesh = bpy.data.meshes.new("ArchCutterMesh")
                bm.to_mesh(mesh)
                bm.free()

                obj = bpy.data.objects.new("ArchCutter", mesh)
                bpy.context.collection.objects.link(obj)

                return obj

            def extrude_profile_to_3d_vertical(bm, profile_verts, thickness, radius, wall_height):
                """将2D轮廓沿Y轴拉伸为3D几何体（垂直XY面）"""
                # 创建前后面
                front_verts = []
                back_verts = []

                for x, y, z in profile_verts:
                    front_verts.append(bm.verts.new((x, thickness/2, z)))
                    back_verts.append(bm.verts.new((x, -thickness/2, z)))

                bm.verts.ensure_lookup_table()

                # 创建前面
                bm.faces.new(front_verts)

                # 创建后面
                bm.faces.new(back_verts[::-1])  # 反转顺序以保持法向一致

                # 创建侧面 - 但不创建矩形和半圆之间的连接面
                for i in range(len(profile_verts) - 1):
                    v1_front = front_verts[i]
                    v2_front = front_verts[i + 1]
                    v1_back = back_verts[i]
                    v2_back = back_verts[i + 1]

                    # 检查是否是矩形和半圆之间的连接
                    # 矩形顶部：Z = wall_height, X = ±radius
                    # 半圆底部：Z = wall_height, X = ±radius
                    # 如果两个顶点都在矩形顶部，则不创建面
                    if (abs(v1_front.co.z - wall_height) < 0.001 and
                        abs(v2_front.co.z - wall_height) < 0.001 and
                        abs(v1_front.co.x) < radius + 0.001 and
                            abs(v2_front.co.x) < radius + 0.001):
                        continue  # 跳过这个面

                    bm.faces.new([v1_front, v2_front, v2_back, v1_back])

                # 连接首尾
                v1_front = front_verts[-1]
                v2_front = front_verts[0]
                v1_back = back_verts[-1]
                v2_back = back_verts[0]

                bm.faces.new([v1_front, v2_front, v2_back, v1_back])

            def create_semicircle_arch_geometry(width, height, thickness, segments=32):
                """创建半圆拱门几何体（保留用于其他用途）"""
                bm = bmesh.new()

                radius = width / 2
                wall_height = height - radius  # 墙体部分高度

                # 创建拱门轮廓点
                profile_verts = []

                # 底部矩形部分
                profile_verts.extend([
                    (-radius, 0, 0), (radius, 0, 0),
                    (radius, wall_height, 0), (-radius, wall_height, 0)
                ])

                # 顶部半圆部分
                for i in range(segments + 1):
                    angle = math.pi * i / segments
                    x = radius * math.cos(angle)
                    y = wall_height + radius * math.sin(angle)
                    profile_verts.append((x, y, 0))

                # 拉伸创建3D几何体
                extrude_profile_to_3d(bm, profile_verts, thickness)

                # 创建网格对象
                mesh = bpy.data.meshes.new("SemicircleArchMesh")
                bm.to_mesh(mesh)
                bm.free()

                obj = bpy.data.objects.new("SemicircleArch", mesh)
                bpy.context.collection.objects.link(obj)

                return obj

            def extrude_profile_to_3d(bm, profile_verts, thickness):
                """将2D轮廓拉伸为3D几何体（保留用于其他用途）"""
                # 创建前后面
                front_verts = []
                back_verts = []

                for x, y, z in profile_verts:
                    front_verts.append(bm.verts.new((x, y, thickness/2)))
                    back_verts.append(bm.verts.new((x, y, -thickness/2)))

                bm.verts.ensure_lookup_table()

                # 创建前面
                bm.faces.new(front_verts)

                # 创建后面
                bm.faces.new(back_verts[::-1])  # 反转顺序以保持法向一致

                # 创建侧面
                for i in range(len(profile_verts) - 1):
                    v1_front = front_verts[i]
                    v2_front = front_verts[i + 1]
                    v1_back = back_verts[i]
                    v2_back = back_verts[i + 1]

                    bm.faces.new([v1_front, v2_front, v2_back, v1_back])

                # 连接首尾
                v1_front = front_verts[-1]
                v2_front = front_verts[0]
                v1_back = back_verts[-1]
                v2_back = back_verts[0]

                bm.faces.new([v1_front, v2_front, v2_back, v1_back])

            # — Glass material setup —
            def get_glass_mat():
                mat = bpy.data.materials.get("IRG_GlassMaterial")
                if not mat:
                    mat = bpy.data.materials.new("IRG_GlassMaterial")
                    mat.use_nodes = True
                    nodes = mat.node_tree.nodes
                    links = mat.node_tree.links
                    for n in list(nodes):
                        nodes.remove(n)
                    out = nodes.new(type='ShaderNodeOutputMaterial')
                    mix = nodes.new(type='ShaderNodeMixShader')
                    fres = nodes.new(type='ShaderNodeFresnel')
                    refr = nodes.new(type='ShaderNodeBsdfRefraction')
                    gloss = nodes.new(type='ShaderNodeBsdfGlossy')
                    fres.inputs['IOR'].default_value = 1.5
                    refr.inputs['IOR'].default_value = 1.5
                    refr.inputs['Roughness'].default_value = 0.0
                    gloss.inputs['Roughness'].default_value = 0.0
                    fres.location = (-400, 200)
                    refr.location = (-200, 300)
                    gloss.location = (-200, 100)
                    mix.location = (0, 200)
                    out.location = (200, 200)
                    links.new(fres.outputs['Fac'],  mix.inputs['Fac'])
                    links.new(refr.outputs['BSDF'], mix.inputs[1])
                    links.new(gloss.outputs['BSDF'], mix.inputs[2])
                    links.new(mix.outputs['Shader'], out.inputs['Surface'])
                return mat
            glass_mat = get_glass_mat()

            # 1) Create floor & walls, then apply scale
            def make_cube(name, loc, scale):
                bpy.ops.mesh.primitive_cube_add(location=loc)
                o = bpy.context.active_object
                o.name = name
                o.scale = scale
                bpy.ops.object.transform_apply(
                    location=False, rotation=False, scale=True)
                return o

            # 房间内空尺寸（用户输入的尺寸）
            room_inner_width = room_width
            room_inner_depth = room_depth
            room_inner_height = room_height

            # 房间外轮廓尺寸（包含墙体）
            room_outer_width = room_inner_width + wall_thickness  # 只有一边有墙
            room_outer_depth = room_inner_depth + wall_thickness  # 只有一边有墙
            room_outer_height = room_inner_height + 2 * wall_thickness  # 上下都有墙（地面+天花板）

            floor = make_cube("Floor",
                              # 地面顶面在Z=0，底面在Z=-wall_thickness
                              (room_outer_width/2,
                               room_outer_depth/2, -wall_thickness/2),
                              (room_outer_width/2, room_outer_depth/2, wall_thickness/2))

            # 创建天花板
            ceiling = make_cube("Ceiling",
                                (room_outer_width/2, room_outer_depth/2,
                                 # 天花板底面在Z=room_height，顶面在Z=room_height+wall_thickness
                                 room_height + wall_thickness/2),
                                (room_outer_width/2, room_outer_depth/2, wall_thickness/2))

            back_wall = make_cube("BackWall",
                                  (room_outer_width/2, room_outer_depth -
                                   wall_thickness/2, room_height/2),
                                  (room_outer_width/2, wall_thickness/2, room_height/2))
            # 生成X=0位置的侧墙，垂直XZ面
            side_wall = make_cube("SideWall",
                                  (wall_thickness/2,
                                   room_outer_depth/2, room_height/2),
                                  (wall_thickness/2, room_outer_depth/2, room_height/2))

            # 2) Window-cut helpers with scale‐apply
            def cube_cut(loc, sx, sy, sz):
                bpy.ops.mesh.primitive_cube_add(location=loc)
                o = bpy.context.active_object
                o.scale = (sx, sy, sz)
                bpy.ops.object.transform_apply(
                    location=False, rotation=False, scale=True)
                return o

            def cyl_cut(loc, dia, depth, rot):
                bpy.ops.mesh.primitive_cylinder_add(
                    vertices=64, radius=dia/2, depth=depth,
                    location=loc, rotation=rot
                )
                o = bpy.context.active_object
                # scale is baked into radius/depth above, so just apply
                bpy.ops.object.transform_apply(
                    location=False, rotation=False, scale=True)
                return o

            # carve windows out of a wall
            def add_windows(wall, axis, wall_len):
                frames = []
                glasses = []
                margin = wall_len * 0.1
                slot = (wall_len - 2*margin) / window_count
                for i in range(window_count):
                    win_h = room_height * window_height_pct
                    z0 = room_height/2
                    if axis == 'X':
                        x0 = margin + (i+0.5)*slot
                        y0 = room_depth - wall_thickness/2
                    else:
                        y0 = margin + (i+0.5)*slot
                        x0 = room_width - wall_thickness/2
                    win_w = slot * window_width_pct
                    pos = (x0, y0, z0)
                    depth_cut = wall_thickness + extra
                    # Boolean cutter
                    if window_type == 'ROUND':
                        dia = min(win_w, win_h)
                        rot = (math.pi/2, 0, 0) if axis == 'X' else (
                            math.pi/2, 0, math.pi/2)
                        cutter = cyl_cut(pos, dia, depth_cut, rot)
                    else:
                        sx = win_w/2 if axis == 'X' else depth_cut/2
                        sy = depth_cut/2 if axis == 'X' else win_w/2
                        sz = win_h/2
                        cutter = cube_cut(pos, sx, sy, sz)
                    # subtract cutter
                    mod = wall.modifiers.new(f"Win_{axis}_{i}", 'BOOLEAN')
                    mod.operation = 'DIFFERENCE'
                    mod.object = cutter
                    bpy.context.view_layer.objects.active = wall
                    bpy.ops.object.modifier_apply(modifier=mod.name)
                    bpy.data.objects.remove(cutter, do_unlink=True)
                    # add glass panes, name & apply scale
                    if window_type == 'ROUND':
                        glass_loc = (
                            x0, y0-(wall_thickness/2-glass_thickness/2), z0
                        ) if axis == 'X' else (
                            x0-(wall_thickness/2-glass_thickness/2), y0, z0
                        )
                        g = cyl_cut(glass_loc, dia, glass_thickness, rot)
                        g.name = "IRG_IsoWindow"
                        g.data.materials.append(glass_mat)
                        glasses.append(g)
                        continue
                    # sash or single pane
                    if window_type == 'SASH' and window_divisions == 2:
                        ft = min(win_w, win_h)*0.08
                        bottom_h = win_h * sash_bottom_pct
                        top_h = win_h - bottom_h - ft
                        # bottom pane
                        bot_cz = z0 - win_h/2 + bottom_h/2
                        loc_b = (x0, y0-(wall_thickness/2-glass_thickness/2), bot_cz) \
                            if axis == 'X' else \
                            (x0-(wall_thickness/2-glass_thickness/2), y0, bot_cz)
                        g_bot = cube_cut(loc_b,
                                         *((win_w/2, glass_thickness/2, bottom_h/2)
                                           if axis == 'X'
                                           else (glass_thickness/2, win_w/2, bottom_h/2)))
                        g_bot.name = "IRG_IsoWindow"
                        g_bot.data.materials.append(glass_mat)
                        glasses.append(g_bot)
                        # divider
                        z_div = z0 - win_h/2 + bottom_h + ft/2
                        d = cube_cut((x0, y0, z_div),
                                     *((win_w/2, depth_cut/2, ft/2)
                                       if axis == 'X'
                                       else (depth_cut/2, win_w/2, ft/2)))
                        frames.append(d)
                        # top pane
                        top_cz = z0 - win_h/2 + bottom_h + ft + top_h/2
                        loc_t = (x0, y0-(wall_thickness/2-glass_thickness/2), top_cz) \
                            if axis == 'X' else \
                            (x0-(wall_thickness/2-glass_thickness/2), y0, top_cz)
                        g_top = cube_cut(loc_t,
                                         *((win_w/2, glass_thickness/2, top_h/2)
                                           if axis == 'X'
                                           else (glass_thickness/2, win_w/2, top_h/2)))
                        g_top.name = "IRG_IsoWindow"
                        g_top.data.materials.append(glass_mat)
                        glasses.append(g_top)
                    else:
                        # single pane
                        loc_g = (x0, y0-(wall_thickness/2-glass_thickness/2), z0) \
                            if axis == 'X' else \
                                (x0-(wall_thickness/2-glass_thickness/2), y0, z0)
                        g = cube_cut(loc_g,
                                     *((win_w/2, glass_thickness/2, win_h/2)
                                       if axis == 'X'
                                       else (glass_thickness/2, win_w/2, win_h/2)))
                        g.name = "IRG_IsoWindow"
                        g.data.materials.append(glass_mat)
                        glasses.append(g)
                return frames, glasses

            # carve windows
            frame_objs = []
            if window_placement in {'BACK', 'BOTH'}:
                f, _ = add_windows(back_wall, 'X', room_width)
                frame_objs += f
            if window_placement in {'SIDE', 'BOTH'}:
                # 改为'X'轴，因为对面墙也是X轴方向
                f, _ = add_windows(side_wall, 'X', room_width)
                frame_objs += f

            # 3) 取消墙面与地面合并，保持独立对象
            # for wall in (back_wall, side_wall):  # 注释掉墙面合并
            #     mod = floor.modifiers.new(f"Union_{wall.name}", 'BOOLEAN')
            #     mod.operation = 'UNION'
            #     mod.object = wall
            #     bpy.context.view_layer.objects.active = floor
            #     bpy.ops.object.modifier_apply(modifier=mod.name)
            #     bpy.data.objects.remove(wall, do_unlink=True)

            # 4) 取消窗户框架合并，保持独立对象
            # bpy.ops.object.select_all(action='DESELECT')
            # floor.select_set(True)
            # for o in frame_objs:
            #     o.select_set(True)
            # bpy.context.view_layer.objects.active = floor
            # bpy.ops.object.join()
            # floor.name = "IRG_IsoRoom"

            # 5) Final weld + normals (只对地面进行)
            bpy.context.view_layer.objects.active = floor
            bpy.ops.object.mode_set(mode='EDIT')
            try:
                bpy.ops.mesh.merge_by_distance(distance=0.001)
            except AttributeError:
                bpy.ops.mesh.remove_doubles(
                    threshold=0.001, use_unselected=False)
            bpy.ops.mesh.normals_make_consistent(inside=False)
            bpy.ops.object.mode_set(mode='OBJECT')

            # 6) 取消天花板与房间主体合并，保持独立对象
            # bpy.ops.object.select_all(action='DESELECT')
            # floor.select_set(True)
            # ceiling.select_set(True)
            # bpy.context.view_layer.objects.active = floor
            # bpy.ops.object.join()
            # floor.name = "IRG_IsoRoom_WithCeiling"

            # 7) 添加拱门
            if bpy.context.scene.sna_arch_settings:
                add_arch_to_room(floor, room_width, room_depth,
                                 room_height, wall_thickness)

            # 8) 最终清理（只对地面进行）
            bpy.context.view_layer.objects.active = floor
            bpy.ops.object.mode_set(mode='EDIT')
            try:
                bpy.ops.mesh.merge_by_distance(distance=0.001)
            except AttributeError:
                bpy.ops.mesh.remove_doubles(
                    threshold=0.001, use_unselected=False)
            bpy.ops.mesh.normals_make_consistent(inside=False)
            bpy.ops.object.mode_set(mode='OBJECT')

            # 9) 将整个房间在X轴负方向上位移墙厚度的距离
            floor.location.x -= wall_thickness
            back_wall.location.x -= wall_thickness
            side_wall.location.x -= wall_thickness
            ceiling.location.x -= wall_thickness
            print(f"房间已向X轴负方向位移 {wall_thickness}m")

        generate_room(room_width, room_depth, room_height,
                      wall_thickness, window_placement,
                      window_count, window_width_pct,
                      window_height_pct, window_type,
                      window_divisions=2, sash_bottom_pct=0.55)
        return {"FINISHED"}

    def invoke(self, context, event):
        return self.execute(context)


class SNA_OT_Gen_Round_Room_A43Ca(bpy.types.Operator):
    bl_idname = "sna.gen_round_room_a43ca"
    bl_label = "Gen Round Room"
    bl_description = "Create Round Iso Room"
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        if bpy.app.version >= (3, 0, 0) and True:
            cls.poll_message_set('')
        return not False

    def execute(self, context):
        diameter = bpy.context.scene.sna_room_diameter_round
        floor_thickness = bpy.context.scene.sna_room_floor_thickness_round
        wall_height = bpy.context.scene.sna_room_height_round
        wall_thickness = bpy.context.scene.sna_wall_thickness_round
        window_count = bpy.context.scene.sna_round_window_amount
        window_width_pct = bpy.context.scene.sna_round_window_width
        window_height_pct = bpy.context.scene.sna_round_window_height
        window_type = bpy.context.scene.sna_window_style_round

        def get_glass_mat():
            mat = bpy.data.materials.get("IRG_GlassMaterial")
            if not mat:
                mat = bpy.data.materials.new("IRG_GlassMaterial")
                mat.use_nodes = True
                nodes = mat.node_tree.nodes
                links = mat.node_tree.links
                for n in list(nodes):
                    nodes.remove(n)
                out = nodes.new('ShaderNodeOutputMaterial')
                mix = nodes.new('ShaderNodeMixShader')
                fres = nodes.new('ShaderNodeFresnel')
                refr = nodes.new('ShaderNodeBsdfRefraction')
                gloss = nodes.new('ShaderNodeBsdfGlossy')
                fres.inputs['IOR'].default_value = 1.5
                refr.inputs['IOR'].default_value = 1.5
                refr.inputs['Roughness'].default_value = 0.0
                gloss.inputs['Roughness'].default_value = 0.0
                links.new(fres.outputs['Fac'],   mix.inputs['Fac'])
                links.new(refr.outputs['BSDF'],  mix.inputs[1])
                links.new(gloss.outputs['BSDF'], mix.inputs[2])
                links.new(mix.outputs['Shader'], out.inputs['Surface'])
            return mat

        def make_curved_glass(name, θ_center, arc_angle, radius, height, segments, z_offset, mat=None):
            bm = bmesh.new()
            verts_top = []
            verts_bottom = []
            for i in range(segments + 1):
                θ = θ_center - arc_angle / 2 + i * (arc_angle / segments)
                x = radius * math.cos(θ)
                y = radius * math.sin(θ)
                verts_top.append(bm.verts.new((x, y, z_offset + height / 2)))
                verts_bottom.append(bm.verts.new(
                    (x, y, z_offset - height / 2)))
            bm.verts.ensure_lookup_table()
            for i in range(segments):
                bm.faces.new(
                    (verts_top[i], verts_bottom[i], verts_bottom[i+1], verts_top[i+1]))
            mesh = bpy.data.meshes.new(name)
            bm.to_mesh(mesh)
            bm.free()
            obj = bpy.data.objects.new(name, mesh)
            bpy.context.collection.objects.link(obj)
            obj.location.z = height / 2
            if mat:
                obj.data.materials.append(mat)
            return obj

        def generate_round_room(
            diameter, floor_thickness, wall_height, wall_thickness,
            window_count, window_width_pct, window_height_pct,
            window_type='SQUARE', sash_bottom_pct=0.55
        ):
            extra = 0.01
            R_out = diameter / 2.0
            R_mid = R_out - wall_thickness / 2.0
            glass_off = extra / 2.0
            glass_mat = get_glass_mat()

            def make_cylinder(name, radius, depth, loc, rot=(0, 0, 0), verts=64):
                bpy.ops.mesh.primitive_cylinder_add(
                    vertices=verts, radius=radius, depth=depth, location=loc, rotation=rot)
                o = bpy.context.active_object
                o.name = name
                bpy.ops.object.transform_apply(
                    location=False, rotation=False, scale=True)
                return o

            def make_cube(name, loc, half_extents, rot=(0, 0, 0)):
                bpy.ops.mesh.primitive_cube_add(location=loc)
                o = bpy.context.active_object
                o.name = name
                o.scale = half_extents
                o.rotation_euler = rot
                bpy.ops.object.transform_apply(
                    location=False, rotation=True, scale=True)
                return o
            floor = make_cylinder(
                "Floor", R_out, floor_thickness, (0, 0, floor_thickness/2))
            wall = make_cylinder("WallOuter", R_out,
                                 wall_height, (0, 0, wall_height/2))
            inner = make_cylinder(
                "WallInner", R_out-wall_thickness, wall_height+extra, (0, 0, wall_height/2))
            mod = wall.modifiers.new("HollowWall", 'BOOLEAN')
            mod.operation, mod.object = 'DIFFERENCE', inner
            bpy.context.view_layer.objects.active = wall
            bpy.ops.object.modifier_apply(modifier=mod.name)
            bpy.data.objects.remove(inner, do_unlink=True)
            cutter = make_cube(
                "FrontCutter", (0, R_out, wall_height/2), (2*R_out, R_out, wall_height))
            mod = wall.modifiers.new("CutFront", 'BOOLEAN')
            mod.operation, mod.object = 'DIFFERENCE', cutter
            bpy.context.view_layer.objects.active = wall
            bpy.ops.object.modifier_apply(modifier=mod.name)
            bpy.data.objects.remove(cutter, do_unlink=True)
            panes = []
            # Only generate windows if applicable
            if window_type.upper() in {'SQUARE', 'SASH'} and window_count > 0:
                start_ang, end_ang = math.pi, 2*math.pi
                seg = (end_ang - start_ang) / window_count
                for i in range(window_count):
                    θ = start_ang + (i+0.5)*seg
                    x, y = R_mid * math.cos(θ), R_mid * math.sin(θ)
                    z = wall_height / 2
                    win_h = wall_height * window_height_pct
                    win_ang = seg * window_width_pct
                    chord = 2 * R_mid * math.sin(win_ang / 2)
                    cut = make_cube(
                        f"Cut_{i}", (x, y, z), (wall_thickness, chord/2 + extra, win_h/2 + extra), rot=(0, 0, θ))
                    mod = wall.modifiers.new(f"WinBool_{i}", 'BOOLEAN')
                    mod.operation, mod.object = 'DIFFERENCE', cut
                    bpy.context.view_layer.objects.active = wall
                    bpy.ops.object.modifier_apply(modifier=mod.name)
                    bpy.data.objects.remove(cut, do_unlink=True)
                    objs = []
                    if window_type.upper() == 'SASH':
                        ft = min(chord, win_h) * 0.08
                        bot_h = win_h * sash_bottom_pct
                        top_h = win_h - bot_h - ft
                        bz = z - win_h/2
                        bot = make_curved_glass(
                            f"IRG_IsoRoom_Window_SashBot_{i}", θ, win_ang, R_out - glass_off, bot_h, 16, bz, glass_mat)
                        objs.append(bot)
                        dz = bz + bot_h
                        bar = make_curved_glass(
                            f"IRG_IsoRoom_Window_SashBar_{i}", θ, win_ang, R_out - glass_off, ft, 16, dz, None)
                        objs.append(bar)
                        tz = dz + ft
                        top = make_curved_glass(
                            f"IRG_IsoRoom_Window_SashTop_{i}", θ, win_ang, R_out - glass_off, top_h, 16, tz, glass_mat)
                        objs.append(top)
                    if window_type.upper() == 'SQUARE':
                        pane = make_curved_glass(
                            f"IRG_IsoRoom_Window_Glass_{i}", θ, win_ang, R_out - glass_off, win_h, 16, z - win_h/2, glass_mat)
                        objs.append(pane)
                    panes.extend(objs)
            mod = floor.modifiers.new("WallUnion", 'BOOLEAN')
            mod.operation, mod.object = 'UNION', wall
            bpy.context.view_layer.objects.active = floor
            bpy.ops.object.modifier_apply(modifier=mod.name)
            bpy.data.objects.remove(wall, do_unlink=True)
            me = floor.data
            bm = bmesh.new()
            bm.from_mesh(me)
            bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.001)
            bm.normal_update()
            bm.to_mesh(me)
            bm.free()
            floor.name = "IRG_IsoRoom_Round"
            return floor, panes
        generate_round_room(
            diameter,
            floor_thickness,
            wall_height,
            wall_thickness,
            window_count,
            window_width_pct,
            window_height_pct,
            window_type
        )
        return {"FINISHED"}

    def invoke(self, context, event):
        return self.execute(context)


def register():
    global _icons
    _icons = bpy.utils.previews.new()
    bpy.types.Scene.sna_room_width = bpy.props.FloatProperty(
        name='Room Width', description='', default=1.0, subtype='NONE', unit='NONE', min=0.10000000149011612, step=3, precision=2)
    bpy.types.Scene.sna_room_depth = bpy.props.FloatProperty(
        name='Room Depth', description='', default=1.0, subtype='NONE', unit='NONE', min=0.10000000149011612, step=3, precision=2)
    bpy.types.Scene.sna_room_height = bpy.props.FloatProperty(
        name='Room Height', description='', default=1.0, subtype='NONE', unit='NONE', min=0.10000000149011612, step=3, precision=2)
    bpy.types.Scene.sna_wall_thickness = bpy.props.FloatProperty(
        name='Wall Thickness', description='', default=0.10000000149011612, subtype='NONE', unit='NONE', min=0.009999999776482582, step=3, precision=2)
    bpy.types.Scene.sna_windows_enum = bpy.props.EnumProperty(name='Windows Enum', description='', items=[('NONE', 'NONE', 'None', 0, 0), (
        'BACK', 'BACK', 'Back Wall Only', 0, 1), ('SIDE', 'SIDE', 'Side Wall Only', 0, 2), ('BOTH', 'BOTH', 'Both Walls', 0, 3)])
    bpy.types.Scene.sna_windows_count = bpy.props.IntProperty(
        name='Windows Count', description='', default=1, subtype='NONE', min=1, max=5)
    bpy.types.Scene.sna_windows_width = bpy.props.FloatProperty(
        name='Windows Width', description='', default=0.25, subtype='NONE', unit='NONE', min=0.10000000149011612, max=1.0, step=3, precision=2)
    bpy.types.Scene.sna_windows_height = bpy.props.FloatProperty(
        name='Windows Height', description='', default=0.25, subtype='NONE', unit='NONE', min=0.10000000149011612, max=1.0, step=3, precision=2)
    bpy.types.Scene.sna_window_style = bpy.props.EnumProperty(name='Window Style', description='', items=[(
        'SQUARE', 'SQUARE', 'SQUARE', 0, 0), ('ROUND', 'ROUND', 'ROUND', 0, 1), ('SASH', 'SASH', 'SASH', 0, 2)])
    bpy.types.Scene.sna_room_settings = bpy.props.BoolProperty(
        name='Room Settings', description='', default=False)
    bpy.types.Scene.sna_winows_settings = bpy.props.BoolProperty(
        name='Winows settings', description='', default=False)
    bpy.types.Scene.sna_style = bpy.props.EnumProperty(name='Style', description='', items=[(
        'Square', 'Square', 'Square Room', 0, 0), ('Round', 'Round', 'Round Room', 0, 1)])

    # 添加拱门相关属性（移除前墙选项）
    bpy.types.Scene.sna_arch_settings = bpy.props.BoolProperty(
        name='Arch Settings', description='', default=False)
    bpy.types.Scene.sna_arch_placement = bpy.props.EnumProperty(
        name='Arch Placement', description='',
        items=[('NONE', 'None', 'No Arch', 0, 0),
               ('BACK', 'Back Wall', 'Back Wall', 0, 1)])
    bpy.types.Scene.sna_arch_width = bpy.props.FloatProperty(
        name='Arch Width', description='', default=1.2, subtype='NONE', unit='NONE', min=0.5, max=3.0, step=3, precision=2)
    bpy.types.Scene.sna_arch_height = bpy.props.FloatProperty(
        name='Arch Height', description='', default=2.4, subtype='NONE', unit='NONE', min=1.5, max=4.0, step=3, precision=2)
    bpy.types.Scene.sna_arch_thickness = bpy.props.FloatProperty(
        name='Arch Thickness', description='', default=0.10, subtype='NONE', unit='NONE', min=0.05, max=0.5, step=3, precision=2)

    bpy.types.Scene.sna_round_room_settings = bpy.props.BoolProperty(
        name='Round Room Settings', description='', default=False)
    bpy.types.Scene.sna_round_window_settings = bpy.props.BoolProperty(
        name='Round Window Settings', description='', default=False)
    bpy.types.Scene.sna_room_diameter_round = bpy.props.FloatProperty(
        name='Room diameter Round', description='', default=10.0, subtype='NONE', unit='NONE', min=0.10000000149011612, step=3, precision=2)
    bpy.types.Scene.sna_room_floor_thickness_round = bpy.props.FloatProperty(
        name='Room Floor thickness Round', description='', default=0.10000000149011612, subtype='NONE', unit='NONE', min=0.10000000149011612, step=3, precision=2)
    bpy.types.Scene.sna_room_height_round = bpy.props.FloatProperty(
        name='Room Height Round', description='', default=3.0, subtype='NONE', unit='NONE', min=0.10000000149011612, step=3, precision=2)
    bpy.types.Scene.sna_wall_thickness_round = bpy.props.FloatProperty(
        name='Wall Thickness round', description='', default=0.20000000298023224, subtype='NONE', unit='NONE', min=0.009999999776482582, step=3, precision=2)
    bpy.types.Scene.sna_window_style_round = bpy.props.EnumProperty(name='Window Style Round', description='', items=[(
        'NONE', 'NONE', 'No Windows', 0, 0), ('SQUARE', 'SQUARE', 'Square Windows', 0, 1), ('SASH', 'SASH', 'Sash Windows', 0, 2)])
    bpy.types.Scene.sna_round_window_amount = bpy.props.IntProperty(
        name='Round Window Amount', description='', default=6, subtype='NONE', min=1)
    bpy.types.Scene.sna_round_window_width = bpy.props.FloatProperty(
        name='Round Window Width', description='', default=0.699999988079071, subtype='NONE', unit='NONE', min=0.10000000149011612, max=1.0, step=3, precision=2)
    bpy.types.Scene.sna_round_window_height = bpy.props.FloatProperty(
        name='Round Window Height', description='', default=0.6000000238418579, subtype='NONE', unit='NONE', min=0.10000000149011612, max=1.0, step=3, precision=2)
    bpy.utils.register_class(SNA_PT_IRG_3542C)
    bpy.utils.register_class(SNA_OT_Gen_Room_1803A)
    bpy.utils.register_class(SNA_OT_Gen_Round_Room_A43Ca)


def unregister():
    global _icons
    bpy.utils.previews.remove(_icons)
    wm = bpy.context.window_manager
    kc = wm.keyconfigs.addon
    for km, kmi in addon_keymaps.values():
        km.keymap_items.remove(kmi)
    addon_keymaps.clear()

    # 清理拱门相关属性
    del bpy.types.Scene.sna_arch_thickness
    del bpy.types.Scene.sna_arch_height
    del bpy.types.Scene.sna_arch_width
    del bpy.types.Scene.sna_arch_placement
    del bpy.types.Scene.sna_arch_settings

    del bpy.types.Scene.sna_round_window_height
    del bpy.types.Scene.sna_round_window_width
    del bpy.types.Scene.sna_round_window_amount
    del bpy.types.Scene.sna_window_style_round
    del bpy.types.Scene.sna_wall_thickness_round
    del bpy.types.Scene.sna_room_height_round
    del bpy.types.Scene.sna_room_floor_thickness_round
    del bpy.types.Scene.sna_room_diameter_round
    del bpy.types.Scene.sna_round_window_settings
    del bpy.types.Scene.sna_round_room_settings
    del bpy.types.Scene.sna_style
    del bpy.types.Scene.sna_winows_settings
    del bpy.types.Scene.sna_room_settings
    del bpy.types.Scene.sna_window_style
    del bpy.types.Scene.sna_windows_height
    del bpy.types.Scene.sna_windows_width
    del bpy.types.Scene.sna_windows_count
    del bpy.types.Scene.sna_windows_enum
    del bpy.types.Scene.sna_wall_thickness
    del bpy.types.Scene.sna_room_height
    del bpy.types.Scene.sna_room_depth
    del bpy.types.Scene.sna_room_width
    bpy.utils.unregister_class(SNA_PT_IRG_3542C)
    bpy.utils.unregister_class(SNA_OT_Gen_Room_1803A)
    bpy.utils.unregister_class(SNA_OT_Gen_Round_Room_A43Ca)
