优化项目架构

This commit is contained in:
2025-09-15 19:10:37 +08:00
parent 4119ed3445
commit 26b856d74e
1361 changed files with 4 additions and 0 deletions

View File

@@ -0,0 +1,463 @@
extends Panel
## 调试面板 - 显示资源加载和设备性能信息
## 特别用于在移动设备上调试资源加载问题
@onready var debug_rich_text: RichTextLabel = $DebugRichText
@onready var copy_button: Button = null # 复制按钮引用
# 调试信息管理
var debug_messages: Array = []
var max_debug_messages: int = 50 # 最大保留消息数量
var update_timer: float = 0.0
var update_interval: float = 1.0 # 每秒更新一次
# 性能监控数据
var performance_data: Dictionary = {
"cpu_usage": 0.0,
"memory_usage": 0,
"memory_peak": 0,
"fps": 0.0,
"loading_progress": 0,
"loaded_textures": 0,
"failed_textures": 0,
"current_loading_item": "",
"device_info": {}
}
# 主游戏引用
var main_game = null
func _ready():
print("[DebugPanel] 调试面板已初始化")
# 获取主游戏引用
main_game = get_node("/root/main")
# 创建复制按钮
_create_copy_button()
# 初始化设备信息
_collect_device_info()
# 添加初始消息
add_debug_message("调试面板已启动", Color.GREEN)
add_debug_message("设备: " + OS.get_name(), Color.CYAN)
add_debug_message("CPU核心: " + str(OS.get_processor_count()), Color.CYAN)
func _process(delta):
update_timer += delta
if update_timer >= update_interval:
update_timer = 0.0
_update_performance_data()
_check_performance_warnings()
_update_debug_display()
## 检查性能警告
func _check_performance_warnings():
# 内存警告
var memory_mb = performance_data["memory_usage"] / (1024 * 1024)
if memory_mb > 800:
report_memory_warning(memory_mb)
# FPS警告
if performance_data["fps"] < 20 and performance_data["fps"] > 0:
report_performance_warning(performance_data["fps"])
# 加载失败警告
if performance_data["failed_textures"] > 10:
add_debug_message("⚠ 大量纹理加载失败: %d" % performance_data["failed_textures"], Color.RED)
## 收集设备基本信息
func _collect_device_info():
performance_data["device_info"] = {
"platform": OS.get_name(),
"processor_count": OS.get_processor_count(),
"processor_name": OS.get_processor_name(),
"memory_total": OS.get_static_memory_usage(),
"gpu_vendor": RenderingServer.get_video_adapter_vendor(),
"gpu_name": RenderingServer.get_video_adapter_name(),
"screen_size": DisplayServer.screen_get_size(),
"screen_dpi": DisplayServer.screen_get_dpi()
}
## 更新性能数据
func _update_performance_data():
# CPU使用率通过帧时间估算
var frame_time = Performance.get_monitor(Performance.TIME_PROCESS)
performance_data["cpu_usage"] = min(frame_time * 100.0, 100.0)
# 内存使用情况
var current_memory = OS.get_static_memory_usage()
performance_data["memory_usage"] = current_memory
if current_memory > performance_data["memory_peak"]:
performance_data["memory_peak"] = current_memory
# FPS
performance_data["fps"] = Engine.get_frames_per_second()
# 从主游戏获取加载信息
if main_game and main_game.crop_texture_manager:
var manager = main_game.crop_texture_manager
# 计算所有加载的纹理数量(新的三阶段系统)
var total_textures = 0
for crop_name in manager.texture_cache.keys():
total_textures += manager.texture_cache[crop_name].size()
total_textures += manager.default_textures.size()
performance_data["loaded_textures"] = total_textures
performance_data["failed_textures"] = manager.failed_resources.size()
# 加载进度
if manager.is_loading:
var total = manager.total_crops * 2 # 序列帧 + 成熟图片
var loaded = manager.loaded_crops
performance_data["loading_progress"] = int((float(loaded) / float(total)) * 100) if total > 0 else 0
else:
performance_data["loading_progress"] = 100
## 更新调试显示
func _update_debug_display():
if not debug_rich_text:
return
var text = ""
# 为复制按钮留出空间,添加一些空行
text += "\n\n"
# 快速摘要(最重要的信息)
text += "[color=yellow][b]=== 快速摘要 ===[/b][/color]\n"
var summary_memory_mb = performance_data["memory_usage"] / (1024 * 1024)
var status_color = "green"
if performance_data["failed_textures"] > 0 or summary_memory_mb > 500 or performance_data["fps"] < 30:
status_color = "red"
elif performance_data["loading_progress"] < 100:
status_color = "yellow"
text += "[color=" + status_color + "]状态: "
if performance_data["loading_progress"] < 100:
text += "加载中 " + str(performance_data["loading_progress"]) + "%"
elif performance_data["failed_textures"] > 0:
text += "" + str(performance_data["failed_textures"]) + " 个资源加载失败"
else:
text += "正常运行"
text += "[/color]\n"
text += "[color=cyan]内存: %.1fMB | FPS: %d | 纹理: %d[/color]\n\n" % [summary_memory_mb, performance_data["fps"], performance_data["loaded_textures"]]
# 设备信息标题
text += "[color=yellow][b]=== 设备信息 ===[/b][/color]\n"
var device = performance_data["device_info"]
text += "[color=cyan]平台:[/color] " + str(device.get("platform", "未知")) + "\n"
text += "[color=cyan]CPU:[/color] " + str(device.get("processor_name", "未知")) + " (" + str(device.get("processor_count", 0)) + "核)\n"
text += "[color=cyan]GPU:[/color] " + str(device.get("gpu_name", "未知")) + "\n"
text += "[color=cyan]屏幕:[/color] " + str(device.get("screen_size", Vector2.ZERO)) + " DPI:" + str(device.get("screen_dpi", 0)) + "\n"
# 性能监控标题
text += "\n[color=yellow][b]=== 性能监控 ===[/b][/color]\n"
# CPU使用率颜色编码
var cpu_color = "green"
if performance_data["cpu_usage"] > 70:
cpu_color = "red"
elif performance_data["cpu_usage"] > 50:
cpu_color = "yellow"
text += "[color=cyan]CPU使用率:[/color] [color=" + cpu_color + "]" + "%.1f%%" % performance_data["cpu_usage"] + "[/color]\n"
# 内存使用情况(颜色编码)
var memory_mb = performance_data["memory_usage"] / (1024 * 1024)
var memory_peak_mb = performance_data["memory_peak"] / (1024 * 1024)
var memory_color = "green"
if memory_mb > 800:
memory_color = "red"
elif memory_mb > 500:
memory_color = "yellow"
text += "[color=cyan]内存使用:[/color] [color=" + memory_color + "]%.1fMB[/color] (峰值: %.1fMB)\n" % [memory_mb, memory_peak_mb]
# FPS颜色编码
var fps_color = "green"
if performance_data["fps"] < 30:
fps_color = "red"
elif performance_data["fps"] < 50:
fps_color = "yellow"
text += "[color=cyan]FPS:[/color] [color=" + fps_color + "]" + str(performance_data["fps"]) + "[/color]\n"
# 资源加载状态标题
text += "\n[color=yellow][b]=== 资源加载状态 ===[/b][/color]\n"
# 加载进度(颜色编码)
var progress_color = "yellow"
if performance_data["loading_progress"] >= 100:
progress_color = "green"
elif performance_data["loading_progress"] < 50:
progress_color = "red"
text += "[color=cyan]加载进度:[/color] [color=" + progress_color + "]" + str(performance_data["loading_progress"]) + "%[/color]\n"
# 纹理统计
text += "[color=cyan]已加载纹理:[/color] " + str(performance_data["loaded_textures"]) + "\n"
# 失败纹理(突出显示)
if performance_data["failed_textures"] > 0:
text += "[color=cyan]失败纹理:[/color] [color=red]" + str(performance_data["failed_textures"]) + "[/color]\n"
else:
text += "[color=cyan]失败纹理:[/color] [color=green]0[/color]\n"
# 当前加载项目
if performance_data["current_loading_item"] != "":
text += "[color=cyan]当前加载:[/color] " + performance_data["current_loading_item"] + "\n"
# 线程信息
if main_game and main_game.crop_texture_manager:
var manager = main_game.crop_texture_manager
text += "[color=cyan]工作线程:[/color] " + str(manager.max_threads) + "\n"
if manager.is_loading:
text += "[color=cyan]队列任务:[/color] " + str(manager.loading_queue.size()) + "\n"
# 调试消息标题
text += "\n[color=yellow][b]=== 调试日志 ===[/b][/color]\n"
# 显示最近的调试消息
var recent_messages = debug_messages.slice(-15) # 显示最近15条消息
for message in recent_messages:
text += message + "\n"
# 更新显示
debug_rich_text.text = text
# 自动滚动到底部
debug_rich_text.scroll_to_line(debug_rich_text.get_line_count())
## 添加调试消息
func add_debug_message(message: String, color: Color = Color.WHITE):
var timestamp = Time.get_datetime_string_from_system()
var time_parts = timestamp.split(" ")
var time_str = ""
# 安全地获取时间部分
if time_parts.size() >= 2:
time_str = time_parts[1].substr(0, 8) # 只要时间部分
else:
# 如果分割失败,使用当前时间
var time_dict = Time.get_time_dict_from_system()
time_str = "%02d:%02d:%02d" % [time_dict.hour, time_dict.minute, time_dict.second]
var color_name = _color_to_name(color)
var formatted_message = "[color=gray]%s[/color] [color=%s]%s[/color]" % [time_str, color_name, message]
debug_messages.append(formatted_message)
# 限制消息数量
if debug_messages.size() > max_debug_messages:
debug_messages = debug_messages.slice(-max_debug_messages)
# 同时输出到控制台
print("[DebugPanel] " + message)
## 颜色转换为名称
func _color_to_name(color: Color) -> String:
if color == Color.RED:
return "red"
elif color == Color.GREEN:
return "green"
elif color == Color.BLUE:
return "blue"
elif color == Color.YELLOW:
return "yellow"
elif color == Color.CYAN:
return "cyan"
elif color == Color.MAGENTA:
return "magenta"
elif color == Color.ORANGE:
return "orange"
elif color == Color.PINK:
return "pink"
else:
return "white"
## 设置当前加载项目
func set_current_loading_item(item_name: String):
performance_data["current_loading_item"] = item_name
if item_name != "":
add_debug_message("正在加载: " + item_name, Color.CYAN)
## 报告加载成功
func report_loading_success(item_name: String):
add_debug_message("✓ 加载成功: " + item_name, Color.GREEN)
## 报告加载失败
func report_loading_failure(item_name: String, reason: String = ""):
var message = "✗ 加载失败: " + item_name
if reason != "":
message += " (" + reason + ")"
add_debug_message(message, Color.RED)
## 报告内存警告
func report_memory_warning(memory_mb: float):
add_debug_message("⚠ 内存使用过高: %.1fMB" % memory_mb, Color.ORANGE)
## 报告性能警告
func report_performance_warning(fps: float):
add_debug_message("⚠ 性能下降: FPS=" + str(fps), Color.ORANGE)
## 清理调试信息
func clear_debug_log():
debug_messages.clear()
add_debug_message("调试日志已清理", Color.YELLOW)
## 导出调试信息到文件
func export_debug_log():
var datetime = Time.get_datetime_dict_from_system()
var filename = "debug_log_%04d%02d%02d_%02d%02d%02d.txt" % [
datetime.year, datetime.month, datetime.day,
datetime.hour, datetime.minute, datetime.second
]
var file_path = OS.get_user_data_dir() + "/" + filename
var file = FileAccess.open(file_path, FileAccess.WRITE)
if file:
file.store_string("=== 萌芽农场调试日志 ===\n\n")
file.store_string("设备信息:\n")
for key in performance_data["device_info"]:
file.store_string(" %s: %s\n" % [key, str(performance_data["device_info"][key])])
file.store_string("\n性能数据:\n")
file.store_string(" CPU使用率: %.1f%%\n" % performance_data["cpu_usage"])
file.store_string(" 内存使用: %.1fMB\n" % (performance_data["memory_usage"] / (1024 * 1024)))
file.store_string(" FPS: %d\n" % performance_data["fps"])
file.store_string(" 已加载纹理: %d\n" % performance_data["loaded_textures"])
file.store_string(" 失败纹理: %d\n" % performance_data["failed_textures"])
file.store_string("\n调试日志:\n")
for message in debug_messages:
# 移除BBCode标签
var clean_message = message.replace("[color=gray]", "").replace("[/color]", "")
clean_message = clean_message.replace("[color=red]", "").replace("[color=green]", "")
clean_message = clean_message.replace("[color=cyan]", "").replace("[color=yellow]", "")
clean_message = clean_message.replace("[color=orange]", "")
file.store_string(clean_message + "\n")
file.close()
add_debug_message("调试日志已导出到: " + filename, Color.GREEN)
return file_path
else:
add_debug_message("导出调试日志失败", Color.RED)
return ""
## 创建复制按钮
func _create_copy_button():
# 复制按钮
copy_button = Button.new()
copy_button.text = "复制调试信息"
copy_button.size = Vector2(140, 35)
copy_button.position = Vector2(10, 10) # 左上角位置
# 设置按钮样式
copy_button.modulate = Color(1.0, 0.8, 0.6, 0.9) # 淡橙色
# 连接点击信号
copy_button.pressed.connect(_on_copy_button_pressed)
# 添加到面板
add_child(copy_button)
# 清理日志按钮
var clear_button = Button.new()
clear_button.text = "清理日志"
clear_button.size = Vector2(100, 35)
clear_button.position = Vector2(160, 10) # 复制按钮右边
# 设置按钮样式
clear_button.modulate = Color(1.0, 0.6, 0.6, 0.9) # 淡红色
# 连接点击信号
clear_button.pressed.connect(_on_clear_button_pressed)
# 添加到面板
add_child(clear_button)
print("[DebugPanel] 复制和清理按钮已创建")
## 清理按钮点击处理
func _on_clear_button_pressed():
clear_debug_log()
print("[DebugPanel] 调试日志已清理")
## 复制按钮点击处理
func _on_copy_button_pressed():
var debug_text = _generate_debug_text_for_copy()
DisplayServer.clipboard_set(debug_text)
add_debug_message("调试信息已复制到剪贴板", Color.GREEN)
print("[DebugPanel] 调试信息已复制到剪贴板")
## 生成用于复制的调试文本(纯文本格式)
func _generate_debug_text_for_copy() -> String:
var text = "=== 萌芽农场调试信息 ===\n\n"
# 设备信息
text += "=== 设备信息 ===\n"
var device = performance_data["device_info"]
text += "平台: " + str(device.get("platform", "未知")) + "\n"
text += "CPU: " + str(device.get("processor_name", "未知")) + " (" + str(device.get("processor_count", 0)) + "核)\n"
text += "GPU: " + str(device.get("gpu_name", "未知")) + "\n"
text += "屏幕: " + str(device.get("screen_size", Vector2.ZERO)) + " DPI:" + str(device.get("screen_dpi", 0)) + "\n"
# 性能监控
text += "\n=== 性能监控 ===\n"
text += "CPU使用率: %.1f%%\n" % performance_data["cpu_usage"]
var memory_mb = performance_data["memory_usage"] / (1024 * 1024)
var memory_peak_mb = performance_data["memory_peak"] / (1024 * 1024)
text += "内存使用: %.1fMB (峰值: %.1fMB)\n" % [memory_mb, memory_peak_mb]
text += "FPS: %d\n" % performance_data["fps"]
# 资源加载状态
text += "\n=== 资源加载状态 ===\n"
text += "加载进度: %d%%\n" % performance_data["loading_progress"]
text += "已加载纹理: %d\n" % performance_data["loaded_textures"]
text += "失败纹理: %d\n" % performance_data["failed_textures"]
if performance_data["current_loading_item"] != "":
text += "当前加载: " + performance_data["current_loading_item"] + "\n"
# 线程信息
if main_game and main_game.crop_texture_manager:
var manager = main_game.crop_texture_manager
text += "工作线程: %d\n" % manager.max_threads
if manager.is_loading:
text += "队列任务: %d\n" % manager.loading_queue.size()
# 调试日志
text += "\n=== 调试日志 ===\n"
for message in debug_messages:
# 移除BBCode标签
var clean_message = _remove_bbcode_tags(message)
text += clean_message + "\n"
return text
## 移除BBCode标签
func _remove_bbcode_tags(text: String) -> String:
var clean_text = text
# 移除所有颜色标签
var color_regex = RegEx.new()
color_regex.compile("\\[color=[^\\]]*\\]|\\[/color\\]")
clean_text = color_regex.sub(clean_text, "", true)
# 移除粗体标签
clean_text = clean_text.replace("[b]", "").replace("[/b]", "")
return clean_text
## 获取当前性能摘要
func get_performance_summary() -> String:
return "CPU:%.1f%% 内存:%.1fMB FPS:%d 纹理:%d/%d" % [
performance_data["cpu_usage"],
performance_data["memory_usage"] / (1024 * 1024),
performance_data["fps"],
performance_data["loaded_textures"],
performance_data["failed_textures"]
]
func _on_quit_button_pressed() -> void:
self.hide()
pass