868 lines
33 KiB
Python
868 lines
33 KiB
Python
"""
|
||
导航网格插件主文件
|
||
"""
|
||
|
||
import time
|
||
import json
|
||
from plugins.plugin_manager import BasePlugin
|
||
from .core.navmesh_manager import NavMeshManager
|
||
from .editor.navmesh_editor import NavMeshEditor
|
||
from .tools.pathfinder import Pathfinder
|
||
from .tools.navmesh_tools import NavMeshTools
|
||
|
||
class Plugin(BasePlugin):
|
||
"""
|
||
导航网格插件
|
||
提供基于导航网格的寻路和路径规划功能
|
||
"""
|
||
|
||
def __init__(self, plugin_manager, name):
|
||
super().__init__(plugin_manager, name)
|
||
self.config = {
|
||
"version": "1.0.0",
|
||
"author": "EG Team",
|
||
"description": "基于导航网格的寻路系统,支持复杂地形的路径规划"
|
||
}
|
||
|
||
# 核心组件
|
||
self.navmesh_manager = None
|
||
self.navmesh_editor = None
|
||
self.pathfinder = None
|
||
self.navmesh_tools = None
|
||
|
||
# GUI元素
|
||
self.gui_elements = []
|
||
|
||
# 事件处理器
|
||
self.event_handlers = {}
|
||
|
||
# 插件状态
|
||
self.is_initialized = False
|
||
self.is_enabled = False
|
||
|
||
# 性能监控
|
||
self.performance_stats = {
|
||
'initialization_time': 0.0,
|
||
'enable_time': 0.0,
|
||
'last_update_time': 0.0,
|
||
'total_updates': 0
|
||
}
|
||
|
||
def initialize(self) -> bool:
|
||
"""
|
||
初始化插件
|
||
"""
|
||
try:
|
||
if self.is_initialized:
|
||
return True
|
||
|
||
init_start_time = time.time()
|
||
print(f"初始化导航网格插件: {self.name}")
|
||
|
||
# 初始化导航网格管理器
|
||
self.navmesh_manager = NavMeshManager(self.plugin_manager.world)
|
||
|
||
# 初始化路径查找器
|
||
self.pathfinder = Pathfinder(self.navmesh_manager)
|
||
|
||
# 初始化导航网格编辑器
|
||
self.navmesh_editor = NavMeshEditor(
|
||
self.plugin_manager.world,
|
||
self.navmesh_manager
|
||
)
|
||
|
||
# 初始化导航网格工具集
|
||
self.navmesh_tools = NavMeshTools(self)
|
||
|
||
self.is_initialized = True
|
||
self.performance_stats['initialization_time'] = time.time() - init_start_time
|
||
print("✓ 导航网格插件初始化完成")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 导航网格插件初始化失败: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
def enable(self) -> bool:
|
||
"""
|
||
启用插件
|
||
"""
|
||
if not super().enable():
|
||
return False
|
||
|
||
if self.is_enabled:
|
||
return True
|
||
|
||
try:
|
||
enable_start_time = time.time()
|
||
print(f"启用导航网格插件: {self.name}")
|
||
|
||
# 启用导航网格管理器
|
||
if self.navmesh_manager:
|
||
self.navmesh_manager.enable()
|
||
|
||
# 注册事件处理器
|
||
self._register_event_handlers()
|
||
|
||
# 创建GUI界面
|
||
self._create_gui()
|
||
|
||
self.is_enabled = True
|
||
self.performance_stats['enable_time'] = time.time() - enable_start_time
|
||
print("✓ 导航网格插件启用成功")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 导航网格插件启用失败: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
def disable(self) -> bool:
|
||
"""
|
||
禁用插件
|
||
"""
|
||
if not super().disable():
|
||
return False
|
||
|
||
if not self.is_enabled:
|
||
return True
|
||
|
||
try:
|
||
print(f"禁用导航网格插件: {self.name}")
|
||
|
||
# 清理GUI界面
|
||
self._cleanup_gui()
|
||
|
||
# 移除事件处理器
|
||
self._unregister_event_handlers()
|
||
|
||
# 禁用导航网格管理器
|
||
if self.navmesh_manager:
|
||
self.navmesh_manager.disable()
|
||
|
||
self.is_enabled = False
|
||
print("✓ 导航网格插件禁用成功")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 导航网格插件禁用失败: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
def finalize(self):
|
||
"""
|
||
清理插件资源
|
||
"""
|
||
print(f"清理导航网格插件资源: {self.name}")
|
||
|
||
# 清理所有组件
|
||
if self.navmesh_editor:
|
||
self.navmesh_editor.cleanup()
|
||
self.navmesh_editor = None
|
||
|
||
if self.pathfinder:
|
||
self.pathfinder = None
|
||
|
||
if self.navmesh_tools:
|
||
self.navmesh_tools = None
|
||
|
||
if self.navmesh_manager:
|
||
self.navmesh_manager.cleanup()
|
||
self.navmesh_manager = None
|
||
|
||
self.is_initialized = False
|
||
self.is_enabled = False
|
||
|
||
def _register_event_handlers(self):
|
||
"""
|
||
注册事件处理器
|
||
"""
|
||
world = self.plugin_manager.world
|
||
|
||
# 导航网格系统控制快捷键
|
||
self.event_handlers['f1'] = self.toggle_navmesh_editor
|
||
self.event_handlers['f2'] = self.toggle_navmesh_visibility
|
||
self.event_handlers['f3'] = self.find_random_path
|
||
self.event_handlers['f4'] = self.clear_paths
|
||
self.event_handlers['f5'] = self.generate_navmesh
|
||
self.event_handlers['f6'] = self.validate_navmesh
|
||
self.event_handlers['f7'] = self.optimize_navmesh
|
||
self.event_handlers['f8'] = self.show_stats
|
||
self.event_handlers['f9'] = self.analyze_navmesh
|
||
self.event_handlers['f10'] = self.export_report
|
||
self.event_handlers['f11'] = self.simplify_navmesh
|
||
self.event_handlers['f12'] = self.detect_bottlenecks
|
||
|
||
# 注册事件
|
||
for event, handler in self.event_handlers.items():
|
||
world.accept(event, handler)
|
||
world.accept(event.upper(), handler) # 同时注册大写事件
|
||
|
||
def _unregister_event_handlers(self):
|
||
"""
|
||
移除事件处理器
|
||
"""
|
||
world = self.plugin_manager.world
|
||
|
||
for event in self.event_handlers.keys():
|
||
world.ignore(event)
|
||
world.ignore(event.upper())
|
||
|
||
self.event_handlers.clear()
|
||
|
||
def _create_gui(self):
|
||
"""
|
||
创建GUI界面
|
||
"""
|
||
try:
|
||
world = self.plugin_manager.world
|
||
|
||
# 检查是否有GUI管理器
|
||
if not hasattr(world, 'gui_manager') or not world.gui_manager:
|
||
print("⚠ GUI管理器不可用,跳过GUI创建")
|
||
return
|
||
|
||
gui_manager = world.gui_manager
|
||
|
||
# 创建导航网格控制面板
|
||
panel_button = gui_manager.createGUIButton(
|
||
pos=(0.02, 0, 0.75),
|
||
text="导航网格",
|
||
size=0.06
|
||
)
|
||
self.gui_elements.append(panel_button)
|
||
|
||
# 创建功能按钮
|
||
functions = [
|
||
("编辑器 [F1]", self.toggle_navmesh_editor),
|
||
("显示/隐藏 [F2]", self.toggle_navmesh_visibility),
|
||
("随机路径 [F3]", self.find_random_path),
|
||
("清除路径 [F4]", self.clear_paths),
|
||
("生成网格 [F5]", self.generate_navmesh),
|
||
("验证网格 [F6]", self.validate_navmesh),
|
||
("优化网格 [F7]", self.optimize_navmesh),
|
||
("显示统计 [F8]", self.show_stats),
|
||
("分析网格 [F9]", self.analyze_navmesh),
|
||
("导出报告 [F10]", self.export_report),
|
||
("简化网格 [F11]", self.simplify_navmesh),
|
||
("检测瓶颈 [F12]", self.detect_bottlenecks)
|
||
]
|
||
|
||
for i, (name, callback) in enumerate(functions):
|
||
button = gui_manager.createGUIButton(
|
||
pos=(0.02, 0, 0.68 - i * 0.055),
|
||
text=name,
|
||
size=0.045
|
||
)
|
||
self.gui_elements.append(button)
|
||
world.accept(f"navmesh_function_{name}", callback)
|
||
|
||
except Exception as e:
|
||
print(f"⚠ GUI创建失败: {e}")
|
||
|
||
def _cleanup_gui(self):
|
||
"""
|
||
清理GUI界面
|
||
"""
|
||
try:
|
||
world = self.plugin_manager.world
|
||
|
||
if hasattr(world, 'gui_manager') and world.gui_manager:
|
||
gui_manager = world.gui_manager
|
||
|
||
# 删除所有GUI元素
|
||
for element in self.gui_elements:
|
||
gui_manager.deleteGUIElement(element)
|
||
|
||
self.gui_elements.clear()
|
||
|
||
except Exception as e:
|
||
print(f"⚠ GUI清理失败: {e}")
|
||
|
||
# 事件处理方法
|
||
def toggle_navmesh_editor(self):
|
||
"""切换导航网格编辑器显示"""
|
||
if self.navmesh_editor:
|
||
self.navmesh_editor.toggle_visibility()
|
||
|
||
def toggle_navmesh_visibility(self):
|
||
"""切换导航网格可见性"""
|
||
if self.navmesh_manager:
|
||
self.navmesh_manager.toggle_visibility()
|
||
|
||
def find_random_path(self):
|
||
"""查找随机路径"""
|
||
if self.pathfinder and self.navmesh_manager:
|
||
# 获取随机起点和终点
|
||
start = self.navmesh_manager.get_random_point()
|
||
end = self.navmesh_manager.get_random_point()
|
||
|
||
if start and end:
|
||
path = self.pathfinder.find_path(start, end)
|
||
if path:
|
||
print(f"✓ 找到路径,包含 {len(path)} 个节点")
|
||
# 可视化路径
|
||
self.navmesh_manager.visualize_path(path)
|
||
else:
|
||
print("⚠ 未找到路径")
|
||
|
||
def clear_paths(self):
|
||
"""清除所有路径可视化"""
|
||
if self.navmesh_manager:
|
||
self.navmesh_manager.clear_path_visualization()
|
||
|
||
def generate_navmesh(self):
|
||
"""生成导航网格"""
|
||
if self.navmesh_manager:
|
||
success = self.navmesh_manager.generate_from_scene()
|
||
if success:
|
||
print("✓ 导航网格生成完成")
|
||
else:
|
||
print("✗ 导航网格生成失败")
|
||
|
||
def validate_navmesh(self):
|
||
"""验证导航网格"""
|
||
if self.navmesh_manager:
|
||
is_valid = self.navmesh_manager.validate_navmesh()
|
||
if is_valid:
|
||
print("✓ 导航网格验证通过")
|
||
else:
|
||
print("✗ 导航网格验证失败")
|
||
|
||
def optimize_navmesh(self):
|
||
"""优化导航网格"""
|
||
if self.navmesh_manager and self.navmesh_tools:
|
||
print("✓ 开始优化导航网格...")
|
||
optimization_result = self.navmesh_tools.optimize_mesh('medium')
|
||
print(f"✓ 导航网格优化完成: {optimization_result}")
|
||
|
||
def show_stats(self):
|
||
"""显示统计信息"""
|
||
if self.navmesh_manager:
|
||
stats = self.navmesh_manager.get_stats()
|
||
print("=== 导航网格统计信息 ===")
|
||
for key, value in stats.items():
|
||
print(f" {key}: {value}")
|
||
|
||
if self.pathfinder:
|
||
path_stats = self.pathfinder.get_pathfinding_stats()
|
||
print("=== 寻路统计信息 ===")
|
||
for key, value in path_stats.items():
|
||
print(f" {key}: {value}")
|
||
|
||
if self.navmesh_editor:
|
||
editor_stats = self.navmesh_editor.get_stats()
|
||
print("=== 编辑器统计信息 ===")
|
||
for key, value in editor_stats.items():
|
||
print(f" {key}: {value}")
|
||
|
||
def analyze_navmesh(self):
|
||
"""分析导航网格"""
|
||
if self.navmesh_tools:
|
||
print("✓ 开始分析导航网格...")
|
||
quality_report = self.navmesh_tools.analyze_mesh_quality()
|
||
suggestions = self.navmesh_tools.suggest_optimizations()
|
||
|
||
print("=== 导航网格质量分析 ===")
|
||
print(f" 多边形数量: {quality_report.get('polygon_count', 0)}")
|
||
print(f" 顶点数量: {quality_report.get('vertex_count', 0)}")
|
||
print(f" 孤立多边形: {quality_report.get('isolated_polygons', 0)}")
|
||
print(f" 小多边形: {quality_report.get('small_polygons', 0)}")
|
||
print(f" 不规则多边形: {quality_report.get('irregular_polygons', 0)}")
|
||
|
||
print("=== 优化建议 ===")
|
||
for i, suggestion in enumerate(suggestions[:5]): # 显示前5个建议
|
||
print(f" {i+1}. {suggestion.get('description', '无描述')}")
|
||
print(f" 建议: {suggestion.get('recommendation', '无建议')}")
|
||
|
||
def export_report(self):
|
||
"""导出分析报告"""
|
||
if self.navmesh_tools:
|
||
print("✓ 开始导出分析报告...")
|
||
timestamp = int(time.time())
|
||
filename = f"navmesh_analysis_report_{timestamp}.json"
|
||
success = self.navmesh_tools.export_report(filename)
|
||
if success:
|
||
print(f"✓ 分析报告已导出到: {filename}")
|
||
else:
|
||
print("✗ 导出分析报告失败")
|
||
|
||
def simplify_navmesh(self):
|
||
"""简化导航网格"""
|
||
if self.navmesh_tools:
|
||
print("✓ 开始简化导航网格...")
|
||
simplification_result = self.navmesh_tools.optimize_mesh('light')
|
||
print(f"✓ 导航网格简化完成: {simplification_result}")
|
||
|
||
def detect_bottlenecks(self):
|
||
"""检测瓶颈区域"""
|
||
if self.navmesh_tools:
|
||
print("✓ 开始检测瓶颈区域...")
|
||
bottlenecks = self.navmesh_tools.detect_bottlenecks()
|
||
|
||
print("=== 瓶颈区域检测结果 ===")
|
||
if bottlenecks:
|
||
for i, bottleneck in enumerate(bottlenecks[:5]): # 显示前5个瓶颈
|
||
position = bottleneck.get('position', '未知')
|
||
compactness = bottleneck.get('compactness', 0)
|
||
print(f" {i+1}. 位置: {position}, 紧凑度: {compactness:.4f}")
|
||
else:
|
||
print(" 未检测到明显的瓶颈区域")
|
||
|
||
def get_info(self) -> dict:
|
||
"""
|
||
获取插件信息
|
||
"""
|
||
info = super().get_info()
|
||
info.update({
|
||
"version": self.config.get("version", "1.0.0"),
|
||
"author": self.config.get("author", "EG Team"),
|
||
"description": self.config.get("description", "导航网格插件"),
|
||
"navmesh_loaded": self.navmesh_manager.is_navmesh_loaded() if self.navmesh_manager else False,
|
||
"navmesh_polygons": self.navmesh_manager.get_polygon_count() if self.navmesh_manager else 0,
|
||
"is_enabled": self.is_enabled,
|
||
"is_initialized": self.is_initialized
|
||
})
|
||
return info
|
||
|
||
# 公共接口方法
|
||
def load_navmesh_from_file(self, filepath: str) -> bool:
|
||
"""从文件加载导航网格"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.load_navmesh_from_file(filepath)
|
||
return False
|
||
|
||
def save_navmesh_to_file(self, filepath: str) -> bool:
|
||
"""保存导航网格到文件"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.save_navmesh_to_file(filepath)
|
||
return False
|
||
|
||
def generate_navmesh_from_scene(self) -> bool:
|
||
"""从当前场景生成导航网格"""
|
||
if self.navmesh_manager:
|
||
return self.navmesh_manager.generate_from_scene()
|
||
return False
|
||
|
||
def find_path(self, start_point, end_point):
|
||
"""查找两点之间的路径"""
|
||
if self.pathfinder:
|
||
return self.pathfinder.find_path(start_point, end_point)
|
||
return None
|
||
|
||
def is_point_walkable(self, point) -> bool:
|
||
"""检查点是否可行走"""
|
||
if self.navmesh_manager:
|
||
return self.navmesh_manager.is_point_walkable(point)
|
||
return False
|
||
|
||
def get_closest_point(self, point):
|
||
"""获取导航网格上最近的点"""
|
||
if self.navmesh_manager:
|
||
return self.navmesh_manager.get_closest_point(point)
|
||
return None
|
||
|
||
def add_dynamic_obstacle(self, position, radius, height):
|
||
"""添加动态障碍物"""
|
||
if self.navmesh_manager:
|
||
obstacle_id = self.navmesh_manager.add_obstacle(position, radius, height)
|
||
# 通知寻路器
|
||
if self.pathfinder:
|
||
self.pathfinder.add_dynamic_obstacle(obstacle_id, [])
|
||
return obstacle_id
|
||
return -1
|
||
|
||
def remove_dynamic_obstacle(self, obstacle_id):
|
||
"""移除动态障碍物"""
|
||
if self.navmesh_manager:
|
||
success = self.navmesh_manager.remove_obstacle(obstacle_id)
|
||
# 通知寻路器
|
||
if self.pathfinder and success:
|
||
self.pathfinder.remove_dynamic_obstacle(obstacle_id)
|
||
return success
|
||
return False
|
||
|
||
def set_navmesh_settings(self, settings: dict):
|
||
"""设置导航网格参数"""
|
||
if self.navmesh_manager:
|
||
if 'cell_size' in settings:
|
||
self.navmesh_manager.set_cell_size(settings['cell_size'])
|
||
if 'agent_height' in settings:
|
||
self.navmesh_manager.set_agent_height(settings['agent_height'])
|
||
if 'agent_radius' in settings:
|
||
self.navmesh_manager.set_agent_radius(settings['agent_radius'])
|
||
if 'max_slope' in settings:
|
||
self.navmesh_manager.set_max_slope(settings['max_slope'])
|
||
if 'max_climb' in settings:
|
||
self.navmesh_manager.set_max_climb(settings['max_climb'])
|
||
if 'min_region_area' in settings:
|
||
self.navmesh_manager.set_min_region_area(settings['min_region_area'])
|
||
if 'merge_region_area' in settings:
|
||
self.navmesh_manager.set_merge_region_area(settings['merge_region_area'])
|
||
if 'edge_max_len' in settings:
|
||
self.navmesh_manager.set_edge_max_len(settings['edge_max_len'])
|
||
if 'edge_max_error' in settings:
|
||
self.navmesh_manager.set_edge_max_error(settings['edge_max_error'])
|
||
if 'verts_per_poly' in settings:
|
||
self.navmesh_manager.set_verts_per_poly(settings['verts_per_poly'])
|
||
|
||
def get_navmesh_settings(self) -> dict:
|
||
"""获取导航网格参数"""
|
||
if self.navmesh_manager:
|
||
return {
|
||
'cell_size': self.navmesh_manager.cell_size,
|
||
'agent_height': self.navmesh_manager.agent_height,
|
||
'agent_radius': self.navmesh_manager.agent_radius,
|
||
'max_slope': self.navmesh_manager.max_slope,
|
||
'max_climb': self.navmesh_manager.max_climb,
|
||
'min_region_area': self.navmesh_manager.min_region_area,
|
||
'merge_region_area': self.navmesh_manager.merge_region_area,
|
||
'edge_max_len': self.navmesh_manager.edge_max_len,
|
||
'edge_max_error': self.navmesh_manager.edge_max_error,
|
||
'verts_per_poly': self.navmesh_manager.verts_per_poly
|
||
}
|
||
return {}
|
||
|
||
def set_pathfinder_algorithm(self, algorithm: str):
|
||
"""设置寻路算法"""
|
||
if self.pathfinder:
|
||
self.pathfinder.set_algorithm(algorithm)
|
||
|
||
def get_available_algorithms(self) -> list:
|
||
"""获取可用的寻路算法"""
|
||
if self.pathfinder:
|
||
return self.pathfinder.get_available_algorithms()
|
||
return []
|
||
|
||
def set_pathfinder_settings(self, settings: dict):
|
||
"""设置寻路参数"""
|
||
if self.pathfinder:
|
||
if 'heuristic_weight' in settings:
|
||
self.pathfinder.set_heuristic_weight(settings['heuristic_weight'])
|
||
if 'max_path_nodes' in settings:
|
||
self.pathfinder.set_max_path_nodes(settings['max_path_nodes'])
|
||
if 'use_funnel_pruning' in settings:
|
||
self.pathfinder.enable_funnel_pruning(settings['use_funnel_pruning'])
|
||
if 'smooth_paths' in settings:
|
||
self.pathfinder.enable_path_smoothing(settings['smooth_paths'])
|
||
|
||
def get_pathfinder_settings(self) -> dict:
|
||
"""获取寻路参数"""
|
||
if self.pathfinder:
|
||
return {
|
||
'heuristic_weight': self.pathfinder.heuristic_weight,
|
||
'max_path_nodes': self.pathfinder.max_path_nodes,
|
||
'use_funnel_pruning': self.pathfinder.use_funnel_pruning,
|
||
'smooth_paths': self.pathfinder.smooth_paths,
|
||
'current_algorithm': self.pathfinder.current_algorithm
|
||
}
|
||
return {}
|
||
|
||
def find_path_with_waypoints(self, waypoints: list):
|
||
"""查找经过多个路点的路径"""
|
||
if self.pathfinder:
|
||
return self.pathfinder.find_path_with_multiple_waypoints(waypoints)
|
||
return None
|
||
|
||
def estimate_path_cost(self, start_point, end_point):
|
||
"""估算路径代价"""
|
||
if self.pathfinder:
|
||
return self.pathfinder.estimate_path_cost(start_point, end_point)
|
||
return None
|
||
|
||
def validate_path(self, path: list) -> bool:
|
||
"""验证路径有效性"""
|
||
if self.pathfinder:
|
||
return self.pathfinder.validate_path(path)
|
||
return False
|
||
|
||
def get_path_complexity(self, path: list) -> dict:
|
||
"""分析路径复杂度"""
|
||
if self.pathfinder:
|
||
return self.pathfinder.get_path_complexity(path)
|
||
return {}
|
||
|
||
def find_alternative_paths(self, start_point, end_point, count: int = 3):
|
||
"""查找备选路径"""
|
||
if self.pathfinder:
|
||
return self.pathfinder.find_alternative_paths(start_point, end_point, count)
|
||
return []
|
||
|
||
def clear_path_cache(self):
|
||
"""清空路径缓存"""
|
||
if self.pathfinder:
|
||
self.pathfinder.clear_cache()
|
||
|
||
def rebuild_navmesh(self):
|
||
"""重新构建导航网格"""
|
||
if self.navmesh_manager:
|
||
return self.navmesh_manager.rebuild_navmesh()
|
||
return False
|
||
|
||
def enable_spatial_hashing(self, enabled: bool):
|
||
"""启用/禁用空间哈希"""
|
||
if self.navmesh_manager:
|
||
self.navmesh_manager.enable_spatial_hashing(enabled)
|
||
|
||
def set_spatial_hash_cell_size(self, size: float):
|
||
"""设置空间哈希网格单元大小"""
|
||
if self.navmesh_manager:
|
||
self.navmesh_manager.set_spatial_hash_cell_size(size)
|
||
|
||
def export_statistics(self, filepath: str) -> bool:
|
||
"""导出统计信息"""
|
||
try:
|
||
stats_data = {
|
||
'plugin_info': self.get_info(),
|
||
'navmesh_settings': self.get_navmesh_settings(),
|
||
'pathfinder_settings': self.get_pathfinder_settings(),
|
||
'performance_stats': self.performance_stats,
|
||
'timestamp': time.strftime("%Y-%m-%d %H:%M:%S")
|
||
}
|
||
|
||
if self.navmesh_manager:
|
||
stats_data['navmesh_stats'] = self.navmesh_manager.get_stats()
|
||
|
||
if self.pathfinder:
|
||
stats_data['pathfinder_stats'] = self.pathfinder.get_pathfinding_stats()
|
||
|
||
if self.navmesh_editor:
|
||
stats_data['editor_stats'] = self.navmesh_editor.get_stats()
|
||
|
||
with open(filepath, 'w', encoding='utf-8') as f:
|
||
json.dump(stats_data, f, indent=2, ensure_ascii=False)
|
||
|
||
print(f"✓ 统计信息已导出到: {filepath}")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 导出统计信息失败: {e}")
|
||
return False
|
||
|
||
def import_settings(self, filepath: str) -> bool:
|
||
"""导入设置"""
|
||
try:
|
||
with open(filepath, 'r', encoding='utf-8') as f:
|
||
settings = json.load(f)
|
||
|
||
# 应用导航网格设置
|
||
if 'navmesh_settings' in settings:
|
||
self.set_navmesh_settings(settings['navmesh_settings'])
|
||
|
||
# 应用寻路设置
|
||
if 'pathfinder_settings' in settings:
|
||
pf_settings = settings['pathfinder_settings']
|
||
self.set_pathfinder_settings(pf_settings)
|
||
|
||
print(f"✓ 设置已从 {filepath} 导入")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 导入设置失败: {e}")
|
||
return False
|
||
|
||
def export_settings(self, filepath: str) -> bool:
|
||
"""导出设置"""
|
||
try:
|
||
settings_data = {
|
||
'navmesh_settings': self.get_navmesh_settings(),
|
||
'pathfinder_settings': self.get_pathfinder_settings()
|
||
}
|
||
|
||
with open(filepath, 'w', encoding='utf-8') as f:
|
||
json.dump(settings_data, f, indent=2, ensure_ascii=False)
|
||
|
||
print(f"✓ 设置已导出到: {filepath}")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 导出设置失败: {e}")
|
||
return False
|
||
|
||
# 新增的工具方法
|
||
def analyze_mesh_quality(self) -> dict:
|
||
"""分析导航网格质量"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.analyze_mesh_quality()
|
||
return {}
|
||
|
||
def suggest_optimizations(self) -> list:
|
||
"""提供优化建议"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.suggest_optimizations()
|
||
return []
|
||
|
||
def analyze_pathfinding_performance(self, sample_count: int = 100) -> dict:
|
||
"""分析寻路性能"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.analyze_pathfinding_performance(sample_count)
|
||
return {}
|
||
|
||
def detect_navigation_bottlenecks(self) -> list:
|
||
"""检测导航网格中的瓶颈区域"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.detect_bottlenecks()
|
||
return []
|
||
|
||
def analyze_coverage(self) -> dict:
|
||
"""分析导航网格覆盖情况"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.analyze_coverage()
|
||
return {}
|
||
|
||
def generate_analysis_report(self) -> dict:
|
||
"""生成完整的分析报告"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.generate_report()
|
||
return {}
|
||
|
||
def export_analysis_report(self, filepath: str) -> bool:
|
||
"""导出分析报告到文件"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.export_report(filepath)
|
||
return False
|
||
|
||
def get_mesh_complexity_score(self) -> float:
|
||
"""计算导航网格复杂度评分"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.get_complexity_score()
|
||
return 0.0
|
||
|
||
def recommend_mesh_simplification(self) -> dict:
|
||
"""推荐网格简化策略"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.recommend_simplification()
|
||
return {}
|
||
|
||
def merge_adjacent_polygons(self) -> int:
|
||
"""合并相邻的多边形"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.merge_adjacent_polygons()
|
||
return 0
|
||
|
||
def simplify_mesh_polygons(self) -> int:
|
||
"""简化多边形(移除不必要的顶点)"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.simplify_polygons()
|
||
return 0
|
||
|
||
def remove_small_mesh_polygons(self) -> int:
|
||
"""移除极小的多边形"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.remove_small_polygons()
|
||
return 0
|
||
|
||
def optimize_navigation_mesh(self, optimization_level: str = 'medium') -> dict:
|
||
"""执行完整的网格优化"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.optimize_mesh(optimization_level)
|
||
return {}
|
||
|
||
def set_optimization_settings(self, settings: dict):
|
||
"""设置优化参数"""
|
||
if self.navmesh_tools:
|
||
self.navmesh_tools.set_optimization_settings(settings)
|
||
|
||
def get_optimization_settings(self) -> dict:
|
||
"""获取优化参数"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.get_optimization_settings()
|
||
return {}
|
||
|
||
def fill_mesh_gaps(self) -> int:
|
||
"""填补导航网格中的空隙"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.fill_gaps()
|
||
return 0
|
||
|
||
def smooth_mesh_boundaries(self) -> int:
|
||
"""平滑多边形边界"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.smooth_boundaries()
|
||
return 0
|
||
|
||
def balance_polygon_sizes(self) -> int:
|
||
"""平衡多边形大小"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.balance_polygon_sizes()
|
||
return 0
|
||
|
||
def serialize_navigation_mesh(self) -> str:
|
||
"""序列化导航网格为字符串"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.serialize_navmesh()
|
||
return ""
|
||
|
||
def deserialize_navigation_mesh(self, data_str: str) -> bool:
|
||
"""从字符串反序列化导航网格"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.deserialize_navmesh(data_str)
|
||
return False
|
||
|
||
def save_navmesh_to_file_advanced(self, filepath: str,
|
||
compress: bool = False, pretty_print: bool = False) -> bool:
|
||
"""保存导航网格到文件(高级选项)"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.save_navmesh_to_file(filepath, compress, pretty_print)
|
||
return False
|
||
|
||
def load_navmesh_from_file_advanced(self, filepath: str) -> bool:
|
||
"""从文件加载导航网格(高级选项)"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.load_navmesh_from_file(filepath)
|
||
return False
|
||
|
||
def export_to_standard_format(self, filepath: str,
|
||
format_type: str = 'obj') -> bool:
|
||
"""导出为标准格式"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.export_to_standard_format(filepath, format_type)
|
||
return False
|
||
|
||
def import_from_standard_format(self, filepath: str,
|
||
format_type: str = 'obj') -> bool:
|
||
"""从标准格式导入"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.import_from_standard_format(filepath, format_type)
|
||
return False
|
||
|
||
def get_navmesh_file_info(self, filepath: str) -> dict:
|
||
"""获取导航网格文件信息"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.get_file_info(filepath)
|
||
return {}
|
||
|
||
def batch_analyze_navmeshes(self, filepaths: list) -> dict:
|
||
"""批量分析多个导航网格文件"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.batch_analyze(filepaths)
|
||
return {}
|
||
|
||
def compare_navigation_meshes(self, navmesh1_path: str, navmesh2_path: str) -> dict:
|
||
"""比较两个导航网格"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.compare_navmeshes(navmesh1_path, navmesh2_path)
|
||
return {}
|
||
|
||
def validate_navmesh_file(self, filepath: str) -> dict:
|
||
"""验证导航网格文件的有效性"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.validate_navmesh_file(filepath)
|
||
return {}
|
||
|
||
def optimize_and_save_navmesh(self, input_filepath: str, output_filepath: str,
|
||
optimization_level: str = 'medium') -> dict:
|
||
"""优化并保存导航网格"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.optimize_and_save(input_filepath, output_filepath, optimization_level)
|
||
return {}
|
||
|
||
def create_optimization_pipeline(self, steps: list) -> dict:
|
||
"""创建优化流水线"""
|
||
if self.navmesh_tools:
|
||
return self.navmesh_tools.create_optimization_pipeline(steps)
|
||
return {} |