extends Control # UI References @onready var archive_grid: GridContainer = %ArchiveGrid @onready var scroll_container: ScrollContainer = %ScrollContainer @onready var current_archive_label: Label = %CurrentArchiveLabel @onready var name_input: LineEdit = %NameInput @onready var save_button: Button = %SaveButton @onready var refresh_button: Button = %RefreshButton # Constants const MAX_MANUAL_ARCHIVES = 99 const GRID_COLUMNS = 4 # Variables var manual_archives: Dictionary = {} # {id: {name: String, path: String, time: String}} var next_available_id: int = 2 # Start from 2 since 1 is reserved for main archive func _ready() -> void: # Setup UI archive_grid.columns = GRID_COLUMNS # Connect signals save_button.pressed.connect(_on_save_button_pressed) refresh_button.pressed.connect(_refresh_archive_list) name_input.text_submitted.connect(_on_name_submitted) # Set default name _update_default_name() # Initial load _refresh_archive_list() _update_current_archive_label() func _update_current_archive_label() -> void: current_archive_label.text = "当前使用存档:1号存档(主存档)" func _update_default_name() -> void: name_input.placeholder_text = "输入存档名称" var chapter_name = EventManager.get_chapter_stage() if chapter_name == 1: chapter_name = "序章" elif chapter_name <= 5: chapter_name = "第%s章" % (chapter_name - 1) elif chapter_name == 6: chapter_name = "结尾" else: chapter_name = "未知" var scene_name = SceneManager.get_current_scene_name() var saving_name = chapter_name + "_" + scene_name name_input.text = _get_unique_archive_name(saving_name) func _on_name_submitted(_text: String) -> void: _on_save_button_pressed() func _on_save_button_pressed() -> void: # Check limit if manual_archives.size() >= MAX_MANUAL_ARCHIVES: _show_notification("已达到最大存档数量限制(99个)") return # Get and validate name var archive_name = name_input.text.strip_edges() if archive_name.is_empty(): archive_name = "未命名存档_" + Time.get_datetime_string_from_system() # Save current progress ArchiveManager.save_all() # Get unique name archive_name = _get_unique_archive_name(archive_name) # Copy current archive _copy_current_archive(archive_name) # Reset input field _update_default_name() name_input.select_all() func _get_unique_archive_name(base_name: String) -> String: var final_name = base_name var counter = 1 # Check if name already exists var name_exists = true while name_exists: name_exists = false for data in manual_archives.values(): if data.name == final_name: name_exists = true final_name = base_name + "_" + str(counter) counter += 1 break return final_name func _copy_current_archive(archive_name: String) -> void: # Get current archive path var current_archive = ArchiveManager.archive if not current_archive: _show_notification("当前没有活动存档") return # Find next available ID while manual_archives.has(next_available_id) and next_available_id <= MAX_MANUAL_ARCHIVES + 1: next_available_id += 1 if next_available_id > MAX_MANUAL_ARCHIVES + 1: _show_notification("无法创建更多存档") return # Create new archive path var new_archive_path = ( ArchiveManager.user_archives_dir + "manual_" + str(next_available_id) + "_" + archive_name.validate_filename() + GlobalConfig.RES_FILE_FORMAT ) # Copy the archive file var source_path = current_archive.resource_path var dir = DirAccess.open(ArchiveManager.user_archives_dir) if dir: var error = dir.copy(source_path, new_archive_path) print("Copying archive from: ", source_path, " to: ", new_archive_path) if error == OK: # Save manual archive info manual_archives[next_available_id] = { "name": archive_name, "path": new_archive_path, "time": Time.get_datetime_string_from_system(false, true) } # Save manual archives data _save_manual_archives_data() # Refresh UI _refresh_archive_list() _show_notification("存档已保存:" + archive_name) next_available_id += 1 else: _show_notification("存档复制失败:" + error_string(error)) else: _show_notification("无法访问存档目录") func _refresh_archive_list() -> void: # refresh debugging name _update_default_name() # Clear existing items for child in archive_grid.get_children(): child.queue_free() # Load manual archives data _load_manual_archives_data() # Create UI items for each manual archive var sorted_ids = manual_archives.keys() sorted_ids.sort() for id in sorted_ids: var data = manual_archives[id] _create_archive_item(id, data) func _create_archive_item(id: int, data: Dictionary) -> void: # Create container for the archive item var item_container = PanelContainer.new() item_container.custom_minimum_size = Vector2(200, 60) var vbox = VBoxContainer.new() vbox.add_theme_constant_override("separation", 4) item_container.add_child(vbox) # Archive name (editable) var name_edit = LineEdit.new() name_edit.text = data.name name_edit.tooltip_text = "创建时间:" + data.time vbox.add_child(name_edit) # Time label var time_label = Label.new() time_label.text = data.time time_label.add_theme_font_size_override("font_size", 12) time_label.modulate.a = 0.7 vbox.add_child(time_label) # Action buttons container var button_container = HBoxContainer.new() button_container.add_theme_constant_override("separation", 4) # Load button var load_btn = Button.new() load_btn.text = "加载" load_btn.size_flags_horizontal = Control.SIZE_EXPAND_FILL button_container.add_child(load_btn) # Delete button var delete_btn = Button.new() delete_btn.text = "删除" delete_btn.size_flags_horizontal = Control.SIZE_EXPAND_FILL button_container.add_child(delete_btn) vbox.add_child(button_container) # Connect signals name_edit.text_changed.connect(func(new_text): _on_archive_renamed(id, new_text)) load_btn.pressed.connect(func(): _load_manual_archive(id, data)) delete_btn.pressed.connect(func(): _delete_manual_archive(id)) archive_grid.add_child(item_container) func _on_archive_renamed(id: int, new_name: String) -> void: if new_name.strip_edges().is_empty(): return # Update name in data manual_archives[id].name = new_name.strip_edges() # Save changes _save_manual_archives_data() func _load_manual_archive(_id: int, data: Dictionary) -> void: # Save current state first ArchiveManager.save_all() # Copy manual archive to archive 1 var dir = DirAccess.open(ArchiveManager.user_archives_dir) if dir: var saving_archive = load(data.path) if saving_archive: var target_path = ArchiveManager.get_archive_path(1) print("Loading archive from: ", data.path, " to: ", target_path) GlobalConfigManager.config.current_selected_archive_id = 1 if ArchiveManager.archive: saving_archive.take_over_path(target_path) else: saving_archive.resource_path = target_path ArchiveManager.archives_dict[1] = saving_archive ArchiveManager.archive = saving_archive print("Loading archive from: ", data.path, " to: ", target_path) # Reload current scene SceneManager.enter_main_scene() else: _show_notification("加载存档失败:" + data.name) func _delete_manual_archive(id: int) -> void: var data = manual_archives[id] # Delete file var dir = DirAccess.open(ArchiveManager.user_archives_dir) if dir: dir.remove(data.path) # Remove from dictionary manual_archives.erase(id) # Save changes _save_manual_archives_data() # Refresh UI _refresh_archive_list() _show_notification("已删除存档:" + data.name) func _save_manual_archives_data() -> void: var save_path = ArchiveManager.user_data_root_dir + "test_manual_archives.dat" var file = FileAccess.open(save_path, FileAccess.WRITE) if file: file.store_var(manual_archives) file.close() func _load_manual_archives_data() -> void: var save_path = ArchiveManager.user_data_root_dir + "test_manual_archives.dat" if FileAccess.file_exists(save_path): var file = FileAccess.open(save_path, FileAccess.READ) if file: manual_archives = file.get_var() file.close() # Find next available ID next_available_id = 2 for id in manual_archives.keys(): if id >= next_available_id: next_available_id = id + 1 func _show_notification(message: String) -> void: SceneManager.pop_notification(message)