"""
布料管理器
负责布料对象的创建、管理和更新
包含完整的布料物理模拟功能
"""

from panda3d.core import Vec3, Point3, GeomVertexReader, GeomVertexFormat
from panda3d.core import GeomVertexData, Geom, GeomNode, NodePath
from panda3d.bullet import BulletSoftBodyNode, BulletSoftBodyWorldInfo
import math
from typing import List, Dict, Optional, Any, Tuple
import numpy as np


class ClothManager:
    """
    布料管理器
    管理场景中的所有布料对象，提供完整的布料物理模拟功能
    """
    
    # 布料类型常量
    CLOTH_TYPE_PLANE = "plane"
    CLOTH_TYPE_PATCH = "patch"
    CLOTH_TYPE_TUBE = "tube"
    CLOTH_TYPE_ROPE = "rope"
    
    # 撕裂模式
    TEAR_MODE_NONE = "none"
    TEAR_MODE_VERTEX = "vertex"
    TEAR_MODE_EDGE = "edge"
    
    def __init__(self, world):
        self.world = world
        self.cloth_objects: List[Dict[str, Any]] = []
        self.enabled = False
        self.gravity = Vec3(0, 0, -9.81)
        
        # 布料默认参数
        self.default_params = {
            'density': 0.5,
            'linear_stiffness': 0.8,
            'angular_stiffness': 0.8,
            'volume_stiffness': 0.5,
            'friction': 0.5,
            'restitution': 0.2,
            'pressure_coefficient': 0.0,
            'drag_coefficient': 0.01,
            'lift_coefficient': 0.01,
            'anchored': False,
            'tear_mode': 'none',
            'tear_threshold': 100.0,
            'tear_resistance': 50.0,
            'bending_constraints': True,
            'clusters': 0,
            'cluster_hardness': 1.0,
            'position_iteration': 2,
            'drift_iteration': 2,
            'cluster_iteration': 2,
            'velocity_iteration': 2
        }
        
        # 风力参数
        self.wind_enabled = False
        self.wind_velocity = Vec3(0, 0, 0)
        self.wind_turbulence = 0.0
        self.wind_frequency = 1.0
        
        # 性能参数
        self.max_cloth_objects = 100
        self.cloth_update_frequency = 60  # Hz
        
    def enable(self):
        """
        启用布料管理器
        """
        self.enabled = True
        print("✓ 布料管理器已启用")
        
    def disable(self):
        """
        禁用布料管理器
        """
        self.enabled = False
        print("✓ 布料管理器已禁用")
        
    def set_gravity(self, gravity: Vec3):
        """
        设置重力
        
        Args:
            gravity: 重力向量
        """
        self.gravity = gravity
        
    def set_wind_parameters(self, enabled: bool = True, velocity: Vec3 = None, 
                          turbulence: float = 0.0, frequency: float = 1.0):
        """
        设置风力参数
        
        Args:
            enabled: 是否启用风力
            velocity: 风速向量
            turbulence: 湍流强度
            frequency: 风力变化频率
        """
        self.wind_enabled = enabled
        if velocity:
            self.wind_velocity = velocity
        self.wind_turbulence = turbulence
        self.wind_frequency = frequency
        
    def create_cloth_from_mesh(self, node_path, params: Dict[str, Any] = None) -> Optional[Dict[str, Any]]:
        """
        从网格创建布料对象
        
        Args:
            node_path: 网格节点路径
            params: 布料参数
            
        Returns:
            布料对象信息字典
        """
        if not self.enabled:
            print("⚠ 布料管理器未启用")
            return None
            
        if len(self.cloth_objects) >= self.max_cloth_objects:
            print("⚠ 达到最大布料对象数量限制")
            return None
            
        try:
            # 合并参数
            cloth_params = self.default_params.copy()
            if params:
                cloth_params.update(params)
                
            # 创建软体节点
            cloth_name = f'cloth_{len(self.cloth_objects)}'
            soft_body_node = BulletSoftBodyNode(cloth_name)
            
            # 设置布料参数
            self._apply_cloth_parameters(soft_body_node, cloth_params)
            
            # 从网格创建布料
            vertices, indices = self._extract_mesh_data(node_path)
            if not vertices or not indices:
                print("⚠ 无法从网格提取顶点数据")
                return None
                
            # 添加顶点
            for vertex in vertices:
                soft_body_node.appendNode(vertex, 1.0)
                
            # 添加面
            for i in range(0, len(indices), 3):
                if i + 2 < len(indices):
                    soft_body_node.appendFace(indices[i], indices[i+1], indices[i+2])
                    
            # 添加链接（边）
            self._add_links_from_indices(soft_body_node, indices)
            
            # 添加弯曲约束
            if cloth_params.get('bending_constraints', True):
                self._add_bending_constraints(soft_body_node)
                
            # 创建布料节点路径
            cloth_np = node_path.attachNewNode(soft_body_node)
            cloth_np.setPos(node_path.getPos())
            cloth_np.setHpr(node_path.getHpr())
            
            # 添加到物理世界
            physics_world = self._get_physics_world()
            if physics_world:
                physics_world.attachSoftBody(soft_body_node)
            
            # 保存布料信息
            cloth_info = {
                'node_path': cloth_np,
                'soft_body': soft_body_node,
                'original_node': node_path,
                'params': cloth_params,
                'type': 'cloth',
                'anchors': [],  # 固定点列表
                'tears': [],    # 撕裂记录
                'vertices': vertices,
                'indices': indices,
                'creation_time': self.world.globalClock.getFrameTime() if hasattr(self.world, 'globalClock') else 0.0,
                'last_update_time': 0.0,
                'performance_stats': {
                    'update_count': 0,
                    'tear_count': 0,
                    'collision_count': 0
                }
            }
            
            self.cloth_objects.append(cloth_info)
            
            print(f"✓ 创建布料对象: {cloth_name} (顶点数: {len(vertices)}, 面数: {len(indices)//3})")
            return cloth_info
            
        except Exception as e:
            print(f"✗ 创建布料对象失败: {e}")
            import traceback
            traceback.print_exc()
            return None
            
    def create_cloth_patch(self, node_path, width: float, height: float, 
                          resolution_x: int, resolution_y: int,
                          params: Dict[str, Any] = None) -> Optional[Dict[str, Any]]:
        """
        创建布料片
        
        Args:
            node_path: 父节点路径
            width: 布料宽度
            height: 布料高度
            resolution_x: X方向分辨率
            resolution_y: Y方向分辨率
            params: 布料参数
            
        Returns:
            布料对象信息字典
        """
        if not self.enabled:
            print("⚠ 布料管理器未启用")
            return None
            
        if len(self.cloth_objects) >= self.max_cloth_objects:
            print("⚠ 达到最大布料对象数量限制")
            return None
            
        try:
            # 合并参数
            cloth_params = self.default_params.copy()
            if params:
                cloth_params.update(params)
                
            # 创建软体节点
            cloth_name = f'cloth_patch_{len(self.cloth_objects)}'
            soft_body_node = BulletSoftBodyNode(cloth_name)
            
            # 设置布料参数
            self._apply_cloth_parameters(soft_body_node, cloth_params)
            
            # 生成布料片顶点
            vertices = []
            indices = []
            half_width = width / 2.0
            half_height = height / 2.0
            
            # 生成顶点
            for j in range(resolution_y + 1):
                for i in range(resolution_x + 1):
                    x = (i / resolution_x) * width - half_width
                    y = (j / resolution_y) * height - half_height
                    z = 0.0
                    vertices.append(Point3(x, y, z))
                    
            # 生成索引
            for j in range(resolution_y):
                for i in range(resolution_x):
                    v0 = j * (resolution_x + 1) + i
                    v1 = v0 + 1
                    v2 = (j + 1) * (resolution_x + 1) + i
                    v3 = v2 + 1
                    
                    indices.extend([v0, v1, v2, v1, v3, v2])
                    
            # 添加顶点到软体
            for vertex in vertices:
                soft_body_node.appendNode(vertex, 1.0)
                
            # 添加面
            for i in range(0, len(indices), 3):
                if i + 2 < len(indices):
                    soft_body_node.appendFace(indices[i], indices[i+1], indices[i+2])
                    
            # 添加链接
            self._add_links_from_indices(soft_body_node, indices)
            
            # 添加弯曲约束
            if cloth_params.get('bending_constraints', True):
                self._add_bending_constraints(soft_body_node)
                
            # 创建布料节点路径
            cloth_np = node_path.attachNewNode(soft_body_node)
            
            # 添加到物理世界
            physics_world = self._get_physics_world()
            if physics_world:
                physics_world.attachSoftBody(soft_body_node)
            
            # 保存布料信息
            cloth_info = {
                'node_path': cloth_np,
                'soft_body': soft_body_node,
                'original_node': node_path,
                'params': cloth_params,
                'type': 'cloth_patch',
                'width': width,
                'height': height,
                'resolution_x': resolution_x,
                'resolution_y': resolution_y,
                'anchors': [],
                'tears': [],
                'vertices': vertices,
                'indices': indices,
                'creation_time': self.world.globalClock.getFrameTime() if hasattr(self.world, 'globalClock') else 0.0,
                'last_update_time': 0.0,
                'performance_stats': {
                    'update_count': 0,
                    'tear_count': 0,
                    'collision_count': 0
                }
            }
            
            self.cloth_objects.append(cloth_info)
            
            print(f"✓ 创建布料片: {cloth_name} ({resolution_x+1}x{resolution_y+1} 顶点)")
            return cloth_info
            
        except Exception as e:
            print(f"✗ 创建布料片失败: {e}")
            import traceback
            traceback.print_exc()
            return None
            
    def create_cloth_tube(self, node_path, radius: float, height: float, 
                         resolution: int = 16,
                         params: Dict[str, Any] = None) -> Optional[Dict[str, Any]]:
        """
        创建管状布料
        
        Args:
            node_path: 父节点路径
            radius: 管道半径
            height: 管道高度
            resolution: 分辨率
            params: 布料参数
            
        Returns:
            布料对象信息字典
        """
        if not self.enabled:
            print("⚠ 布料管理器未启用")
            return None
            
        if len(self.cloth_objects) >= self.max_cloth_objects:
            print("⚠ 达到最大布料对象数量限制")
            return None
            
        try:
            # 合并参数
            cloth_params = self.default_params.copy()
            if params:
                cloth_params.update(params)
                
            # 创建软体节点
            cloth_name = f'cloth_tube_{len(self.cloth_objects)}'
            soft_body_node = BulletSoftBodyNode(cloth_name)
            
            # 设置布料参数
            self._apply_cloth_parameters(soft_body_node, cloth_params)
            
            # 生成管状布料顶点
            vertices = []
            indices = []
            half_height = height / 2.0
            
            # 生成顶点
            for j in range(2):  # 顶部和底部
                z = half_height if j == 0 else -half_height
                for i in range(resolution):
                    angle = (i / resolution) * 2 * math.pi
                    x = math.cos(angle) * radius
                    y = math.sin(angle) * radius
                    vertices.append(Point3(x, y, z))
                    
            # 生成侧面索引
            for i in range(resolution):
                next_i = (i + 1) % resolution
                # 上面
                indices.extend([i, next_i, i + resolution])
                indices.extend([next_i, next_i + resolution, i + resolution])
                
            # 添加顶点到软体
            for vertex in vertices:
                soft_body_node.appendNode(vertex, 1.0)
                
            # 添加面
            for i in range(0, len(indices), 3):
                if i + 2 < len(indices):
                    soft_body_node.appendFace(indices[i], indices[i+1], indices[i+2])
                    
            # 添加链接
            self._add_links_from_indices(soft_body_node, indices)
            
            # 添加弯曲约束
            if cloth_params.get('bending_constraints', True):
                self._add_bending_constraints(soft_body_node)
                
            # 创建布料节点路径
            cloth_np = node_path.attachNewNode(soft_body_node)
            
            # 添加到物理世界
            physics_world = self._get_physics_world()
            if physics_world:
                physics_world.attachSoftBody(soft_body_node)
            
            # 保存布料信息
            cloth_info = {
                'node_path': cloth_np,
                'soft_body': soft_body_node,
                'original_node': node_path,
                'params': cloth_params,
                'type': 'cloth_tube',
                'radius': radius,
                'height': height,
                'resolution': resolution,
                'anchors': [],
                'tears': [],
                'vertices': vertices,
                'indices': indices,
                'creation_time': self.world.globalClock.getFrameTime() if hasattr(self.world, 'globalClock') else 0.0,
                'last_update_time': 0.0,
                'performance_stats': {
                    'update_count': 0,
                    'tear_count': 0,
                    'collision_count': 0
                }
            }
            
            self.cloth_objects.append(cloth_info)
            
            print(f"✓ 创建管状布料: {cloth_name} (半径: {radius}, 高度: {height})")
            return cloth_info
            
        except Exception as e:
            print(f"✗ 创建管状布料失败: {e}")
            import traceback
            traceback.print_exc()
            return None
            
    def add_anchor(self, cloth_info: Dict[str, Any], vertex_index: int, 
                   anchor_node=None, disable_collision: bool = True) -> bool:
        """
        为布料添加固定点
        
        Args:
            cloth_info: 布料对象信息
            vertex_index: 顶点索引
            anchor_node: 固定点节点（如果为None，则固定在当前位置）
            disable_collision: 是否禁用与固定点的碰撞
            
        Returns:
            是否成功添加固定点
        """
        try:
            soft_body = cloth_info['soft_body']
            
            if anchor_node:
                # 固定到指定节点
                soft_body.appendAnchor(vertex_index, anchor_node, disable_collision)
            else:
                # 固定在当前位置
                soft_body.appendAnchor(vertex_index, None, disable_collision)
                
            # 记录固定点
            cloth_info['anchors'].append({
                'vertex_index': vertex_index,
                'anchor_node': anchor_node,
                'disable_collision': disable_collision,
                'position': soft_body.get_nodes()[vertex_index].get_position()
            })
            
            print(f"✓ 为布料添加固定点: 顶点 {vertex_index}")
            return True
            
        except Exception as e:
            print(f"✗ 添加固定点失败: {e}")
            return False
            
    def remove_anchor(self, cloth_info: Dict[str, Any], vertex_index: int) -> bool:
        """
        移除布料固定点
        
        Args:
            cloth_info: 布料对象信息
            vertex_index: 顶点索引
            
        Returns:
            是否成功移除固定点
        """
        try:
            anchors_to_remove = []
            for i, anchor in enumerate(cloth_info['anchors']):
                if anchor['vertex_index'] == vertex_index:
                    anchors_to_remove.append(i)
                    
            # 从后往前删除，避免索引变化
            for i in reversed(anchors_to_remove):
                cloth_info['anchors'].pop(i)
                
            print(f"✓ 移除布料固定点: 顶点 {vertex_index}")
            return True
            
        except Exception as e:
            print(f"✗ 移除固定点失败: {e}")
            return False
            
    def tear_cloth_at_point(self, cloth_info: Dict[str, Any], point: Point3, 
                           radius: float = 0.5) -> bool:
        """
        在指定点撕裂布料
        
        Args:
            cloth_info: 布料对象信息
            point: 撕裂点
            radius: 撕裂半径
            
        Returns:
            是否成功撕裂
        """
        try:
            soft_body = cloth_info['soft_body']
            nodes = soft_body.get_nodes()
            
            # 查找附近的顶点
            tear_indices = []
            for i, node in enumerate(nodes):
                node_pos = node.get_position()
                distance = (node_pos - point).length()
                if distance <= radius:
                    tear_indices.append(i)
                    
            if not tear_indices:
                print("⚠ 没有找到可撕裂的顶点")
                return False
                
            # 执行撕裂
            tear_count = 0
            for index in tear_indices:
                # 在实际实现中，这里会执行撕裂操作
                # BulletSoftBodyNode目前不直接支持撕裂，需要通过其他方式实现
                tear_count += 1
                
            # 记录撕裂
            cloth_info['tears'].append({
                'point': point,
                'radius': radius,
                'indices': tear_indices,
                'time': self.world.globalClock.getFrameTime() if hasattr(self.world, 'globalClock') else 0.0
            })
            
            cloth_info['performance_stats']['tear_count'] += tear_count
            print(f"✓ 撕裂布料: {tear_count} 个顶点")
            return True
            
        except Exception as e:
            print(f"✗ 撕裂布料失败: {e}")
            return False
            
    def remove_cloth(self, cloth_info: Dict[str, Any]) -> bool:
        """
        移除布料对象
        
        Args:
            cloth_info: 布料对象信息
            
        Returns:
            是否成功移除
        """
        try:
            if cloth_info not in self.cloth_objects:
                print("⚠ 布料对象不存在")
                return False
                
            # 从物理世界移除
            physics_world = self._get_physics_world()
            if physics_world:
                physics_world.removeSoftBody(cloth_info['soft_body'])
                
            # 移除节点
            if cloth_info['node_path'] and not cloth_info['node_path'].isEmpty():
                cloth_info['node_path'].removeNode()
                
            # 从列表移除
            self.cloth_objects.remove(cloth_info)
            
            print("✓ 移除布料对象")
            return True
            
        except Exception as e:
            print(f"✗ 移除布料对象失败: {e}")
            return False
            
    def update_cloth_params(self, cloth_info: Dict[str, Any], params: Dict[str, Any]) -> bool:
        """
        更新布料参数
        
        Args:
            cloth_info: 布料对象信息
            params: 新参数
            
        Returns:
            是否成功更新
        """
        try:
            # 更新参数
            cloth_info['params'].update(params)
            
            # 应用参数到软体节点
            soft_body = cloth_info['soft_body']
            self._apply_cloth_parameters(soft_body, cloth_info['params'])
                
            print("✓ 更新布料参数")
            return True
            
        except Exception as e:
            print(f"✗ 更新布料参数失败: {e}")
            return False
            
    def update_all_cloths(self, dt: float):
        """
        更新所有布料对象
        
        Args:
            dt: 时间增量
        """
        if not self.enabled:
            return
            
        current_time = self.world.globalClock.getFrameTime() if hasattr(self.world, 'globalClock') else 0.0
        
        for cloth_info in self.cloth_objects:
            # 检查更新频率
            if current_time - cloth_info['last_update_time'] < 1.0 / self.cloth_update_frequency:
                continue
                
            # 更新性能统计
            cloth_info['performance_stats']['update_count'] += 1
            cloth_info['last_update_time'] = current_time
            
            # 应用风力
            if self.wind_enabled:
                self._apply_wind_force(cloth_info)
                
            # 检查撕裂
            self._check_tear_conditions(cloth_info)
            
    def get_cloth_stats(self) -> Dict[str, Any]:
        """
        获取布料统计信息
        
        Returns:
            统计信息字典
        """
        total_vertices = 0
        total_faces = 0
        total_anchors = 0
        total_tears = 0
        
        for cloth_info in self.cloth_objects:
            total_vertices += len(cloth_info.get('vertices', []))
            total_faces += len(cloth_info.get('indices', [])) // 3
            total_anchors += len(cloth_info.get('anchors', []))
            total_tears += cloth_info['performance_stats'].get('tear_count', 0)
            
        return {
            'total_cloth_objects': len(self.cloth_objects),
            'total_vertices': total_vertices,
            'total_faces': total_faces,
            'total_anchors': total_anchors,
            'total_tears': total_tears,
            'enabled': self.enabled,
            'wind_enabled': self.wind_enabled
        }
        
    def cleanup(self):
        """
        清理所有布料对象
        """
        for cloth_info in self.cloth_objects[:]:
            self.remove_cloth(cloth_info)
        self.cloth_objects.clear()
        print("✓ 布料管理器已清理")
        
    def _apply_cloth_parameters(self, soft_body: BulletSoftBodyNode, params: Dict[str, Any]):
        """
        应用布料参数到软体节点
        
        Args:
            soft_body: 软体节点
            params: 参数字典
        """
        cfg = soft_body.get_cfg()
        
        # 物理参数
        if 'linear_stiffness' in params:
            cfg.set_kDF(params['linear_stiffness'])
        if 'angular_stiffness' in params:
            cfg.set_kDG(params['angular_stiffness'])
        if 'volume_stiffness' in params:
            cfg.set_kVC(params['volume_stiffness'])
        if 'pressure_coefficient' in params:
            cfg.set_kPR(params['pressure_coefficient'])
        if 'drag_coefficient' in params:
            cfg.set_kDG(params['drag_coefficient'])
        if 'lift_coefficient' in params:
            cfg.set_kLF(params['lift_coefficient'])
        if 'cluster_hardness' in params:
            cfg.set_kCHR(params['cluster_hardness'])
        if 'kinetic_hardness' in params:
            cfg.set_kKHR(params['kinetic_hardness'])
        if 'soft_hardness' in params:
            cfg.set_kSHR(params['soft_hardness'])
        if 'anchor_hardness' in params:
            cfg.set_kAHR(params['anchor_hardness'])
            
        # 迭代次数
        if 'position_iteration' in params:
            cfg.set_piterations(params['position_iteration'])
        if 'drift_iteration' in params:
            cfg.set_diterations(params['drift_iteration'])
        if 'cluster_iteration' in params:
            cfg.set_citerations(params['cluster_iteration'])
        if 'velocity_iteration' in params:
            cfg.set_viterations(params['velocity_iteration'])
            
        # 材质属性
        if 'friction' in params:
            soft_body.setFriction(params['friction'])
        if 'restitution' in params:
            soft_body.setRestitution(params['restitution'])
        if 'density' in params:
            soft_body.setTotalMass(params['density'])
            
        # 集群
        if 'clusters' in params and params['clusters'] > 0:
            soft_body.generateClusters(params['clusters'])
            
    def _extract_mesh_data(self, node_path) -> Tuple[List[Point3], List[int]]:
        """
        从节点路径提取网格数据
        
        Args:
            node_path: 节点路径
            
        Returns:
            (顶点列表, 索引列表)
        """
        try:
            vertices = []
            indices = []
            
            # 查找几何节点
            geom_nodes = node_path.findAllMatches('**/+GeomNode')
            for geom_node_path in geom_nodes:
                geom_node = geom_node_path.node()
                for i in range(geom_node.getNumGeoms()):
                    geom = geom_node.getGeom(i)
                    vdata = geom.getVertexData()
                    
                    # 提取顶点
                    vertex_reader = GeomVertexReader(vdata, 'vertex')
                    while not vertex_reader.isAtEnd():
                        vertices.append(vertex_reader.getData3())
                        
                    # 提取索引
                    for prim in geom.getPrimitives():
                        index_reader = prim.getIndexIterator()
                        while not index_reader.isAtEnd():
                            indices.append(index_reader.getData())
                            index_reader.next()
                            
            return vertices, indices
            
        except Exception as e:
            print(f"⚠ 提取网格数据失败: {e}")
            return [], []
            
    def _add_links_from_indices(self, soft_body: BulletSoftBodyNode, indices: List[int]):
        """
        根据索引添加链接
        
        Args:
            soft_body: 软体节点
            indices: 索引列表
        """
        try:
            # 创建边集合以避免重复
            edges = set()
            
            # 从三角形面提取边
            for i in range(0, len(indices), 3):
                if i + 2 < len(indices):
                    # 三角形的三条边
                    edges.add(tuple(sorted([indices[i], indices[i+1]])))
                    edges.add(tuple(sorted([indices[i+1], indices[i+2]])))
                    edges.add(tuple(sorted([indices[i+2], indices[i]])))
                    
            # 添加链接
            for edge in edges:
                soft_body.appendLink(edge[0], edge[1])
                
        except Exception as e:
            print(f"⚠ 添加链接失败: {e}")
            
    def _add_bending_constraints(self, soft_body: BulletSoftBodyNode):
        """
        添加弯曲约束
        
        Args:
            soft_body: 软体节点
        """
        try:
            # 在实际实现中，这里会添加弯曲约束
            # BulletSoftBodyNode目前通过generateBendingConstraints方法添加
            soft_body.generateBendingConstraints(2)
            
        except Exception as e:
            print(f"⚠ 添加弯曲约束失败: {e}")
            
    def _apply_wind_force(self, cloth_info: Dict[str, Any]):
        """
        对布料应用风力
        
        Args:
            cloth_info: 布料对象信息
        """
        try:
            soft_body = cloth_info['soft_body']
            
            # 在实际实现中，这里会应用风力
            # BulletSoftBodyWorldInfo可以设置风力参数
            # 这里简化处理
            pass
            
        except Exception as e:
            print(f"⚠ 应用风力失败: {e}")
            
    def _check_tear_conditions(self, cloth_info: Dict[str, Any]):
        """
        检查撕裂条件
        
        Args:
            cloth_info: 布料对象信息
        """
        try:
            tear_mode = cloth_info['params'].get('tear_mode', 'none')
            if tear_mode == 'none':
                return
                
            tear_threshold = cloth_info['params'].get('tear_threshold', 100.0)
            # 在实际实现中，这里会检查撕裂条件
            # 由于BulletSoftBodyNode目前不直接支持撕裂，这里简化处理
            
        except Exception as e:
            print(f"⚠ 检查撕裂条件失败: {e}")
            
    def _get_physics_world(self):
        """
        获取物理世界对象
        
        Returns:
            物理世界对象或None
        """
        try:
            # 尝试从世界对象获取物理世界
            if hasattr(self.world, 'physics_world'):
                return self.world.physics_world.bullet_world
            elif hasattr(self.world, 'bullet_world'):
                return self.world.bullet_world
            else:
                # 查找物理插件
                physics_plugin = self.world.plugins.get('rigid_body_physics')
                if physics_plugin and hasattr(physics_plugin, 'physics_world'):
                    return physics_plugin.physics_world.bullet_world
        except Exception as e:
            print(f"⚠ 获取物理世界失败: {e}")
            
        return None