实现可配置的自动存档机制

This commit is contained in:
cakipaul 2024-12-24 19:24:55 +08:00
parent cdac22503b
commit 33f3088ba7
25 changed files with 441 additions and 252 deletions

View File

@ -1,8 +0,0 @@
#1111
class_name EntryPoint
extends Marker2D
@export var direction := heroine.Direction.RIGHT
func _ready() -> void:
add_to_group("entry_points")

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,9 @@
class_name AssembledArchive extends Resource
@export var archive_id := 0
@export var current_chapter := 0
@export var current_section := 0
@export var game_seconds_all := 0
@export var game_seconds_current := 0
@export var created_time := "2024-12-24 00:00:00"

View File

@ -5,8 +5,7 @@ class DeploymentItemConfig:
extends Resource extends Resource
var entity_name: String = "" var entity_name: String = ""
var position: Vector2 = Vector2(0, 0) var position: Vector2 = Vector2(0, 0)
var initial_state := ""
@export var scene_name: String = "" @export var scene_name: String = ""
@export var items: Array[DeploymentItemConfig] @export var items := {} # entity_name: DeploymentItemConfig

View File

@ -1,10 +1,17 @@
class_name DialogConfig extends Resource class_name DialogConfig extends Resource
@export var dialog_name: String
# font style and effect are defined according to the character # font style and effect are defined according to the character
@export var dialog_character_name: String
@export var effect := ""
@export var dialog_character_animation: String # empty string means no animation class DialogItem:
@export var dialog_content: String extends Resource
@export var dialog_audio: String var dialog_character_name: String = ""
@export var dialog_skipable := true var effect: String = ""
var dialog_character_animation: String = ""
var dialog_content: String = ""
var dialog_audio: String = ""
var dialog_skipable: bool = true
@export var dialog_name: String
@export var dialog_items: Array[DialogItem]

View File

@ -3,29 +3,22 @@ class_name EntityConfig extends Resource
class EntityStateConfig: class EntityStateConfig:
extends Resource extends Resource
var state_name: String = ""
var animation: String = "" var animation: String = ""
var scale: Vector2 = Vector2.ONE
var offset: Vector2 = Vector2.ZERO
var expected_duration: float = 1.0 # for placeholder demo only
var loop: bool = false var loop: bool = false
var sound: String = "" var sound: String = ""
var state_title: String = "" # use default if empty
var state_note: String = "" # use default if empty
var actions: Array[String] = []
class EntityActionConfig:
extends Resource
var action_name: String = ""
var next_state: String = "" # empty means keep current state
var animation: String = ""
var sound: String = ""
var callback: Callable
@export var entity_name: String = "" @export var entity_name: String = ""
@export var placeholder_size: Vector2 = Vector2(32, 64) @export var placeholder_size := Vector2(32, 64)
@export var offset: Vector2 = Vector2(0, 0) @export var offset := Vector2(0, 0)
@export var entity_title: String = "" @export var entity_title: String = ""
@export var entity_note: String = "" @export var entity_note: String = ""
@export var initializer: Callable @export var entity_state_default: EntityStateConfig
@export var entity_states: Array[EntityStateConfig] @export var physical_vibe_effect: PackedScene
@export var entity_actions: Array[EntityActionConfig] @export var pickable := false
@export var entity_state_hud: EntityStateConfig
@export var entity_state_inspection: EntityStateConfig
@export var inspection_gameplay: PackedScene

View File

@ -13,11 +13,10 @@
{ {
"event_date": "12/23/2024", "event_date": "12/23/2024",
"item_id": "4123576587", "item_id": "4123576587",
"log_content": "动画资产管理:分页加载资源\n\n定义基本的规格配置、组装部署、资产填充数据结构", "log_content": "* 完善消息提示功能\n * 0.5s 浮现,显示 3s0.5s 隐藏(通过调整 alpha 通道实现)\n * 支持堆积消息\n * 如果有堆积的消息,显示 2s而不是 3s",
"tags": [ "tags": [
"2@ui", "2@ui",
"3@art_tool", "2@code"
"2@design"
], ],
"update_date": "12/24/2024" "update_date": "12/24/2024"
}, },
@ -82,4 +81,4 @@
"update_date": "12/22/2024" "update_date": "12/22/2024"
} }
] ]
} }

View File

