zhong (钟鹏群) 1 mesiac pred
rodič
commit
cc138b77f6
2 zmenil súbory, kde vykonal 251 pridanie a 21 odobranie
  1. BIN
      __pycache__/ball-demo.cpython-310.pyc
  2. 251 21
      ball-demo.py

BIN
__pycache__/ball-demo.cpython-310.pyc


+ 251 - 21
ball-demo.py

@@ -1,6 +1,13 @@
 import pygame
 import math
 import time
+import os
+try:
+    import pyperclip
+    clipboard_available = True
+except ImportError:
+    clipboard_available = False
+    print("警告: pyperclip 模块未安装,剪贴板功能不可用。请运行 'pip install pyperclip' 安装。")
 
 from pygame.locals import *
 from OpenGL.GL import *
@@ -41,47 +48,270 @@ gluPerspective(45, (width/height), 0.1, 50.0)
 # 移动相机
 glTranslatef(0.0, 0.0, -5)
 
-# 旋转角度
-angle = 0.0
+def build_directory_tree(root_path, max_depth=3, max_children_per_node=30):
+    # 递归扫描目录树
+    nodes = []  # 每个节点: (name, is_dir, parent_id, depth)
+    edges = []  # (parent_id, child_id)
+    
+    # 递归扫描函数
+    def scan_directory(current_path, parent_id, depth):
+        if depth >= max_depth:
+            return
+        
+        try:
+            entries = os.listdir(current_path)
+        except (PermissionError, FileNotFoundError):
+            return
+        
+        # 过滤掉一些不需要的目录
+        filtered_entries = []
+        for entry in entries:
+            # 过滤常见的版本控制和IDE目录
+            if entry in ['.git', '.vscode', '.idea', 'node_modules', '__pycache__']:
+                continue
+            filtered_entries.append(entry)
+        
+        # 限制每个节点的最大子项数量
+        filtered_entries = filtered_entries[:max_children_per_node]
+        
+        # 当前目录的节点ID:根节点为0,其他目录为parent_id
+        current_node_id = 0 if parent_id == -1 else parent_id
+        
+        for entry in filtered_entries:
+            entry_path = os.path.join(current_path, entry)
+            is_dir = os.path.isdir(entry_path)
+            
+            # 添加子节点
+            child_id = len(nodes)
+            nodes.append((entry, is_dir, current_node_id, depth + 1, entry_path))
+            edges.append((current_node_id, child_id))
+            
+            # 如果是目录,递归扫描
+            if is_dir:
+                scan_directory(entry_path, child_id, depth + 1)
+    
+    # 添加根节点
+    root_name = os.path.basename(root_path.rstrip('\\'))
+    nodes.append((root_name, True, -1, 0, root_path))
+    
+    # 从根节点开始递归扫描
+    scan_directory(root_path, -1, 0)
+    
+    # 计算节点位置
+    positions = []
+    for i in range(len(nodes)):
+        positions.append([0.0, 0.0, 0.0])  # 初始位置
+    
+    # 构建子节点列表
+    children = [[] for _ in range(len(nodes))]
+    for edge in edges:
+        parent_id, child_id = edge
+        children[parent_id].append(child_id)
+    
+    # 计算最大深度
+    max_depth_found = 0
+    for node in nodes:
+        max_depth_found = max(max_depth_found, node[3])
+    
+    # 递归计算位置
+    def calculate_positions(node_id, start_angle, end_angle, depth):
+        if depth > max_depth_found:
+            return
+        
+        # 计算当前节点位置
+        if node_id == 0:  # 根节点
+            positions[node_id] = [0.0, max_depth_found * 0.8, 0.0]  # 顶部
+        else:
+            parent_id = nodes[node_id][2]
+            if parent_id >= 0:
+                # 子节点围绕父节点在圆上分布
+                child_index = children[parent_id].index(node_id)
+                num_siblings = len(children[parent_id])
+                
+                # 计算角度(在父节点周围的圆上)
+                angle = start_angle + (end_angle - start_angle) * (child_index / max(num_siblings, 1))
+                
+                # 半径随深度减小
+                radius = 1.5 * (0.75 ** depth)  # 深度越大,半径越小
+                
+                # 计算位置
+                px, py, pz = positions[parent_id]
+                x = px + radius * math.cos(angle)
+                y = py - 1.3  # 每层向下移动
+                z = pz + radius * math.sin(angle)
+                
+                positions[node_id] = [x, y, z]
+        
+        # 为子节点递归计算位置
+        node_children = children[node_id]
+        if node_children:
+            # 计算子节点的角度范围
+            angle_range = math.pi * 1.5  # 270度范围
+            angle_start = -angle_range / 2
+            angle_step = angle_range / len(node_children)
+            
+            for i, child_id in enumerate(node_children):
+                child_angle_start = angle_start + i * angle_step
+                child_angle_end = angle_start + (i + 1) * angle_step
+                calculate_positions(child_id, child_angle_start, child_angle_end, depth + 1)
+    
+    # 从根节点开始计算位置
+    calculate_positions(0, -math.pi, math.pi, 0)
+    
+    return nodes, edges, positions, children
+
+# 构建目录树
+root_path = "E:\\agricultural_research_platform"
+tree_nodes, tree_edges, node_positions, tree_children = build_directory_tree(root_path)
+
+# 初始化选中节点(根节点)
+selected_node_index = 0
+
+# 剪贴板相关变量
+clipboard_content = ""
+clipboard_check_time = 0
+blinking_nodes = set()
+file_content_cache = {}
+blink_start_time = pygame.time.get_ticks()
 
 # 主循环
 running = True
 while running:
