120 lines
3.2 KiB
GDScript3
120 lines
3.2 KiB
GDScript3
|
|
class_name MessageBottleReader
|
||
|
|
extends Control
|
||
|
|
|
||
|
|
signal closed
|
||
|
|
|
||
|
|
const MAX_PARCHMENT_SIZE := Vector2(640.0, 480.0)
|
||
|
|
const FALLBACK_PARCHMENT_ASPECT: float = 4.0 / 3.0
|
||
|
|
const VIEWPORT_MARGIN := Vector2(32.0, 32.0)
|
||
|
|
|
||
|
|
@export var parchment_texture: Texture2D:
|
||
|
|
set(value):
|
||
|
|
parchment_texture = value
|
||
|
|
_apply_parchment_texture()
|
||
|
|
|
||
|
|
@onready var _parchment_surface: Control = %ParchmentSurface
|
||
|
|
@onready var _fallback_panel: Control = %FallbackPanel
|
||
|
|
@onready var _parchment_art: TextureRect = %ParchmentArt
|
||
|
|
@onready var _message_label: Label = %MessageLabel
|
||
|
|
@onready var _close_button: Button = %CloseButton
|
||
|
|
|
||
|
|
var _previous_focus: WeakRef
|
||
|
|
|
||
|
|
|
||
|
|
func _ready() -> void:
|
||
|
|
_close_button.pressed.connect(dismiss)
|
||
|
|
_close_button.focus_neighbor_left = _close_button.get_path_to(_close_button)
|
||
|
|
_close_button.focus_neighbor_right = _close_button.get_path_to(_close_button)
|
||
|
|
_close_button.focus_neighbor_top = _close_button.get_path_to(_close_button)
|
||
|
|
_close_button.focus_neighbor_bottom = _close_button.get_path_to(_close_button)
|
||
|
|
_apply_parchment_texture()
|
||
|
|
_resize_parchment()
|
||
|
|
hide()
|
||
|
|
|
||
|
|
|
||
|
|
func present(message_text: String) -> void:
|
||
|
|
if not is_node_ready():
|
||
|
|
call_deferred("present", message_text)
|
||
|
|
return
|
||
|
|
if not is_open():
|
||
|
|
var focus_owner: Control = get_viewport().gui_get_focus_owner()
|
||
|
|
_previous_focus = weakref(focus_owner) if focus_owner != null else null
|
||
|
|
_message_label.text = message_text
|
||
|
|
show()
|
||
|
|
_close_button.call_deferred("grab_focus")
|
||
|
|
|
||
|
|
|
||
|
|
func dismiss() -> void:
|
||
|
|
if not is_open():
|
||
|
|
return
|
||
|
|
hide()
|
||
|
|
_restore_previous_focus.call_deferred()
|
||
|
|
closed.emit()
|
||
|
|
|
||
|
|
|
||
|
|
func is_open() -> bool:
|
||
|
|
return visible
|
||
|
|
|
||
|
|
|
||
|
|
func consume_escape() -> bool:
|
||
|
|
if not is_open():
|
||
|
|
return false
|
||
|
|
dismiss()
|
||
|
|
return true
|
||
|
|
|
||
|
|
|
||
|
|
func _unhandled_input(event: InputEvent) -> void:
|
||
|
|
if not is_open() or not event.is_action_pressed(&"ui_cancel"):
|
||
|
|
return
|
||
|
|
if consume_escape():
|
||
|
|
get_viewport().set_input_as_handled()
|
||
|
|
|
||
|
|
|
||
|
|
func _notification(what: int) -> void:
|
||
|
|
if what == NOTIFICATION_RESIZED and is_node_ready():
|
||
|
|
_resize_parchment()
|
||
|
|
|
||
|
|
|
||
|
|
func _resize_parchment() -> void:
|
||
|
|
var available_size: Vector2 = (
|
||
|
|
get_viewport_rect().size - VIEWPORT_MARGIN
|
||
|
|
).max(Vector2.ONE)
|
||
|
|
var target_size: Vector2 = MAX_PARCHMENT_SIZE.min(available_size)
|
||
|
|
var aspect: float = FALLBACK_PARCHMENT_ASPECT
|
||
|
|
if parchment_texture != null:
|
||
|
|
var texture_size: Vector2 = parchment_texture.get_size()
|
||
|
|
if texture_size.x > 0.0 and texture_size.y > 0.0:
|
||
|
|
aspect = texture_size.x / texture_size.y
|
||
|
|
if target_size.x / target_size.y > aspect:
|
||
|
|
target_size.x = target_size.y * aspect
|
||
|
|
else:
|
||
|
|
target_size.y = target_size.x / aspect
|
||
|
|
_parchment_surface.custom_minimum_size = target_size.floor()
|
||
|
|
|
||
|
|
|
||
|
|
func _apply_parchment_texture() -> void:
|
||
|
|
if _parchment_art == null:
|
||
|
|
return
|
||
|
|
_parchment_art.texture = parchment_texture
|
||
|
|
_parchment_art.visible = parchment_texture != null
|
||
|
|
if _fallback_panel != null:
|
||
|
|
_fallback_panel.visible = parchment_texture == null
|
||
|
|
_resize_parchment()
|
||
|
|
|
||
|
|
|
||
|
|
func _restore_previous_focus() -> void:
|
||
|
|
if _previous_focus == null:
|
||
|
|
get_viewport().gui_release_focus()
|
||
|
|
return
|
||
|
|
var previous: Control = _previous_focus.get_ref() as Control
|
||
|
|
_previous_focus = null
|
||
|
|
if (
|
||
|
|
is_instance_valid(previous)
|
||
|
|
and previous.is_inside_tree()
|
||
|
|
and previous.is_visible_in_tree()
|
||
|
|
and previous.focus_mode != Control.FOCUS_NONE
|
||
|
|
):
|
||
|
|
previous.grab_focus()
|
||
|
|
else:
|
||
|
|
get_viewport().gui_release_focus()
|