@ -1,124 +1,159 @@
extends Node extends Node
@export var user_archive_root_dir := "user://archive/" # must end with "/" @export var user_root_dir := "user://data/" # must end with "/"
@export var save_dir_prefix := "save" @export var archive_dir := "user://data/archives/"
@export var archive_prefix := "save"
@export var archive: AssembledArchive # current archive
var accessible := false
var archives: Array[int] # archive id list in ascending order var archives: Array[int] # archive id list in ascending order
var managers = {
"TimeManager": TimeManager,
"EntityManager": EntityManager,
"SceneManager": SceneManager,
"InputManager": InputManager,
# "ArchiveManager" : ArchiveManager, #self
# "AudioManager" : AudioManager,
# "EventManager" : EventManager,
# "CameraManager" : CameraManager,
# "DialogManager" : DialogManager,
# "CgManager": CgManager,
}
var autosave_timer := Timer.new() var autosave_timer := Timer.new()
func _ready() -> void: func _ready() -> void:
accessible = _check_archive_dirs() if not _check_dirs_and_archives():
if !accessible: # TODO warning and exist
return return
# _open_log_file()
add_child(autosave_timer)
autosave_timer.wait_time = GlobalConfigManager.config.auto_save_seconds
autosave_timer.one_shot = false
autosave_timer.timeout.connect(_try_auto_save) autosave_timer.timeout.connect(_try_auto_save)
autosave_timer.stop() autosave_timer.stop()
GlobalConfigManager.config.current_selected_save_changed.connect(_check_autosave_options) add_child(autosave_timer)
GlobalConfigManager.config.auto_save_seconds_changed.connect(_check_autosave_options) # config should be loaded first
load_all() load_config()
# TODO NOTICE auto load archive on debug mode
if GlobalConfig.DEBUG:
if archives.size() == 0:
create_and_use_new_archive()
else:
GlobalConfigManager.config.current_selected_archive_id = archives[0]
func _archive_id_changed():
var selected_id = GlobalConfigManager.config.current_selected_archive_id
if archive:
if selected_id != archive.archive_id:
ResourceSaver.save(archive)
archive = null
else:
return
if selected_id < 0:
return
var path = archive_dir + archive_prefix + str(selected_id) + GlobalConfig.RES_FILE_FORMAT
archive = ResourceLoader.load(path, "", ResourceLoader.CACHE_MODE_REPLACE_DEEP)
if !archive:
create_and_use_new_archive(selected_id)
SceneManager.pop_notification("已创建新存档")
else:
load_archive()
func _check_autosave_options(): func _check_autosave_options():
if ( if archive and GlobalConfigManager.config.auto_save_seconds > 1:
GlobalConfigManager.config.auto_save_seconds > 5 # reset left time
and GlobalConfigManager.config.current_selected_save >= 0 autosave_timer.stop()
): autosave_timer.one_shot = false
autosave_timer.wait_time = GlobalConfigManager.config.auto_save_seconds
autosave_timer.start() autosave_timer.start()
else: else:
autosave_timer.stop() autosave_timer.stop()
func _try_auto_save(): func _try_auto_save():
if ( print("Auto save")
GlobalConfigManager.config.auto_save_seconds > 5 if archive and GlobalConfigManager.config.auto_save_seconds > 1:
and GlobalConfigManager.config.current_selected_save >= 0
):
save_all() save_all()
SceneManager.pop_notification("自动保存成功") SceneManager.pop_notification("自动保存成功")
func _check_archive_dirs() -> bool: func _check_dirs_and_archives() -> bool:
if !DirAccess.dir_exists_absolute(user_root_dir):
DirAccess.make_dir_recursive_absolute(user_root_dir)
print("Create user_root_dir:", user_root_dir)
# Check if the archive directory is accessible # Check if the archive directory is accessible
if !DirAccess.dir_exists_absolute(user_archive_root_dir): if !DirAccess.dir_exists_absolute(archive_dir):
DirAccess.make_dir_recursive_absolute(user_archive_root_dir) DirAccess.make_dir_recursive_absolute(archive_dir)
print("Create archive directory:", user_archive_root_dir) print("Create archive_dir:", archive_dir)
var archive_dir_access = DirAccess.open(user_archive_root_dir) var archive_dir_access = DirAccess.open(archive_dir)
if !archive_dir_access: if !archive_dir_access:
printerr("Archive directory is not accessible") _handle_load_error("存档目录", "读取")
# TODO pop up a dialog to inform the user # TODO pop up a dialog to inform the user
return false return false
var files = archive_dir_access.get_files() var files = archive_dir_access.get_files()
# get archive number # get archive number
for file in files: for file in files:
if file.begins_with(save_dir_prefix): if file.begins_with(archive_prefix):
var id_str = file.substr(save_dir_prefix.length()) var id_str = file.substr(archive_prefix.length())
var id = int(id_str) var id = int(id_str)
archives.append(id) archives.append(id)
archives.sort() archives.sort()
return true return true
# id = -1 means create a new archive, otherwise create an archive with the given id
func create_and_use_new_archive(id := -1) -> void:
_check_dirs_and_archives()
archive = AssembledArchive.new()
var archive_path = archive_dir + archive_prefix + str(id) + GlobalConfig.RES_FILE_FORMAT
if id < 0:
id = 0
# find a new id
archive_path = (archive_dir + archive_prefix + str(id) + GlobalConfig.RES_FILE_FORMAT)
while FileAccess.file_exists(archive_path):
id += 1
archive_path = (archive_dir + archive_prefix + str(id) + GlobalConfig.RES_FILE_FORMAT)
archive.archive_id = id
archive.resource_path = archive_path
archive.created_time = Time.get_datetime_string_from_system(false, true)
ResourceSaver.save(archive, archive_path)
archives.append(id)
# this will auto trigger signal and load the new archive
GlobalConfigManager.config.current_selected_archive_id = id
func save_all() -> void: func save_all() -> void:
# save config # save config
var config = GlobalConfigManager.config var config = GlobalConfigManager.config
var path = user_archive_root_dir + "config" + GlobalConfig.RES_FILE_FORMAT if config:
ResourceSaver.save(config, path) ResourceSaver.save(config)
if not accessible or GlobalConfigManager.config.current_selected_save == -1: if archive:
ResourceSaver.save(archive)
# reset autosave timer
_check_autosave_options()
func load_config() -> void:
if GlobalConfigManager.config:
return return
# Save all managers by the current selected save var path = user_root_dir + "config" + GlobalConfig.RES_FILE_FORMAT
for manager in managers:
# .tres
var res = managers[manager].get_data_res()
if !res:
continue
# save to file
path = (
user_archive_root_dir
+ str(config.current_selected_save)
+ "/"
+ manager
+ GlobalConfig.RES_FILE_FORMAT
)
ResourceSaver.save(res, path)
func load_all() -> void:
_check_archive_dirs()
# load config
var path = user_archive_root_dir + "config" + GlobalConfig.RES_FILE_FORMAT
var config
if FileAccess.file_exists(path): if FileAccess.file_exists(path):
config = ResourceLoader.load(path) var config = ResourceLoader.load(path)
GlobalConfigManager.load_data_res(config) GlobalConfigManager.config = config
else: else:
config = GlobalConfigManager.config var config = GlobalConfig.new()
# save config GlobalConfigManager.config = config
ResourceSaver.save(config, path) ResourceSaver.save(config, path)
if not accessible or config.current_selected_save == -1: GlobalConfigManager.config.resource_path = path
# connect signals
GlobalConfigManager.config.current_selected_archive_id_changed.connect(_archive_id_changed)
GlobalConfigManager.config.auto_save_seconds_changed.connect(_check_autosave_options)
func load_archive() -> void:
_check_dirs_and_archives()
var selected_id = GlobalConfigManager.config.current_selected_archive_id
if not archives.has(selected_id):
_handle_load_error(str(selected_id) + " 号存档", "查找")
return return
# Load managers by the current selected save var path = archive_dir + archive_prefix + str(selected_id) + GlobalConfig.RES_FILE_FORMAT
path = user_archive_root_dir + save_dir_prefix + str(config.current_selected_save) + "/" archive = ResourceLoader.load(path)
for manager in managers: if !archive:
var manager_path = path + manager + GlobalConfig.RES_FILE_FORMAT _handle_load_error(str(selected_id) + " 号存档", "加载")
if FileAccess.file_exists(manager_path): return
var res = ResourceLoader.load(manager_path) archive.resource_path = path
managers[manager].load_data_res(res) _check_autosave_options()
func _handle_load_error(target, action) -> void:
var msg = str(target) + " " + str(action) + " 失败"
SceneManager.pop_notification(msg)
printerr(msg)
# TODO handle error

