xiandie/scene/ground/ground_loader.gd

175 lines
5.2 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@tool
class_name GroundLoader extends Node2D
@export_group("Scene")
@export var ignore_archive := false
@export var current_scene := "c02_s01"
@export var entrance_portal := "left"
@export var debug_reload := false:
set(new_val):
debug_reload = false
if current_scene and entrance_portal:
transition_to_scene(current_scene, entrance_portal, true)
@export var archive_scene := ""
@export var archive_portal := ""
var first_entered := true
var ground: Ground2D
var scenes_dir = "res://scene/ground/scene/"
var ground_dict = {}
func _ready() -> void:
_read_grounds()
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:
# read grounds
var dir = DirAccess.open(scenes_dir)
for c_dir in dir.get_directories():
var c_path = scenes_dir + c_dir + "/"
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 都初始化 archive
# for key in ground_dict.keys():
# if GlobalConfig.DEBUG:
# print("check ground_archive:", key)
# ArchiveManager.archive.ground_archive(key)
func _load_save():
if not Engine.is_editor_hint() and ArchiveManager.archive:
if ArchiveManager.archive.current_scene:
archive_scene = ArchiveManager.archive.current_scene
if ArchiveManager.archive.entrance_portal:
archive_portal = ArchiveManager.archive.entrance_portal
func transition_to_scene(key: String, portal: String, immediately := false) -> void:
var scene_path = ground_dict[key]
if scene_path:
var scene = load(scene_path).instantiate()
current_scene = key
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
else:
print("Scene not found: " + key)
func _update_player_position():
if ignore_archive or Engine.is_editor_hint():
return
var player = SceneManager.get_player() as MainPlayer
if player and ArchiveManager.archive:
# if GlobalConfig.DEBUG:
# print("update player position", ArchiveManager.archive.player_global_position)
player.global_position = ArchiveManager.archive.player_global_position
# fixed y
if ground.player_y_fixed:
player.global_position.y = ground.player_y
player.set_facing_direction(ArchiveManager.archive.player_direction)
func _do_transition(scene: Node2D):
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.name = "Ground"
if not Engine.is_editor_hint():
var portal_node = ground.get_node_or_null("DeployLayer/portal_" + entrance_portal) as Node2D
if portal_node:
var player = SceneManager.get_player()
if player:
# player.global_position.x = -20.0
player.global_position.x = portal_node.global_position.x
if GlobalConfig.DEBUG:
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()
func _update_archive():
if not Engine.is_editor_hint() and ArchiveManager.archive:
ArchiveManager.archive.current_scene = current_scene
ArchiveManager.archive.entrance_portal = entrance_portal
archive_scene = current_scene
archive_portal = entrance_portal
var update_watcher: Timer
var last_modify_time = 0
# DEBUG 时重新加载资源
func _watch_scene_update():
var scene_path = ground_dict[current_scene]
if scene_path:
last_modify_time = FileAccess.get_modified_time(scene_path)
if not update_watcher:
update_watcher = Timer.new()
update_watcher.wait_time = 1
update_watcher.one_shot = false
add_child(update_watcher)
update_watcher.start()
else:
# remove all connections
for c in update_watcher.timeout.get_connections():
update_watcher.timeout.disconnect(c.callable)
update_watcher.timeout.connect(_check_scene_update.bind(scene_path))
func _check_scene_update(scene_path):
var modify = FileAccess.get_modified_time(scene_path)
if modify != last_modify_time:
last_modify_time = modify
_on_resources_reload(scene_path)
func _on_resources_reload(res):
print("resources_reload processing:", res)
if not Engine.is_editor_hint() and res.ends_with(".tscn"):
ArchiveManager.save_all()
transition_to_scene(current_scene, entrance_portal, true)