"""
流体可视化模块
负责流体的可视化渲染，包括粒子系统、表面网格、流线等
"""

from panda3d.core import Vec3, Point3, NodePath, Vec4, LVector3f
from panda3d.core import GeomVertexFormat, GeomVertexData, Geom, GeomVertexWriter, GeomTriangles
from panda3d.core import GeomNode, TransparencyAttrib, ColorAttrib
from panda3d.core import Texture, TexGenAttrib, Shader
from panda3d.core import PerspectiveLens, PointLight, AmbientLight
import math
import numpy as np
from scipy.spatial import cKDTree

class FluidVisualizer:
    """
    流体可视化类
    提供多种流体可视化方式
    """
    
    # 可视化模式
    VISUAL_MODE_PARTICLES = "particles"        # 粒子模式
    VISUAL_MODE_SURFACE_MESH = "surface_mesh"  # 表面网格模式
    VISUAL_MODE_SPLASH_MESH = "splash_mesh"    # 飞溅网格模式
    VISUAL_MODE_STREAMLINES = "streamlines"    # 流线模式
    VISUAL_MODE_VELOCITY_FIELD = "velocity_field"  # 速度场模式
    
    def __init__(self, fluid_world, world):
        """
        初始化流体可视化器
        
        Args:
            fluid_world: 流体世界对象的引用
            world: 主世界对象的引用
        """
        self.fluid_world = fluid_world
        self.world = world  # 主世界对象引用
        
        # 可视化设置
        self.visual_mode = self.VISUAL_MODE_PARTICLES
        self.particle_size = 2.0
        self.transparency = 0.8
        self.color = Vec4(0.0, 0.5, 1.0, 0.8)
        self.smoothing_radius = 1.0  # 用于表面重建的半径
        
        # 渲染节点
        self.fluid_nodes = []  # 所有流体相关节点
        self.particle_nodes = []  # 粒子节点
        self.surface_nodes = []  # 表面节点
        self.splash_nodes = []  # 飞溅节点
        self.streamline_nodes = []  # 流线节点
        self.velocity_field_nodes = []  # 速度场节点
        
        # 着色器
        self.surface_shader = None
        self.particle_shader = None
        
        # 表面重建参数
        self.surface_reconstruction_resolution = 64  # 用于网格重建的分辨率
        self.surface_isolevel = 0.5  # 等值面水平
        
        # 性能优化
        self.max_visible_particles = 10000  # 最大可见粒子数
        self.update_frequency = 60  # 更新频率
        self.frame_counter = 0
        
        # 材质设置
        self.roughness = 0.1
        self.metallic = 0.0
        self.specular = 0.9
        self.refraction_index = 1.33
        
        # 流体材质
        self.fluid_material = None
        
        print("流体可视化器初始化完成")
        
    def set_visual_mode(self, mode):
        """
        设置可视化模式
        
        Args:
            mode (str): 可视化模式
        """
        self.visual_mode = mode
        
    def set_particle_size(self, size):
        """
        设置粒子大小
        
        Args:
            size (float): 粒子大小
        """
        self.particle_size = size
        # 更新所有粒子节点
        for node in self.particle_nodes:
            # 在Panda3D中，粒子大小通常在粒子系统中设置
            pass
            
    def set_transparency(self, transparency):
        """
        设置透明度
        
        Args:
            transparency (float): 透明度值 (0-1)
        """
        self.transparency = max(0.0, min(1.0, transparency))
        # 更新所有节点的透明度
        for node in self.fluid_nodes:
            node.setTransparency(TransparencyAttrib.MAlpha)
            current_color = node.getColor()
            node.setColor(Vec4(current_color[0], current_color[1], current_color[2], self.transparency))
            
    def set_color(self, color):
        """
        设置流体颜色
        
        Args:
            color (Vec4): 颜色值 (RGBA)
        """
        self.color = Vec4(color[0], color[1], color[2], self.transparency)
        # 更新所有节点的颜色
        for node in self.fluid_nodes:
            node.setColor(self.color)
            
    def create_particle_visualization(self, name="fluid_particles", max_particles=2000):
        """
        创建粒子可视化
        
        Args:
            name (str): 节点名称
            max_particles (int): 最大粒子数
            
        Returns:
            NodePath: 粒子节点路径
        """
        # 在Panda3D中，我们需要使用几何体来表示粒子
        # 创建顶点数据格式
        format = GeomVertexFormat.getV3c4()  # 位置和颜色
        
        # 为每个粒子创建一个四边形面片（billboard）
        vdata = GeomVertexData(name, format, Geom.UHDynamic)  # 动态更新
        vdata.setNumRows(max_particles * 4)  # 每个粒子4个顶点
        
        vertex = GeomVertexWriter(vdata, 'vertex')
        color = GeomVertexWriter(vdata, 'color')
        
        # 为所有粒子添加初始顶点（简化：只添加一个粒子的顶点）
        for i in range(max_particles):
            # 每个粒子用一个点表示（实际上需要创建一个面片，但这里简化处理）
            # 真实实现中，我们需要为每个粒子创建一个面向摄像机的四边形
            pass
        
        # 创建几何体
        geom = Geom(vdata)
        
        # 创建几何节点
        geom_node = GeomNode(name)
        geom_node.addGeom(geom)
        
        # 创建节点路径
        node_path = self.world.render.attachNewNode(geom_node)
        
        # 设置渲染状态
        node_path.setTransparency(TransparencyAttrib.MAlpha)
        node_path.setColor(self.color)
        
        # 添加到管理系统
        self.particle_nodes.append(node_path)
        self.fluid_nodes.append(node_path)
        
        return node_path
        
    def create_surface_mesh(self, name="fluid_surface", resolution=32):
        """
        创建流体表面网格（使用Marching Cubes算法）
        
        Args:
            name (str): 网格名称
            resolution (int): 网格分辨率
            
        Returns:
            NodePath: 网格节点路径
        """
        # 创建体素网格用于表面重建
        self.surface_reconstruction_resolution = resolution
        
        # 创建顶点数据格式
        format = GeomVertexFormat.getV3n3c4()  # 位置、法线、颜色
        vdata = GeomVertexData(name, format, Geom.UHDynamic)
        
        # 预分配顶点（最坏情况下的顶点数）
        max_vertices = resolution * resolution * resolution * 5  # 估算值
        vdata.setNumRows(max_vertices)
        
        # 创建几何体
        geom = Geom(vdata)
        
        # 创建几何节点
        geom_node = GeomNode(name)
        geom_node.addGeom(geom)
        
        # 创建节点路径
        node_path = self.world.render.attachNewNode(geom_node)
        
        # 设置渲染状态
        node_path.setTransparency(TransparencyAttrib.MAlpha)
        node_path.setColor(self.color)
        
        # 添加材质属性
        node_path.setTwoSided(True)  # 双面渲染
        
        # 添加到管理系统
        self.surface_nodes.append(node_path)
        self.fluid_nodes.append(node_path)
        
        return node_path
        
    def create_splash_mesh(self, name="fluid_splash"):
        """
        创建流体飞溅效果网格
        
        Args:
            name (str): 网格名称
            
        Returns:
            NodePath: 网格节点路径
        """
        # 专门用于渲染飞溅和波纹效果的网格
        format = GeomVertexFormat.getV3n3c4t2()  # 位置、法线、颜色、纹理坐标
        vdata = GeomVertexData(name, format, Geom.UHDynamic)
        
        # 对于飞溅效果，我们可以使用较少的顶点
        vdata.setNumRows(1000)  # 预分配1000个顶点
        
        # 创建几何体
        geom = Geom(vdata)
        
        # 创建几何节点
        geom_node = GeomNode(name)
        geom_node.addGeom(geom)
        
        # 创建节点路径
        node_path = self.world.render.attachNewNode(geom_node)
        
        # 设置渲染状态
        node_path.setTransparency(TransparencyAttrib.MAlpha)
        node_path.setColor(self.color)
        
        # 添加到管理系统
        self.splash_nodes.append(node_path)
        self.fluid_nodes.append(node_path)
        
        return node_path
        
    def create_streamlines(self, name="fluid_streamlines", num_lines=50):
        """
        创建流线可视化
        
        Args:
            name (str): 流线名称
            num_lines (int): 流线数量
            
        Returns:
            NodePath: 流线节点路径
        """
        # 流线是显示流体流动方向的线
        format = GeomVertexFormat.getV3c4()  # 位置、颜色
        vdata = GeomVertexData(name, format, Geom.UHDynamic)
        
        # 每条流线最多100个点
        max_vertices = num_lines * 100
        vdata.setNumRows(max_vertices)
        
        # 创建几何体
        geom = Geom(vdata)
        
        # 创建几何节点
        geom_node = GeomNode(name)
        geom_node.addGeom(geom)
        
        # 创建节点路径
        node_path = self.world.render.attachNewNode(geom_node)
        
        # 设置渲染状态
        node_path.setTransparency(TransparencyAttrib.MAlpha)
        node_path.setColor(Vec4(1.0, 1.0, 0.0, 0.8))  # 黄色流线
        
        # 添加到管理系统
        self.streamline_nodes.append(node_path)
        self.fluid_nodes.append(node_path)
        
        return node_path
        
    def create_velocity_field(self, name="fluid_velocity_field", grid_density=10):
        """
        创建速度场可视化
        
        Args:
            name (str): 速度场名称
            grid_density (int): 网格密度
            
        Returns:
            NodePath: 速度场节点路径
        """
        # 速度场显示流体中各点的速度方向和大小
        format = GeomVertexFormat.getV3c4()  # 位置、颜色
        vdata = GeomVertexData(name, format, Geom.UHDynamic)
        
        # 3D网格，每条线2个点
        max_vertices = grid_density * grid_density * grid_density * 2
        vdata.setNumRows(max_vertices)
        
        # 创建几何体
        geom = Geom(vdata)
        
        # 创建几何节点
        geom_node = GeomNode(name)
        geom_node.addGeom(geom)
        
        # 创建节点路径
        node_path = self.world.render.attachNewNode(geom_node)
        
        # 设置渲染状态
        node_path.setTransparency(TransparencyAttrib.MAlpha)
        node_path.setColor(Vec4(1.0, 0.0, 0.0, 0.8))  # 红色速度向量
        
        # 添加到管理系统
        self.velocity_field_nodes.append(node_path)
        self.fluid_nodes.append(node_path)
        
        return node_path
        
    def update_visualization(self, dt):
        """
        更新流体可视化
        
        Args:
            dt (float): 时间步长
        """
        self.frame_counter += 1
        
        # 根据可视化模式更新相应的可视化组件
        if self.visual_mode == self.VISUAL_MODE_PARTICLES:
            self._update_particle_visualization()
        elif self.visual_mode == self.VISUAL_MODE_SURFACE_MESH:
            self._update_surface_mesh()
        elif self.visual_mode == self.VISUAL_MODE_SPLASH_MESH:
            self._update_splash_mesh()
        elif self.visual_mode == self.VISUAL_MODE_STREAMLINES:
            self._update_streamlines()
        elif self.visual_mode == self.VISUAL_MODE_VELOCITY_FIELD:
            self._update_velocity_field()
        else:
            # 默认更新粒子可视化
            self._update_particle_visualization()
            
    def _update_particle_visualization(self):
        """
        更新粒子可视化
        """
        if not self.fluid_world.fluid_particles or not self.particle_nodes:
            return
            
        # 限制更新的粒子数量以提高性能
        particles_to_update = min(len(self.fluid_world.fluid_particles), 
                                 self.max_visible_particles)
        
        for node in self.particle_nodes:
            # 获取几何体
            geom = node.node().getGeom(0)
            vdata = geom.modifyVertexData()
            
            # 获取顶点写入器
            vertex = GeomVertexWriter(vdata, 'vertex')
            
            # 更新粒子位置（这里简化处理，实际需要为每个粒子创建面片）
            for i in range(min(particles_to_update, vdata.getNumRows() // 4)):
                particle = self.fluid_world.fluid_particles[i]
                pos = particle['position']
                
                # 为粒子创建一个面向摄像机的四边形（简化为单个点）
                # 在真实实现中，这里需要创建billboard四边形
                vertex.setData3f(pos)
                
    def _update_surface_mesh(self):
        """
        更新表面网格（使用Marching Cubes算法）
        """
        if not self.fluid_world.fluid_particles or not self.surface_nodes:
            return
            
        # 创建密度场
        resolution = self.surface_reconstruction_resolution
        density_grid = self._create_density_grid(resolution)
        
        # 使用Marching Cubes算法生成网格
        vertices, triangles = self._marching_cubes(density_grid, self.surface_isolevel)
        
        # 更新几何体
        if vertices and triangles and self.surface_nodes:
            node = self.surface_nodes[0]  # 使用第一个表面节点
            geom = node.node().getGeom(0)
            vdata = geom.modifyVertexData()
            
            # 确保有足够的行数
            if vdata.getNumRows() < len(vertices) * 3:  # 位置、法线、颜色
                vdata.setNumRows(len(vertices) * 3)
                
            vertex_writer = GeomVertexWriter(vdata, 'vertex')
            normal_writer = GeomVertexWriter(vdata, 'normal')
            color_writer = GeomVertexWriter(vdata, 'color')
            
            # 写入顶点数据
            for v in vertices:
                vertex_writer.setData3f(v[0], v[1], v[2])
                # 这里应该计算法线，简化为(0,0,1)
                normal_writer.setData3f(0, 0, 1)
                color_writer.setData4f(self.color)
                
            # 更新图元
            prim = GeomTriangles(Geom.UHDynamic)
            for t in triangles:
                prim.addVertices(t[0], t[1], t[2])
            prim.closePrimitive()
            
            # 替换旧的图元
            geom.removePrimitive(0)
            geom.addPrimitive(prim)
            
    def _create_density_grid(self, resolution):
        """
        创建流体密度网格用于表面重建
        
        Args:
            resolution (int): 网格分辨率
            
        Returns:
            numpy.ndarray: 3D密度网格
        """
        if not self.fluid_world.fluid_particles:
            return np.zeros((resolution, resolution, resolution))
            
        # 确定网格边界
        min_bound = Point3(float('inf'), float('inf'), float('inf'))
        max_bound = Point3(float('-inf'), float('-inf'), float('-inf'))
        
        for particle in self.fluid_world.fluid_particles:
            pos = particle['position']
            min_bound.setX(min(min_bound.getX(), pos.getX()))
            min_bound.setY(min(min_bound.getY(), pos.getY()))
            min_bound.setZ(min(min_bound.getZ(), pos.getZ()))
            max_bound.setX(max(max_bound.getX(), pos.getX()))
            max_bound.setY(max(max_bound.getY(), pos.getY()))
            max_bound.setZ(max(max_bound.getZ(), pos.getZ()))
            
        # 添加边界填充
        padding = self.smoothing_radius
        min_bound -= Vec3(padding, padding, padding)
        max_bound += Vec3(padding, padding, padding)
        
        # 创建密度网格
        grid = np.zeros((resolution, resolution, resolution), dtype=np.float32)
        
        # 计算网格步长
        step_x = (max_bound.getX() - min_bound.getX()) / resolution
        step_y = (max_bound.getY() - min_bound.getY()) / resolution
        step_z = (max_bound.getZ() - min_bound.getZ()) / resolution
        
        # 对每个粒子贡献到网格
        for particle in self.fluid_world.fluid_particles:
            pos = particle['position']
            
            # 计算粒子在网格中的位置
            grid_x = int((pos.getX() - min_bound.getX()) / step_x)
            grid_y = int((pos.getY() - min_bound.getY()) / step_y)
            grid_z = int((pos.getZ() - min_bound.getZ()) / step_z)
            
            # 确保索引在范围内
            if 0 <= grid_x < resolution and 0 <= grid_y < resolution and 0 <= grid_z < resolution:
                # 使用SPH核函数计算密度贡献
                for dx in range(-2, 3):
                    for dy in range(-2, 3):
                        for dz in range(-2, 3):
                            nx, ny, nz = grid_x + dx, grid_y + dy, grid_z + dz
                            if 0 <= nx < resolution and 0 <= ny < resolution and 0 <= nz < resolution:
                                # 计算网格点的实际位置
                                gx = min_bound.getX() + nx * step_x
                                gy = min_bound.getY() + ny * step_y
                                gz = min_bound.getZ() + nz * step_z
                                
                                # 计算距离
                                dist = math.sqrt((gx - pos.getX())**2 + 
                                               (gy - pos.getY())**2 + 
                                               (gz - pos.getZ())**2)
                                               
                                if dist < self.smoothing_radius:
                                    # 使用核函数
                                    kernel_value = self._sph_kernel(dist)
                                    grid[nz, ny, nx] += kernel_value
        
        return grid
        
    def _sph_kernel(self, r):
        """
        SPH核函数 (Poly6 kernel)
        
        Args:
            r (float): 距离
            
        Returns:
            float: 核函数值
        """
        if r >= self.smoothing_radius:
            return 0.0
            
        h = self.smoothing_radius
        coefficient = 315.0 / (64.0 * math.pi * h**9)
        return coefficient * (h*h - r*r)**3
        
    def _marching_cubes(self, density_grid, isolevel):
        """
        Marching Cubes算法生成等值面网格
        
        Args:
            density_grid (numpy.ndarray): 3D密度网格
            isolevel (float): 等值面水平
            
        Returns:
            tuple: (vertices, triangles)
        """
        # 这是一个简化的Marching Cubes实现
        # 实际应用中可能需要更完整的实现
        vertices = []
        triangles = []
        
        shape = density_grid.shape
        for z in range(shape[0] - 1):
            for y in range(shape[1] - 1):
                for x in range(shape[2] - 1):
                    # 获取立方体8个角点的密度值
                    cube = [
                        density_grid[z, y, x],
                        density_grid[z, y, x+1],
                        density_grid[z, y+1, x+1],
                        density_grid[z, y+1, x],
                        density_grid[z+1, y, x],
                        density_grid[z+1, y, x+1],
                        density_grid[z+1, y+1, x+1],
                        density_grid[z+1, y+1, x]
                    ]
                    
                    # 检查是否与等值面相交
                    bits = 0
                    for i, value in enumerate(cube):
                        if value > isolevel:
                            bits |= (1 << i)
                            
                    # 如果相交，生成三角形（这里使用预定义的配置表）
                    # 为了简化，我们只生成一个示例三角形
                    if bits != 0 and bits != 0xFF:
                        # 在实际实现中，这里会根据bits值查找预定义的三角形配置
                        # 并在边的交点处插入顶点
                        center_x = x + 0.5
                        center_y = y + 0.5
                        center_z = z + 0.5
                        vertices.append([center_x, center_y, center_z])
                        triangles.append([len(vertices)-1, len(vertices)-1, len(vertices)-1])
        
        return vertices, triangles
        
    def _update_splash_mesh(self):
        """
        更新飞溅网格
        """
        # 飞溅效果通常在高流速或碰撞区域显示
        if not self.fluid_world.fluid_particles or not self.splash_nodes:
            return
            
        # 检测高流速粒子（可能产生飞溅）
        splash_particles = []
        for particle in self.fluid_world.fluid_particles:
            if particle['velocity'].length() > 5.0:  # 速度阈值
                splash_particles.append(particle)
                
        # 更新飞溅几何体
        if splash_particles and self.splash_nodes:
            node = self.splash_nodes[0]
            geom = node.node().getGeom(0)
            vdata = geom.modifyVertexData()
            
            if vdata.getNumRows() < len(splash_particles) * 4:  # 预分配
                vdata.setNumRows(len(splash_particles) * 4)
                
            vertex_writer = GeomVertexWriter(vdata, 'vertex')
            color_writer = GeomVertexWriter(vdata, 'color')
            
            for particle in splash_particles:
                pos = particle['position']
                # 创建一个小的四边形代表飞溅
                size = 0.2
                vertex_writer.setData3f(pos.getX() - size, pos.getY() - size, pos.getZ())
                vertex_writer.setData3f(pos.getX() + size, pos.getY() - size, pos.getZ())
                vertex_writer.setData3f(pos.getX() + size, pos.getY() + size, pos.getZ())
                vertex_writer.setData3f(pos.getX() - size, pos.getY() + size, pos.getZ())
                
                # 飞溅使用更亮的颜色
                splash_color = Vec4(1.0, 1.0, 1.0, self.transparency)
                for _ in range(4):
                    color_writer.setData4f(splash_color)
                    
    def _update_streamlines(self):
        """
        更新流线
        """
        if not self.fluid_world.fluid_particles or not self.streamline_nodes:
            return
            
        # 简化的流线更新
        # 在实际实现中，这将追踪流体中的轨迹线
        if self.streamline_nodes:
            node = self.streamline_nodes[0]
            geom = node.node().getGeom(0)
            vdata = geom.modifyVertexData()
            
            # 创建一些示例流线
            if len(self.fluid_world.fluid_particles) > 0:
                # 使用前几个粒子作为流线起点
                for i in range(min(10, len(self.fluid_world.fluid_particles))):
                    particle = self.fluid_world.fluid_particles[i]
                    start_pos = particle['position']
                    end_pos = start_pos + particle['velocity'] * 0.1  # 简化的方向线
                    
                    vertex_writer = GeomVertexWriter(vdata, 'vertex')
                    color_writer = GeomVertexWriter(vdata, 'color')
                    
                    vertex_writer.setData3f(start_pos)
                    vertex_writer.setData3f(end_pos)
                    
                    color_writer.setData4f(Vec4(1.0, 1.0, 0.0, self.transparency))
                    color_writer.setData4f(Vec4(1.0, 1.0, 0.0, self.transparency))
                    
    def _update_velocity_field(self):
        """
        更新速度场
        """
        if not self.fluid_world.fluid_particles or not self.velocity_field_nodes:
            return
            
        # 创建规则网格上的速度向量
        if self.velocity_field_nodes:
            node = self.velocity_field_nodes[0]
            geom = node.node().getGeom(0)
            vdata = geom.modifyVertexData()
            
            # 简化的速度场显示
            if len(self.fluid_world.fluid_particles) > 0:
                # 显示部分粒子的速度向量
                step = max(1, len(self.fluid_world.fluid_particles) // 20)  # 限制显示数量
                
                vertex_writer = GeomVertexWriter(vdata, 'vertex')
                color_writer = GeomVertexWriter(vdata, 'color')
                
                for i in range(0, len(self.fluid_world.fluid_particles), step):
                    if i >= len(self.fluid_world.fluid_particles):
                        break
                        
                    particle = self.fluid_world.fluid_particles[i]
                    pos = particle['position']
                    vel = particle['velocity']
                    
                    # 标准化速度向量以便可视化
                    normalized_vel = vel.normalized() * 0.5  # 缩放以便可视化
                    
                    # 创建速度向量线段
                    start_pos = pos
                    end_pos = pos + normalized_vel
                    
                    vertex_writer.setData3f(start_pos)
                    vertex_writer.setData3f(end_pos)
                    
                    # 根据速度大小设置颜色
                    speed = vel.length()
                    speed_color = min(1.0, speed / 10.0)  # 假设最大速度为10
                    color = Vec4(speed_color, 0.0, 1.0 - speed_color, self.transparency)
                    
                    color_writer.setData4f(color)
                    color_writer.setData4f(color)
                    
    def set_material_properties(self, roughness=None, metallic=None, specular=None, refraction_index=None):
        """
        设置流体材质属性
        
        Args:
            roughness (float): 粗糙度
            metallic (float): 金属度
            specular (float): 镜面反射
            refraction_index (float): 折射率
        """
        if roughness is not None:
            self.roughness = max(0.0, min(1.0, roughness))
        if metallic is not None:
            self.metallic = max(0.0, min(1.0, metallic))
        if specular is not None:
            self.specular = max(0.0, min(1.0, specular))
        if refraction_index is not None:
            self.refraction_index = max(1.0, refraction_index)
            
        # 应用到所有节点
        for node in self.fluid_nodes:
            # 在Panda3D中，这些属性通常通过着色器或材质节点应用
            pass
            
    def set_surface_reconstruction_params(self, resolution=None, isolevel=None):
        """
        设置表面重建参数
        
        Args:
            resolution (int): 重建分辨率
            isolevel (float): 等值面水平
        """
        if resolution is not None:
            self.surface_reconstruction_resolution = resolution
        if isolevel is not None:
            self.surface_isolevel = isolevel
            
    def set_performance_params(self, max_visible_particles=None, update_frequency=None):
        """
        设置性能参数
        
        Args:
            max_visible_particles (int): 最大可见粒子数
            update_frequency (int): 更新频率
        """
        if max_visible_particles is not None:
            self.max_visible_particles = max_visible_particles
        if update_frequency is not None:
            self.update_frequency = update_frequency
            
    def get_visualization_stats(self):
        """
        获取可视化统计信息
        
        Returns:
            dict: 统计信息
        """
        stats = {
            'active_nodes': len(self.fluid_nodes),
            'particle_nodes': len(self.particle_nodes),
            'surface_nodes': len(self.surface_nodes),
            'splash_nodes': len(self.splash_nodes),
            'streamline_nodes': len(self.streamline_nodes),
            'velocity_field_nodes': len(self.velocity_field_nodes),
            'visual_mode': self.visual_mode,
            'particle_count': len(self.fluid_world.fluid_particles) if self.fluid_world else 0
        }
        
        return stats
        
    def cleanup(self):
        """
        清理可视化资源
        """
        # 清理所有节点
        for node_list in [self.fluid_nodes, self.particle_nodes, self.surface_nodes,
                         self.splash_nodes, self.streamline_nodes, self.velocity_field_nodes]:
            for node in node_list:
                node.removeNode()
            node_list.clear()
            
        # 清空总节点列表
        self.fluid_nodes.clear()
        
        print("流体可视化资源已清理")