View File

@ -1,11 +1,5 @@
extends Node extends Node
# Called when the node enters the scene tree for the first time. func play_sfx(sfx: String) -> void:
func _ready() -> void: pass
pass # Replace with function body.
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
pass

View File

@ -13,16 +13,15 @@ const CANVAS_LAYER_UI = 99
const CANVAS_LAYER_FG = 50 const CANVAS_LAYER_FG = 50
const CANVAS_LAYER_BG = -100 const CANVAS_LAYER_BG = -100
signal current_selected_save_changed signal current_selected_archive_id_changed
signal auto_save_seconds_changed signal auto_save_seconds_changed
# 注意:编辑与新增属性时,需要同时编辑 GlobalConfigManager.gd 中的 load_data_res 方法 @export var game_total_seconds := 0 # 游戏总时长
@export var game_total_seconds := 0 # 游戏总时长
@export var game_rounds := 1 # 当前周目数 @export var game_rounds := 1 # 当前周目数
@export var current_selected_save := -1: # 当前选定存档 id, -1 means no save selected @export var current_selected_archive_id := -1: # 当前选定存档, -1 为未选择
set(val): set(val):
current_selected_save = val current_selected_archive_id = val
current_selected_save_changed.emit() current_selected_archive_id_changed.emit()
@export var auto_save_seconds := 60: @export var auto_save_seconds := 60:
set(val): set(val):
auto_save_seconds = val auto_save_seconds = val

