2025-07-16 15:20:55 +00:00
|
|
|
|
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:
|
2025-07-18 11:52:49 +00:00
|
|
|
|
# refresh debugging name
|
2025-07-16 15:20:55 +00:00
|
|
|
|
_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
|
2025-07-19 07:02:32 +00:00
|
|
|
|
SceneManager.enter_main_scene()
|
2025-07-16 15:20:55 +00:00
|
|
|
|
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)
|