+    # 获取当前时间(用于闪烁效果)
+    current_time = pygame.time.get_ticks()
+    
+    # 检查剪贴板内容是否变化(如果剪贴板功能可用)
+    if clipboard_available:
+        if current_time - clipboard_check_time > 1000:  # 每秒检查一次
+            clipboard_check_time = current_time
+            try:
+                new_clipboard_content = pyperclip.paste()
+                if new_clipboard_content != clipboard_content:
+                    clipboard_content = new_clipboard_content
+                    # 剪贴板内容变化,重新检查所有文件节点
+                    blinking_nodes.clear()
+                    if clipboard_content.strip():  # 剪贴板非空
+                        for i, (name, is_dir, parent_id, depth, full_path) in enumerate(tree_nodes):
+                            if not is_dir:  # 文件节点
+                                # 检查文件内容是否包含剪贴板文本
+                                try:
+                                    # 从缓存读取或加载文件内容
+                                    if i not in file_content_cache:
+                                        with open(full_path, 'r', encoding='utf-8', errors='ignore') as f:
+                                            file_content_cache[i] = f.read()
+                                    file_content = file_content_cache[i]
+                                    if clipboard_content in file_content:
+                                        blinking_nodes.add(i)
+                                except Exception as e:
+                                    pass  # 忽略读取错误
+            except Exception as e:
+                pass  # 忽略剪贴板访问错误
+    
     # 处理事件
     for event in pygame.event.get():
         if event.type == pygame.QUIT:
             running = False
+        elif event.type == pygame.KEYDOWN:
+            # 获取当前节点信息
+            current_node = tree_nodes[selected_node_index]
+            current_parent_id = current_node[2]
+            current_depth = current_node[3]
+            
+            if event.key == pygame.K_UP:  # 上键:移动到父节点
+                if current_parent_id >= 0:  # 有父节点
+                    selected_node_index = current_parent_id
+            elif event.key == pygame.K_DOWN:  # 下键:移动到第一个子节点
+                if tree_children[selected_node_index]:  # 有子节点
+                    selected_node_index = tree_children[selected_node_index][0]
+            elif event.key == pygame.K_LEFT:  # 左键:移动到前一个兄弟节点
+                if current_parent_id >= 0:  # 有父节点
+                    siblings = tree_children[current_parent_id]
+                    if len(siblings) > 1:
+                        current_index_in_siblings = siblings.index(selected_node_index)
+                        # 移动到前一个兄弟,如果当前是第一个则移动到最后一个
+                        new_index = (current_index_in_siblings - 1) % len(siblings)
+                        selected_node_index = siblings[new_index]
+            elif event.key == pygame.K_RIGHT:  # 右键:移动到后一个兄弟节点
+                if current_parent_id >= 0:  # 有父节点
+                    siblings = tree_children[current_parent_id]
+                    if len(siblings) > 1:
+                        current_index_in_siblings = siblings.index(selected_node_index)
+                        # 移动到后一个兄弟,如果当前是最后一个则移动到第一个
+                        new_index = (current_index_in_siblings + 1) % len(siblings)
+                        selected_node_index = siblings[new_index]
     
     # 清除屏幕
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
     
-    # 旋转整个场景
-    glRotatef(1, 1, 1, 1)
+    # 目录树可视化
+    ball_radius = 0.0667  # 节点球的半径(原来的1/3)
     