View File

@ -1,15 +1,3 @@
extends Node extends Node
var config = GlobalConfig.new() var config: GlobalConfig
func get_data_res() -> Resource:
return config
func load_data_res(data: Resource) -> void:
var new_config = data as GlobalConfig
config.game_total_seconds = new_config.game_total_seconds
config.game_rounds = new_config.game_rounds
config.current_selected_save = new_config.current_selected_save
config.auto_save_seconds = new_config.auto_save_seconds

View File

@ -0,0 +1,3 @@
[gd_scene format=3 uid="uid://ducfqojekphh6"]
[node name="Assembler" type="Node2D"]

View File

@ -0,0 +1,23 @@
@tool
extends Node2D
@export var placeholder_name := "placeholder":
set(val):
placeholder_name = val
_reload()
@export var placeholder_size: Vector2 = Vector2(32, 64):
set(val):
placeholder_size = val
_reload()
@export var offset: Vector2 = Vector2(0, 0):
set(val):
offset = val
_reload()
@export var packed_scene: PackedScene:
set(val):
packed_scene = val
_reload()
func _reload():
pass

View File

@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://c1ekdt4b08nac"]
[ext_resource type="Script" path="res://manager/deploy/assemble/placeholder_2d.gd" id="1_0l7tn"]
[node name="Placeholder2D" type="Node2D"]
script = ExtResource("1_0l7tn")

View File

@ -0,0 +1,74 @@
@tool
class_name EntityLoader extends Node2D
@export var state: String:
set(value):
state = value
_init_state()
@export var entity_config: EntityConfig:
set(value):
entity_config = value
entity_config.changed.connect(_reload)
# Load the entity config
_reload()
@export
var sprite_frames = preload("res://config/animation/player_sprite_frames.tres") as SpriteFrames
@onready var sprite2d = %AnimatedSprite2D as AnimatedSprite2D
func _ready() -> void:
if GlobalConfig.DEBUG:
add_child(DebugLabel.new())
func _reload() -> void:
# rm children
state = entity_config.initial_state
_init_state()
func _init_state() -> void:
if not entity_config:
return
## free unused children
# TODO Load current state according to entity config
var success := false
# Add placeholder if state's missing
if not success:
_init_placeholder()
else:
sprite2d.scale = entity_config.scale
func _init_placeholder():
if not entity_config.placeholder_size:
return
var sprite = get_node_or_null("PlaceholderSprite") as Node2D
if sprite:
sprite.visible = true
else:
sprite = Sprite2D.new()
add_child(sprite)
sprite.texture = placeholder_pic
sprite.scale = entity_config.placeholder_size / sprite.texture.get_size()
sprite.offset = entity_config.offset
sprite.name = "PlaceholderSprite"
var label = get_node_or_null("PlaceholderLabel") as Node2D
if label:
label.visible = true
else:
label = Label.new()
add_child(label)
label.text = "[" + entity_config.entity_name + "]" + entity_config.entity_title + ":" + state
label.modulate = Color.GREEN
label.name = "PlaceholderLabel"
func switch_state(state_name: String) -> void:
state = state_name
_init_state()
func action(action_name: String) -> void:
# TODO
pass

