# QuestCurtain (40250 uiquest.py:58-105 对齐) # 剧情 / 过场运镜模式的 16:9 电影上下黑边(Curtain / Letterbox) class_name QuestCurtain extends Control const CURTAIN_SPEED := 200.0 const MIN_BAR_HEIGHT := 50.0 var top_bar: ColorRect var bottom_bar: ColorRect var _bar_height := 60.0 var _is_open := false var _tween: Tween func _init() -> void: name = "QuestCurtain" set_anchors_preset(PRESET_FULL_RECT) mouse_filter = MOUSE_FILTER_IGNORE z_index = 95 top_bar = ColorRect.new() top_bar.name = "TopBar" top_bar.color = Color.BLACK top_bar.mouse_filter = MOUSE_FILTER_IGNORE add_child(top_bar) bottom_bar = ColorRect.new() bottom_bar.name = "BottomBar" bottom_bar.color = Color.BLACK bottom_bar.mouse_filter = MOUSE_FILTER_IGNORE add_child(bottom_bar) _reset_layout() func _ready() -> void: get_viewport().size_changed.connect(_on_size_changed) _reset_layout() func _get_screen_size() -> Vector2: if is_inside_tree() and get_viewport(): return get_viewport_rect().size return Vector2(1024, 768) func _on_size_changed() -> void: if _is_open: _calculate_bar_height() var sz := _get_screen_size() top_bar.position = Vector2(0, 0) top_bar.size = Vector2(sz.x, _bar_height) bottom_bar.position = Vector2(0, sz.y - _bar_height) bottom_bar.size = Vector2(sz.x, _bar_height) else: _reset_layout() func _calculate_bar_height() -> float: var sz := _get_screen_size() # 40250: (GetScreenHeight() - GetScreenWidth() * 9 // 16) // 2 var h: float = floorf((sz.y - sz.x * 9.0 / 16.0) / 2.0) if h < MIN_BAR_HEIGHT: h = MIN_BAR_HEIGHT _bar_height = h return _bar_height func _reset_layout() -> void: var sz := _get_screen_size() _calculate_bar_height() top_bar.position = Vector2(0, -_bar_height - 1.0) top_bar.size = Vector2(sz.x, _bar_height) bottom_bar.position = Vector2(0, sz.y + 1.0) bottom_bar.size = Vector2(sz.x, _bar_height) func open(duration: float = 0.4) -> void: _is_open = true var sz := _get_screen_size() _calculate_bar_height() if _tween and _tween.is_valid(): _tween.kill() _tween = create_tween().set_parallel(true).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT) top_bar.size = Vector2(sz.x, _bar_height) bottom_bar.size = Vector2(sz.x, _bar_height) _tween.tween_property(top_bar, "position:y", 0.0, duration) _tween.tween_property(bottom_bar, "position:y", sz.y - _bar_height, duration) func close(duration: float = 0.4) -> void: _is_open = false var sz := _get_screen_size() if _tween and _tween.is_valid(): _tween.kill() _tween = create_tween().set_parallel(true).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_IN) _tween.tween_property(top_bar, "position:y", -_bar_height - 1.0, duration) _tween.tween_property(bottom_bar, "position:y", sz.y + 1.0, duration) func is_open() -> bool: return _is_open