-    # 黄色材质(完整设置)
-    yellow = [1.0, 1.0, 0.0, 1.0]
-    yellow_ambient = [0.3, 0.3, 0.0, 1.0]
-    yellow_specular = [1.0, 1.0, 0.5, 1.0]
-    shininess = [50.0]
+    # 绘制所有连线(目录树边)
+    glDisable(GL_LIGHTING)  # 禁用光照以使用纯色
+    glColor3f(1.0, 1.0, 1.0)  # 白色连线
+    glLineWidth(2.0)
     
-    glMaterialfv(GL_FRONT, GL_AMBIENT, yellow_ambient)
-    glMaterialfv(GL_FRONT, GL_DIFFUSE, yellow)
-    glMaterialfv(GL_FRONT, GL_SPECULAR, yellow_specular)
-    glMaterialfv(GL_FRONT, GL_SHININESS, shininess)
+    glBegin(GL_LINES)
+    for edge in tree_edges:
+        node1_idx, node2_idx = edge
+        x1, y1, z1 = node_positions[node1_idx]
+        x2, y2, z2 = node_positions[node2_idx]
+        glVertex3f(x1, y1, z1)
+        glVertex3f(x2, y2, z2)
+    glEnd()
     
-    # 创建二次曲面 → 画光滑球
-    quad = gluNewQuadric()
-    gluQuadricNormals(quad, GLU_SMOOTH)
-    gluSphere(quad, 1.0, 50, 50)
-    gluDeleteQuadric(quad)
+    glEnable(GL_LIGHTING)  # 重新启用光照
+    
+    # 绘制所有节点球(根据类型使用不同颜色)
+    for i, (name, is_dir, parent_id, depth, full_path) in enumerate(tree_nodes):
+        x, y, z = node_positions[i]
+        
+        # 根据节点类型设置材质颜色(选中节点显示为红色)
+        if i in blinking_nodes:  # 闪烁节点
+            # 计算闪烁因子(正弦波,周期约2秒)
+            blink_factor = (math.sin((current_time - blink_start_time) * 0.005) + 1) * 0.5
+            # 颜色在黄色(1,1,0)和红色(1,0,0)之间变化
+            color = [1.0, blink_factor, 0.0, 1.0]
+            ambient = [0.3, blink_factor * 0.3, 0.0, 1.0]
+            specular = [1.0, blink_factor * 0.5, 0.5, 1.0]
+        elif i == selected_node_index:  # 选中节点
+            color = [1.0, 0.0, 0.0, 1.0]  # 红色
+            ambient = [0.3, 0.0, 0.0, 1.0]
+            specular = [1.0, 0.5, 0.5, 1.0]
+        elif i == 0:  # 根节点
+            color = [1.0, 1.0, 0.0, 1.0]  # 黄色
+            ambient = [0.3, 0.3, 0.0, 1.0]
+            specular = [1.0, 1.0, 0.5, 1.0]
+        elif is_dir:  # 目录
+            color = [0.0, 0.5, 1.0, 1.0]  # 蓝色
+            ambient = [0.0, 0.2, 0.3, 1.0]
+            specular = [0.5, 0.7, 1.0, 1.0]
+        else:  # 文件
+            color = [0.0, 0.8, 1.0, 1.0]  # 亮蓝色
+            ambient = [0.0, 0.1, 0.2, 1.0]
+            specular = [0.6, 0.9, 1.0, 1.0]
+        
+        shininess = [50.0]
+        
+        glMaterialfv(GL_FRONT, GL_AMBIENT, ambient)
+        glMaterialfv(GL_FRONT, GL_DIFFUSE, color)
+        glMaterialfv(GL_FRONT, GL_SPECULAR, specular)
+        glMaterialfv(GL_FRONT, GL_SHININESS, shininess)
+        
+        glPushMatrix()
+        glTranslatef(x, y, z)
+        quad = gluNewQuadric()
+        gluQuadricNormals(quad, GLU_SMOOTH)
+        # 根据深度调整球体大小:深度越大,球体越小
+        current_radius = ball_radius * (0.85 ** depth)
+        gluSphere(quad, current_radius, 32, 32)
+        gluDeleteQuadric(quad)
+        glPopMatrix()
     
     # 交换缓冲区
     pygame.display.flip()
     # 控制帧率
     pygame.time.wait(10)
-    
-    # 更新角度
-    angle += 1
 
 # 退出 Pygame
 pygame.quit()