promiscuity/game/scenes/UI/dialog_system.gd
Zeeshaun 6dc4d53ba0
All checks were successful
Deploy Promiscuity Auth API / deploy (push) Successful in 47s
Deploy Promiscuity Character API / deploy (push) Successful in 43s
Deploy Promiscuity Locations API / deploy (push) Successful in 44s
k8s smoke test / test (push) Successful in 7s
Dialog bug fix/tweaks
2026-02-13 11:55:19 -06:00

171 lines
4.5 KiB
GDScript

extends CanvasLayer
var _interactables: Array[Node] = []
var _active_interactable: Node = null
var _dialog_visible := false
var _dialog_source: Node = null
var _prompt_label: Label
var _dialog_panel: PanelContainer
var _dialog_label: RichTextLabel
func _ready() -> void:
layer = 50
process_mode = Node.PROCESS_MODE_ALWAYS
_setup_ui()
_set_dialog_visible(false)
_update_prompt_visibility()
func _process(_delta: float) -> void:
if Input.is_action_just_pressed("interact"):
if _dialog_visible:
_set_dialog_visible(false)
return
if _active_interactable != null:
_open_dialog_for(_active_interactable)
func register_interactable(interactable: Node) -> void:
if interactable == null:
return
if _interactables.has(interactable):
return
_interactables.append(interactable)
_refresh_active_interactable()
func unregister_interactable(interactable: Node) -> void:
if interactable == null:
return
_interactables.erase(interactable)
_refresh_active_interactable()
func _refresh_active_interactable() -> void:
while _interactables.size() > 0 and not is_instance_valid(_interactables[_interactables.size() - 1]):
_interactables.pop_back()
_active_interactable = _interactables[_interactables.size() - 1] if _interactables.size() > 0 else null
_update_prompt_visibility()
func _open_dialog_for(interactable: Node) -> void:
if _dialog_label:
_dialog_label.text = _get_dialog_text(interactable)
_dialog_source = interactable
_set_dialog_visible(true)
func show_text(text: String) -> void:
if _dialog_label:
_dialog_label.text = text
_dialog_source = null
_set_dialog_visible(true)
func show_text_from(source: Node, text: String) -> void:
if _dialog_label:
_dialog_label.text = text
_dialog_source = source
_set_dialog_visible(true)
func close_if_text(expected_text: String) -> void:
if not _dialog_visible:
return
if _dialog_label == null:
return
if _dialog_label.text != expected_text:
return
_set_dialog_visible(false)
func is_dialog_open() -> bool:
return _dialog_visible
func is_dialog_open_from(source: Node) -> bool:
return _dialog_visible and _dialog_source == source
func close_if_source(source: Node) -> void:
if not _dialog_visible:
return
if _dialog_source != source:
return
_set_dialog_visible(false)
func _set_dialog_visible(dialog_open: bool) -> void:
_dialog_visible = dialog_open
if not _dialog_visible:
_dialog_source = null
if _dialog_panel:
_dialog_panel.visible = _dialog_visible
_update_prompt_visibility()
func _update_prompt_visibility() -> void:
if _prompt_label == null:
return
var has_active := _active_interactable != null
_prompt_label.visible = has_active and not _dialog_visible
if _prompt_label.visible:
_prompt_label.text = _get_prompt_text(_active_interactable)
func _get_prompt_text(interactable: Node) -> String:
if interactable == null:
return ""
if interactable.has_method("get_dialog_prompt"):
return String(interactable.call("get_dialog_prompt"))
return "Press E to interact"
func _get_dialog_text(interactable: Node) -> String:
if interactable == null:
return ""
if interactable.has_method("get_dialog_text"):
return String(interactable.call("get_dialog_text"))
return "..."
func _setup_ui() -> void:
var root := Control.new()
root.name = "DialogRoot"
root.set_anchors_preset(Control.PRESET_FULL_RECT)
root.mouse_filter = Control.MOUSE_FILTER_IGNORE
add_child(root)
_prompt_label = Label.new()
_prompt_label.name = "PromptLabel"
_prompt_label.set_anchors_preset(Control.PRESET_CENTER_BOTTOM)
_prompt_label.offset_left = -140.0
_prompt_label.offset_top = -64.0
_prompt_label.offset_right = 140.0
_prompt_label.offset_bottom = -36.0
_prompt_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
_prompt_label.mouse_filter = Control.MOUSE_FILTER_IGNORE
_prompt_label.text = "Press E to interact"
root.add_child(_prompt_label)
_dialog_panel = PanelContainer.new()
_dialog_panel.name = "DialogPanel"
_dialog_panel.visible = false
_dialog_panel.set_anchors_preset(Control.PRESET_CENTER_BOTTOM)
_dialog_panel.offset_left = -300.0
_dialog_panel.offset_top = -220.0
_dialog_panel.offset_right = 300.0
_dialog_panel.offset_bottom = -80.0
_dialog_panel.mouse_filter = Control.MOUSE_FILTER_IGNORE
root.add_child(_dialog_panel)
_dialog_label = RichTextLabel.new()
_dialog_label.name = "DialogText"
_dialog_label.custom_minimum_size = Vector2(560.0, 120.0)
_dialog_label.fit_content = true
_dialog_label.scroll_active = false
_dialog_label.bbcode_enabled = true
_dialog_label.text = ""
_dialog_panel.add_child(_dialog_label)