From 5e0183a8a466304693f8a13576c9a9fd16fbf40e Mon Sep 17 00:00:00 2001 From: cakipaul Date: Tue, 21 Jan 2025 15:58:21 +0800 Subject: [PATCH] =?UTF-8?q?GroundLoader=20=E5=AE=9E=E7=8E=B0=E9=A2=84?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E9=82=BB=E5=B1=85=E5=9C=BA=E6=99=AF=EF=BC=9B?= =?UTF-8?q?=E5=AE=8C=E5=96=84=E8=BD=AC=E5=9C=BA=E6=95=88=E6=9E=9C=EF=BC=9B?= =?UTF-8?q?=E5=85=A8=E5=B1=80=E6=8E=A7=E5=88=B6=20player=20=E5=A5=94?= =?UTF-8?q?=E8=B7=91=E9=94=81=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- addons/gif-importer/importer_plugin.gd | 6 +- asset/art/ui/{ => prop}/prop遮罩.png | Bin asset/art/ui/{ => prop}/prop遮罩.png.import | 6 +- asset/art/ui/prop/遮罩.png | Bin 0 -> 38717 bytes asset/art/ui/prop/遮罩.png.import | 34 ++++ config/animation/frames_display_card.gd | 5 +- manager/archive_manager/archive_manager.gd | 5 +- manager/archive_manager/assembled_archive.gd | 10 ++ manager/config_manager/global_config.gd | 3 +- .../config_manager/global_config_manager.gd | 4 +- scene/entity/portal.gd | 2 +- scene/ground/ground.gd | 6 + scene/ground/ground_loader.gd | 147 ++++++++++++------ scene/ground/ground_loader.tscn | 13 ++ scene/ground/scene/animation_root.gd | 11 ++ scene/ground/scene/c01/s05_animation.gd | 3 + scene/ground/scene/c01/s05_院长房间.tscn | 35 ++++- scene/ground/scene/c01/s06_animation.gd | 2 + .../ground/scene/c01/s06_孤儿院长廊围墙.tscn | 3 + scene/ground/scene/c02/s01_街道.tscn | 3 +- scene/ground/scene/c02/s02_animation.gd | 2 + scene/ground/scene/c02/s02_走道.tscn | 1 + scene/ground/scene/c02/s03_animation.gd | 2 + scene/ground/scene/c02/s03_院子切换.tscn | 5 +- scene/ground/scene/template_animation.gd | 2 + scene/player/main_player.gd | 11 ++ scene/prop/prop_inspector.tscn | 6 +- util/lru.gd | 49 ++++++ 28 files changed, 304 insertions(+), 72 deletions(-) rename asset/art/ui/{ => prop}/prop遮罩.png (100%) rename asset/art/ui/{ => prop}/prop遮罩.png.import (71%) create mode 100644 asset/art/ui/prop/遮罩.png create mode 100644 asset/art/ui/prop/遮罩.png.import create mode 100644 util/lru.gd diff --git a/addons/gif-importer/importer_plugin.gd b/addons/gif-importer/importer_plugin.gd index ac4f0d0d..e7c52eb6 100644 --- a/addons/gif-importer/importer_plugin.gd +++ b/addons/gif-importer/importer_plugin.gd @@ -97,10 +97,10 @@ func _import(source_file, save_path, options, platform_variants, gen_files): var image = texture.get_image() var image_path = dir_name + str(i) + ".png" image.save_png(image_path) - image.resource_path = image_path - var new_texture = ImageTexture.create_from_image(image) + texture = ImageTexture.create_from_image(image) + texture.take_over_path(image_path) var duration = frames.get_frame_duration("gif", i) - sprite_frames.add_frame(animation_name, new_texture, duration) + sprite_frames.add_frame(animation_name, texture, duration) print_debug("Created images and added to SpriteFrames: ", animation_name) ResourceSaver.save(sprite_frames) return code diff --git a/asset/art/ui/prop遮罩.png b/asset/art/ui/prop/prop遮罩.png similarity index 100% rename from asset/art/ui/prop遮罩.png rename to asset/art/ui/prop/prop遮罩.png diff --git a/asset/art/ui/prop遮罩.png.import b/asset/art/ui/prop/prop遮罩.png.import similarity index 71% rename from asset/art/ui/prop遮罩.png.import rename to asset/art/ui/prop/prop遮罩.png.import index 52749b4f..745ff902 100644 --- a/asset/art/ui/prop遮罩.png.import +++ b/asset/art/ui/prop/prop遮罩.png.import @@ -3,15 +3,15 @@ importer="texture" type="CompressedTexture2D" uid="uid://cgghff16powfg" -path="res://.godot/imported/prop遮罩.png-f0336d91e6b2ddd4060007c0fc87eea0.ctex" +path="res://.godot/imported/prop遮罩.png-85fb17d3ccb28d9d3887ddc81281a85f.ctex" metadata={ "vram_texture": false } [deps] -source_file="res://asset/art/ui/prop遮罩.png" -dest_files=["res://.godot/imported/prop遮罩.png-f0336d91e6b2ddd4060007c0fc87eea0.ctex"] +source_file="res://asset/art/ui/prop/prop遮罩.png" +dest_files=["res://.godot/imported/prop遮罩.png-85fb17d3ccb28d9d3887ddc81281a85f.ctex"] [params] diff --git a/asset/art/ui/prop/遮罩.png b/asset/art/ui/prop/遮罩.png new file mode 100644 index 0000000000000000000000000000000000000000..58951e30009b790b03db1ff55f1f324110577065 GIT binary patch literal 38717 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 b8`1v-q$>S&X9cIg00000NkvXXu0mjf@TN3M literal 0 HcmV?d00001 diff --git a/asset/art/ui/prop/遮罩.png.import b/asset/art/ui/prop/遮罩.png.import new file mode 100644 index 00000000..caaa4943 --- /dev/null +++ b/asset/art/ui/prop/遮罩.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://f186lvt5y2ql" +path="res://.godot/imported/遮罩.png-dab9f7c60166ce0e17692f077a460bfb.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://asset/art/ui/prop/遮罩.png" +dest_files=["res://.godot/imported/遮罩.png-dab9f7c60166ce0e17692f077a460bfb.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/config/animation/frames_display_card.gd b/config/animation/frames_display_card.gd index a5b28af8..6b98640d 100644 --- a/config/animation/frames_display_card.gd +++ b/config/animation/frames_display_card.gd @@ -152,9 +152,10 @@ func _create_mirror(): var flipped_image = mirrored_frame.get_image() as Image flipped_image.flip_x() var flipped_img_path = mirror_dir_path + "/" + id + ".png" - flipped_image.resource_path = flipped_img_path flipped_image.save_png(flipped_img_path) - sprite_frames.add_frame(mirror_mapping, load(flipped_img_path)) + var texture = ImageTexture.create_from_image(flipped_image) + texture.take_over_path(flipped_img_path) + sprite_frames.add_frame(mirror_mapping, texture) sprite_frames.set_animation_speed(mapping_name, frames_per_sec) diff --git a/manager/archive_manager/archive_manager.gd b/manager/archive_manager/archive_manager.gd index 0672df5a..61e8c6b9 100644 --- a/manager/archive_manager/archive_manager.gd +++ b/manager/archive_manager/archive_manager.gd @@ -3,9 +3,8 @@ extends Node signal archive_loaded -static var archive := ( - load("user://data/archives/save0" + GlobalConfig.RES_FILE_FORMAT) as AssembledArchive -) # current archive +static var archive: AssembledArchive +# current archive static var user_root_dir := "user://data/" # must end with "/" static var archive_dir := "user://data/archives/" static var archive_prefix := "save" diff --git a/manager/archive_manager/assembled_archive.gd b/manager/archive_manager/assembled_archive.gd index b5f5efc0..3e02ab0b 100644 --- a/manager/archive_manager/assembled_archive.gd +++ b/manager/archive_manager/assembled_archive.gd @@ -21,10 +21,14 @@ class_name AssembledArchive extends Resource # created time @export var created_time := "2024-12-24 00:00:00" +# 全局参数 +@export var global_data_dict := {} # 不同场景的地面物品状态存档 @export var ground_archives = {} # true 为匿名,false 非匿名 @export var npc_anonymous_states = {} +# 玩家跑步锁定状态 +@export var player_running_locked := true # prop hud 显示道具 @export var prop_inventory: PropInventory @@ -51,3 +55,9 @@ func ground_archive(scene_name := current_scene) -> GroundArchive: return ground_archives[scene_name] +func set_global_entry(property: StringName, value) -> void: + global_data_dict[property] = value + + +func get_global_value(property: StringName) -> Variant: + return global_data_dict.get(property) diff --git a/manager/config_manager/global_config.gd b/manager/config_manager/global_config.gd index 56c306bc..83aaf4e3 100644 --- a/manager/config_manager/global_config.gd +++ b/manager/config_manager/global_config.gd @@ -11,7 +11,8 @@ const CANVAS_LAYER_DIALOG = 23 const CANVAS_LAYER_UI = 22 const CANVAS_LAYER_PROP_INSPECTOR = 21 const CANVAS_LAYER_SETTINGS = 20 -const CANVAS_LAYER_BAG = 11 +const CANVAS_LAYER_BAG = 12 +const CANVAS_LAYER_GROUND_MASK = 11 const CANVAS_LAYER_SHADING = 10 const CANVAS_LAYER_FG = 2 const CANVAS_LAYER_HD_ENTITY = 1 diff --git a/manager/config_manager/global_config_manager.gd b/manager/config_manager/global_config_manager.gd index 1cac5337..053843e4 100644 --- a/manager/config_manager/global_config_manager.gd +++ b/manager/config_manager/global_config_manager.gd @@ -1,9 +1,7 @@ @tool extends Node -static var config := ( - load("user://data/config" + GlobalConfig.RES_FILE_FORMAT) as GlobalConfig -): +static var config: GlobalConfig: set = _set_config var timer = Timer.new() diff --git a/scene/entity/portal.gd b/scene/entity/portal.gd index 77ebe819..8b7f5162 100644 --- a/scene/entity/portal.gd +++ b/scene/entity/portal.gd @@ -72,7 +72,7 @@ func _on_interacted() -> void: # 传送,queue free 导致 sfx 无法播放,使用全局声源 sfx.global_play() if GlobalConfig.DEBUG: - print("传送前往", target_scene, target_portal) + print("传送前往", target_scene, target_portal, " immediately=", immediately) var ground_loader = SceneManager.get_ground_loader() as GroundLoader if ground_loader: ground_loader.transition_to_scene(target_scene, target_portal, immediately) diff --git a/scene/ground/ground.gd b/scene/ground/ground.gd index aa9bb839..90af3e36 100644 --- a/scene/ground/ground.gd +++ b/scene/ground/ground.gd @@ -1,6 +1,7 @@ @tool class_name Ground2D extends Node2D +@export var scene_name := "" @export_group("Player", "player_") @export var player_y_fixed := true @export var player_y := 70: @@ -45,6 +46,11 @@ const FOOTSTEP_AUDIO = { func _ready() -> void: foreground.layer = GlobalConfig.CANVAS_LAYER_FG _reset_player_positon() + # 检查 scene_name 是否合法 + scene_name = scene_name.strip_edges() + if not scene_name or scene_name.length() != 7: + printerr("scene_name is not valid") + return if Engine.is_editor_hint(): return # 如果 debug 模式下不通过 GroundLoader 启动,读取 palyer 位置 diff --git a/scene/ground/ground_loader.gd b/scene/ground/ground_loader.gd index b0c5816a..ea2e29ea 100644 --- a/scene/ground/ground_loader.gd +++ b/scene/ground/ground_loader.gd @@ -8,35 +8,36 @@ class_name GroundLoader extends Node2D @export var debug_reload := false: set(new_val): debug_reload = false - if current_scene and entrance_portal: + if is_node_ready() and current_scene and entrance_portal: transition_to_scene(current_scene, entrance_portal, true) @export var archive_scene := "" @export var archive_portal := "" +@onready var mask_layer := %MaskLayer as CanvasLayer +@onready var mask := %Mask as ColorRect + var first_entered := true var ground: Ground2D +var display_mask_time = 0.0 var scenes_dir = "res://scene/ground/scene/" -var ground_dict = {} +# 场景名字映射到路径 +var ground_scene_path_dict = {} -# 预加载 portal 通往的场景 -var neighbor_scene_cache = {} func _ready() -> void: + mask_layer.layer = GlobalConfig.CANVAS_LAYER_GROUND_MASK + mask.visible = true + mask.color.a = 0.0 + # grounds _read_grounds() - ground = get_node_or_null("Ground") + # ground = get_node_or_null("Ground") # load save if not ignore_archive: _load_save() - if archive_scene and archive_portal: - current_scene = archive_scene - entrance_portal = archive_portal if current_scene and entrance_portal: transition_to_scene(current_scene, entrance_portal, true) - elif ground: - ground.queue_free() - ground = null func _read_grounds() -> void: @@ -47,9 +48,9 @@ func _read_grounds() -> void: for s_file in DirAccess.open(c_path).get_files(): if s_file.ends_with(".tscn"): var s_path = c_path + s_file - ground_dict[c_dir.substr(0, 3) + "_" + s_file.substr(0, 3)] = s_path + ground_scene_path_dict[c_dir.substr(0, 3) + "_" + s_file.substr(0, 3)] = s_path # # 确保每个 ground 都初始化 archive - # for key in ground_dict.keys(): + # for key in ground_scene_path_dict.keys(): # if GlobalConfig.DEBUG: # print("check ground_archive:", key) # ArchiveManager.archive.ground_archive(key) @@ -61,35 +62,41 @@ func _load_save(): archive_scene = ArchiveManager.archive.current_scene if ArchiveManager.archive.entrance_portal: archive_portal = ArchiveManager.archive.entrance_portal + # 使用 archive 所记录的场景 + if archive_scene and archive_portal: + current_scene = archive_scene + entrance_portal = archive_portal -func transition_to_scene(key: String, portal: String, immediately := false) -> void: - var scene_path = ground_dict[key] +func _toggle_mask(display: bool, _immediately: bool) -> Tween: + var tween = get_tree().create_tween() + if display: + tween.tween_property(mask, "color:a", 1.0, 0.3).set_trans(Tween.TRANS_CUBIC) + display_mask_time = Time.get_ticks_msec() + else: + # var time = Time.get_ticks_msec() + # # 转场至少 0.6s, 除去 0.3s 最后的淡出,需要 0.3s 的等待时间(包含 mask 的淡入) + # if not _immediately: + # var wait_time = max(display_mask_time + 300 - time, 0.0) * 0.001 + # if wait_time: + # tween.tween_interval(wait_time) + tween.tween_property(mask, "color:a", 0.0, 0.3).set_trans(Tween.TRANS_CUBIC) + return tween + + +func transition_to_scene(scene_name: String, portal: String, immediately: bool) -> void: + var scene_path = ground_scene_path_dict.get(scene_name) if scene_path: - var scene = load(scene_path).instantiate() - current_scene = key + current_scene = scene_name entrance_portal = portal # 优先更新 archive,使 ground 可以访问自己的 current_scene 键值 _update_archive() - if immediately: - _do_transition(scene) - # 更新玩家位置 - if first_entered: - _update_player_position() - else: - var tween = create_tween() as Tween - var player = SceneManager.get_player() as MainPlayer - if player: - player.action_locked = true - #TODO 转场效果 - # - tween.tween_interval(0.2) - tween.tween_callback(_do_transition.bind(scene)) - if player: - tween.tween_callback(func(): player.action_locked = false) - first_entered = false + # 转场效果,在 _load_ground_node 之前播放 + var tween = _toggle_mask(true, immediately) + tween.tween_callback(_do_transition.bind(scene_name)) + tween.tween_callback(_toggle_mask.bind(false, immediately)) else: - print("Scene not found: " + key) + print("Scene not found: " + scene_name) func _update_player_position(): @@ -104,17 +111,30 @@ func _update_player_position(): player.set_facing_direction(ArchiveManager.archive.player_direction) -func _do_transition(scene: Node2D): +func _do_transition(scene_name: String): + # SceneManager.freeze_player(0) + var ground_node = _load_ground_node(scene_name) + if ground == ground_node: + return if ground: # 提前移除,防止命名冲突 remove_child(ground) - ground.queue_free() - ground = scene.get_child(0) - scene.remove_child(ground) - ground.owner = null - scene.queue_free() - add_child(ground) + # 不需要释放,因为会缓存,在 ground_node_cache 中释放 + # ground.queue_free() + # 先设置 ground,再添加到场景中 + # 因为 ground 在 enter_tree 时会用到 SceneManager 的方法 + # 其中间接用到了 GroundLoader 的 ground + ground = ground_node + _add_ground() + # 预先加载邻居场景 + _post_transition() + if GlobalConfig.DEBUG and not Engine.is_editor_hint(): + _watch_scene_update() + + +func _add_ground(): ground.name = "Ground" + add_child(ground) if not Engine.is_editor_hint(): var portal_node = ground.get_node_or_null("DeployLayer/portal_" + entrance_portal) as Node2D if portal_node: @@ -126,8 +146,11 @@ func _do_transition(scene: Node2D): print("move player to portal:", entrance_portal, portal_node.global_position) else: printerr(current_scene + " portal not found: " + entrance_portal) - if GlobalConfig.DEBUG and not Engine.is_editor_hint(): - _watch_scene_update() + # 更新玩家位置 + if first_entered and not Engine.is_editor_hint(): + _update_player_position() + first_entered = false + # SceneManager.release_player() func _update_archive(): @@ -138,13 +161,47 @@ func _update_archive(): archive_portal = entrance_portal +func _load_ground_node(scene_name: String) -> Node2D: + if not ground_scene_path_dict.has(scene_name): + return null + var path = ground_scene_path_dict[scene_name] + var scene = ResourceLoader.load(path) as PackedScene + if scene: + var instance = scene.instantiate() as Node2D + var ground_node = instance.get_child(0) + instance.remove_child(ground_node) + ground_node.owner = null + instance.queue_free() + return ground_node + return null + + +# 读取 portals,预加载邻居场景 +func _post_transition(): + if ground: + var scene_names = [] + var deploy_layer = ground.get_node("DeployLayer") + if deploy_layer: + for node in deploy_layer.get_children(): + var portal = node as Portal2D + if not portal or not portal.target_scene: + continue + if ground_scene_path_dict.has(portal.target_scene): + scene_names.append(portal.target_scene) + if scene_names: + for scene_name in scene_names: + ResourceLoader.load_threaded_request(ground_scene_path_dict[scene_name]) + if GlobalConfig.DEBUG: + print("preload neighbor scenes:", scene_names) + + var update_watcher: Timer var last_modify_time = 0 # DEBUG 时重新加载资源 func _watch_scene_update(): - var scene_path = ground_dict[current_scene] + var scene_path = ground_scene_path_dict[current_scene] if scene_path: last_modify_time = FileAccess.get_modified_time(scene_path) if not update_watcher: diff --git a/scene/ground/ground_loader.tscn b/scene/ground/ground_loader.tscn index b984198c..0abb65ed 100644 --- a/scene/ground/ground_loader.tscn +++ b/scene/ground/ground_loader.tscn @@ -4,3 +4,16 @@ [node name="GroundLoader" type="Node2D"] script = ExtResource("1_6mjre") + +[node name="MaskLayer" type="CanvasLayer" parent="."] +unique_name_in_owner = true + +[node name="Mask" type="ColorRect" parent="MaskLayer"] +unique_name_in_owner = true +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +color = Color(0, 0, 0, 0) diff --git a/scene/ground/scene/animation_root.gd b/scene/ground/scene/animation_root.gd index 0e652613..ed4ed5cb 100644 --- a/scene/ground/scene/animation_root.gd +++ b/scene/ground/scene/animation_root.gd @@ -73,6 +73,17 @@ func set_data(property: StringName, value: Variant) -> bool: return false +func set_global_entry(property: StringName, value: Variant) -> void: + ArchiveManager.archive.set_global_entry(property, value) + + +func get_global_value(property: StringName, default_value = null) -> Variant: + var val = ArchiveManager.archive.get_global_value(property) + if val == null: + return default_value + return val + + func _get(property: StringName) -> Variant: if property == "oneshot_animation": return oneshot_animation diff --git a/scene/ground/scene/c01/s05_animation.gd b/scene/ground/scene/c01/s05_animation.gd index b4fb39cf..d564cccd 100644 --- a/scene/ground/scene/c01/s05_animation.gd +++ b/scene/ground/scene/c01/s05_animation.gd @@ -15,6 +15,8 @@ func _default_data() -> Dictionary: func _ready() -> void: super._ready() + if Engine.is_editor_hint(): + return func play_intro_dialogue(): @@ -42,6 +44,7 @@ func _on_deploy_layer_ready() -> void: if paper.interacted_times > 0: paper.visible = false paper.enabled = false + right_door.enabled = true else: paper.visible = true paper.enabled = true diff --git a/scene/ground/scene/c01/s05_院长房间.tscn b/scene/ground/scene/c01/s05_院长房间.tscn index 4005fbd0..3497d297 100644 --- a/scene/ground/scene/c01/s05_院长房间.tscn +++ b/scene/ground/scene/c01/s05_院长房间.tscn @@ -206,6 +206,30 @@ tracks/14/keys = { "update": 0, "values": [Vector2(1, 1)] } +tracks/15/type = "value" +tracks/15/imported = false +tracks/15/enabled = true +tracks/15/path = NodePath("DeployLayer/oneshot纸片/Sign:display_sign") +tracks/15/interp = 1 +tracks/15/loop_wrap = true +tracks/15/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [true] +} +tracks/16/type = "value" +tracks/16/imported = false +tracks/16/enabled = true +tracks/16/path = NodePath("DeployLayer/oneshot纸片/Sign:position") +tracks/16/interp = 1 +tracks/16/loop_wrap = true +tracks/16/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector2(3, -4)] +} [sub_resource type="Animation" id="Animation_7k2c8"] resource_name = "intro" @@ -546,6 +570,7 @@ metadata/_edit_horizontal_guides_ = [88.0, 122.0] [node name="Ground" parent="." instance=ExtResource("1_ff4yb")] position = Vector2(1, 0) +scene_name = "c01_s05" [node name="AnimationPlayer" parent="Ground" index="0"] libraries = { @@ -566,6 +591,7 @@ position = Vector2(27, 3) position = Vector2(503, 11) texture = ExtResource("4_gdhoy") enabled = false +immediately = false target_scene = "c01_s06" target_portal = "left" default_texture = ExtResource("4_gdhoy") @@ -644,11 +670,10 @@ file = "物品查看.mp3" [node name="Sign" parent="Ground/DeployLayer/oneshot纸片" index="2"] modulate = Color(1, 1, 1, 0) -offset_left = 35.0 -offset_top = -70.0 -offset_right = 35.0 -offset_bottom = -70.0 -display_sign = false +offset_left = 3.0 +offset_top = -4.0 +offset_right = 3.0 +offset_bottom = -4.0 [node name="CollisionShape2D" parent="Ground/DeployLayer/oneshot纸片/Area2D" index="0"] shape = SubResource("RectangleShape2D_5s1ih") diff --git a/scene/ground/scene/c01/s06_animation.gd b/scene/ground/scene/c01/s06_animation.gd index 66ddaabd..e8124393 100644 --- a/scene/ground/scene/c01/s06_animation.gd +++ b/scene/ground/scene/c01/s06_animation.gd @@ -9,6 +9,8 @@ func _default_data() -> Dictionary: func _ready() -> void: super._ready() + if Engine.is_editor_hint(): + return func _on_deploy_layer_ready() -> void: diff --git a/scene/ground/scene/c01/s06_孤儿院长廊围墙.tscn b/scene/ground/scene/c01/s06_孤儿院长廊围墙.tscn index 81f5b353..552e6df6 100644 --- a/scene/ground/scene/c01/s06_孤儿院长廊围墙.tscn +++ b/scene/ground/scene/c01/s06_孤儿院长廊围墙.tscn @@ -14,6 +14,7 @@ metadata/_edit_horizontal_guides_ = [158.0, 88.0] [node name="Ground" parent="." instance=ExtResource("1_bitx7")] +scene_name = "c01_s06" [node name="AnimationPlayer" parent="Ground" index="0"] script = ExtResource("2_fkfhi") @@ -30,11 +31,13 @@ centered = false [node name="portal_left" parent="Ground/DeployLayer" index="0"] position = Vector2(144, 20) +immediately = false target_scene = "c01_s05" target_portal = "right" [node name="portal_right" parent="Ground/DeployLayer" index="1"] position = Vector2(1886, 28) +immediately = false [node name="男孩" type="AnimatedSprite2D" parent="Ground/DeployLayer" index="2"] position = Vector2(547.5, 0.5) diff --git a/scene/ground/scene/c02/s01_街道.tscn b/scene/ground/scene/c02/s01_街道.tscn index 82e45b19..f3b5ca31 100644 --- a/scene/ground/scene/c02/s01_街道.tscn +++ b/scene/ground/scene/c02/s01_街道.tscn @@ -9,6 +9,7 @@ [node name="S01" type="Node2D"] [node name="Ground" parent="." instance=ExtResource("1_gdcov")] +scene_name = "c02_s01" [node name="AnimationPlayer" parent="Ground" index="0"] script = ExtResource("2_uuwn3") @@ -38,7 +39,7 @@ dialogue = "c02" position = Vector2(135, 56) [node name="MainPlayer" parent="Ground" index="5"] -position = Vector2(78, 40) +position = Vector2(78, 88) [node name="FGSprite2D" parent="Ground/ParallaxForeground/FGParallaxLayer" index="0"] texture = null diff --git a/scene/ground/scene/c02/s02_animation.gd b/scene/ground/scene/c02/s02_animation.gd index 0cdc2957..1b15eddc 100644 --- a/scene/ground/scene/c02/s02_animation.gd +++ b/scene/ground/scene/c02/s02_animation.gd @@ -11,6 +11,8 @@ func _default_data() -> Dictionary: func _ready() -> void: super._ready() + if Engine.is_editor_hint(): + return func _on_deploy_layer_ready() -> void: diff --git a/scene/ground/scene/c02/s02_走道.tscn b/scene/ground/scene/c02/s02_走道.tscn index 4d1989d9..044dc021 100644 --- a/scene/ground/scene/c02/s02_走道.tscn +++ b/scene/ground/scene/c02/s02_走道.tscn @@ -43,6 +43,7 @@ size = Vector2(35, 70) [node name="S02" type="Node2D"] [node name="Ground" parent="." instance=ExtResource("1_wrr6r")] +scene_name = "c02_s02" [node name="AnimationPlayer" parent="Ground" index="0"] libraries = { diff --git a/scene/ground/scene/c02/s03_animation.gd b/scene/ground/scene/c02/s03_animation.gd index 48a3c043..f107c44a 100644 --- a/scene/ground/scene/c02/s03_animation.gd +++ b/scene/ground/scene/c02/s03_animation.gd @@ -9,6 +9,8 @@ func _default_data() -> Dictionary: func _ready() -> void: super._ready() + if Engine.is_editor_hint(): + return func _on_deploy_layer_ready() -> void: diff --git a/scene/ground/scene/c02/s03_院子切换.tscn b/scene/ground/scene/c02/s03_院子切换.tscn index 49bd6570..6a0332f7 100644 --- a/scene/ground/scene/c02/s03_院子切换.tscn +++ b/scene/ground/scene/c02/s03_院子切换.tscn @@ -23,6 +23,7 @@ size = Vector2(40, 70) [node name="S03" type="Node2D"] [node name="Ground" parent="." instance=ExtResource("1_lheeb")] +scene_name = "c02_s03" [node name="AnimationPlayer" parent="Ground" index="0"] script = ExtResource("2_l2oec") @@ -41,7 +42,7 @@ position = Vector2(629, 2) [node name="Npc" parent="Ground/DeployLayer" index="2" instance=ExtResource("2_r5smg")] position = Vector2(465, 23) -frame_progress = 0.799802 +frame_progress = 0.514003 character_name = "张胖子" dialogue_title = "张胖子_01" @@ -72,7 +73,7 @@ ambient_light_energy = 2.0 position = Vector2(1120, 5) [node name="MainPlayer" parent="Ground" index="5"] -position = Vector2(25, 40) +position = Vector2(25, 88) [node name="BGParallaxLayer" parent="Ground/ParallaxForeground" index="0"] use_parent_material = true diff --git a/scene/ground/scene/template_animation.gd b/scene/ground/scene/template_animation.gd index 66ddaabd..e8124393 100644 --- a/scene/ground/scene/template_animation.gd +++ b/scene/ground/scene/template_animation.gd @@ -9,6 +9,8 @@ func _default_data() -> Dictionary: func _ready() -> void: super._ready() + if Engine.is_editor_hint(): + return func _on_deploy_layer_ready() -> void: diff --git a/scene/player/main_player.gd b/scene/player/main_player.gd index 7c4ba989..325b7217 100644 --- a/scene/player/main_player.gd +++ b/scene/player/main_player.gd @@ -62,6 +62,17 @@ func _ready() -> void: footstep_timer.timeout.connect(_on_footstep_timer_timeout) footstep_timer.stop() # SceneManager.focus_player(self) + _check_character_status() + + +func _enter_tree() -> void: + if is_node_ready(): + _check_character_status() + + +func _check_character_status(): + # 检查角色锁定状态 + running_locked = ArchiveManager.archive.player_running_locked func _on_footstep_timer_timeout(): diff --git a/scene/prop/prop_inspector.tscn b/scene/prop/prop_inspector.tscn index 6a0bf496..936041c6 100644 --- a/scene/prop/prop_inspector.tscn +++ b/scene/prop/prop_inspector.tscn @@ -1,8 +1,8 @@ [gd_scene load_steps=5 format=3 uid="uid://cekhj65axie0p"] [ext_resource type="Script" path="res://scene/prop/prop_inspector.gd" id="1_2wpwe"] +[ext_resource type="Texture2D" uid="uid://f186lvt5y2ql" path="res://asset/art/ui/prop/遮罩.png" id="2_j83lq"] [ext_resource type="Texture2D" uid="uid://cvgw2mxrlr6io" path="res://asset/art/scene/c02/s02_走道/ux_进门鼠疫海报yz.png" id="2_wr575"] -[ext_resource type="Texture2D" uid="uid://cgghff16powfg" path="res://asset/art/ui/prop遮罩.png" id="3_uf004"] [sub_resource type="LabelSettings" id="LabelSettings_5qe7a"] line_spacing = 1.0 @@ -25,7 +25,7 @@ grow_horizontal = 2 grow_vertical = 2 size_flags_horizontal = 4 mouse_filter = 2 -texture = ExtResource("3_uf004") +texture = ExtResource("2_j83lq") [node name="CenterContainer" type="CenterContainer" parent="."] anchors_preset = 8 @@ -108,6 +108,6 @@ unique_name_in_owner = true modulate = Color(1, 1, 1, 0) layout_mode = 2 size_flags_horizontal = 4 -text = "Q: 退出 E: 阅读" +text = "Q: ui_退出 E: ui_阅读" horizontal_alignment = 1 vertical_alignment = 1 diff --git a/util/lru.gd b/util/lru.gd new file mode 100644 index 00000000..351075d1 --- /dev/null +++ b/util/lru.gd @@ -0,0 +1,49 @@ +@tool +class_name LRU extends RefCounted + +# LRU 算法 +var cache_size = 1 +# keys. 新的在后面,旧的在前面 +var lru_list = [] +# key -> value +var cache = {} +var cache_mutex = Mutex.new() + + +func _init(size := 8) -> void: + cache_size = size + + +func _get(key: Variant) -> Variant: + var v = null + cache_mutex.lock() + if cache.has(key): + lru_list.erase(key) + lru_list.append(key) + v = cache[key] + cache_mutex.unlock() + return v + + +func _set(key: StringName, value: Variant) -> bool: + cache_mutex.lock() + if cache.has(key): + lru_list.erase(key) + if cache[key] != value: + _release_value(cache[key]) + cache[key] = value + lru_list.append(key) + if lru_list.size() > cache_size: + var k = lru_list.pop_front() + _release_value(cache[k]) + cache.erase(k) + cache_mutex.unlock() + return true + + +func _release_value(v: Variant) -> void: + if v is Node: + if not v.is_inside_tree() and is_instance_valid(v): + v.queue_free() + elif not v is RefCounted: + v.free()