View File

@ -0,0 +1,65 @@
[gd_scene load_steps=7 format=3 uid="uid://do5j7vqrviv48"]
[ext_resource type="Script" path="res://manager/deploy/entity/entity_loader.gd" id="1_0ynbr"]
[ext_resource type="SpriteFrames" uid="uid://cs44glabs8sma" path="res://config/animation/player_sprite_frames.tres" id="2_7crsu"]
[sub_resource type="GDScript" id="GDScript_gcl2t"]
[sub_resource type="GDScript" id="GDScript_dhqgj"]
[sub_resource type="GDScript" id="GDScript_ybgaq"]
script/source = "class_name EntityConfig extends Resource
class EntityStateConfig:
extends Resource
var state_name: String = \"default\"
var animation: String = \"\"
var loop: bool = false
var sound: String = \"\"
var state_title: String = \"\" # use default if empty
var state_note: String = \"\" # use default if empty
var actions: Array[String] = []
class EntityActionConfig:
extends Resource
var action_name: String = \"\"
var next_state: String = \"\" # empty means keep current state
var animation: String = \"\"
var sound: String = \"\"
var callback: Callable # receive the entity as argument
@export var entity_name: String = \"\"
@export var placeholder_size: Vector2 = Vector2(32, 64)
@export var offset: Vector2 = Vector2(0, 0)
@export var entity_title: String = \"\"
@export var entity_note: String = \"\"
@export var initial_state: String = \"default\"
@export var initializer: Callable
@export var entity_states: Array[EntityStateConfig]
@export var entity_actions: Array[EntityActionConfig]
"
[sub_resource type="Resource" id="Resource_6wfuj"]
script = SubResource("GDScript_ybgaq")
entity_name = ""
placeholder_size = Vector2(32, 64)
offset = Vector2(0, 0)
entity_title = ""
entity_note = ""
initial_state = "default"
initializer = Callable()
entity_states = Array[SubResource("GDScript_dhqgj")]([])
entity_actions = Array[SubResource("GDScript_gcl2t")]([])
[node name="EntityLoader" type="Node2D"]
script = ExtResource("1_0ynbr")
state = "default"
entity_config = SubResource("Resource_6wfuj")
sprite_frames = null
[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."]
unique_name_in_owner = true
sprite_frames = ExtResource("2_7crsu")

View File

@ -9,10 +9,3 @@ func _ready() -> void:
# Called every frame. 'delta' is the elapsed time since the previous frame. # Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void: func _process(delta: float) -> void:
pass pass
func get_data_res() -> Resource:
return null
func load_data_res(data: Resource) -> void:
pass

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@ -5,11 +5,4 @@ func pop_notification(msg: String, number := 1) -> void:
if notification_node: if notification_node:
notification_node.show_notification(msg, number) notification_node.show_notification(msg, number)
else: else:
printerr("Notification node not found") printerr("Notification node not found")
func get_data_res() -> Resource:
return null
func load_data_res(data: Resource) -> void:
pass

View File

@ -10,10 +10,3 @@ func _ready() -> void:
func _process(delta: float) -> void: func _process(delta: float) -> void:
pass pass
func get_data_res() -> Resource:
return null
func load_data_res(data: Resource) -> void:
pass

View File

@ -1,15 +1,11 @@
extends Node extends Node
@export var current_chapter := 0
@export var current_section := 0
@export var game_seconds_all := 0
@export var game_seconds_current := 0
var timer: Timer var timer: Timer
func _ready() -> void: func _ready() -> void:
timer = Timer.new() timer = Timer.new()
timer.wait_time = 1 timer.wait_time = 5
timer.one_shot = false timer.one_shot = false
timer.timeout.connect(_on_timer_timeout) timer.timeout.connect(_on_timer_timeout)
add_child(timer) add_child(timer)
@ -17,33 +13,40 @@ func _ready() -> void:
func _on_timer_timeout(): func _on_timer_timeout():
game_seconds_all += 1 var archive = ArchiveManager.archive
game_seconds_current += 1 if archive:
GlobalConfigManager.config.game_total_seconds += 1 archive.game_seconds_all += 5
archive.game_seconds_current += 5
GlobalConfigManager.config.game_total_seconds += 5
func pack_current_time(): func pack_current_time():
var packed_time = PackedTime.new() var packed_time = PackedTime.new()
packed_time.time = Time.get_datetime_string_from_system(false, true) packed_time.time = Time.get_datetime_string_from_system(false, true)
packed_time.chapter = current_chapter var archive = ArchiveManager.archive
packed_time.section = current_section if archive:
packed_time.game_archive_id = ArchiveManager.current_archive_id packed_time.chapter = archive.current_chapter
packed_time.game_seconds_all = game_seconds_all packed_time.section = archive.current_section
packed_time.game_seconds_current = game_seconds_current packed_time.game_archive_id = archive.archive_id
packed_time.game_seconds_all = archive.game_seconds_all
packed_time.game_seconds_current = archive.game_seconds_current
# for log use # for log use
func get_concise_timemark() -> String: func get_concise_timemark() -> String:
var hour := game_seconds_current / 3600 as int var archive = ArchiveManager.archive
var minute := (game_seconds_current % 3600) / 60 as int if not archive:
var second := game_seconds_current % 60 return "r0_c0_s0 00:00:00"
var hour = archive.game_seconds_current / 3600 as int
var minute = (archive.game_seconds_current % 3600) / 60 as int
var second = archive.game_seconds_current % 60
return ( return (
"r" "r"
+ str(ArchiveManager.current_archive_id) + str(ArchiveManager.current_archive_id)
+ "_c" + "_c"
+ str(current_chapter) + str(archive.current_chapter)
+ "_s" + "_s"
+ str(current_section) + str(archive.current_section)
+ " " + " "
+ str(hour) + str(hour)
+ ":" + ":"
@ -51,13 +54,3 @@ func get_concise_timemark() -> String:
+ ":" + ":"
+ str(second) + str(second)
) )
func get_data_res() -> Resource:
return pack_current_time()
func load_data_res(data: Resource) -> void:
var packed_time = data as PackedTime
game_seconds_all = packed_time.game_seconds_all
game_seconds_current = packed_time.game_seconds_current
current_chapter = packed_time.chapter
current_section = packed_time.section

View File

@ -34,11 +34,11 @@ buses/default_bus_layout="res://config/default_bus_layout.tres"
DebugMenu="*res://addons/debug_menu/debug_menu.tscn" DebugMenu="*res://addons/debug_menu/debug_menu.tscn"
GlobalConfigManager="*res://manager/config_manager/global_config_manager.gd" GlobalConfigManager="*res://manager/config_manager/global_config_manager.gd"
TimeManager="*res://manager/time_manager/time_manager.gd" TimeManager="*res://manager/time_manager/time_manager.gd"
EntityManager="*res://manager/assemble/entity/entity_manager.gd" EntityManager="*res://manager/deploy/entity/entity_manager.gd"
SceneManager="*res://manager/assemble/scene/scene_manager.gd" SceneManager="*res://manager/deploy/scene/scene_manager.gd"
AudioManager="*res://manager/audio_manager/audio_manager.gd" AudioManager="*res://manager/audio_manager/audio_manager.gd"
EventManager="*res://manager/event_manager/event_manager.gd" EventManager="*res://manager/event_manager/event_manager.gd"
DialogManager="*res://manager/assemble/dialog/dialog_manager.gd" DialogManager="*res://manager/deploy/dialog/dialog_manager.gd"
CameraManager="*res://manager/camera_manager/camera_manager.gd" CameraManager="*res://manager/camera_manager/camera_manager.gd"
CgManager="*res://manager/cg_manager/cg_manager.gd" CgManager="*res://manager/cg_manager/cg_manager.gd"
InputManager="*res://manager/input/input_manager.gd" InputManager="*res://manager/input/input_manager.gd"

View File

@ -40,7 +40,7 @@ func show_notification(msg, number):
func _check_next(): func _check_next():
tweening = false
if pending_notifications.size() > 0: if pending_notifications.size() > 0:
var n = pending_notifications.pop_front() var n = pending_notifications.pop_front()
tweening = false
show_notification(n[0], n[1]) show_notification(n[0], n[1])

22
util/debug_label.gd Normal file
View File

@ -0,0 +1,22 @@
class_name DebugLabel extends Label
@export var enabled := false:
set(value):
enabled = value
if enabled:
_display()
else:
_hide()
func _ready() -> void:
if not GlobalConfig.DEBUG:
return
func _hide():
visible = false
func _display():
pass