#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 跨平台路径处理工具 """ import os import platform from pathlib import Path from panda3d.core import Filename class CrossPlatformPathHandler: """跨平台路径处理器""" def __init__(self): self.system = platform.system() self.is_windows = self.system == "Windows" self.is_linux = self.system == "Linux" self.is_mac = self.system == "Darwin" print(f"路径处理器初始化 - 系统: {self.system}") def normalize_model_path(self, filepath): """标准化模型文件路径""" try: #print(f"\n=== 路径标准化处理 ===") #print(f"原始路径: {filepath}") #print(f"当前系统: {self.system}") # 步骤1: 检查原始路径是否存在 if self._check_file_exists(filepath): return self._panda3d_normalize(filepath) # 步骤2: 路径修复尝试 fixed_path = self._attempt_path_fixes(filepath) if fixed_path: return self._panda3d_normalize(fixed_path) # 步骤3: 智能搜索 found_path = self._smart_file_search(filepath) if found_path: return self._panda3d_normalize(found_path) # 步骤4: 用户友好的错误处理 self._handle_path_not_found(filepath) return filepath except Exception as e: print(f"❌ 路径标准化失败: {e}") return filepath def _check_file_exists(self, filepath): """检查文件是否存在""" exists = os.path.exists(filepath) return exists def _panda3d_normalize(self, filepath): """使用Panda3D标准化路径""" try: panda_filename = Filename.from_os_specific(filepath) normalized_path = panda_filename.get_fullpath() print(f"✓ Panda3D标准化: {normalized_path}") return normalized_path except Exception as e: print(f"⚠️ Panda3D标准化失败: {e}") return filepath def _attempt_path_fixes(self, filepath): """尝试各种路径修复方法""" print("🔧 尝试路径修复...") # 修复方法1: 处理Windows/Linux路径分隔符 fixed_path = self._fix_path_separators(filepath) if fixed_path and self._check_file_exists(fixed_path): return fixed_path # 修复方法2: 处理绝对路径到相对路径的转换 relative_path = self._convert_to_relative_path(filepath) if relative_path and self._check_file_exists(relative_path): return relative_path # 修复方法3: 处理路径中的特殊字符 cleaned_path = self._clean_special_characters(filepath) if cleaned_path and self._check_file_exists(cleaned_path): return cleaned_path return None def _fix_path_separators(self, filepath): """修复路径分隔符""" try: if self.is_windows: # Windows: 将正斜杠转换为反斜杠 fixed = filepath.replace('/', '\\') else: # Linux/Mac: 将反斜杠转换为正斜杠 fixed = filepath.replace('\\', '/') if fixed != filepath: print(f" 路径分隔符修复: {fixed}") return fixed return None except Exception as e: print(f" 路径分隔符修复失败: {e}") return None def _convert_to_relative_path(self, filepath): """转换绝对路径为相对路径""" try: # 如果是绝对路径,尝试转换为相对路径 if os.path.isabs(filepath): filename = os.path.basename(filepath) print(f" 尝试相对路径: {filename}") return filename return None except Exception as e: print(f" 相对路径转换失败: {e}") return None def _clean_special_characters(self, filepath): """清理路径中的特殊字符""" try: # 处理路径中的特殊字符(如中文路径中的+号) import urllib.parse # URL解码 decoded = urllib.parse.unquote(filepath) if decoded != filepath: print(f" URL解码: {decoded}") return decoded return None except Exception as e: print(f" 特殊字符清理失败: {e}") return None def _smart_file_search(self, filepath): """智能文件搜索""" print("🔍 开始智能文件搜索...") filename = os.path.basename(filepath) print(f" 搜索文件名: {filename}") # 搜索策略1: 在常见目录中搜索 found_path = self._search_in_common_directories(filename) if found_path: return found_path # 搜索策略2: 递归搜索当前目录 found_path = self._recursive_search(filename) if found_path: return found_path # 搜索策略3: 搜索用户常用目录 found_path = self._search_user_directories(filename) if found_path: return found_path return None def _search_in_common_directories(self, filename): """在常见目录中搜索""" common_dirs = [ "models", "assets", "assets/models", "resources", "data", "scene", ".", "..", "../models", "../assets" ] for directory in common_dirs: if os.path.exists(directory): potential_path = os.path.join(directory, filename) if os.path.exists(potential_path): print(f" ✓ 在常见目录中找到: {potential_path}") return potential_path return None def _recursive_search(self, filename, max_depth=3): """递归搜索文件""" try: current_depth = 0 for root, dirs, files in os.walk("."): # 限制搜索深度 depth = root.replace(".", "").count(os.sep) if depth > max_depth: continue if filename in files: found_path = os.path.join(root, filename) print(f" ✓ 递归搜索找到: {found_path}") return found_path return None except Exception as e: print(f" 递归搜索失败: {e}") return None def _search_user_directories(self, filename): """搜索用户常用目录""" try: user_dirs = [] if self.is_windows: # Windows常用目录 user_dirs.extend([ os.path.expanduser("~/Desktop"), os.path.expanduser("~/Documents"), "C:/模型", "D:/模型", "E:/模型" ]) else: # Linux/Mac常用目录 user_dirs.extend([ os.path.expanduser("~/Desktop"), os.path.expanduser("~/Documents"), os.path.expanduser("~/models"), "/tmp", "/var/tmp" ]) for directory in user_dirs: if os.path.exists(directory): potential_path = os.path.join(directory, filename) if os.path.exists(potential_path): print(f" ✓ 在用户目录中找到: {potential_path}") return potential_path return None except Exception as e: print(f" 用户目录搜索失败: {e}") return None def _handle_path_not_found(self, filepath): """处理路径未找到的情况""" print(f"\n❌ 无法找到文件: {filepath}") print("💡 建议解决方案:") print("1. 检查文件路径是否正确") print("2. 确保文件确实存在") print("3. 尝试使用相对路径而不是绝对路径") print("4. 检查文件名中是否包含特殊字符") print("5. 将模型文件复制到项目的 models/ 目录下") # 显示当前工作目录 print(f"当前工作目录: {os.getcwd()}") # 显示Panda3D模型搜索路径 try: from panda3d.core import getModelPath model_path = getModelPath() print(f"Panda3D模型搜索路径: {model_path}") except: pass def suggest_file_placement(self, filename): """建议文件放置位置""" suggestions = [] # 创建推荐的目录结构 recommended_dirs = ["models", "assets/models", "resources"] for directory in recommended_dirs: if not os.path.exists(directory): try: os.makedirs(directory, exist_ok=True) suggestions.append(f"已创建目录: {directory}") except: pass suggested_path = os.path.join(directory, filename) suggestions.append(f"建议放置位置: {suggested_path}") return suggestions # 全局路径处理器实例 path_handler = CrossPlatformPathHandler() def normalize_model_path(filepath): """便捷函数:标准化模型路径""" return path_handler.normalize_model_path(filepath) def suggest_file_placement(filename): """便捷函数:建议文件放置位置""" return path_handler.suggest_file_placement(filename)