P24-02: 操作と通知の全受入

This commit is contained in:
Agent Control Runner
2026-10-13 12:53:16 +09:00
parent 1a5abc6516
commit 666c87bd7d
17 changed files with 1952 additions and 12 deletions
+81 -6
View File
@@ -12,19 +12,38 @@ var _new_path := ""
var _new_name := ""
var _message: Label
var _slots: ItemList
var _label_edit: LineEdit
var _validation_label: Label
var _rows: Array[Dictionary] = []
func _ready() -> void:
name = "ManualSaveSlotsDialog"
cancel_button_text = "戻る"
var column := VBoxContainer.new()
column.custom_minimum_size = Vector2(460, 220)
column.custom_minimum_size = Vector2(460, 240)
add_child(column)
_message = Label.new()
_message.name = "ManualSaveSlotsMessage"
_message.custom_minimum_size.x = 460
_message.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
column.add_child(_message)
_label_edit = LineEdit.new()
_label_edit.name = "ManualSaveLabelEdit"
_label_edit.custom_minimum_size = Vector2(460, 32)
_label_edit.placeholder_text = "セーブデータの名前(日本語入力可)"
_label_edit.max_length = 60
_label_edit.text_changed.connect(_on_label_text_changed)
column.add_child(_label_edit)
_label_edit.hide()
_validation_label = Label.new()
_validation_label.name = "ManualSaveValidationLabel"
_validation_label.add_theme_font_size_override("font_size", 11)
_validation_label.add_theme_color_override("font_color", Color("e06c75"))
column.add_child(_validation_label)
_validation_label.hide()
_slots = ItemList.new()
_slots.name = "ManualSaveSlotsList"
_slots.custom_minimum_size = Vector2(460, 150)
@@ -50,9 +69,20 @@ func show_new_save(current_path: String) -> void:
_new_name = "手動保存 " + Time.get_datetime_string_from_system(false, true)
var fresh: bool = not _new_path.is_empty() and is_fresh_slot(_new_path)
get_ok_button().disabled = not fresh
_message.text = "今の進行は、元の保存とは別に保存します。\n元の保存は残り、あとから読込一覧で選べます。\n\n" + _new_name if fresh else "新しい保存先を用意できませんでした。\n元の保存は変更していません。"
popup_centered(Vector2i(520, 300))
get_cancel_button().grab_focus()
_message.text = "今の進行は、元の保存とは別に保存します。\n元の保存は残り、あとから読込一覧で選べます。\n保存の名前(日本語入力対応):" if fresh else "新しい保存先を用意できませんでした。\n元の保存は変更していません。"
if fresh:
_label_edit.show()
_label_edit.text = _new_name
_validation_label.hide()
else:
_label_edit.hide()
_validation_label.hide()
popup_centered(Vector2i(520, 320))
if fresh:
_label_edit.grab_focus()
_label_edit.select_all()
else:
get_cancel_button().grab_focus()
func show_load_slots(current_path: String) -> void:
_clear_choice()
@@ -61,6 +91,8 @@ func show_load_slots(current_path: String) -> void:
title = "保存スロットを選んで読込"
ok_button_text = "選んで読込"
_message.text = "読み込む保存を選んでください。\n現在の未保存の進行は、選んだ保存で置き換わります。"
_label_edit.hide()
_validation_label.hide()
_slots.show()
_slots.clear()
_rows = read_slot_rows(_directory)
@@ -121,12 +153,48 @@ static func read_slot_rows(directory: String) -> Array[Dictionary]:
rows.append({&"path": path, &"label": label, &"loadable": loadable})
return rows
static func is_valid_label_text(text: String) -> Dictionary:
if text.length() > 60:
return {&"ok": false, &"error": "セーブ名は60文字以内で入力してください。"}
for i in range(text.length()):
var c := text.unicode_at(i)
if c < 32 and c != 9:
return {&"ok": false, &"error": "制御文字は入力できません。"}
return {&"ok": true, &"error": ""}
func _on_label_text_changed(new_text: String) -> void:
if _mode != "new":
return
var fresh: bool = not _new_path.is_empty() and is_fresh_slot(_new_path)
if not fresh:
get_ok_button().disabled = true
return
var check := is_valid_label_text(new_text)
if not bool(check[&"ok"]):
_validation_label.text = String(check[&"error"])
_validation_label.show()
get_ok_button().disabled = true
else:
_validation_label.hide()
get_ok_button().disabled = false
func _select_slot(index: int) -> void:
get_ok_button().disabled = index < 0 or index >= _rows.size() or not _rows[index][&"loadable"]
func _confirm_choice() -> void:
if _mode == "new" and is_fresh_slot(_new_path):
new_slot_requested.emit(_new_path, _new_name)
if _mode == "new":
if not is_fresh_slot(_new_path):
_clear_choice()
return
var raw_name := _label_edit.text.strip_edges() if _label_edit != null else ""
var check := is_valid_label_text(raw_name)
if not bool(check[&"ok"]):
_validation_label.text = String(check[&"error"])
_validation_label.show()
get_ok_button().disabled = true
return
var final_name := raw_name if not raw_name.is_empty() else _new_name
new_slot_requested.emit(_new_path, final_name)
elif _mode == "load":
var selected: PackedInt32Array = _slots.get_selected_items()
if selected.size() == 1 and selected[0] >= 0 and selected[0] < _rows.size() and _rows[selected[0]][&"loadable"]:
@@ -137,8 +205,15 @@ func _clear_choice() -> void:
_mode = ""
_new_path = ""
_new_name = ""
if _label_edit != null:
_label_edit.text = ""
_label_edit.hide()
if _validation_label != null:
_validation_label.hide()
_rows.clear()
func apply_layer_skin(layer: int) -> void:
if _message != null: LayerSkin.register_text(_message, layer)
if _validation_label != null: LayerSkin.register_status_text(_validation_label, false, layer)
LayerSkin.apply_tree(self, layer)